diff options
author | Roberto C. Sanchez <roberto@connexer.com> | 2014-03-29 10:54:01 -0400 |
---|---|---|
committer | Roberto C. Sanchez <roberto@connexer.com> | 2014-03-29 10:54:01 -0400 |
commit | 71a39f4652cd51df814c930dd268f3c9ad2aee86 (patch) | |
tree | 5994350a603908c4e4d660bc9d72c4ec43dd648e /src | |
parent | 03134fa5f6f25d92724ce4c183f9bbe12a9e37dc (diff) |
Imported Upstream version 1.6.0+dfsg
Diffstat (limited to 'src')
163 files changed, 5748 insertions, 16502 deletions
diff --git a/src/frontend/framework/femain.cpp b/src/frontend/framework/femain.cpp index 415ab6f..e6580cb 100644 --- a/src/frontend/framework/femain.cpp +++ b/src/frontend/framework/femain.cpp @@ -1,3 +1,20 @@ +/* + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + #include <femain.h> FEMain::FEMain() { diff --git a/src/frontend/im/hebrewmcim.cpp b/src/frontend/im/hebrewmcim.cpp index 9ec55a9..c8bb5fa 100644 --- a/src/frontend/im/hebrewmcim.cpp +++ b/src/frontend/im/hebrewmcim.cpp @@ -8,6 +8,19 @@ * @version 1.0 */ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + + #include <hebrewmcim.h> HebrewMCIM::HebrewMCIM() diff --git a/src/frontend/im/nullim.cpp b/src/frontend/im/nullim.cpp index a4f4aad..bceeb23 100644 --- a/src/frontend/im/nullim.cpp +++ b/src/frontend/im/nullim.cpp @@ -1,3 +1,20 @@ +/* + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + #include <nullim.h> diff --git a/src/frontend/im/swinputmeth.cpp b/src/frontend/im/swinputmeth.cpp index 7f64865..7ba60dd 100644 --- a/src/frontend/im/swinputmeth.cpp +++ b/src/frontend/im/swinputmeth.cpp @@ -7,6 +7,18 @@ * @version 1.0 */ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + #include <swinputmeth.h> SWInputMethod::SWInputMethod() { diff --git a/src/frontend/swdisp.cpp b/src/frontend/swdisp.cpp index e7208e0..bf46ff2 100644 --- a/src/frontend/swdisp.cpp +++ b/src/frontend/swdisp.cpp @@ -1,8 +1,24 @@ /****************************************************************************** * swdisp.cpp - code for base class 'swdisp'. swdisp is the basis for all * types of displays (e.g. raw textout, curses, xwindow, etc.) + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #ifndef _WIN32_WCE #include <iostream> #endif diff --git a/src/frontend/swlog.cpp b/src/frontend/swlog.cpp index 13b025b..74b6bd4 100644 --- a/src/frontend/swlog.cpp +++ b/src/frontend/swlog.cpp @@ -1,3 +1,20 @@ +/* + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + //--------------------------------------------------------------------------- #include <stdarg.h> diff --git a/src/keys/genarray.c b/src/keys/genarray.c index 331d4af..112b0f6 100644 --- a/src/keys/genarray.c +++ b/src/keys/genarray.c @@ -1,3 +1,20 @@ +/* + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + #include <stdio.h> #include <fcntl.h> #include <stdlib.h> diff --git a/src/keys/listkey.cpp b/src/keys/listkey.cpp index ffafdd4..49bf369 100644 --- a/src/keys/listkey.cpp +++ b/src/keys/listkey.cpp @@ -1,9 +1,26 @@ /****************************************************************************** * listkey.cpp - code for base class 'ListKey'. ListKey is the basis for all - * types of keys that have lists of specified indexes - * (e.g. a list of verses, place, etc.) + * types of keys that have lists of specified indexes + * (e.g. a list of verses, place, etc.) + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <utilstr.h> #include <stdlib.h> #include <swkey.h> @@ -41,6 +58,8 @@ ListKey::ListKey(ListKey const &k) : SWKey(k.keytext) { void ListKey::init() { myclass = &classdef; + // this is a listkey, bound is always set + boundSet = true; } @@ -281,6 +300,24 @@ const char *ListKey::getRangeText() const { /****************************************************************************** + * ListKey::getOSISRefRangeText - returns parsable range text for this key + */ + +const char *ListKey::getOSISRefRangeText() const { + char *buf = new char[(arraycnt + 1) * 255]; + buf[0] = 0; + for (int i = 0; i < arraycnt; i++) { + strcat(buf, array[i]->getOSISRefRangeText()); + if (i < arraycnt-1) + strcat(buf, ";"); + } + stdstr(&rangeText, buf); + delete [] buf; + return rangeText; +} + + +/****************************************************************************** * ListKey::getText - returns text key if (const char *) cast is requested */ diff --git a/src/keys/strkey.cpp b/src/keys/strkey.cpp index 1d84650..4171e36 100644 --- a/src/keys/strkey.cpp +++ b/src/keys/strkey.cpp @@ -1,9 +1,26 @@ /****************************************************************************** * StrKey.cpp - code for class 'StrKey'- a standard string key class (used - * for modules that index on single strings (eg. cities, - * names, words, etc.) + * for modules that index on single strings (eg. cities, + * names, words, etc.) + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <swmacs.h> #include <strkey.h> #include <stdio.h> diff --git a/src/keys/swkey.cpp b/src/keys/swkey.cpp index 0557c40..3709cdc 100644 --- a/src/keys/swkey.cpp +++ b/src/keys/swkey.cpp @@ -2,16 +2,35 @@ * swkey.cpp - code for base class 'SWKey'. SWKey is the basis for all * types of keys for indexing into modules (e.g. verse, word, * place, etc.) + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <swkey.h> #include <utilstr.h> #include <string.h> +#include <localemgr.h> SWORD_NAMESPACE_START static const char *classes[] = {"SWKey", "SWObject", 0}; SWClass SWKey::classdef(classes); +SWKey::LocaleCache SWKey::localeCache; /****************************************************************************** * SWKey Constructor - initializes instance of SWKey @@ -21,6 +40,7 @@ SWClass SWKey::classdef(classes); SWKey::SWKey(const char *ikey) { + init(); index = 0; persist = 0; keytext = 0; @@ -28,11 +48,12 @@ SWKey::SWKey(const char *ikey) error = 0; userData = 0; stdstr(&keytext, ikey); - init(); } SWKey::SWKey(SWKey const &k) { + init(); + stdstr(&localeName, k.localeName); index = k.index; persist = k.persist; userData = k.userData; @@ -40,12 +61,14 @@ SWKey::SWKey(SWKey const &k) rangeText = 0; error = k.error; setText(k.getText()); - init(); } void SWKey::init() { myclass = &classdef; boundSet = false; + locale = 0; + localeName = 0; + setLocale(LocaleMgr::getSystemLocaleMgr()->getDefaultLocaleName()); } SWKey *SWKey::clone() const @@ -58,10 +81,9 @@ SWKey *SWKey::clone() const */ SWKey::~SWKey() { - if (keytext) - delete [] keytext; - if (rangeText) - delete [] rangeText; + delete [] keytext; + delete [] rangeText; + delete [] localeName; } @@ -80,6 +102,28 @@ char SWKey::Persist() const /****************************************************************************** + * SWKey::getPrivateLocale - Gets a real locale object from our name + * + * RET: locale object associated with our name + */ + +SWLocale *SWKey::getPrivateLocale() const { + if (!locale) { + if ((!localeCache.name) || (strcmp(localeCache.name, localeName))) { + stdstr(&(localeCache.name), localeName); + // this line is the entire bit of work we're trying to avoid with the cache + // worth it? compare time examples/cmdline/search KJV "God love world" to + // same with this method reduced to: + // if (!local) local = ... (call below); return locale; + localeCache.locale = LocaleMgr::getSystemLocaleMgr()->getLocale(localeName); + } + locale = localeCache.locale; + } + return locale; +} + + +/****************************************************************************** * SWKey::Persist - Set/gets whether this object itself persists within a * module that it was used to setKey or just a copy. * (1 - persists in module; 0 - a copy is attempted @@ -133,6 +177,7 @@ void SWKey::setText(const char *ikey) { void SWKey::copyFrom(const SWKey &ikey) { // not desirable Persist(ikey.Persist()); + setLocale(ikey.getLocale()); setText((const char *)ikey); } @@ -157,6 +202,15 @@ const char *SWKey::getRangeText() const { /****************************************************************************** + * SWKey::getOSISRefRangeText - returns parsable range text for this key + */ + +const char *SWKey::getOSISRefRangeText() const { + return getRangeText(); +} + + +/****************************************************************************** * SWKey::compare - Compares another VerseKey object * * ENT: ikey - key to compare with this one diff --git a/src/keys/treekey.cpp b/src/keys/treekey.cpp index 2b217ee..ce769a1 100644 --- a/src/keys/treekey.cpp +++ b/src/keys/treekey.cpp @@ -1,7 +1,7 @@ /****************************************************************************** * versekey.h - code for class 'versekey'- a standard Biblical verse key * - * $Id: treekey.cpp 1994 2006-11-20 20:24:06Z scribe $ + * $Id: treekey.cpp 2178 2008-06-20 15:10:47Z scribe $ * * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -32,6 +32,7 @@ SWClass TreeKey::classdef(classes); void TreeKey::init() { myclass = &classdef; unsnappedKeyText = ""; + posChangeListener = 0; } diff --git a/src/keys/treekeyidx.cpp b/src/keys/treekeyidx.cpp index 738d17a..cc93fc0 100644 --- a/src/keys/treekeyidx.cpp +++ b/src/keys/treekeyidx.cpp @@ -1,7 +1,7 @@ /****************************************************************************** * versekey.h - code for class 'versekey'- a standard Biblical verse key * - * $Id: treekeyidx.cpp 2147 2008-03-14 06:54:18Z scribe $ + * $Id: treekeyidx.cpp 2280 2009-03-07 15:34:36Z scribe $ * * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -91,7 +91,7 @@ const char *TreeKeyIdx::getLocalName() { } -const char *TreeKeyIdx::getUserData(int *size) { +const char *TreeKeyIdx::getUserData(int *size) const { unsnappedKeyText = ""; if (size) *size = (int)currentNode.dsize; @@ -127,12 +127,25 @@ void TreeKeyIdx::save() { void TreeKeyIdx::root() { error = getTreeNodeFromIdxOffset(0, ¤tNode); + positionChanged(); +} + +int TreeKeyIdx::getLevel() { + TreeNode iterator; + iterator.parent = currentNode.parent; + int level = 0; + while (iterator.parent > -1) { + level++; + getTreeNodeFromIdxOffset(iterator.parent, &iterator); + } + return level; } bool TreeKeyIdx::parent() { if (currentNode.parent > -1) { error = getTreeNodeFromIdxOffset(currentNode.parent, ¤tNode); + positionChanged(); return true; } return false; @@ -142,6 +155,7 @@ bool TreeKeyIdx::parent() { bool TreeKeyIdx::firstChild() { if (currentNode.firstChild > -1) { error = getTreeNodeFromIdxOffset(currentNode.firstChild, ¤tNode); + positionChanged(); return true; } return false; @@ -151,6 +165,7 @@ bool TreeKeyIdx::firstChild() { bool TreeKeyIdx::nextSibling() { if (currentNode.next > -1) { error = getTreeNodeFromIdxOffset(currentNode.next, ¤tNode); + positionChanged(); return true; } return false; @@ -168,6 +183,7 @@ bool TreeKeyIdx::previousSibling() { getTreeNodeFromIdxOffset(iterator.next, &iterator); if (iterator.next > -1) { error = getTreeNodeFromIdxOffset(iterator.offset, ¤tNode); + positionChanged(); return true; } } @@ -195,6 +211,7 @@ void TreeKeyIdx::append() { currentNode.clear(); currentNode.offset = idxOffset; currentNode.parent = parent; + positionChanged(); } } @@ -212,6 +229,7 @@ void TreeKeyIdx::appendChild() { currentNode.offset = idxOffset; currentNode.parent = parent; } + positionChanged(); } @@ -253,6 +271,7 @@ void TreeKeyIdx::remove() { } } } + positionChanged(); } } @@ -292,7 +311,7 @@ signed char TreeKeyIdx::create(const char *ipath) { newTree.saveTreeNode(&root); delete [] path; - + return 0; } @@ -394,6 +413,7 @@ unsigned long TreeKeyIdx::getOffset() const { void TreeKeyIdx::setOffset(unsigned long offset) { error = getTreeNodeFromIdxOffset(offset, ¤tNode); + positionChanged(); } @@ -461,6 +481,7 @@ void TreeKeyIdx::copyFrom(const TreeKeyIdx &ikey) { idxfd = FileMgr::getSystemFileMgr()->open(ikey.idxfd->path, ikey.idxfd->mode, ikey.idxfd->perms); datfd = FileMgr::getSystemFileMgr()->open(ikey.datfd->path, ikey.datfd->mode, ikey.datfd->perms); } + positionChanged(); } @@ -520,6 +541,7 @@ void TreeKeyIdx::setText(const char *ikey) { error = KEYERR_OUTOFBOUNDS; delete [] buf; unsnappedKeyText = ikey; + positionChanged(); } @@ -527,6 +549,7 @@ void TreeKeyIdx::setText(const char *ikey) { void TreeKeyIdx::copyFrom(const SWKey &ikey) { unsnappedKeyText = ikey; SWKey::copyFrom(ikey); + positionChanged(); } void TreeKeyIdx::setPosition(SW_POSITION p) { @@ -538,6 +561,7 @@ void TreeKeyIdx::setPosition(SW_POSITION p) { error = getTreeNodeFromIdxOffset(idxfd->seek(-4, SEEK_END), ¤tNode); break; } + positionChanged(); Error(); // clear error from normalize } @@ -557,10 +581,15 @@ int TreeKeyIdx::compare(const SWKey &ikey) { void TreeKeyIdx::decrement(int steps) { error = getTreeNodeFromIdxOffset(currentNode.offset - (4*steps), ¤tNode); + positionChanged(); } void TreeKeyIdx::increment(int steps) { error = getTreeNodeFromIdxOffset(currentNode.offset + (4*steps), ¤tNode); + if (error) { +// SWLog::getSystemLog()->logError("error: %d", error); + } + positionChanged(); /* // assert positive diff --git a/src/keys/versekey.cpp b/src/keys/versekey.cpp index cb7bbfc..9c50a04 100644 --- a/src/keys/versekey.cpp +++ b/src/keys/versekey.cpp @@ -1,7 +1,24 @@ /****************************************************************************** * VerseKey.cpp - code for class 'VerseKey'- a standard Biblical verse key + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <swmacs.h> #include <stdio.h> #include <fcntl.h> @@ -13,9 +30,9 @@ #include <swkey.h> #include <swlog.h> #include <versekey.h> -#include <localemgr.h> #include <swlocale.h> #include <roman.h> +#include <versemgr.h> SWORD_NAMESPACE_START @@ -26,23 +43,15 @@ SWClass VerseKey::classdef(classes); * Initialize static members of VerseKey */ -#include <canon.h> // Initialize static members of canonical books structure - -struct sbook *VerseKey::builtin_books[2] = {0,0}; -const char VerseKey::builtin_BMAX[2] = {39, 27}; -long *VerseKey::offsets[2][2] = {{VerseKey::otbks, VerseKey::otcps}, {VerseKey::ntbks, VerseKey::ntcps}}; int VerseKey::instance = 0; -VerseKey::LocaleCache VerseKey::localeCache; /****************************************************************************** * VerseKey::init - initializes instance of VerseKey */ -void VerseKey::init() { +void VerseKey::init(const char *v11n) { myclass = &classdef; - if (!instance) - initstatics(); instance++; autonorm = 1; // default auto normalization to true @@ -50,13 +59,15 @@ void VerseKey::init() { upperBound = 0; lowerBound = 0; boundSet = false; - testament = 0; - book = 0; - chapter = 0; - verse = 0; - locale = 0; - - setLocale(LocaleMgr::getSystemLocaleMgr()->getDefaultLocaleName()); + testament = 1; + book = 1; + chapter = 1; + verse = 1; + suffix = 0; + tmpClone = 0; + refSys = 0; + + setVersificationSystem(v11n); } /****************************************************************************** @@ -104,6 +115,57 @@ VerseKey::VerseKey(VerseKey const &k) : SWKey(k) /****************************************************************************** + * VerseKey::setFromOther - Positions this VerseKey to another VerseKey + */ + +void VerseKey::setFromOther(const VerseKey &ikey) { + if (refSys == ikey.refSys) { + testament = ikey.Testament(); + book = ikey.Book(); + chapter = ikey.Chapter(); + verse = ikey.Verse(); + suffix = ikey.getSuffix(); + } + // Here is where we will do v11n system conversions in the future + // when we have a conversion mechanism (Ben Morgan has started + // thinking about this) + else { + // For now, this is the best we can do + setText(ikey.getText()); + } +} + + +void VerseKey::positionFrom(const SWKey &ikey) { + error = 0; + const SWKey *fromKey = &ikey; + ListKey *tryList = SWDYNAMIC_CAST(ListKey, fromKey); + if (tryList) { + SWKey *k = tryList->getElement(); + if (k) fromKey = k; + } + VerseKey *tryVerse = SWDYNAMIC_CAST(VerseKey, fromKey); + if (tryVerse) { + setFromOther(*tryVerse); + } + else { + SWKey::positionFrom(*fromKey); + parse(); + } + + // should we always perform bounds checks? Tried but seems to cause infinite recursion + if (_compare(UpperBound()) > 0) { + setFromOther(UpperBound()); + error = KEYERR_OUTOFBOUNDS; + } + if (_compare(LowerBound()) < 0) { + setFromOther(LowerBound()); + error = KEYERR_OUTOFBOUNDS; + } +} + + +/****************************************************************************** * VerseKey::copyFrom - Equates this VerseKey to another VerseKey */ @@ -114,6 +176,9 @@ void VerseKey::copyFrom(const VerseKey &ikey) { book = ikey.Book(); chapter = ikey.Chapter(); verse = ikey.Verse(); + suffix = ikey.getSuffix(); + setLocale(ikey.getLocale()); + setVersificationSystem(ikey.getVersificationSystem()); if (ikey.isBoundSet()) { LowerBound(ikey.LowerBound()); UpperBound(ikey.UpperBound()); @@ -145,11 +210,19 @@ void VerseKey::copyFrom(const SWKey &ikey) { } -VerseKey::VerseKey(const char *min, const char *max) : SWKey() +VerseKey::VerseKey(const char *min, const char *max, const char *v11n) : SWKey() { - init(); - LowerBound(min); - UpperBound(max); + init(v11n); + ListKey tmpListKey = ParseVerseList(min); + if (tmpListKey.Count()) { + VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement(0)); + LowerBound(*newElement); + } + tmpListKey = ParseVerseList(max, min, true); + if (tmpListKey.Count()) { + VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement(0)); + UpperBound((newElement->isBoundSet())?newElement->UpperBound():*newElement); + } setPosition(TOP); } @@ -167,117 +240,33 @@ SWKey *VerseKey::clone() const */ VerseKey::~VerseKey() { - if (upperBound) - delete upperBound; - if (lowerBound) - delete lowerBound; - if (locale) - delete [] locale; + + delete tmpClone; --instance; } -void VerseKey::setLocale(const char *name) { - char *BMAX; - struct sbook **lbooks; - bool useCache = false; +void VerseKey::setVersificationSystem(const char *name) { + const VerseMgr::System *newRefSys = VerseMgr::getSystemVerseMgr()->getVersificationSystem(name); + // TODO: cheese, but what should we do if requested v11n system isn't found? + if (!newRefSys) newRefSys = VerseMgr::getSystemVerseMgr()->getVersificationSystem("KJV"); + if (refSys != newRefSys) { + refSys = newRefSys; + BMAX[0] = refSys->getBMAX()[0]; + BMAX[1] = refSys->getBMAX()[1]; - if (localeCache.name) - useCache = (!strcmp(localeCache.name, name)); - - if (!useCache) { // if we're setting params for a new locale - stdstr(&(localeCache.name), name); - localeCache.abbrevsCnt = 0; - } - - SWLocale *locale = (useCache) ? localeCache.locale : LocaleMgr::getSystemLocaleMgr()->getLocale(name); - localeCache.locale = locale; - - if (locale) { - locale->getBooks(&BMAX, &lbooks); - setBooks(BMAX, lbooks); - setBookAbbrevs(locale->getBookAbbrevs(), localeCache.abbrevsCnt); - localeCache.abbrevsCnt = abbrevsCnt; + // TODO: adjust bounds for versificaion system ??? + // TODO: when we have mapping done, rethink this + //necessary as our bounds might not mean anything in the new v11n system + ClearBounds(); } - else { - setBooks(builtin_BMAX, builtin_books); - setBookAbbrevs(builtin_abbrevs, localeCache.abbrevsCnt); - localeCache.abbrevsCnt = abbrevsCnt; - } - stdstr(&(this->locale), localeCache.name); - - if (lowerBound) - LowerBound().setLocale(name); - if (upperBound) - UpperBound().setLocale(name); -} - -void VerseKey::setBooks(const char *iBMAX, struct sbook **ibooks) { - BMAX = iBMAX; - books = ibooks; -} - -void VerseKey::setBookAbbrevs(const struct abbrev *bookAbbrevs, unsigned int size) { - abbrevs = bookAbbrevs; - if (!size) { - for (abbrevsCnt = 0; *abbrevs[abbrevsCnt].ab; abbrevsCnt++) { - /* - if (strcmp(abbrevs[abbrevsCnt-1].ab, abbrevs[abbrevsCnt].ab) > 0) { - fprintf(stderr, "ERROR: book abbreviation (canon.h or locale) misordered at entry: %s\n", abbrevs[abbrevsCnt].ab); - exit(-1); - } - */ - } - - if (SWLog::getSystemLog()->getLogLevel() > 0) { //make sure log is wanted, this loop stuff costs a lot of time - for (int t = 0; t < 2; t++) { - for (int i = 0; i < BMAX[t]; i++) { - const int bn = getBookAbbrev(books[t][i].name); - if ((bn-1)%39 != i) { - SWLog::getSystemLog()->logError("VerseKey::Book: %s does not have a matching toupper abbrevs entry! book number returned was: %d(%d). Required entry should be:", - books[t][i].name, bn, i); - char *abbr = 0; - stdstr(&abbr, books[t][i].name, 2); - strstrip(abbr); - - StringMgr* stringMgr = StringMgr::getSystemStringMgr(); - const bool hasUTF8Support = StringMgr::hasUTF8Support(); - if (hasUTF8Support) { //we have support for UTF-8 handling; we expect UTF-8 encoded locales - stringMgr->upperUTF8(abbr, strlen(abbr)*2); - } - else { - stringMgr->upperLatin1(abbr); - } - SWLog::getSystemLog()->logError("%s=%d", abbr, (t*39)+i+1); - } - } - } - } - } - else abbrevsCnt = size; } -/****************************************************************************** - * VerseKey::initstatics - initializes statics. Performed only when first - * instance on VerseKey (or descendent) is created. - */ - -void VerseKey::initstatics() { - int l1, l2, chaptmp = 0; - - builtin_books[0] = otbooks; - builtin_books[1] = ntbooks; +const char *VerseKey::getVersificationSystem() const { return refSys->getName(); } - for (l1 = 0; l1 < 2; l1++) { - for (l2 = 0; l2 < builtin_BMAX[l1]; l2++) { - builtin_books[l1][l2].versemax = &vm[chaptmp]; - chaptmp += builtin_books[l1][l2].chapmax; - } - } -} /****************************************************************************** @@ -288,37 +277,18 @@ void VerseKey::initstatics() { char VerseKey::parse(bool checkAutoNormalize) { - - - testament = 2; - book = BMAX[1]; + testament = BMAX[1]?2:1; + book = BMAX[BMAX[1]?1:0]; chapter = 1; verse = 1; - int booklen = 0; int error = 0; if (keytext) { - ListKey tmpListKey = VerseKey::ParseVerseList(keytext); + ListKey tmpListKey = ParseVerseList(keytext); if (tmpListKey.Count()) { - SWKey::setText((const char *)tmpListKey); - for (int i = 1; i < 3; i++) { - for (int j = 1; j <= BMAX[i-1]; j++) { - int matchlen = strlen(books[i-1][j-1].name); - if (!strncmp(keytext, books[i-1][j-1].name, matchlen)) { - if (matchlen > booklen) { - booklen = matchlen; - testament = i; - book = j; - } - } - } - } - - if (booklen) { - sscanf(&keytext[booklen], "%d:%d", &chapter, &verse); - } - else error = 1; + this->positionFrom(*tmpListKey.getElement(0)); + error = this->error; } else error = 1; } if (checkAutoNormalize) { @@ -338,7 +308,7 @@ char VerseKey::parse(bool checkAutoNormalize) void VerseKey::freshtext() const { char buf[2024]; - int realtest = testament; + int realTest = testament; int realbook = book; if (book < 1) { @@ -347,14 +317,18 @@ void VerseKey::freshtext() const else sprintf(buf, "[ Testament %d Heading ]", (int)testament); } else { - if (realbook > BMAX[realtest-1]) { - realbook -= BMAX[realtest-1]; - if (realtest < 2) - realtest++; - if (realbook > BMAX[realtest-1]) - realbook = BMAX[realtest-1]; + if (realbook > BMAX[realTest-1]) { + realbook -= BMAX[realTest-1]; + if (realTest < 2) + realTest++; + if (realbook > BMAX[realTest-1]) + realbook = BMAX[realTest-1]; + } + sprintf(buf, "%s %d:%d", getBookName(), chapter, verse); + if (suffix) { + buf[strlen(buf)+1] = 0; + buf[strlen(buf)] = suffix; } - sprintf(buf, "%s %d:%d", books[realtest-1][realbook-1].name, chapter, verse); } stdstr((char **)&keytext, buf); @@ -362,19 +336,24 @@ void VerseKey::freshtext() const -/****************************************************************************** - * VerseKey::getBookAbbrev - Attempts to find a book abbreviation for a buffer +/************************************************************************ + * VerseKey::getBookAbbrev - Attempts to find a book no from a name or + * abbreviation * * ENT: abbr - key for which to search; * RET: book number or < 0 = not valid */ -int VerseKey::getBookAbbrev(const char *iabbr) +int VerseKey::getBookAbbrev(const char *iabbr) const { int diff, abLen, min, max, target, retVal = -1; char *abbr = 0; + int abbrevsCnt; + + const struct abbrev *abbrevs = getPrivateLocale()->getBookAbbrevs(&abbrevsCnt); + StringMgr* stringMgr = StringMgr::getSystemStringMgr(); const bool hasUTF8Support = StringMgr::hasUTF8Support(); @@ -420,7 +399,15 @@ int VerseKey::getBookAbbrev(const char *iabbr) break; } - retVal = (!diff) ? abbrevs[target].book : -1; + if (!diff) { + // lets keep moving forward till we find an abbrev in our refSys + retVal = refSys->getBookNumberByOSISName(abbrevs[target].osis); + while ((retVal < 0) && (target < max) && (!strncmp(abbr, abbrevs[target+1].ab, abLen))) { + target++; + retVal = refSys->getBookNumberByOSISName(abbrevs[target].osis); + } + } + else retVal = -1; } if (retVal > 0) break; @@ -431,6 +418,36 @@ int VerseKey::getBookAbbrev(const char *iabbr) /****************************************************************************** + * VerseKey::validateCurrentLocale - be sure a locale book abbrevs set is complete + * + */ +void VerseKey::validateCurrentLocale() const { + if (SWLog::getSystemLog()->getLogLevel() >= SWLog::LOG_DEBUG) { //make sure log is wanted, this loop stuff costs a lot of time + for (int i = 0; i < refSys->getBookCount(); i++) { + const int bn = getBookAbbrev(getPrivateLocale()->translate(refSys->getBook(i)->getLongName())); + if (bn != i+1) { + char *abbr = 0; + stdstr(&abbr, getPrivateLocale()->translate(refSys->getBook(i)->getLongName()), 2); + strstrip(abbr); + SWLog::getSystemLog()->logDebug("VerseKey::Book: %s does not have a matching toupper abbrevs entry! book number returned was: %d, should be %d. Required entry to add to locale:", abbr, bn, i); + + StringMgr* stringMgr = StringMgr::getSystemStringMgr(); + const bool hasUTF8Support = StringMgr::hasUTF8Support(); + if (hasUTF8Support) { //we have support for UTF-8 handling; we expect UTF-8 encoded locales + stringMgr->upperUTF8(abbr, strlen(abbr)*2); + } + else { + stringMgr->upperLatin1(abbr); + } + SWLog::getSystemLog()->logDebug("%s=%s\n", abbr, refSys->getBook(i)->getOSISName()); + delete [] abbr; + } + } + } +} + + +/****************************************************************************** * VerseKey::ParseVerseList - Attempts to parse a buffer into separate * verse entries returned in a ListKey * @@ -446,19 +463,24 @@ int VerseKey::getBookAbbrev(const char *iabbr) * COMMENT: This code works but wreaks. Rewrite to make more maintainable. */ -ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool expandRange) { - char book[2048]; - char number[2048]; +ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool expandRange, bool useChapterAsVerse) { + + // hold on to our own copy of params, as threads/recursion may change outside values + const char *bufStart = buf; + SWBuf iBuf = buf; + buf = iBuf.c_str(); + SWBuf iDefaultKey = defaultKey; + if (defaultKey) defaultKey = iDefaultKey.c_str(); + + char book[2048]; // TODO: bad, remove + char number[2048]; // TODO: bad, remove *book = 0; *number = 0; int tobook = 0; int tonumber = 0; + char suffix = 0; int chap = -1, verse = -1; int bookno = 0; - VerseKey curKey, lBound, lastKey; - curKey.setLocale(getLocale()); - lBound.setLocale(getLocale()); - lastKey.setLocale(getLocale()); int loop; char comma = 0; char dash = 0; @@ -470,13 +492,50 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e bool inTerm = true; int notAllDigits = 0; - curKey.AutoNormalize(0); - if (defaultKey) lastKey = defaultKey; - + // assert we have a buffer + if (!buf) return internalListKey; + + VerseKey *curKey = (VerseKey *)this->clone(); + VerseKey *lastKey = (VerseKey *)this->clone(); + lastKey->ClearBounds(); + curKey->ClearBounds(); + + // some silly checks for corner cases + if (!strcmp(buf, "[ Module Heading ]")) { + curKey->Verse(0); + curKey->Chapter(0); + curKey->Book(0); + curKey->Testament(0); + lastKey->LowerBound(*curKey); + lastKey->UpperBound(*curKey); + internalListKey << *lastKey; + delete curKey; + delete lastKey; + return internalListKey; + } + if ((!strncmp(buf, "[ Testament ", 12)) && + (isdigit(buf[12])) && + (!strcmp(buf+13, " Heading ]"))) { + curKey->Verse(0); + curKey->Chapter(0); + curKey->Book(0); + curKey->Testament(buf[12]-48); + lastKey->LowerBound(*curKey); + lastKey->UpperBound(*curKey); + internalListKey << *lastKey; + delete curKey; + delete lastKey; + return internalListKey; + } + + curKey->AutoNormalize(AutoNormalize()); + lastKey->AutoNormalize(0); + if (defaultKey) *lastKey = defaultKey; + while (*buf) { switch (*buf) { case ':': - if (buf[1] != ' ') { // for silly Mat 1:1: this verse.... + if (buf[1] != ' ') { // for silly "Mat 1:1: this verse...." number[tonumber] = 0; tonumber = 0; if (*number) @@ -502,7 +561,7 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e break; } - case '-': + case '-': case ',': // on number new verse case ';': // on number new chapter number[tonumber] = 0; @@ -535,7 +594,8 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e for (loop = strlen(book) - 1; loop+1; loop--) { if (book[loop] == ' ') { - if (isroman(&book[loop+1])) { + // "PS C" is ok, but "II C" is not ok + if (isroman(&book[loop+1]) && !isroman(book,loop)) { if (verse == -1) { verse = chap; chap = from_rom(&book[loop+1]); @@ -549,49 +609,64 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e if ((!stricmp(book, "V")) || (!stricmp(book, "VER"))) { // Verse abbrev if (verse == -1) { verse = chap; - chap = lastKey.Chapter(); + chap = lastKey->Chapter(); *book = 0; } } if ((!stricmp(book, "ch")) || (!stricmp(book, "chap"))) { // Verse abbrev - strcpy(book, lastKey.getBookName()); + strcpy(book, lastKey->getBookName()); } bookno = getBookAbbrev(book); } if (((bookno > -1) || (!*book)) && ((*book) || (chap >= 0) || (verse >= 0))) { char partial = 0; - curKey.Verse(1); - curKey.Chapter(1); - curKey.Book(1); + curKey->Verse(1); + curKey->Chapter(1); + curKey->Book(1); if (bookno < 0) { - curKey.Testament(lastKey.Testament()); - curKey.Book(lastKey.Book()); + curKey->Testament(lastKey->Testament()); + curKey->Book(lastKey->Book()); } else { - curKey.Testament(1); - curKey.Book(bookno); + int t = 1; + if (bookno > BMAX[0]) { + t++; + bookno -= BMAX[0]; + } + curKey->Testament(t); + curKey->Book(bookno); } + if (((comma)||((verse < 0)&&(bookno < 0)))&&(!lastPartial)) { // if (comma) { - curKey.Chapter(lastKey.Chapter()); - curKey.Verse(chap); // chap because this is the first number captured + curKey->Chapter(lastKey->Chapter()); + curKey->Verse(chap); // chap because this is the first number captured } else { + if (useChapterAsVerse && verse < 0 && chap > 0 && curKey->getChapterMax() == 1) { + verse = chap; + chap = 1; + } + + if (chap >= 0) { - curKey.Chapter(chap); + curKey->Chapter(chap); } else { partial++; - curKey.Chapter(1); + curKey->Chapter(1); } if (verse >= 0) { - curKey.Verse(verse); + curKey->Verse(verse); + if (suffix) { + curKey->setSuffix(suffix); + } } else { partial++; - curKey.Verse(1); + curKey->Verse(1); } } @@ -599,43 +674,42 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e for (q = 0; ((buf[q]) && (buf[q] == ' ')); q++); if ((buf[q] == '-') && (expandRange)) { // if this is a dash save lowerBound and wait for upper buf+=q; - lastKey.LowerBound(curKey); - lastKey.setPosition(TOP); - tmpListKey << lastKey; - tmpListKey.GetElement()->userData = (void *)buf; + lastKey->LowerBound(*curKey); + lastKey->setPosition(TOP); + tmpListKey << *lastKey; + tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); } else { if (!dash) { // if last separator was not a dash just add if (expandRange && partial) { - lastKey.LowerBound(curKey); + lastKey->LowerBound(*curKey); if (partial > 1) - curKey.setPosition(MAXCHAPTER); + curKey->setPosition(MAXCHAPTER); if (partial > 0) - curKey = MAXVERSE; - lastKey.UpperBound(curKey); - lastKey = TOP; - tmpListKey << lastKey; - tmpListKey.GetElement()->userData = (void *)buf; + *curKey = MAXVERSE; + lastKey->UpperBound(*curKey); + *lastKey = TOP; + tmpListKey << *lastKey; + tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); } else { - // we store non-range entries as strings so we don't traverse - // maybe we should consider just setting - // lowerBound and upperBound to the same value - tmpListKey << curKey.getText(); - tmpListKey.GetElement()->userData = (void *)buf; - lastKey = curKey; + lastKey->LowerBound(*curKey); + lastKey->UpperBound(*curKey); + *lastKey = TOP; + tmpListKey << *lastKey; + tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); } } else if (expandRange) { VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement()); if (newElement) { if (partial > 1) - curKey = MAXCHAPTER; + *curKey = MAXCHAPTER; if (partial > 0) - curKey = MAXVERSE; - newElement->UpperBound(curKey); + *curKey = MAXVERSE; + newElement->UpperBound(*curKey); *newElement = TOP; - tmpListKey.GetElement()->userData = (void *)buf; + tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); } } } @@ -644,6 +718,7 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e *book = 0; chap = -1; verse = -1; + suffix = 0; if (*buf == ',') comma = 1; else comma = 0; @@ -652,13 +727,13 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e else dash = 0; break; case 10: // ignore these - case 13: - case '[': - case ']': - case '(': - case ')': - case '{': - case '}': + case 13: + case '[': + case ']': + case '(': + case ')': + case '{': + case '}': break; case '.': if (buf > orig) // ignore (break) if preceeding char is not a digit @@ -675,7 +750,7 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e chap = atoi(number); *number = 0; break; - + default: if (isdigit(*buf)) { number[tonumber++] = *buf; @@ -683,12 +758,17 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e else { switch (*buf) { case ' ': // ignore these and don't reset number - case 'f': case 'F': break; default: - number[tonumber] = 0; - tonumber = 0; + // suffixes (and oddly 'f'-- ff.) + if ((*buf >= 'a' && *buf <= 'z') && (chap >=0)) { + suffix = *buf; + } + else { + number[tonumber] = 0; + tonumber = 0; + } break; } } @@ -726,7 +806,8 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e for (loop = strlen(book) - 1; loop+1; loop--) { if (book[loop] == ' ') { - if (isroman(&book[loop+1])) { + // "PS C" is ok, but "II C" is not ok + if (isroman(&book[loop+1]) && !isroman(book,loop)) { if (verse == -1) { verse = chap; chap = from_rom(&book[loop+1]); @@ -735,92 +816,109 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e } break; } - } - + } + if ((!stricmp(book, "V")) || (!stricmp(book, "VER"))) { // Verse abbrev. if (verse == -1) { verse = chap; - chap = lastKey.Chapter(); + chap = lastKey->Chapter(); *book = 0; } } - + if ((!stricmp(book, "ch")) || (!stricmp(book, "chap"))) { // Verse abbrev - strcpy(book, lastKey.getBookName()); + strcpy(book, lastKey->getBookName()); } bookno = getBookAbbrev(book); } if (((bookno > -1) || (!*book)) && ((*book) || (chap >= 0) || (verse >= 0))) { char partial = 0; - curKey.Verse(1); - curKey.Chapter(1); - curKey.Book(1); + curKey->Verse(1); + curKey->Chapter(1); + curKey->Book(1); if (bookno < 0) { - curKey.Testament(lastKey.Testament()); - curKey.Book(lastKey.Book()); + curKey->Testament(lastKey->Testament()); + curKey->Book(lastKey->Book()); } else { - curKey.Testament(1); - curKey.Book(bookno); + int t = 1; + if (bookno > BMAX[0]) { + t++; + bookno -= BMAX[0]; + } + curKey->Testament(t); + curKey->Book(bookno); } if (((comma)||((verse < 0)&&(bookno < 0)))&&(!lastPartial)) { - curKey.Chapter(lastKey.Chapter()); - curKey.Verse(chap); // chap because this is the first number captured + curKey->Chapter(lastKey->Chapter()); + curKey->Verse(chap); // chap because this is the first number captured } else { + if (useChapterAsVerse && verse < 0 && chap > 0 && curKey->getChapterMax() == 1) { + verse = chap; + chap = 1; + } + + if (chap >= 0) { - curKey.Chapter(chap); + curKey->Chapter(chap); } else { partial++; - curKey.Chapter(1); + curKey->Chapter(1); } if (verse >= 0) { - curKey.Verse(verse); + curKey->Verse(verse); + if (suffix) { + curKey->setSuffix(suffix); + } } else { partial++; - curKey.Verse(1); + curKey->Verse(1); } } if ((*buf == '-') && (expandRange)) { // if this is a dash save lowerBound and wait for upper - lastKey.LowerBound(curKey); - lastKey = TOP; - tmpListKey << lastKey; - tmpListKey.GetElement()->userData = (void *)buf; + lastKey->LowerBound(*curKey); + *lastKey = TOP; + tmpListKey << *lastKey; + tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); } else { if (!dash) { // if last separator was not a dash just add if (expandRange && partial) { - lastKey.LowerBound(curKey); + lastKey->LowerBound(*curKey); if (partial > 1) - curKey = MAXCHAPTER; + *curKey = MAXCHAPTER; if (partial > 0) - curKey = MAXVERSE; - lastKey.UpperBound(curKey); - lastKey = TOP; - tmpListKey << lastKey; - tmpListKey.GetElement()->userData = (void *)buf; + *curKey = MAXVERSE; + lastKey->UpperBound(*curKey); + *lastKey = TOP; + tmpListKey << *lastKey; + tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); } else { - tmpListKey << curKey.getText(); - tmpListKey.GetElement()->userData = (void *)buf; - lastKey = curKey; + lastKey->LowerBound(*curKey); + lastKey->UpperBound(*curKey); + *lastKey = TOP; + tmpListKey << *lastKey; +// tmpListKey << curKey->getText(); + tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); } } else if (expandRange) { VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement()); if (newElement) { if (partial > 1) - curKey = MAXCHAPTER; + *curKey = MAXCHAPTER; if (partial > 0) - curKey = MAXVERSE; - newElement->UpperBound(curKey); + *curKey = MAXVERSE; + newElement->UpperBound(*curKey); *newElement = TOP; - tmpListKey.GetElement()->userData = (void *)buf; + tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); } } } @@ -830,6 +928,9 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e internalListKey = tmpListKey; internalListKey = TOP; // Align internalListKey to first element before passing back; + delete curKey; + delete lastKey; + return internalListKey; } @@ -838,16 +939,23 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e * VerseKey::LowerBound - sets / gets the lower boundary for this key */ -VerseKey &VerseKey::LowerBound(const char *lb) +VerseKey &VerseKey::LowerBound(const VerseKey &lb) { - if (!lowerBound) - initBounds(); + initBounds(); - (*lowerBound) = lb; - lowerBound->Normalize(); - lowerBound->setLocale( this->getLocale() ); + lowerBound = lb.Index(); + lowerBoundComponents.test = lb.getTestament(); + lowerBoundComponents.book = lb.getBook(); + lowerBoundComponents.chap = lb.getChapter(); + lowerBoundComponents.verse = lb.getVerse(); + + // both this following check and UpperBound check force upperBound to + // change allowing LowerBound then UpperBound logic to always flow + // and set values without restrictions, as expected + if (upperBound < lowerBound) upperBound = lowerBound; boundSet = true; - return (*lowerBound); + + return LowerBound(); } @@ -855,40 +963,21 @@ VerseKey &VerseKey::LowerBound(const char *lb) * VerseKey::UpperBound - sets / gets the upper boundary for this key */ -VerseKey &VerseKey::UpperBound(const char *ub) +VerseKey &VerseKey::UpperBound(const VerseKey &ub) { - if (!upperBound) - initBounds(); - -// need to set upperbound parsing to resolve to max verse/chap if not specified - (*upperBound) = ub; - if (*upperBound < *lowerBound) - *upperBound = *lowerBound; - upperBound->Normalize(); - upperBound->setLocale( this->getLocale() ); - -// until we have a proper method to resolve max verse/chap use this kludge - int len = strlen(ub); - bool alpha = false; - bool versespec = false; - bool chapspec = false; - for (int i = 0; i < len; i++) { - if (isalpha(ub[i])) - alpha = true; - if (ub[i] == ':') // if we have a : we assume verse spec - versespec = true; - if ((isdigit(ub[i])) && (alpha)) // if digit after alpha assume chap spec - chapspec = true; - } - if (!chapspec) - *upperBound = MAXCHAPTER; - if (!versespec) - *upperBound = MAXVERSE; - + initBounds(); + + upperBound = ub.Index(); + upperBoundComponents.test = ub.getTestament(); + upperBoundComponents.book = ub.getBook(); + upperBoundComponents.chap = ub.getChapter(); + upperBoundComponents.verse = ub.getVerse(); -// -- end kludge + // see LowerBound comment, above + if (upperBound < lowerBound) upperBound = lowerBound; boundSet = true; - return (*upperBound); + + return UpperBound(); } @@ -898,10 +987,16 @@ VerseKey &VerseKey::UpperBound(const char *ub) VerseKey &VerseKey::LowerBound() const { - if (!lowerBound) - initBounds(); + initBounds(); + if (!isAutoNormalize()) { + tmpClone->testament = lowerBoundComponents.test; + tmpClone->book = lowerBoundComponents.book; + tmpClone->chapter = lowerBoundComponents.chap; + tmpClone->setVerse (lowerBoundComponents.verse); + } + else tmpClone->Index(lowerBound); - return (*lowerBound); + return (*tmpClone); } @@ -911,10 +1006,16 @@ VerseKey &VerseKey::LowerBound() const VerseKey &VerseKey::UpperBound() const { - if (!upperBound) - initBounds(); + initBounds(); + if (!isAutoNormalize()) { + tmpClone->testament = upperBoundComponents.test; + tmpClone->book = upperBoundComponents.book; + tmpClone->chapter = upperBoundComponents.chap; + tmpClone->setVerse (upperBoundComponents.verse); + } + else tmpClone->Index(upperBound); - return (*upperBound); + return (*tmpClone); } @@ -924,33 +1025,36 @@ VerseKey &VerseKey::UpperBound() const void VerseKey::ClearBounds() { - initBounds(); + delete tmpClone; + tmpClone = 0; + boundSet = false; } void VerseKey::initBounds() const { - if (!upperBound) { - upperBound = new VerseKey(); - upperBound->AutoNormalize(0); - upperBound->Headings(1); - } - if (!lowerBound) { - lowerBound = new VerseKey(); - lowerBound->AutoNormalize(0); - lowerBound->Headings(1); - } - - lowerBound->Testament(0); - lowerBound->Book(0); - lowerBound->Chapter(0); - lowerBound->Verse(0); + if (!tmpClone) { + tmpClone = (VerseKey *)this->clone(); + tmpClone->AutoNormalize(0); + tmpClone->Headings(1); + tmpClone->Testament((BMAX[1])?2:1); + tmpClone->Book(BMAX[(BMAX[1])?1:0]); + tmpClone->Chapter(tmpClone->getChapterMax()); + tmpClone->Verse(tmpClone->getVerseMax()); + upperBound = tmpClone->Index(); + upperBoundComponents.test = tmpClone->getTestament(); + upperBoundComponents.book = tmpClone->getBook(); + upperBoundComponents.chap = tmpClone->getChapter(); + upperBoundComponents.verse = tmpClone->getVerse(); + + lowerBound = 0; + lowerBoundComponents.test = 0; + lowerBoundComponents.book = 0; + lowerBoundComponents.chap = 0; + lowerBoundComponents.verse = 0; - upperBound->Testament(2); - upperBound->Book(BMAX[1]); - upperBound->Chapter(books[1][BMAX[1]-1].chapmax); - upperBound->Verse(books[1][BMAX[1]-1].versemax[upperBound->Chapter()-1]); - boundSet = false; + } + else tmpClone->setLocale(getLocale()); } @@ -975,7 +1079,7 @@ const char *VerseKey::getShortText() const { else sprintf(buf, "[ Testament %d Heading ]", (int)testament); } else { - sprintf(buf, "%s %d:%d", books[testament-1][book-1].prefAbbrev, chapter, verse); + sprintf(buf, "%s %d:%d", getBookAbbrev(), chapter, verse); } stdstr(&stext, buf); return stext; @@ -983,13 +1087,20 @@ const char *VerseKey::getShortText() const { const char *VerseKey::getBookName() const { - return books[testament-1][book-1].name; + return getPrivateLocale()->translate(refSys->getBook(((testament>1)?BMAX[0]:0)+book-1)->getLongName()); +} + + +const char *VerseKey::getOSISBookName() const { + return refSys->getBook(((testament>1)?BMAX[0]:0)+book-1)->getOSISName(); } const char *VerseKey::getBookAbbrev() const { - return books[testament-1][book-1].prefAbbrev; + return refSys->getBook(((testament>1)?BMAX[0]:0)+book-1)->getPreferredAbbreviation(); } + + /****************************************************************************** * VerseKey::setPosition(SW_POSITION) - Positions this key * @@ -1000,32 +1111,50 @@ const char *VerseKey::getBookAbbrev() const { void VerseKey::setPosition(SW_POSITION p) { switch (p) { - case POS_TOP: - testament = LowerBound().Testament(); - book = LowerBound().Book(); - chapter = LowerBound().Chapter(); - verse = LowerBound().Verse(); + case POS_TOP: { + const VerseKey *lb = &LowerBound(); + testament = (lb->Testament() || headings) ? lb->Testament() : 1; + book = (lb->Book() || headings) ? lb->Book() : 1; + chapter = (lb->Chapter() || headings) ? lb->Chapter() : 1; + verse = (lb->Verse() || headings) ? lb->Verse() : 1; + suffix = lb->getSuffix(); break; - case POS_BOTTOM: - testament = UpperBound().Testament(); - book = UpperBound().Book(); - chapter = UpperBound().Chapter(); - verse = UpperBound().Verse(); + } + case POS_BOTTOM: { + const VerseKey *ub = &UpperBound(); + testament = (ub->Testament() || headings) ? ub->Testament() : 1; + book = (ub->Book() || headings) ? ub->Book() : 1; + chapter = (ub->Chapter() || headings) ? ub->Chapter() : 1; + verse = (ub->Verse() || headings) ? ub->Verse() : 1; + suffix = ub->getSuffix(); break; + } case POS_MAXVERSE: Normalize(); - verse = books[testament-1][book-1].versemax[chapter-1]; + verse = getVerseMax(); + suffix = 0; break; case POS_MAXCHAPTER: verse = 1; + suffix = 0; Normalize(); - chapter = books[testament-1][book-1].chapmax; + chapter = getChapterMax(); break; - } + } Normalize(1); Error(); // clear error from normalize } +int VerseKey::getChapterMax() const { + const VerseMgr::Book *b = refSys->getBook(((testament>1)?BMAX[0]:0)+book-1); + return (b) ? b->getChapterMax() : -1; +} + +int VerseKey::getVerseMax() const { + const VerseMgr::Book *b = refSys->getBook(((testament>1)?BMAX[0]:0)+book-1); + return (b) ? b->getVerseMax(chapter) : -1; +} + /****************************************************************************** * VerseKey::increment - Increments key a number of verses @@ -1079,11 +1208,11 @@ void VerseKey::decrement(int step) { void VerseKey::Normalize(char autocheck) { - error = 0; if (((!autocheck) || (autonorm)) // only normalize if we were explicitely called or if autonorm is turned on && ((!headings) || ((verse) && (chapter)))) { // this is cheeze and temporary until deciding what actions should be taken; so headings should only be turned on when positioning with Index() or incrementors + error = 0; while ((testament < 3) && (testament > 0)) { @@ -1100,40 +1229,45 @@ void VerseKey::Normalize(char autocheck) continue; } - if (chapter > books[testament-1][book-1].chapmax) { - chapter -= books[testament-1][book-1].chapmax; + if (chapter > getChapterMax()) { + chapter -= getChapterMax(); book++; continue; } - if (chapter < 1) { - if (--book > 0) { - chapter += books[testament-1][book-1].chapmax; - } - else { - if (testament > 1) { - chapter += books[0][BMAX[0]-1].chapmax; - } - } - continue; - } + if (chapter < 1) { + if (--book > 0) { + chapter += getChapterMax(); + verse = getVerseMax(); + } + else { + if (testament > 1) { + chapter += refSys->getBook(BMAX[0]-1)->getChapterMax(); + verse = refSys->getBook(BMAX[0]-1)->getVerseMax(chapter); + } + } + continue; + } - if (verse > books[testament-1][book-1].versemax[chapter-1]) { // -1 because e.g chapter 1 of Matthew is books[1][0].versemax[0] - verse -= books[testament-1][book-1].versemax[chapter++ - 1]; + if (verse > getVerseMax()) { // -1 because e.g chapter 1 of Matthew is books[1][0].versemax[0] + verse -= getVerseMax(); + chapter++; continue; } if (verse < 1) { if (--chapter > 0) { - verse += books[testament-1][book-1].versemax[chapter-1]; + verse += getVerseMax(); } else { if (book > 1) { - verse += books[testament-1][book-2].versemax[books[testament-1][book-2].chapmax-1]; + const VerseMgr::Book *prevBook = refSys->getBook(((testament>1)?BMAX[0]:0)+book-2); + verse += prevBook->getVerseMax(prevBook->getChapterMax()); } else { if (testament > 1) { - verse += books[0][BMAX[0]-1].versemax[books[0][BMAX[0]-1].chapmax-1]; + const VerseMgr::Book *lastOTBook = refSys->getBook(BMAX[0]-1); + verse += lastOTBook->getVerseMax(lastOTBook->getChapterMax()); } } } @@ -1143,11 +1277,11 @@ void VerseKey::Normalize(char autocheck) break; // If we've made it this far (all failure checks continue) we're ok } - if (testament > 2) { - testament = 2; + if (testament > (BMAX[1]?2:1)) { + testament = BMAX[1]?2:1; book = BMAX[testament-1]; - chapter = books[testament-1][book-1].chapmax; - verse = books[testament-1][book-1].versemax[chapter-1]; + chapter = getChapterMax(); + verse = getVerseMax(); error = KEYERR_OUTOFBOUNDS; } @@ -1161,11 +1295,11 @@ void VerseKey::Normalize(char autocheck) // should we always perform bounds checks? Tried but seems to cause infinite recursion if (_compare(UpperBound()) > 0) { - setText(UpperBound(), false); + positionFrom(UpperBound()); error = KEYERR_OUTOFBOUNDS; } if (_compare(LowerBound()) < 0) { - setText(LowerBound(), false); + positionFrom(LowerBound()); error = KEYERR_OUTOFBOUNDS; } } @@ -1173,24 +1307,24 @@ void VerseKey::Normalize(char autocheck) /****************************************************************************** - * VerseKey::Testament - Gets testament + * VerseKey::getTestament - Gets testament * * RET: value of testament */ -char VerseKey::Testament() const +char VerseKey::getTestament() const { return testament; } /****************************************************************************** - * VerseKey::Book - Gets book + * VerseKey::getBook - Gets book * * RET: value of book */ -char VerseKey::Book() const +char VerseKey::getBook() const { return book; } @@ -1202,7 +1336,7 @@ char VerseKey::Book() const * RET: value of chapter */ -int VerseKey::Chapter() const +int VerseKey::getChapter() const { return chapter; } @@ -1214,14 +1348,14 @@ int VerseKey::Chapter() const * RET: value of verse */ -int VerseKey::Verse() const +int VerseKey::getVerse() const { return verse; } /****************************************************************************** - * VerseKey::Testament - Sets/gets testament + * VerseKey::setTestament - Sets/gets testament * * ENT: itestament - value which to set testament * [MAXPOS(char)] - only get @@ -1230,64 +1364,68 @@ int VerseKey::Verse() const * if changed -> previous value of testament */ -char VerseKey::Testament(char itestament) +void VerseKey::setTestament(char itestament) { - char retval = testament; - if (itestament != MAXPOS(char)) { testament = itestament; Normalize(1); } - return retval; } /****************************************************************************** - * VerseKey::Book - Sets/gets book + * VerseKey::setBook - Sets/gets book * * ENT: ibook - value which to set book - * [MAXPOS(char)] - only get - * - * RET: if unchanged -> value of book - * if changed -> previous value of book */ -char VerseKey::Book(char ibook) +void VerseKey::setBook(char ibook) { - char retval = book; - - Chapter(1); - book = ibook; + verse = ibook ? 1 : 0; + chapter = ibook ? 1 : 0; + book = ibook; Normalize(1); - - return retval; } + /****************************************************************************** - * VerseKey::Chapter - Sets/gets chapter - * - * ENT: ichapter - value which to set chapter - * [MAXPOS(int)] - only get + * VerseKey::setBookName - Sets/gets book by name * - * RET: if unchanged -> value of chapter - * if changed -> previous value of chapter + * ENT: bname - book name/abbrev */ -int VerseKey::Chapter(int ichapter) +void VerseKey::setBookName(const char *bname) { - int retval = chapter; + int bnum = getBookAbbrev(bname); + if (bnum > -1) { + if (bnum > BMAX[0]) { + bnum -= BMAX[0]; + testament = 2; + } + else testament = 1; + setBook(bnum); + } + else error = KEYERR_OUTOFBOUNDS; +} + + +/****************************************************************************** + * VerseKey::setChapter - Sets/gets chapter + * + * ENT: ichapter - value which to set chapter + */ - Verse(1); +void VerseKey::setChapter(int ichapter) +{ + verse = ichapter ? 1 : 0; chapter = ichapter; Normalize(1); - - return retval; } /****************************************************************************** - * VerseKey::Verse - Sets/gets verse + * VerseKey::setVerse - Sets/gets verse * * ENT: iverse - value which to set verse * [MAXPOS(int)] - only get @@ -1296,37 +1434,36 @@ int VerseKey::Chapter(int ichapter) * if changed -> previous value of verse */ -int VerseKey::Verse(int iverse) +void VerseKey::setVerse(int iverse) { - int retval = verse; - + setSuffix(0); verse = iverse; Normalize(1); +} - return retval; + +char VerseKey::getSuffix() const { + return suffix; } +void VerseKey::setSuffix(char suf) { + suffix = suf; +} /****************************************************************************** * VerseKey::AutoNormalize - Sets/gets flag that tells VerseKey to auto- * matically normalize itself when modified - * - * ENT: iautonorm - value which to set autonorm - * [MAXPOS(char)] - only get - * - * RET: if unchanged -> value of autonorm - * if changed -> previous value of autonorm */ -char VerseKey::AutoNormalize(char iautonorm) +bool VerseKey::isAutoNormalize() const { - char retval = autonorm; + return autonorm; +} - if (iautonorm != MAXPOS(char)) { - autonorm = iautonorm; - Normalize(1); - } - return retval; +void VerseKey::setAutoNormalize(bool iautonorm) +{ + autonorm = iautonorm?1:0; + Normalize(1); } @@ -1392,34 +1529,27 @@ long VerseKey::Index() const if (!testament) { // if we want module heading offset = 0; - verse = 0; + } + else if (!book) { // we want testament heading + offset = ((testament == 2) ? refSys->getNTStartOffset():0) + 1; } else { - if (!book) - chapter = 0; - if (!chapter) - verse = 0; - - offset = offsets[testament-1][0][book]; - offset = offsets[testament-1][1][(int)offset + chapter]; - if (!(offset|verse)) // if we have a testament but nothing else. - offset = 1; + offset = refSys->getOffsetFromVerse((((testament>1)?BMAX[0]:0)+book-1), chapter, verse); } - return (offset + verse); + return offset; } /****************************************************************************** - * VerseKey::Index - Gets index based upon current verse + * VerseKey::TestamentIndex - Gets index based upon current verse * * RET: offset */ -long VerseKey::NewIndex() const +long VerseKey::TestamentIndex() const { - static long otMaxIndex = 32300 - 8245; // total positions - new testament positions -// static long otMaxIndex = offsets[0][1][(int)offsets[0][0][BMAX[0]] + books[0][BMAX[0]].chapmax]; - return ((testament-1) * otMaxIndex) + Index(); + long offset = Index(); + return (testament > 1) ? offset - refSys->getNTStartOffset() : offset; } @@ -1433,60 +1563,31 @@ long VerseKey::NewIndex() const long VerseKey::Index(long iindex) { - long offset; - -// This is the dirty stuff -------------------------------------------- - - if (!testament) - testament = 1; - - if (iindex < 1) { // if (-) or module heading - if (testament < 2) { - if (iindex < 0) { - testament = 0; // previously we changed 0 -> 1 - error = KEYERR_OUTOFBOUNDS; - } - else testament = 0; // we want module heading - } - else { - testament--; - iindex = (offsets[testament-1][1][offsize[testament-1][1]-1] + books[testament-1][BMAX[testament-1]-1].versemax[books[testament-1][BMAX[testament-1]-1].chapmax-1]) + iindex; // What a doozy! ((offset of last chapter + number of verses in the last chapter) + iindex) - } + int b; + error = refSys->getVerseFromOffset(iindex, &b, &chapter, &verse); + book = (unsigned char)b; + testament = 1; + if (book > BMAX[0]) { + book -= BMAX[0]; + testament = 2; } + // special case for Module and Testament heading + if (book < 0) { testament = 0; book = 0; } + if (chapter < 0) { book = 0; chapter = 0; } -// -------------------------------------------------------------------- - - - if (testament) { - if ((!error) && (iindex)) { - offset = findindex(offsets[testament-1][1], offsize[testament-1][1], iindex); - verse = iindex - offsets[testament-1][1][offset]; - book = findindex(offsets[testament-1][0], offsize[testament-1][0], offset); - chapter = offset - offsets[testament-1][0][VerseKey::book]; - verse = (chapter) ? verse : 0; // funny check. if we are index=1 (testmt header) all gets set to 0 exept verse. Don't know why. Fix if you figure out. Think its in the offsets table. - if (verse) { // only check if -1 won't give negative - if (verse > books[testament-1][book-1].versemax[chapter-1]) { - if (testament > 1) { - verse = books[testament-1][book-1].versemax[chapter-1]; - error = KEYERR_OUTOFBOUNDS; - } - else { - testament++; - Index(verse - books[testament-2][book-1].versemax[chapter-1]); - } - } - } - } - } - if (_compare(UpperBound()) > 0) { - *this = UpperBound(); + long i = Index(); + + initBounds(); + if (i > upperBound) { + i = Index(upperBound); error = KEYERR_OUTOFBOUNDS; } - if (_compare(LowerBound()) < 0) { - *this = LowerBound(); + if (i < lowerBound) { + i = Index(lowerBound); error = KEYERR_OUTOFBOUNDS; } - return Index(); + + return i; } @@ -1524,37 +1625,23 @@ int VerseKey::compare(const SWKey &ikey) int VerseKey::_compare(const VerseKey &ivkey) { - long keyval1 = 0; - long keyval2 = 0; + unsigned long keyval1 = 0; + unsigned long keyval2 = 0; - keyval1 += Testament() * 1000000000; + keyval1 += Testament() * 1000000000; keyval2 += ivkey.Testament() * 1000000000; - keyval1 += Book() * 1000000; - keyval2 += ivkey.Book() * 1000000; - keyval1 += Chapter() * 1000; - keyval2 += ivkey.Chapter() * 1000; - keyval1 += Verse(); - keyval2 += ivkey.Verse(); - keyval1 -= keyval2; - keyval1 = (keyval1) ? ((keyval1 > 0) ? 1 : -1) /*keyval1/labs(keyval1)*/:0; // -1 | 0 | 1 + keyval1 += Book() * 10000000; + keyval2 += ivkey.Book() * 10000000; + keyval1 += Chapter() * 10000; + keyval2 += ivkey.Chapter() * 10000; + keyval1 += Verse() * 50; + keyval2 += ivkey.Verse() * 50; + keyval1 += (int)getSuffix(); + keyval2 += (int)ivkey.getSuffix(); + keyval1 = (keyval1 != keyval2) ? ((keyval1 > keyval2) ? 1 : -1) : 0; // -1 | 0 | 1 return keyval1; } -const char *VerseKey::osisotbooks[] = { - "Gen","Exod","Lev","Num","Deut","Josh","Judg","Ruth","1Sam","2Sam", - "1Kgs","2Kgs","1Chr","2Chr","Ezra","Neh","Esth","Job","Ps", - "Prov", // added this. Was not in OSIS spec - "Eccl", - "Song","Isa","Jer","Lam","Ezek","Dan","Hos","Joel","Amos","Obad", - "Jonah","Mic","Nah","Hab","Zeph","Hag","Zech","Mal","Bar","PrAzar", - "Bel","Sus","1Esd","2Esd","AddEsth","EpJer","Jdt","1Macc","2Macc","3Macc", - "4Macc","PrMan","Ps151","Sir","Tob","Wis"}; -const char *VerseKey::osisntbooks[] = { - "Matt","Mark","Luke","John","Acts","Rom","1Cor","2Cor","Gal","Eph", - "Phil","Col","1Thess","2Thess","1Tim","2Tim","Titus","Phlm","Heb","Jas", - "1Pet","2Pet","1John","2John","3John","Jude","Rev"}; -const char **VerseKey::osisbooks[] = { osisotbooks, osisntbooks }; - const char *VerseKey::getOSISRef() const { static char buf[5][254]; @@ -1564,53 +1651,50 @@ const char *VerseKey::getOSISRef() const { loop = 0; if (Verse()) - sprintf(buf[loop], "%s.%d.%d", osisbooks[Testament()-1][Book()-1], (int)Chapter(), (int)Verse()); + sprintf(buf[loop], "%s.%d.%d", getOSISBookName(), (int)Chapter(), (int)Verse()); else if (Chapter()) - sprintf(buf[loop], "%s.%d", osisbooks[Testament()-1][Book()-1], (int)Chapter()); + sprintf(buf[loop], "%s.%d", getOSISBookName(), (int)Chapter()); else if (Book()) - sprintf(buf[loop], "%s", osisbooks[Testament()-1][Book()-1]); + sprintf(buf[loop], "%s", getOSISBookName()); else buf[loop][0] = 0; return buf[loop++]; } -const int VerseKey::getOSISBookNum(const char *bookab) { - int i; - for (i=0; i < 39; i++) - { - if (!strncmp(bookab, osisotbooks[i], strlen(osisotbooks[i]))) - { - //printf("VerseKey::getOSISBookNum %s is OT %d\n", bookab, i+1); - return i+1; - } - } - for (i=0; i < 27; i++) - { - if (!strncmp(bookab, osisntbooks[i], strlen(osisotbooks[i]))) - { - //printf("VerseKey::getOSISBookNum %s is NT %d\n", bookab, i+1); - return i+1; - } - } - return -1; -} - - /****************************************************************************** * VerseKey::getRangeText - returns parsable range text for this key */ const char *VerseKey::getRangeText() const { - if (isBoundSet()) { - char buf[1023]; - sprintf(buf, "%s-%s", (const char *)LowerBound(), (const char *)UpperBound()); - stdstr(&rangeText, buf); + if (isBoundSet() && lowerBound != upperBound) { + SWBuf buf = (const char *)LowerBound(); + buf += "-"; + buf += (const char *)UpperBound(); + stdstr(&rangeText, buf.c_str()); } else stdstr(&rangeText, getText()); return rangeText; } +/****************************************************************************** + * VerseKey::getOSISRefRangeText - returns parsable range text for this key + */ + +const char *VerseKey::getOSISRefRangeText() const { + if (isBoundSet() && (lowerBound != upperBound)) { + SWBuf buf = LowerBound().getOSISRef(); + buf += "-"; + buf += UpperBound().getOSISRef(); + stdstr(&rangeText, buf.c_str()); + } + else stdstr(&rangeText, getOSISRef()); + return rangeText; +} + + +// TODO: this is static so we have no context. We can only parse KJV v11n now +// possibly add a const char *versification = KJV param? const char *VerseKey::convertToOSIS(const char *inRef, const SWKey *lastKnownKey) { static SWBuf outRef; @@ -1620,12 +1704,13 @@ const char *VerseKey::convertToOSIS(const char *inRef, const SWKey *lastKnownKey ListKey verses = defLanguage.ParseVerseList(inRef, (*lastKnownKey), true); const char *startFrag = inRef; for (int i = 0; i < verses.Count(); i++) { - VerseKey *element = SWDYNAMIC_CAST(VerseKey, verses.GetElement(i)); - char buf[5120]; + SWKey *element = verses.GetElement(i); +// VerseKey *element = SWDYNAMIC_CAST(VerseKey, verses.GetElement(i)); + SWBuf buf; + // TODO: This code really needs to not use fixed size arrays char frag[800]; char preJunk[800]; char postJunk[800]; - memset(buf, 0, 5120); memset(frag, 0, 800); memset(preJunk, 0, 800); memset(postJunk, 0, 800); @@ -1633,32 +1718,26 @@ const char *VerseKey::convertToOSIS(const char *inRef, const SWKey *lastKnownKey outRef += *startFrag; startFrag++; } - if (element) { - memmove(frag, startFrag, ((const char *)element->userData - startFrag) + 1); - frag[((const char *)element->userData - startFrag) + 1] = 0; - int j; - for (j = strlen(frag)-1; j && (strchr(" {};,()[].", frag[j])); j--); - if (frag[j+1]) - strcpy(postJunk, frag+j+1); - frag[j+1]=0; - startFrag += ((const char *)element->userData - startFrag) + 1; - sprintf(buf, "<reference osisRef=\"%s-%s\">%s</reference>%s", element->LowerBound().getOSISRef(), element->UpperBound().getOSISRef(), frag, postJunk); - } - else { - memmove(frag, startFrag, ((const char *)verses.GetElement(i)->userData - startFrag) + 1); - frag[((const char *)verses.GetElement(i)->userData - startFrag) + 1] = 0; - int j; - for (j = strlen(frag)-1; j && (strchr(" {};,()[].", frag[j])); j--); - if (frag[j+1]) - strcpy(postJunk, frag+j+1); - frag[j+1]=0; - startFrag += ((const char *)verses.GetElement(i)->userData - startFrag) + 1; - sprintf(buf, "<reference osisRef=\"%s\">%s</reference>%s", VerseKey(*verses.GetElement(i)).getOSISRef(), frag, postJunk); - } - outRef+=buf; + memmove(frag, startFrag, ((const char *)element->userData - startFrag) + 1); + frag[((const char *)element->userData - startFrag) + 1] = 0; + int j; + for (j = strlen(frag)-1; j && (strchr(" {};,()[].", frag[j])); j--); + if (frag[j+1]) + strcpy(postJunk, frag+j+1); + frag[j+1]=0; + startFrag += ((const char *)element->userData - startFrag) + 1; + buf = "<reference osisRef=\""; + buf += element->getOSISRefRangeText(); + buf += "\">"; + buf += frag; + buf += "</reference>"; + buf += postJunk; + + outRef += buf; + } if (startFrag < (inRef + strlen(inRef))) - outRef+=startFrag; + outRef += startFrag; return outRef.c_str(); } SWORD_NAMESPACE_END diff --git a/src/keys/versetreekey.cpp b/src/keys/versetreekey.cpp index b73672d..edfbcc3 100644 --- a/src/keys/versetreekey.cpp +++ b/src/keys/versetreekey.cpp @@ -1,9 +1,27 @@ /****************************************************************************** * VerseTreeKey.cpp - code for class 'VerseTreeKey'- versekey using treekey * for data retrieval + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <versetreekey.h> +#include <ctype.h> SWORD_NAMESPACE_START @@ -20,7 +38,7 @@ SWClass VerseTreeKey::classdef(classes); VerseTreeKey::VerseTreeKey(TreeKey *treeKey, const SWKey *ikey) : VerseKey(ikey) { - this->treeKey = treeKey; + init(treeKey); if (ikey) parse(); } @@ -35,7 +53,7 @@ VerseTreeKey::VerseTreeKey(TreeKey *treeKey, const SWKey *ikey) : VerseKey(ikey) VerseTreeKey::VerseTreeKey(TreeKey *treeKey, const char *ikey) : VerseKey(ikey) { - this->treeKey = treeKey; + init(treeKey); if (ikey) parse(); } @@ -43,13 +61,22 @@ VerseTreeKey::VerseTreeKey(TreeKey *treeKey, const char *ikey) : VerseKey(ikey) VerseTreeKey::VerseTreeKey(VerseTreeKey const &k) : VerseKey(k) { - treeKey = k.treeKey; + init(k.treeKey); } VerseTreeKey::VerseTreeKey(TreeKey *treeKey, const char *min, const char *max) : VerseKey(min, max) { - this->treeKey = treeKey; + init(treeKey); +} + + +void VerseTreeKey::init(TreeKey *treeKey) +{ + myclass = &classdef; + this->treeKey = (TreeKey *)treeKey->clone(); + this->treeKey->setPositionChangeListener(this); + internalPosChange = false; } @@ -59,6 +86,33 @@ SWKey *VerseTreeKey::clone() const } +int VerseTreeKey::getBookAbbrev(const char *iabbr) +{ + int bookno = VerseKey::getBookAbbrev(iabbr); + if (bookno < 0) { +/* + vector<struct sbook>::iterator it = find(books, iabbr); + if (it == books.end()) { + TreeKey *tkey = this->treeKey; + int saveError = tkey->Error(); + long bookmark = tkey->getOffset(); + SWBuf segment; + internalPosChange = true; + do { + segment = (SWBuf)tkey->getLocalName(); + } while (tkey->parent()); + segment << 1; + if (saveError) { + error = saveError; + } + tkey->setOffset(bookmark); + } + books.push_back(sbook(iabbr)); +*/ + } + return bookno; +} + /****************************************************************************** * VerseTreeKey Destructor - cleans up instance of VerseTreeKey * @@ -66,7 +120,183 @@ SWKey *VerseTreeKey::clone() const */ VerseTreeKey::~VerseTreeKey() { + delete treeKey; +} + + +void VerseTreeKey::decrement(int steps) { + int treeError = 0; + if (!error) lastGoodOffset = getTreeKey()->getOffset(); + do { + treeKey->decrement(); + treeError = treeKey->Error(); + // iterate until 3 levels and no versekey parse errors + } while (!treeError && ((treeKey->getLevel() < 3) || error)); + if (error && !treeError) { + int saveError = error; + increment(); + error = saveError; + } + if (treeError) { + treeKey->setOffset(lastGoodOffset); + error = treeError; + } + if (_compare(UpperBound()) > 0) { + positionFrom(UpperBound()); + error = KEYERR_OUTOFBOUNDS; + } + if (_compare(LowerBound()) < 0) { + positionFrom(LowerBound()); + error = KEYERR_OUTOFBOUNDS; + } +} + + +void VerseTreeKey::increment(int steps) { + int treeError = 0; + if (!error) lastGoodOffset = getTreeKey()->getOffset(); + do { + treeKey->increment(); + treeError = treeKey->Error(); + // iterate until 3 levels and no versekey parse errors + } while (!treeError && ((treeKey->getLevel() < 3) || error)); + if (error && !treeError) { + int saveError = error; + decrement(); + error = saveError; + } + if (treeError) { + treeKey->setOffset(lastGoodOffset); + error = treeError; + } + // bounds + if (_compare(UpperBound()) > 0) { + positionFrom(UpperBound()); + error = KEYERR_OUTOFBOUNDS; + } + if (_compare(LowerBound()) < 0) { + positionFrom(LowerBound()); + error = KEYERR_OUTOFBOUNDS; + } } +void VerseTreeKey::positionChanged() { + if (!internalPosChange) { + TreeKey *tkey = this->TreeKey::PositionChangeListener::getTreeKey(); + int saveError = tkey->Error(); + long bookmark = tkey->getOffset(); + SWBuf seg[4]; + internalPosChange = true; + int legs = 0; + do { + seg[legs] = tkey->getLocalName(); + legs++; + } while (tkey->parent() && (legs < 4)); + + legs--; + + if ((legs < 2) && (!seg[0].length() || seg[0] == "/")) { //"[ Module Heading ]"; + testament = 0; + book = 0; + chapter = 0; + setVerse(0); + } + else if ((legs < 2) + && ((!strncmp(seg[0].c_str(), "[ Testament ", 12)) && //"[ Testament n Heading ]"; + (isdigit(seg[0][12])) && + (!strcmp(seg[0].c_str()+13, " Heading ]")))) { + testament = (seg[0][12]-48); + book = 0; + chapter = 0; + setVerse(0); + } //path = "[ Module Heading ]"; + else { + setBookName(seg[--legs]); + chapter = (legs > 0) ? atoi(seg[--legs]) : 0; + setVerse((legs > 0) ? atoi(seg[--legs]) : 0); + } + +// setText(path); + if (saveError) { + error = saveError; + } + tkey->setOffset(bookmark); + tkey->setError(saveError); + internalPosChange = false; + } +} + + +void VerseTreeKey::syncVerseToTree() { + internalPosChange = true; + SWBuf path; + if (!Testament()) path = "/"; // "[ Module Heading ]"; + else if (!Book()) path.setFormatted("/[ Testament %d Heading ]", Testament()); + else path.setFormatted("/%s/%d/%d", getOSISBookName(), getChapter(), getVerse()); + if (getSuffix()) path += getSuffix(); + long bookmark = treeKey->getOffset(); + treeKey->setText(path); + + // if our module has jacked inconsistencies, then let's put our tree back to where it was + if (treeKey->Error()) { + treeKey->setOffset(bookmark); + } + + internalPosChange = false; +} + + +TreeKey *VerseTreeKey::getTreeKey() { + syncVerseToTree(); + return treeKey; +} + +// can autonormalize yet (ever?) +void VerseTreeKey::Normalize(char autocheck) { + error = 0; +} + +long VerseTreeKey::NewIndex() const { + return treeKey->getOffset(); +} + + +void VerseTreeKey::setPosition(SW_POSITION p) { + + if (isBoundSet()) { + return VerseKey::setPosition(p); + } + + switch (p) { + case POS_TOP: + Error(); + treeKey->setPosition(p); + increment(); + decrement(); + Error(); + break; + case POS_BOTTOM: + Error(); + treeKey->setPosition(p); + decrement(); + increment(); + Error(); + break; + case POS_MAXVERSE: + case POS_MAXCHAPTER: + VerseKey::setPosition(p); + break; + } +} + + +/****************************************************************************** + * VerseTreeKey::copyFrom - Equates this VerseTreeKey to another VerseTreeKey + +void VerseTreeKey::copyFrom(const VerseTreeKey &ikey) { + VerseKey::copyFrom(ikey); +} + */ + SWORD_NAMESPACE_END diff --git a/src/mgr/Makefile.am b/src/mgr/Makefile.am index 1b1e33b..10d7158 100644 --- a/src/mgr/Makefile.am +++ b/src/mgr/Makefile.am @@ -11,6 +11,7 @@ AM_CPPFLAGS += -D_FTPLIB_NO_COMPAT if WITHCURL FTP_SOURCES = $(mgrdir)/curlftpt.cpp +FTP_SOURCES += $(mgrdir)/curlhttpt.cpp else FTP_SOURCES = $(mgrdir)/ftplibftpt.cpp endif @@ -22,6 +23,7 @@ libsword_la_SOURCES += $(mgrdir)/swfiltermgr.cpp libsword_la_SOURCES += $(mgrdir)/encfiltmgr.cpp libsword_la_SOURCES += $(mgrdir)/markupfiltmgr.cpp libsword_la_SOURCES += $(mgrdir)/filemgr.cpp +libsword_la_SOURCES += $(mgrdir)/versemgr.cpp libsword_la_SOURCES += $(mgrdir)/ftptrans.cpp libsword_la_SOURCES += $(mgrdir)/swlocale.cpp libsword_la_SOURCES += $(mgrdir)/localemgr.cpp diff --git a/src/mgr/curlftpt.cpp b/src/mgr/curlftpt.cpp index bb47958..91d8e82 100644 --- a/src/mgr/curlftpt.cpp +++ b/src/mgr/curlftpt.cpp @@ -1,7 +1,24 @@ /***************************************************************************** * CURLFTPTransport functions * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <curlftpt.h> @@ -109,7 +126,8 @@ char CURLFTPTransport::getURL(const char *destPath, const char *sourceURL, SWBuf if (session) { curl_easy_setopt(session, CURLOPT_URL, sourceURL); - curl_easy_setopt(session, CURLOPT_USERPWD, "ftp:installmgr@user.com"); + SWBuf credentials = u + ":" + p; + curl_easy_setopt(session, CURLOPT_USERPWD, credentials.c_str()); curl_easy_setopt(session, CURLOPT_WRITEFUNCTION, my_fwrite); if (!passive) curl_easy_setopt(session, CURLOPT_FTPPORT, "-"); diff --git a/src/mgr/curlhttpt.cpp b/src/mgr/curlhttpt.cpp new file mode 100644 index 0000000..8ddb1cf --- /dev/null +++ b/src/mgr/curlhttpt.cpp @@ -0,0 +1,178 @@ + /***************************************************************************** + * CURLHTTPTransport functions + * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + + + +#include <curlhttpt.h> + +#include <fcntl.h> + +#include <curl/curl.h> +#include <curl/types.h> +#include <curl/easy.h> + +#include <swlog.h> + +SWORD_NAMESPACE_START + + +struct FtpFile { + const char *filename; + FILE *stream; + SWBuf *destBuf; +}; + + +int my_httpfwrite(void *buffer, size_t size, size_t nmemb, void *stream); +int my_httpfprogress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); + +static CURLHTTPTransport_init _CURLHTTPTransport_init; + +CURLHTTPTransport_init::CURLHTTPTransport_init() { + //curl_global_init(CURL_GLOBAL_DEFAULT); // curl_easy_init automatically calls it if needed +} + +CURLHTTPTransport_init::~CURLHTTPTransport_init() { +// CURLFTPT d-tor cleans this up +// curl_global_cleanup(); +} + +int my_httpfwrite(void *buffer, size_t size, size_t nmemb, void *stream) { + struct FtpFile *out=(struct FtpFile *)stream; + if (out && !out->stream && !out->destBuf) { + /* open file for writing */ + out->stream=fopen(out->filename, "wb"); + if (!out->stream) + return -1; /* failure, can't open file to write */ + } + if (out->destBuf) { + int s = out->destBuf->size(); + out->destBuf->size(s+(size*nmemb)); + memcpy(out->destBuf->getRawData()+s, buffer, size*nmemb); + return nmemb; + } + return fwrite(buffer, size, nmemb, out->stream); +} + + +int my_httpfprogress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { + if (clientp) { + ((StatusReporter *)clientp)->statusUpdate(dltotal, dlnow); + } + return 0; +} + + +static int myhttp_trace(CURL *handle, curl_infotype type, unsigned char *data, size_t size, void *userp) { + SWBuf header; + (void)userp; /* prevent compiler warning */ + (void)handle; /* prevent compiler warning */ + + switch (type) { + case CURLINFO_TEXT: header = "TEXT"; break; + case CURLINFO_HEADER_OUT: header = "=> Send header"; break; + case CURLINFO_HEADER_IN: header = "<= Recv header"; break; + + // these we don't want to log (HUGE) + case CURLINFO_DATA_OUT: header = "=> Send data"; + case CURLINFO_SSL_DATA_OUT: header = "=> Send SSL data"; + case CURLINFO_DATA_IN: header = "<= Recv data"; + case CURLINFO_SSL_DATA_IN: header = "<= Recv SSL data"; + default: /* in case a new one is introduced to shock us */ + return 0; + } + + if (size > 120) size = 120; + SWBuf text; + text.size(size); + memcpy(text.getRawData(), data, size); + SWLog::getSystemLog()->logDebug("CURLHTTPTransport: %s: %s", header.c_str(), text.c_str()); + return 0; +} + +CURLHTTPTransport::CURLHTTPTransport(const char *host, StatusReporter *sr) : FTPTransport(host, sr) { + session = (CURL *)curl_easy_init(); +} + + +CURLHTTPTransport::~CURLHTTPTransport() { + curl_easy_cleanup(session); +} + + +char CURLHTTPTransport::getURL(const char *destPath, const char *sourceURL, SWBuf *destBuf) { + signed char retVal = 0; + struct FtpFile ftpfile = {destPath, 0, destBuf}; + + CURLcode res; + + if (session) { + curl_easy_setopt(session, CURLOPT_URL, sourceURL); + + SWBuf credentials = u + ":" + p; + curl_easy_setopt(session, CURLOPT_USERPWD, credentials.c_str()); + curl_easy_setopt(session, CURLOPT_WRITEFUNCTION, my_httpfwrite); + if (!passive) + curl_easy_setopt(session, CURLOPT_FTPPORT, "-"); + curl_easy_setopt(session, CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(session, CURLOPT_PROGRESSDATA, statusReporter); + curl_easy_setopt(session, CURLOPT_PROGRESSFUNCTION, my_httpfprogress); + curl_easy_setopt(session, CURLOPT_DEBUGFUNCTION, myhttp_trace); + /* Set a pointer to our struct to pass to the callback */ + curl_easy_setopt(session, CURLOPT_FILE, &ftpfile); + + /* Switch on full protocol/debug output */ + curl_easy_setopt(session, CURLOPT_VERBOSE, true); + + /* FTP connection settings */ + +#if (LIBCURL_VERSION_MAJOR > 7) || \ + ((LIBCURL_VERSION_MAJOR == 7) && (LIBCURL_VERSION_MINOR > 10)) || \ + ((LIBCURL_VERSION_MAJOR == 7) && (LIBCURL_VERSION_MINOR == 10) && (LIBCURL_VERSION_PATCH >= 5)) +# define EPRT_AVAILABLE 1 +#endif + +#ifdef EPRT_AVAILABLE + curl_easy_setopt(session, CURLOPT_FTP_USE_EPRT, 0); + SWLog::getSystemLog()->logDebug("***** using CURLOPT_FTP_USE_EPRT\n"); +#endif + + + SWLog::getSystemLog()->logDebug("***** About to perform curl easy action. \n"); + SWLog::getSystemLog()->logDebug("***** destPath: %s \n", destPath); + SWLog::getSystemLog()->logDebug("***** sourceURL: %s \n", sourceURL); + res = curl_easy_perform(session); + SWLog::getSystemLog()->logDebug("***** Finished performing curl easy action. \n"); + + if(CURLE_OK != res) { + retVal = -1; + } + } + + if (ftpfile.stream) + fclose(ftpfile.stream); /* close the local file */ + + return retVal; +} + + +SWORD_NAMESPACE_END + diff --git a/src/mgr/encfiltmgr.cpp b/src/mgr/encfiltmgr.cpp index 970900c..cb6dab4 100644 --- a/src/mgr/encfiltmgr.cpp +++ b/src/mgr/encfiltmgr.cpp @@ -22,7 +22,6 @@ #include <encfiltmgr.h> #include <utilstr.h> -#include <scsuutf8.h> #include <latin1utf8.h> #include <unicodertf.h> @@ -45,7 +44,6 @@ SWORD_NAMESPACE_START EncodingFilterMgr::EncodingFilterMgr (char enc) : SWFilterMgr() { - scsuutf8 = new SCSUUTF8(); latin1utf8 = new Latin1UTF8(); encoding = enc; @@ -72,8 +70,6 @@ EncodingFilterMgr::EncodingFilterMgr (char enc) * EncodingFilterMgr Destructor - Cleans up instance of EncodingFilterMgr */ EncodingFilterMgr::~EncodingFilterMgr() { - if (scsuutf8) - delete scsuutf8; if (latin1utf8) delete latin1utf8; if (targetenc) @@ -88,9 +84,6 @@ void EncodingFilterMgr::AddRawFilters(SWModule *module, ConfigEntMap §ion) { if (!encoding.length() || !stricmp(encoding.c_str(), "Latin-1")) { module->AddRawFilter(latin1utf8); } - else if (!stricmp(encoding.c_str(), "SCSU")) { - module->AddRawFilter(scsuutf8); - } } void EncodingFilterMgr::AddEncodingFilters(SWModule *module, ConfigEntMap §ion) { diff --git a/src/mgr/filemgr.cpp b/src/mgr/filemgr.cpp index 4a91dfa..dd49913 100644 --- a/src/mgr/filemgr.cpp +++ b/src/mgr/filemgr.cpp @@ -2,7 +2,7 @@ * filemgr.cpp - implementation of class FileMgr used for pooling file * handles * - * $Id: filemgr.cpp 2108 2007-10-13 20:35:02Z scribe $ + * $Id: filemgr.cpp 2245 2009-02-10 23:22:28Z scribe $ * * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -481,7 +481,7 @@ char FileMgr::getLine(FileDesc *fDesc, SWBuf &line) { line.append(chunk+start, size); } } - return ((len>0) || line.length()); + return ((len > 0) || line.length()); } diff --git a/src/mgr/ftplibftpt.cpp b/src/mgr/ftplibftpt.cpp index 4921dd5..108d93e 100644 --- a/src/mgr/ftplibftpt.cpp +++ b/src/mgr/ftplibftpt.cpp @@ -1,7 +1,24 @@ /***************************************************************************** * FTPLibFTPTransport functions * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <stdio.h> #include <fcntl.h> @@ -43,7 +60,7 @@ char FTPLibFTPTransport::assureLoggedIn() { if (ftpConnection == 0) { SWLog::getSystemLog()->logDebug("connecting to host %s\n", host.c_str()); if (FtpConnect(host, &ftpConnection)) - if (FtpLogin("anonymous", "installmgr@user.com", ftpConnection)) { + if (FtpLogin(u.c_str(), p.c_str(), ftpConnection)) { retVal = 0; } else { diff --git a/src/mgr/ftptrans.cpp b/src/mgr/ftptrans.cpp index ab0a605..76e8679 100644 --- a/src/mgr/ftptrans.cpp +++ b/src/mgr/ftptrans.cpp @@ -1,7 +1,25 @@ /***************************************************************************** * FTPTransport functions * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + + #include <ftptrans.h> @@ -11,6 +29,9 @@ #include <dirent.h> #include <swlog.h> +extern "C" { +#include <ftpparse.h> +} using std::vector; @@ -40,6 +61,8 @@ void StatusReporter::statusUpdate(double dtTotal, double dlNow) { FTPTransport::FTPTransport(const char *host, StatusReporter *statusReporter) { this->statusReporter = statusReporter; this->host = host; + u = "ftp"; + p = "installmgr@user.com"; term = false; } diff --git a/src/mgr/installmgr.cpp b/src/mgr/installmgr.cpp index 6a1704f..c3fec1a 100644 --- a/src/mgr/installmgr.cpp +++ b/src/mgr/installmgr.cpp @@ -2,9 +2,26 @@ * InstallMgr functions to be made into something usefully exposed by * master Glassey * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #ifndef EXCLUDEZLIB extern "C" { #include <untgz.h> @@ -28,10 +45,12 @@ extern "C" { #ifdef CURLAVAILABLE #include <curlftpt.h> +#include <curlhttpt.h> #else #include <ftplibftpt.h> #endif +#include <iostream> SWORD_NAMESPACE_START namespace { @@ -43,6 +62,8 @@ void removeTrailingSlash(SWBuf &buf) { buf.size(len-1); } +const char *masterRepoList = "masterRepoList.conf"; + }; @@ -66,13 +87,24 @@ FTPTransport *InstallMgr::createFTPTransport(const char *host, StatusReporter *s #endif } +FTPTransport *InstallMgr::createHTTPTransport(const char *host, StatusReporter *statusReporter) { +#ifdef CURLAVAILABLE + return new CURLHTTPTransport(host, statusReporter); +#else + return 0; +#endif +} -InstallMgr::InstallMgr(const char *privatePath, StatusReporter *sr) { +InstallMgr::InstallMgr(const char *privatePath, StatusReporter *sr, SWBuf u, SWBuf p) { + userDisclaimerConfirmed = false; statusReporter = sr; + this->u = u; + this->p = p; this->privatePath = 0; this->transport = 0; + installConf = 0; stdstr(&(this->privatePath), privatePath); if (this->privatePath) { int len = strlen(this->privatePath); @@ -80,39 +112,59 @@ InstallMgr::InstallMgr(const char *privatePath, StatusReporter *sr) { || (this->privatePath[len-1] == '\\')) this->privatePath[len-1] = 0; } - SWBuf confPath = (SWBuf)privatePath + "/InstallMgr.conf"; + confPath = (SWBuf)privatePath + "/InstallMgr.conf"; FileMgr::createParent(confPath.c_str()); - installConf = new SWConfig(confPath.c_str()); + readInstallConf(); +} - SectionMap::iterator sourcesSection; - ConfigEntMap::iterator sourceBegin; - ConfigEntMap::iterator sourceEnd; +InstallMgr::~InstallMgr() { + delete [] privatePath; + delete installConf; + clearSources(); +} + +void InstallMgr::clearSources() { + for (InstallSourceMap::iterator it = sources.begin(); it != sources.end(); ++it) { + delete it->second; + } sources.clear(); +} + +void InstallMgr::readInstallConf() { + + if (installConf) delete installConf; + + installConf = new SWConfig(confPath.c_str()); + + clearSources(); - setFTPPassive(stricmp((*installConf)["General"]["PassiveFTP"].c_str(), "false")!=0); + setFTPPassive(stricmp((*installConf)["General"]["PassiveFTP"].c_str(), "false") != 0); - sourcesSection = installConf->Sections.find("Sources"); - if (sourcesSection != installConf->Sections.end()) { - sourceBegin = sourcesSection->second.lower_bound("FTPSource"); - sourceEnd = sourcesSection->second.upper_bound("FTPSource"); + SectionMap::iterator confSection = installConf->Sections.find("Sources"); + ConfigEntMap::iterator sourceBegin; + ConfigEntMap::iterator sourceEnd; + + if (confSection != installConf->Sections.end()) { + sourceBegin = confSection->second.lower_bound("FTPSource"); + sourceEnd = confSection->second.upper_bound("FTPSource"); while (sourceBegin != sourceEnd) { InstallSource *is = new InstallSource("FTP", sourceBegin->second.c_str()); sources[is->caption] = is; - SWBuf parent = (SWBuf)privatePath + "/" + is->source + "/file"; + SWBuf parent = (SWBuf)privatePath + "/" + is->uid + "/file"; FileMgr::createParent(parent.c_str()); - is->localShadow = (SWBuf)privatePath + "/" + is->source; + is->localShadow = (SWBuf)privatePath + "/" + is->uid; sourceBegin++; } } defaultMods.clear(); - sourcesSection = installConf->Sections.find("General"); - if (sourcesSection != installConf->Sections.end()) { - sourceBegin = sourcesSection->second.lower_bound("DefaultMod"); - sourceEnd = sourcesSection->second.upper_bound("DefaultMod"); + confSection = installConf->Sections.find("General"); + if (confSection != installConf->Sections.end()) { + sourceBegin = confSection->second.lower_bound("DefaultMod"); + sourceEnd = confSection->second.upper_bound("DefaultMod"); while (sourceBegin != sourceEnd) { defaultMods.insert(sourceBegin->second.c_str()); @@ -122,18 +174,24 @@ InstallMgr::InstallMgr(const char *privatePath, StatusReporter *sr) { } -InstallMgr::~InstallMgr() { - delete [] privatePath; - delete installConf; +void InstallMgr::saveInstallConf() { + + installConf->Sections["Sources"].erase("FTPSource"); for (InstallSourceMap::iterator it = sources.begin(); it != sources.end(); ++it) { - delete it->second; + if (it->second) { + installConf->Sections["Sources"].insert(ConfigEntMap::value_type("FTPSource", it->second->getConfEnt().c_str())); + } } + (*installConf)["General"]["PassiveFTP"] = (isFTPPassive()) ? "true" : "false"; + + installConf->Save(); } void InstallMgr::terminate() { if (transport) transport->terminate(); } + int InstallMgr::removeModule(SWMgr *manager, const char *moduleName) { SectionMap::iterator module; ConfigEntMap::iterator fileBegin; @@ -148,7 +206,7 @@ int InstallMgr::removeModule(SWMgr *manager, const char *moduleName) { // to be sure all files are closed // this does not remove the .conf information from SWMgr manager->deleteModule(modName); - + fileBegin = module->second.lower_bound("File"); fileEnd = module->second.upper_bound("File"); @@ -201,11 +259,23 @@ int InstallMgr::removeModule(SWMgr *manager, const char *moduleName) { int InstallMgr::ftpCopy(InstallSource *is, const char *src, const char *dest, bool dirTransfer, const char *suffix) { + + // assert user disclaimer has been confirmed + if (!isUserDisclaimerConfirmed()) return -1; + int retVal = 0; FTPTransport *trans = createFTPTransport(is->source, statusReporter); transport = trans; // set classwide current transport for other thread terminate() call + if (is->u.length()) { + trans->setUser(is->u); + trans->setPasswd(is->p); + } + else { + trans->setUser(u); + trans->setPasswd(p); + } trans->setPassive(passive); - + SWBuf urlPrefix = (SWBuf)"ftp://" + is->source; // let's be sure we can connect. This seems to be necessary but sucks @@ -215,7 +285,7 @@ int InstallMgr::ftpCopy(InstallSource *is, const char *src, const char *dest, bo // return -1; // } - + if (dirTransfer) { SWBuf dir = (SWBuf)is->directory.c_str(); removeTrailingSlash(dir); @@ -270,7 +340,7 @@ int InstallMgr::installModule(SWMgr *destMgr, const char *fromLocation, const ch SWLog::getSystemLog()->logDebug("***** modName: %s \n", modName); if (is) - sourceDir = (SWBuf)privatePath + "/" + is->source; + sourceDir = (SWBuf)privatePath + "/" + is->uid; else sourceDir = fromLocation; removeTrailingSlash(sourceDir); @@ -409,53 +479,16 @@ int InstallMgr::installModule(SWMgr *destMgr, const char *fromLocation, const ch return 1; } +int InstallMgr::refreshRemoteSource(InstallSource *is) { -// override this and provide an input mechanism to allow your users -// to enter the decipher code for a module. -// return true you added the cipher code to the config. -// default to return 'aborted' -bool InstallMgr::getCipherCode(const char *modName, SWConfig *config) { - return false; - -/* a sample implementation, roughly taken from the windows installmgr - - SectionMap::iterator section; - ConfigEntMap::iterator entry; - SWBuf tmpBuf; - section = config->Sections.find(modName); - if (section != config->Sections.end()) { - entry = section->second.find("CipherKey"); - if (entry != section->second.end()) { - entry->second = GET_USER_INPUT(); - config->Save(); - - // LET'S SHOW THE USER SOME SAMPLE TEXT FROM THE MODULE - SWMgr *mgr = new SWMgr(); - SWModule *mod = mgr->Modules[modName]; - mod->setKey("Ipet 2:12"); - tmpBuf = mod->StripText(); - mod->setKey("gen 1:10"); - tmpBuf += "\n\n"; - tmpBuf += mod->StripText(); - SOME_DIALOG_CONTROL->SETTEXT(tmpBuf.c_str()); - delete mgr; - - // if USER CLICKS OK means we should return true - return true; - } - } - return false; -*/ - -} - + // assert user disclaimer has been confirmed + if (!isUserDisclaimerConfirmed()) return -1; -int InstallMgr::refreshRemoteSource(InstallSource *is) { - SWBuf root = (SWBuf)privatePath + (SWBuf)"/" + is->source.c_str(); + SWBuf root = (SWBuf)privatePath + (SWBuf)"/" + is->uid.c_str(); removeTrailingSlash(root); SWBuf target = root + "/mods.d"; int errorCode = -1; //0 means successful - + FileMgr::removeDir(target.c_str()); if (!FileMgr::existsDir(target)) @@ -463,17 +496,17 @@ int InstallMgr::refreshRemoteSource(InstallSource *is) { #ifndef EXCLUDEZLIB SWBuf archive = root + "/mods.d.tar.gz"; - + errorCode = ftpCopy(is, "mods.d.tar.gz", archive.c_str(), false); if (!errorCode) { //sucessfully downloaded the tar,gz of module configs FileDesc *fd = FileMgr::getSystemFileMgr()->open(archive.c_str(), FileMgr::RDONLY); untargz(fd->getFd(), root.c_str()); FileMgr::getSystemFileMgr()->close(fd); } - else if (!term) //if the tar.gz download was canceled don't continue with another download + else #endif errorCode = ftpCopy(is, "mods.d", target.c_str(), true, ".conf"); //copy the whole directory - + is->flush(); return errorCode; } @@ -536,19 +569,96 @@ map<SWModule *, int> InstallMgr::getModuleStatus(const SWMgr &base, const SWMgr } +/************************************************************************ + * refreshRemoteSourceConfiguration - grab master list of know remote + * sources and integrate it with our configurations. + */ +int InstallMgr::refreshRemoteSourceConfiguration() { + + // assert user disclaimer has been confirmed + if (!isUserDisclaimerConfirmed()) return -1; + + SWBuf root = (SWBuf)privatePath; + removeTrailingSlash(root); + SWBuf masterRepoListPath = root + "/" + masterRepoList; + InstallSource is("FTP"); + is.source = "ftp.crosswire.org"; + is.directory = "/pub/sword"; + int errorCode = ftpCopy(&is, masterRepoList, masterRepoListPath.c_str(), false); + if (!errorCode) { //sucessfully downloaded the repo list + SWConfig masterList(masterRepoListPath); + SectionMap::iterator sections = masterList.Sections.find("Repos"); + if (sections != masterList.Sections.end()) { + for (ConfigEntMap::iterator actions = sections->second.begin(); actions != sections->second.end(); actions++) { + // Search through our current sources and see if we have a matching UID + InstallSourceMap::iterator it; + for (it = sources.begin(); it != sources.end(); ++it) { + // is this our UID? + if ((it->second) && (it->second->uid == actions->first)) { + if (actions->second == "REMOVE") { + // be sure to call save/reload after this + // or this could be dangerous + delete it->second; + it->second = 0; + } + else { + SWBuf key = actions->second.stripPrefix('='); + if (key == "FTPSource") { + // we might consider instantiating a temp IS + // from our config string and then copy only + // some entries. This would allow the use to + // change some fields and not have them overwritten + // but it seems like we might want to change any + // of the current fields so we don't do this now + // InstallSource i("FTP", actions->second); + delete it->second; + it->second = new InstallSource("FTP", actions->second.c_str()); + it->second->uid = actions->first; + } + } + break; + } + } + // didn't find our UID, let's add it + if (it == sources.end()) { + SWBuf key = actions->second.stripPrefix('='); + if (key == "FTPSource") { + if (actions->second != "REMOVE") { + InstallSource *is = new InstallSource("FTP", actions->second.c_str()); + is->uid = actions->first; + sources[is->caption] = is; + } + } + } + } + + // persist and re-read + saveInstallConf(); + readInstallConf(); + + return 0; + } + } + return -1; +} + + InstallSource::InstallSource(const char *type, const char *confEnt) { this->type = type; mgr = 0; userData = 0; if (confEnt) { - char *buf = 0; - stdstr(&buf, confEnt); + SWBuf buf = confEnt; + caption = buf.stripPrefix('|', true); + source = buf.stripPrefix('|', true); + directory = buf.stripPrefix('|', true); + u = buf.stripPrefix('|', true); + p = buf.stripPrefix('|', true); + uid = buf.stripPrefix('|', true); + + if (!uid.length()) uid = source; - caption = strtok(buf, "|"); - source = strtok(0, "|"); - directory = strtok(0, "|"); removeTrailingSlash(directory); - delete [] buf; } } diff --git a/src/mgr/localemgr.cpp b/src/mgr/localemgr.cpp index ead076a..af57ca0 100644 --- a/src/mgr/localemgr.cpp +++ b/src/mgr/localemgr.cpp @@ -2,7 +2,7 @@ * localemgr.cpp - implementation of class LocaleMgr used to interact with * registered locales for a sword installation * - * $Id: localemgr.cpp 2080 2007-09-17 06:21:29Z scribe $ + * $Id: localemgr.cpp 2321 2009-04-13 01:17:00Z scribe $ * * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -49,8 +49,9 @@ public: LocaleMgr *LocaleMgr::getSystemLocaleMgr() { - if (!systemLocaleMgr) - systemLocaleMgr = new LocaleMgr(); + if (!systemLocaleMgr) { + setSystemLocaleMgr(new LocaleMgr()); + } return systemLocaleMgr; } @@ -60,6 +61,8 @@ void LocaleMgr::setSystemLocaleMgr(LocaleMgr *newLocaleMgr) { if (systemLocaleMgr) delete systemLocaleMgr; systemLocaleMgr = newLocaleMgr; + SWLocale *locale = new SWLocale(0); + systemLocaleMgr->locales->insert(LocaleMap::value_type(locale->getName(), locale)); } @@ -67,18 +70,29 @@ LocaleMgr::LocaleMgr(const char *iConfigPath) { locales = new LocaleMap(); char *prefixPath = 0; char *configPath = 0; + SWConfig *sysConf = 0; char configType = 0; SWBuf path; std::list<SWBuf> augPaths; + ConfigEntMap::iterator entry; defaultLocaleName = 0; if (!iConfigPath) { SWLog::getSystemLog()->logDebug("LOOKING UP LOCALE DIRECTORY..."); - SWMgr::findConfig(&configType, &prefixPath, &configPath, &augPaths); + SWMgr::findConfig(&configType, &prefixPath, &configPath, &augPaths, &sysConf); + if (sysConf) { + if ((entry = sysConf->Sections["Install"].find("LocalePath")) != sysConf->Sections["Install"].end()) { + configType = 9; // our own + stdstr(&prefixPath, (char *)entry->second.c_str()); + SWLog::getSystemLog()->logDebug("LocalePath provided in sysConfig."); + } + } SWLog::getSystemLog()->logDebug("LOOKING UP LOCALE DIRECTORY COMPLETE."); } - else configPath = (char *)iConfigPath; + else { + loadConfigDir(iConfigPath); + } if (prefixPath) { switch (configType) { @@ -102,7 +116,7 @@ LocaleMgr::LocaleMgr(const char *iConfigPath) { } } - if (augPaths.size()) { //load locale files from all augmented paths + if (augPaths.size() && configType != 9) { //load locale files from all augmented paths std::list<SWBuf>::iterator it = augPaths.begin(); std::list<SWBuf>::iterator end = augPaths.end(); @@ -117,13 +131,16 @@ LocaleMgr::LocaleMgr(const char *iConfigPath) { // Locales will be invalidated if you change the StringMgr // So only use the default hardcoded locale and let the // frontends change the locale if they want - stdstr(&defaultLocaleName, "en_US"); + stdstr(&defaultLocaleName, SWLocale::DEFAULT_LOCALE_NAME); if (prefixPath) delete [] prefixPath; if (configPath) delete [] configPath; + + if (sysConf) + delete sysConf; } @@ -200,7 +217,7 @@ SWLocale *LocaleMgr::getLocale(const char *name) { return (*it).second; SWLog::getSystemLog()->logWarning("LocaleMgr::getLocale failed to find %s\n", name); - return 0; + return (*locales)[SWLocale::DEFAULT_LOCALE_NAME]; } diff --git a/src/mgr/swconfig.cpp b/src/mgr/swconfig.cpp index 376c206..309f686 100644 --- a/src/mgr/swconfig.cpp +++ b/src/mgr/swconfig.cpp @@ -2,7 +2,7 @@ * swconfig.cpp - implementation of Class SWConfig used for saving and * retrieval of configuration information * - * $Id: swconfig.cpp 1828 2005-06-10 16:24:46Z scribe $ + * $Id: swconfig.cpp 2218 2008-12-23 09:33:38Z scribe $ * * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -28,6 +28,9 @@ SWORD_NAMESPACE_START +SWConfig::SWConfig() { +} + SWConfig::SWConfig(const char * ifilename) { filename = ifilename; Load(); @@ -38,6 +41,9 @@ SWConfig::~SWConfig() { } void SWConfig::Load() { + + if (!filename.size()) return; // assert we have a filename + FileDesc *cfile; char *buf, *data; SWBuf line; @@ -60,27 +66,30 @@ void SWConfig::Load() { } while (goodLine) { - buf = new char [ line.length() + 1 ]; - strcpy(buf, line.c_str()); - if (*strstrip(buf) == '[') { - if (!first) - Sections.insert(SectionMap::value_type(sectname, cursect)); - else first = false; - - cursect.erase(cursect.begin(), cursect.end()); - - strtok(buf, "]"); - sectname = buf+1; - } - else { - strtok(buf, "="); - if ((*buf) && (*buf != '=')) { - if ((data = strtok(NULL, ""))) - cursect.insert(ConfigEntMap::value_type(buf, strstrip(data))); - else cursect.insert(ConfigEntMap::value_type(buf, "")); + // ignore commented lines + if (!line.startsWith("#")) { + buf = new char [ line.length() + 1 ]; + strcpy(buf, line.c_str()); + if (*strstrip(buf) == '[') { + if (!first) + Sections.insert(SectionMap::value_type(sectname, cursect)); + else first = false; + + cursect.erase(cursect.begin(), cursect.end()); + + strtok(buf, "]"); + sectname = buf+1; } + else { + strtok(buf, "="); + if ((*buf) && (*buf != '=')) { + if ((data = strtok(NULL, ""))) + cursect.insert(ConfigEntMap::value_type(buf, strstrip(data))); + else cursect.insert(ConfigEntMap::value_type(buf, "")); + } + } + delete [] buf; } - delete [] buf; goodLine = FileMgr::getLine(cfile, line); } if (!first) @@ -92,6 +101,9 @@ void SWConfig::Load() { void SWConfig::Save() { + + if (!filename.size()) return; // assert we have a filename + FileDesc *cfile; SWBuf buf; SectionMap::iterator sit; diff --git a/src/mgr/swlocale.cpp b/src/mgr/swlocale.cpp index facb1ee..3d09313 100644 --- a/src/mgr/swlocale.cpp +++ b/src/mgr/swlocale.cpp @@ -2,7 +2,7 @@ * swlocale.cpp - implementation of Class SWLocale used for retrieval * of locale lookups * - * $Id: swlocale.cpp 1864 2005-11-20 06:06:40Z scribe $ + * $Id: swlocale.cpp 2346 2009-04-27 01:53:58Z scribe $ * * Copyright 2000 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -25,29 +25,42 @@ #include <map> #include <swconfig.h> #include <versekey.h> +#include <versemgr.h> SWORD_NAMESPACE_START typedef std::map < SWBuf, SWBuf, std::less < SWBuf > >LookupMap; +const char *SWLocale::DEFAULT_LOCALE_NAME="en_US"; + // I have bridge patterns, but this hides swconfig and map from lots o stuff class SWLocale::Private { public: LookupMap lookupTable; + LookupMap mergedAbbrevs; }; -SWLocale::SWLocale(const char * ifilename) { +SWLocale::SWLocale(const char *ifilename) { p = new Private; ConfigEntMap::iterator confEntry; - name = 0; - description = 0; - encoding = 0; - bookAbbrevs = 0; - BMAX = 0; - books = 0; - localeSource = new SWConfig(ifilename); + name = 0; + description = 0; + encoding = 0; + bookAbbrevs = 0; + bookLongNames = 0; + bookPrefAbbrev = 0; + if (ifilename) { + localeSource = new SWConfig(ifilename); + } + else { + localeSource = new SWConfig(0); + (*localeSource)["Meta"]["Name"] = DEFAULT_LOCALE_NAME; + (*localeSource)["Meta"]["Description"] = "English (US)"; + bookAbbrevs = (struct abbrev *)builtin_abbrevs; + for (abbrevsCnt = 0; builtin_abbrevs[abbrevsCnt].osis[0]; abbrevsCnt++); + } confEntry = localeSource->Sections["Meta"].find("Name"); if (confEntry != localeSource->Sections["Meta"].end()) @@ -76,15 +89,9 @@ SWLocale::~SWLocale() { if (name) delete [] name; - if (bookAbbrevs) + if (bookAbbrevs != builtin_abbrevs) delete [] bookAbbrevs; - if (BMAX) { - for (int i = 0; i < 2; i++) - delete [] books[i]; - delete [] BMAX; - delete [] books; - } delete p; } @@ -145,60 +152,35 @@ void SWLocale::augment(SWLocale &addFrom) { *localeSource += *addFrom.localeSource; } -//#define NONNUMERICLOCALETHING 1 -const struct abbrev *SWLocale::getBookAbbrevs() { +const struct abbrev *SWLocale::getBookAbbrevs(int *retSize) { static const char *nullstr = ""; if (!bookAbbrevs) { - ConfigEntMap::iterator it; - int i, j; - int size = localeSource->Sections["Book Abbrevs"].size(); + // Assure all english abbrevs are present + for (int j = 0; builtin_abbrevs[j].osis[0]; j++) { + p->mergedAbbrevs[builtin_abbrevs[j].ab] = builtin_abbrevs[j].osis; + } + ConfigEntMap::iterator it = localeSource->Sections["Book Abbrevs"].begin(); + ConfigEntMap::iterator end = localeSource->Sections["Book Abbrevs"].end(); + for (; it != end; it++) { + p->mergedAbbrevs[it->first.c_str()] = it->second.c_str(); + } + int size = p->mergedAbbrevs.size(); bookAbbrevs = new struct abbrev[size + 1]; - for (i = 0, j = 0, it = localeSource->Sections["Book Abbrevs"].begin(); it != localeSource->Sections["Book Abbrevs"].end(); it++, i++) { - #ifdef NONNUMERICLOCALETHING - int booknum = VerseKey::getOSISBookNum((*it).second.c_str()); - if (booknum != -1) { - bookAbbrevs[j].ab = (*it).first.c_str(); - bookAbbrevs[j].book = booknum; - j++; - } - #else - bookAbbrevs[i].ab = (*it).first.c_str(); - bookAbbrevs[i].book = atoi((*it).second.c_str()); - j++; - #endif - //printf("SWLocale::getBookAbbrevs %s:%s %d\n",bookAbbrevs[i].ab, - // (*it).second.c_str(), bookAbbrevs[i].book); + int i = 0; + for (LookupMap::iterator it = p->mergedAbbrevs.begin(); it != p->mergedAbbrevs.end(); it++, i++) { + bookAbbrevs[i].ab = it->first.c_str(); + bookAbbrevs[i].osis = it->second.c_str(); } - bookAbbrevs[j].ab = nullstr; - bookAbbrevs[j].book = -1; + + bookAbbrevs[i].ab = nullstr; + bookAbbrevs[i].osis = nullstr; + abbrevsCnt = size; } + *retSize = abbrevsCnt; return bookAbbrevs; } -void SWLocale::getBooks(char **iBMAX, struct sbook ***ibooks) { - if (!BMAX) { - BMAX = new char [2]; - BMAX[0] = VerseKey::builtin_BMAX[0]; - BMAX[1] = VerseKey::builtin_BMAX[1]; - - books = new struct sbook *[2]; - books[0] = new struct sbook[BMAX[0]]; - books[1] = new struct sbook[BMAX[1]]; - - for (int i = 0; i < 2; i++) { - for (int j = 0; j < BMAX[i]; j++) { - books[i][j] = VerseKey::builtin_books[i][j]; - books[i][j].name = translate(VerseKey::builtin_books[i][j].name); - } - } - } - - *iBMAX = BMAX; - *ibooks = books; -} - - SWORD_NAMESPACE_END diff --git a/src/mgr/swmgr.cpp b/src/mgr/swmgr.cpp index 86c04d7..3ee253f 100644 --- a/src/mgr/swmgr.cpp +++ b/src/mgr/swmgr.cpp @@ -2,7 +2,7 @@ * swmgr.cpp - implementaion of class SWMgr used to interact with an install * base of sword modules. * - * $Id: swmgr.cpp 2169 2008-05-18 02:50:53Z scribe $ + * $Id: swmgr.cpp 2374 2009-05-04 03:48:01Z scribe $ * * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -58,6 +58,7 @@ #include <osislemma.h> #include <osisredletterwords.h> #include <osismorphsegmentation.h> +#include <osisruby.h> #include <osisscripref.h> #include <thmlstrongs.h> #include <thmlfootnotes.h> @@ -75,6 +76,7 @@ #include <utf8greekaccents.h> #include <utf8cantillation.h> #include <utf8hebrewpoints.h> +#include <utf8arabicpoints.h> #include <greeklexattribs.h> #include <swfiltermgr.h> #include <swcipher.h> @@ -177,6 +179,10 @@ void SWMgr::init() { optionFilters.insert(OptionFilterMap::value_type("OSISMorphSegmentation", tmpFilter)); cleanupFilters.push_back(tmpFilter); + tmpFilter = new OSISRuby(); + optionFilters.insert(OptionFilterMap::value_type("OSISRuby", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + tmpFilter = new ThMLStrongs(); optionFilters.insert(OptionFilterMap::value_type("ThMLStrongs", tmpFilter)); cleanupFilters.push_back(tmpFilter); @@ -209,6 +215,10 @@ void SWMgr::init() { optionFilters.insert(OptionFilterMap::value_type("UTF8HebrewPoints", tmpFilter)); cleanupFilters.push_back(tmpFilter); + tmpFilter = new UTF8ArabicPoints(); + optionFilters.insert(OptionFilterMap::value_type("UTF8ArabicPoints", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + tmpFilter = new UTF8Cantillation(); optionFilters.insert(OptionFilterMap::value_type("UTF8Cantillation", tmpFilter)); cleanupFilters.push_back(tmpFilter); @@ -240,7 +250,24 @@ void SWMgr::init() { teiplain = new TEIPlain(); cleanupFilters.push_back(teiplain); -//#endif +} + + +SWBuf SWMgr::getHomeDir() { + + // figure out 'home' directory for app data + SWBuf homeDir = getenv("HOME"); + if (!homeDir.length()) { + // silly windows + homeDir = getenv("APPDATA"); + } + if (homeDir.length()) { + if ((homeDir[homeDir.length()-1] != '\\') && (homeDir[homeDir.length()-1] != '/')) { + homeDir += "/"; + } + } + + return homeDir; } @@ -259,10 +286,10 @@ void SWMgr::commonInit(SWConfig *iconfig, SWConfig *isysconfig, bool autoload, S } else config = 0; if (isysconfig) { - sysconfig = isysconfig; + sysConfig = isysconfig; mysysconfig = 0; } - else sysconfig = 0; + else sysConfig = 0; if (autoload) Load(); @@ -311,7 +338,7 @@ SWMgr::SWMgr(const char *iConfigPath, bool autoload, SWFilterMgr *filterMgr, boo } config = 0; - sysconfig = 0; + sysConfig = 0; if (autoload && configPath) Load(); @@ -345,32 +372,46 @@ SWMgr::~SWMgr() { } -void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, std::list<SWBuf> *augPaths, SWConfig *providedSysConf) { +void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, std::list<SWBuf> *augPaths, SWConfig **providedSysConf) { SWBuf path; SWBuf sysConfPath; ConfigEntMap::iterator entry; ConfigEntMap::iterator lastEntry; - char *envsworddir = getenv("SWORD_PATH"); - char *envhomedir = getenv("HOME"); SWConfig *sysConf = 0; + SWBuf sysConfDataPath = ""; *configType = 0; + SWBuf homeDir = getHomeDir(); + // check for a sysConf passed in to us SWLog::getSystemLog()->logDebug("Checking for provided SWConfig(\"sword.conf\")..."); - if (providedSysConf) { - sysConf = providedSysConf; + if (providedSysConf && *providedSysConf) { + sysConf = *providedSysConf; SWLog::getSystemLog()->logDebug("found."); } - else { + + // if we haven't been given our datapath in a sysconf, we need to track it down + if (!sysConf) { // check working directory SWLog::getSystemLog()->logDebug("Checking working directory for sword.conf..."); if (FileMgr::existsFile(".", "sword.conf")) { SWLog::getSystemLog()->logDebug("Overriding any systemwide or ~/.sword/ sword.conf with one found in current directory."); sysConfPath = "./sword.conf"; + sysConf = new SWConfig(sysConfPath); + if ((entry = sysConf->Sections["Install"].find("DataPath")) != sysConf->Sections["Install"].end()) { + sysConfDataPath = (*entry).second; + } + if (providedSysConf) { + *providedSysConf = sysConf; + } + else { + delete sysConf; + sysConf = 0; + } } - else { + if (!sysConfDataPath.size()) { SWLog::getSystemLog()->logDebug("Checking working directory for mods.conf..."); if (FileMgr::existsFile(".", "mods.conf")) { SWLog::getSystemLog()->logDebug("found."); @@ -388,7 +429,7 @@ void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, s return; } - // check working directory ../library/ + // check working directory ../library/ SWLog::getSystemLog()->logDebug("Checking working directory ../library/ for mods.d..."); if (FileMgr::existsDir("../library", "mods.d")) { SWLog::getSystemLog()->logDebug("found."); @@ -399,13 +440,14 @@ void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, s } // check environment variable SWORD_PATH - SWLog::getSystemLog()->logDebug("Checking SWORD_PATH..."); + SWLog::getSystemLog()->logDebug("Checking $SWORD_PATH..."); - if (envsworddir != NULL) { + SWBuf envsworddir = getenv("SWORD_PATH"); + if (envsworddir.length()) { - SWLog::getSystemLog()->logDebug("found (%s).", envsworddir); + SWLog::getSystemLog()->logDebug("found (%s).", envsworddir.c_str()); path = envsworddir; - if ((envsworddir[strlen(envsworddir)-1] != '\\') && (envsworddir[strlen(envsworddir)-1] != '/')) + if ((envsworddir[envsworddir.length()-1] != '\\') && (envsworddir[envsworddir.length()-1] != '/')) path += "/"; SWLog::getSystemLog()->logDebug("Checking $SWORD_PATH for mods.conf..."); @@ -446,29 +488,38 @@ void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, s sysConfPath = gfp; delete [] globPaths; - SWBuf homeDir = envhomedir; - if (homeDir.size() > 0) { - if ((homeDir[homeDir.size()-1] != '\\') && (homeDir[homeDir.size()-1] != '/')) - homeDir += "/"; - homeDir += ".sword/sword.conf"; - if (FileMgr::existsFile(homeDir)) { - SWLog::getSystemLog()->logDebug("Overriding any systemwide sword.conf with one found in users home directory."); - sysConfPath = homeDir; + if (homeDir.length()) { + SWBuf tryPath = homeDir; + tryPath += ".sword/sword.conf"; + if (FileMgr::existsFile(tryPath)) { + SWLog::getSystemLog()->logDebug("Overriding any systemwide sword.conf with one found in users home directory (%s)", tryPath.c_str()); + sysConfPath = tryPath; + } + else { + SWBuf tryPath = homeDir; + tryPath += "sword/sword.conf"; + if (FileMgr::existsFile(tryPath)) { + SWLog::getSystemLog()->logDebug("Overriding any systemwide sword.conf with one found in users home directory (%s)", tryPath.c_str()); + sysConfPath = tryPath; + } } } } } - if (sysConfPath.size()) { + if (!sysConf && sysConfPath.size()) { sysConf = new SWConfig(sysConfPath); } if (sysConf) { if ((entry = sysConf->Sections["Install"].find("DataPath")) != sysConf->Sections["Install"].end()) { - path = (*entry).second; - if (((*entry).second.c_str()[strlen((*entry).second.c_str())-1] != '\\') && ((*entry).second.c_str()[strlen((*entry).second.c_str())-1] != '/')) - path += "/"; + sysConfDataPath = (*entry).second; + } + if (sysConfDataPath.size()) { + if ((!sysConfDataPath.endsWith("\\")) && (!sysConfDataPath.endsWith("/"))) + sysConfDataPath += "/"; + path = sysConfDataPath; SWLog::getSystemLog()->logDebug("DataPath in %s is set to %s.", sysConfPath.c_str(), path.c_str()); SWLog::getSystemLog()->logDebug("Checking for mods.conf in DataPath..."); @@ -490,6 +541,10 @@ void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, s *configType = 1; } } + } + + // do some extra processing of sysConf if we have one + if (sysConf) { if (augPaths) { augPaths->clear(); entry = sysConf->Sections["Install"].lower_bound("AugmentPath"); @@ -501,23 +556,72 @@ void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, s augPaths->push_back(path); } } - } - - if ((sysConf) && (!providedSysConf)) { - delete sysConf; + if (providedSysConf) { + *providedSysConf = sysConf; + } + else delete sysConf; } if (*configType) return; + // WE STILL HAVEN'T FOUND A CONFIGURATION. LET'S LOOK IN SOME OS SPECIFIC + // LOCATIONS + // + // for various flavors of windoze... + // check %ALLUSERSPROFILE%/Application Data/sword/ + + SWLog::getSystemLog()->logDebug("Checking $ALLUSERSPROFILE/Application Data/sword/..."); + + SWBuf envallusersdir = getenv("ALLUSERSPROFILE"); + if (envallusersdir.length()) { + SWLog::getSystemLog()->logDebug("found (%s).", envallusersdir.c_str()); + path = envallusersdir; + if ((!path.endsWith("\\")) && (!path.endsWith("/"))) + path += "/"; + + path += "Application Data/sword/"; + SWLog::getSystemLog()->logDebug("Checking %s for mods.d...", path.c_str()); + if (FileMgr::existsDir(path.c_str(), "mods.d")) { + SWLog::getSystemLog()->logDebug("found."); + stdstr(prefixPath, path.c_str()); + path += "mods.d"; + stdstr(configPath, path.c_str()); + *configType = 1; + return; + } + } + + // for Mac OSX... + // check $HOME/Library/Application Support/Sword/ + + SWLog::getSystemLog()->logDebug("Checking $HOME/Library/Application Support/Sword/..."); + + SWBuf pathCheck = getHomeDir(); + if (pathCheck.length()) { + SWLog::getSystemLog()->logDebug("found (%s).", pathCheck.c_str()); + path = pathCheck; + if ((!path.endsWith("\\")) && (!path.endsWith("/"))) + path += "/"; + + SWLog::getSystemLog()->logDebug("Checking %s for mods.d...", path.c_str()); + if (FileMgr::existsDir(path.c_str(), "mods.d")) { + SWLog::getSystemLog()->logDebug("found."); + stdstr(prefixPath, path.c_str()); + path += "mods.d"; + stdstr(configPath, path.c_str()); + *configType = 1; + return; + } + } + + // FINALLY CHECK PERSONAL HOME DIRECTORY LOCATIONS // check ~/.sword/ SWLog::getSystemLog()->logDebug("Checking home directory for ~/.sword..."); - if (envhomedir != NULL) { - path = envhomedir; - if ((envhomedir[strlen(envhomedir)-1] != '\\') && (envhomedir[strlen(envhomedir)-1] != '/')) - path += "/"; + if (homeDir.length()) { + path = homeDir; path += ".sword/"; SWLog::getSystemLog()->logDebug(" Checking for %smods.conf...", path.c_str()); if (FileMgr::existsFile(path.c_str(), "mods.conf")) { @@ -537,6 +641,18 @@ void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, s *configType = 2; return; } + + path = homeDir; + path += "sword/"; + SWLog::getSystemLog()->logDebug(" Checking for %smods.d...", path.c_str()); + if (FileMgr::existsDir(path.c_str(), "mods.d")) { + SWLog::getSystemLog()->logDebug("found."); + stdstr(prefixPath, path.c_str()); + path += "mods.d"; + stdstr(configPath, path.c_str()); + *configType = 2; + return; + } } } @@ -551,21 +667,19 @@ void SWMgr::loadConfigDir(const char *ipath) rewinddir(dir); while ((ent = readdir(dir))) { //check whether it ends with .conf, if it doesn't skip it! - if (ent->d_name && (strlen(ent->d_name) > 5) && strncmp(".conf", (ent->d_name + strlen(ent->d_name) - 5), 5 )) { + if (!ent->d_name || (strlen(ent->d_name) <= 5) || strncmp(".conf", (ent->d_name + strlen(ent->d_name) - 5), 5 )) { continue; } - if ((strcmp(ent->d_name, ".")) && (strcmp(ent->d_name, ".."))) { - newmodfile = ipath; - if ((ipath[strlen(ipath)-1] != '\\') && (ipath[strlen(ipath)-1] != '/')) - newmodfile += "/"; - newmodfile += ent->d_name; - if (config) { - SWConfig tmpConfig(newmodfile.c_str()); - *config += tmpConfig; - } - else config = myconfig = new SWConfig(newmodfile.c_str()); + newmodfile = ipath; + if ((ipath[strlen(ipath)-1] != '\\') && (ipath[strlen(ipath)-1] != '/')) + newmodfile += "/"; + newmodfile += ent->d_name; + if (config) { + SWConfig tmpConfig(newmodfile.c_str()); + *config += tmpConfig; } + else config = myconfig = new SWConfig(newmodfile.c_str()); } closedir(dir); @@ -646,7 +760,9 @@ signed char SWMgr::Load() { if (!config) { // If we weren't passed a config object at construction, find a config file if (!configPath) { // If we weren't passed a config path at construction... SWLog::getSystemLog()->logDebug("LOOKING UP MODULE CONFIGURATION..."); - findConfig(&configType, &prefixPath, &configPath, &augPaths, sysconfig); + SWConfig *externalSysConf = sysConfig; // if we have a sysConf before findConfig, then we were provided one from an external source. + findConfig(&configType, &prefixPath, &configPath, &augPaths, &sysConfig); + if (!externalSysConf) mysysconfig = sysConfig; // remind us to delete our own sysConfig in d-tor SWLog::getSystemLog()->logDebug("LOOKING UP MODULE CONFIGURATION COMPLETE."); } if (configPath) { @@ -680,17 +796,18 @@ signed char SWMgr::Load() { } if (augmentHome) { // augment config with ~/.sword/mods.d if it exists --------------------- - char *envhomedir = getenv("HOME"); - if (envhomedir != NULL && configType != 2) { // 2 = user only - SWBuf path = envhomedir; - if ((envhomedir[strlen(envhomedir)-1] != '\\') && (envhomedir[strlen(envhomedir)-1] != '/')) - path += "/"; + SWBuf homeDir = getHomeDir(); + if (homeDir.length() && configType != 2) { // 2 = user only + SWBuf path = homeDir; path += ".sword/"; augmentModules(path.c_str(), mgrModeMultiMod); + path = homeDir; + path += "sword/"; + augmentModules(path.c_str(), mgrModeMultiMod); } } // ------------------------------------------------------------------------- - if ( !Modules.size() ) // config exists, but no modules + if (!Modules.size()) // config exists, but no modules ret = 1; } @@ -718,6 +835,8 @@ SWModule *SWMgr::CreateMod(const char *name, const char *driver, ConfigEntMap &s if ((prefixPath[strlen(prefixPath)-1] != '\\') && (prefixPath[strlen(prefixPath)-1] != '/')) datapath += "/"; + SWBuf versification = ((entry = section.find("Versification")) != section.end()) ? (*entry).second : (SWBuf)"KJV"; + // DataPath - relative path to data used by module driver. May be a directory, may be a File. // Typically not useful by outside world. See AbsoluteDataPath, PrefixPath, and RelativePrefixPath // below. @@ -749,9 +868,7 @@ SWModule *SWMgr::CreateMod(const char *name, const char *driver, ConfigEntMap &s else markup = FMT_GBF; - if (!stricmp(encoding.c_str(), "SCSU")) - enc = ENC_SCSU; - else if (!stricmp(encoding.c_str(), "UTF-8")) { + if (!stricmp(encoding.c_str(), "UTF-8")) { enc = ENC_UTF8; } else enc = ENC_LATIN1; @@ -795,17 +912,17 @@ SWModule *SWMgr::CreateMod(const char *name, const char *driver, ConfigEntMap &s if (compress) { if (!stricmp(driver, "zText")) - newmod = new zText(datapath.c_str(), name, description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str()); - else newmod = new zCom(datapath.c_str(), name, description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str()); + newmod = new zText(datapath.c_str(), name, description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str(), versification); + else newmod = new zCom(datapath.c_str(), name, description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str(), versification); } } if (!stricmp(driver, "RawText")) { - newmod = new RawText(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str()); + newmod = new RawText(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str(), versification); } if (!stricmp(driver, "RawText4")) { - newmod = new RawText4(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str()); + newmod = new RawText4(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str(), versification); } // backward support old drivers @@ -814,11 +931,11 @@ SWModule *SWMgr::CreateMod(const char *name, const char *driver, ConfigEntMap &s } if (!stricmp(driver, "RawCom")) { - newmod = new RawCom(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str()); + newmod = new RawCom(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str(), versification); } if (!stricmp(driver, "RawCom4")) { - newmod = new RawCom4(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str()); + newmod = new RawCom4(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str(), versification); } if (!stricmp(driver, "RawFiles")) { @@ -888,11 +1005,11 @@ SWModule *SWMgr::CreateMod(const char *name, const char *driver, ConfigEntMap &s */ } - // if a specific module type is set in the config, use this - if ((entry = section.find("Type")) != section.end()) - newmod->Type(entry->second.c_str()); + if (newmod) { + // if a specific module type is set in the config, use this + if ((entry = section.find("Type")) != section.end()) + newmod->Type(entry->second.c_str()); - if (newmod){ newmod->setConfig(§ion); } diff --git a/src/mgr/versemgr.cpp b/src/mgr/versemgr.cpp new file mode 100644 index 0000000..0673746 --- /dev/null +++ b/src/mgr/versemgr.cpp @@ -0,0 +1,369 @@ +/****************************************************************************** + * versemgr.cpp - implementation of class VerseMgr used for managing + * versification systems + * + * $Id: versemgr.cpp 2108 2007-10-13 20:35:02Z scribe $ + * + * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#include <versemgr.h> +#include <vector> +#include <map> +#include <treekey.h> +#include <canon.h> // KJV internal versification system +#include <swlog.h> +#include <algorithm> + +#include <canon_null.h> // null v11n system + +#include <canon_leningrad.h> // Leningrad Codex (WLC) v11n system +#include <canon_mt.h> // Masoretic Text (MT) v11n system +#include <canon_kjva.h> // KJV + Apocrypha v11n system +#include <canon_nrsv.h> // NRSV v11n system +#include <canon_nrsva.h> // NRSVA + Apocrypha v11n system + +using std::vector; +using std::map; +using std::distance; +using std::lower_bound; + +SWORD_NAMESPACE_START + + +VerseMgr *VerseMgr::getSystemVerseMgr() { + if (!systemVerseMgr) { + systemVerseMgr = new VerseMgr(); + systemVerseMgr->registerVersificationSystem("KJV", otbooks, ntbooks, vm); + systemVerseMgr->registerVersificationSystem("Leningrad", otbooks_leningrad, ntbooks_null, vm_leningrad); + systemVerseMgr->registerVersificationSystem("MT", otbooks_mt, ntbooks_null, vm_mt); + systemVerseMgr->registerVersificationSystem("KJVA", otbooks_kjva, ntbooks, vm_kjva); + systemVerseMgr->registerVersificationSystem("NRSV", otbooks, ntbooks, vm_nrsv); + systemVerseMgr->registerVersificationSystem("NRSVA", otbooks_nrsva, ntbooks, vm_nrsva); + } + return systemVerseMgr; +} + + +class VerseMgr::System::Private { +public: + /** Array[chapmax] of maximum verses in chapters */ + vector<Book> books; + map<SWBuf, int> osisLookup; + + Private() { + } + Private(const VerseMgr::System::Private &other) { + books = other.books; + osisLookup = other.osisLookup; + } + VerseMgr::System::Private &operator =(const VerseMgr::System::Private &other) { + books = other.books; + osisLookup = other.osisLookup; + return *this; + } +}; + + +class VerseMgr::Book::Private { +friend struct BookOffsetLess; +public: + /** Array[chapmax] of maximum verses in chapters */ + vector<int> verseMax; + vector<long> offsetPrecomputed; + + Private() { + verseMax.clear(); + } + Private(const VerseMgr::Book::Private &other) { + verseMax.clear(); + verseMax = other.verseMax; + offsetPrecomputed = other.offsetPrecomputed; + } + VerseMgr::Book::Private &operator =(const VerseMgr::Book::Private &other) { + verseMax.clear(); + verseMax = other.verseMax; + offsetPrecomputed = other.offsetPrecomputed; + return *this; + } +}; + +struct BookOffsetLess { + bool operator() (const VerseMgr::Book &o1, const VerseMgr::Book &o2) const { return o1.p->offsetPrecomputed[0] < o2.p->offsetPrecomputed[0]; } + bool operator() (const long &o1, const VerseMgr::Book &o2) const { return o1 < o2.p->offsetPrecomputed[0]; } + bool operator() (const VerseMgr::Book &o1, const long &o2) const { return o1.p->offsetPrecomputed[0] < o2; } + bool operator() (const long &o1, const long &o2) const { return o1 < o2; } +}; + +void VerseMgr::Book::init() { + p = new Private(); +} + +void VerseMgr::System::init() { + p = new Private(); + BMAX[0] = 0; + BMAX[1] = 0; + ntStartOffset = 0; +} + + +VerseMgr::System::System(const System &other) { + init(); + name = other.name; + BMAX[0] = other.BMAX[0]; + BMAX[1] = other.BMAX[1]; + (*p) = *(other.p); + ntStartOffset = other.ntStartOffset; +} + +VerseMgr::System &VerseMgr::System::operator =(const System &other) { + name = other.name; + BMAX[0] = other.BMAX[0]; + BMAX[1] = other.BMAX[1]; + (*p) = *(other.p); + ntStartOffset = other.ntStartOffset; + return *this; +} + + +VerseMgr::System::~System() { + delete p; +} + +const VerseMgr::Book *VerseMgr::System::getBook(int number) const { + return (number < (signed int)p->books.size()) ? &(p->books[number]) : 0; +} + + +int VerseMgr::System::getBookNumberByOSISName(const char *bookName) const { + map<SWBuf, int>::const_iterator it = p->osisLookup.find(bookName); + return (it != p->osisLookup.end()) ? it->second : -1; +} + + +void VerseMgr::System::loadFromSBook(const sbook *ot, const sbook *nt, int *chMax) { + int chap = 0; + int book = 0; + long offset = 0; // module heading + offset++; // testament heading + while (ot->chapmax) { + p->books.push_back(Book(ot->name, ot->osis, ot->prefAbbrev, ot->chapmax)); + offset++; // book heading + Book &b = p->books[p->books.size()-1]; + p->osisLookup[b.getOSISName()] = p->books.size(); + for (int i = 0; i < ot->chapmax; i++) { + b.p->verseMax.push_back(chMax[chap]); + offset++; // chapter heading + b.p->offsetPrecomputed.push_back(offset); + offset += chMax[chap++]; + } + ot++; + book++; + } + BMAX[0] = book; + book = 0; + ntStartOffset = offset; + offset++; // testament heading + while (nt->chapmax) { + p->books.push_back(Book(nt->name, nt->osis, nt->prefAbbrev, nt->chapmax)); + offset++; // book heading + Book &b = p->books[p->books.size()-1]; + p->osisLookup[b.getOSISName()] = p->books.size(); + for (int i = 0; i < nt->chapmax; i++) { + b.p->verseMax.push_back(chMax[chap]); + offset++; // chapter heading + b.p->offsetPrecomputed.push_back(offset); + offset += chMax[chap++]; + } + nt++; + book++; + } + BMAX[1] = book; + + // TODO: build offset speed array +} + + +VerseMgr::Book::Book(const Book &other) { + longName = other.longName; + osisName = other.osisName; + prefAbbrev = other.prefAbbrev; + chapMax = other.chapMax; + init(); + (*p) = *(other.p); +} + +VerseMgr::Book& VerseMgr::Book::operator =(const Book &other) { + longName = other.longName; + osisName = other.osisName; + prefAbbrev = other.prefAbbrev; + chapMax = other.chapMax; + init(); + (*p) = *(other.p); + return *this; +} + + +VerseMgr::Book::~Book() { + delete p; +} + + +int VerseMgr::Book::getVerseMax(int chapter) const { + chapter--; + return (p && (chapter < (signed int)p->verseMax.size()) && (chapter > -1)) ? p->verseMax[chapter] : -1; +} + + +int VerseMgr::System::getBookCount() const { + return (p ? p->books.size() : 0); +} + + +long VerseMgr::System::getOffsetFromVerse(int book, int chapter, int verse) const { + long offset = -1; + chapter--; + + const Book *b = getBook(book); + + if (!b) return -1; // assert we have a valid book + if ((chapter > -1) && (chapter >= (signed int)b->p->offsetPrecomputed.size())) return -1; // assert we have a valid chapter + + offset = b->p->offsetPrecomputed[(chapter > -1)?chapter:0]; + if (chapter < 0) offset--; + +/* old code + * + offset = offsets[testament-1][0][book]; + offset = offsets[testament-1][1][(int)offset + chapter]; + if (!(offset|verse)) // if we have a testament but nothing else. + offset = 1; + +*/ + + return (offset + verse); +} + + +char VerseMgr::System::getVerseFromOffset(long offset, int *book, int *chapter, int *verse) const { + + if (offset < 1) { // just handle the module heading corner case up front (and error case) + (*book) = -1; + (*chapter) = 0; + (*verse) = 0; + return offset; // < 0 = error + } + + // binary search for book + vector<Book>::iterator b = lower_bound(p->books.begin(), p->books.end(), offset, BookOffsetLess()); + if (b == p->books.end()) b--; + (*book) = distance(p->books.begin(), b)+1; + if (offset < (*(b->p->offsetPrecomputed.begin()))-((((!(*book)) || (*book)==BMAX[0]+1))?2:1)) { // -1 for chapter headings + (*book)--; + if (b != p->books.begin()) { + b--; + } + } + vector<long>::iterator c = lower_bound(b->p->offsetPrecomputed.begin(), b->p->offsetPrecomputed.end(), offset); + + // if we're a book heading, we are lessthan chapter precomputes, but greater book. This catches corner case. + if (c == b->p->offsetPrecomputed.end()) { + c--; + } + if ((offset < *c) && (c == b->p->offsetPrecomputed.begin())) { + (*chapter) = (offset - *c)+1; // should be 0 or -1 (for testament heading) + (*verse) = 0; + } + else { + if (offset < *c) c--; + (*chapter) = distance(b->p->offsetPrecomputed.begin(), c)+1; + (*verse) = (offset - *c); + } + return ((*chapter > 0) && (*verse > b->getVerseMax(*chapter))) ? KEYERR_OUTOFBOUNDS : 0; +} + + +/*************************************************** + * VerseMgr + */ + +class VerseMgr::Private { +public: + Private() { + } + Private(const VerseMgr::Private &other) { + systems = other.systems; + } + VerseMgr::Private &operator =(const VerseMgr::Private &other) { + systems = other.systems; + return *this; + } + map<SWBuf, System> systems; +}; +// ---------------- statics ----------------- +VerseMgr *VerseMgr::systemVerseMgr = 0; + +class __staticsystemVerseMgr { +public: + __staticsystemVerseMgr() { } + ~__staticsystemVerseMgr() { delete VerseMgr::systemVerseMgr; } +} _staticsystemVerseMgr; + + +void VerseMgr::init() { + p = new Private(); +} + + +VerseMgr::~VerseMgr() { + delete p; +} + + +void VerseMgr::setSystemVerseMgr(VerseMgr *newVerseMgr) { + if (systemVerseMgr) + delete systemVerseMgr; + systemVerseMgr = newVerseMgr; +} + + +const VerseMgr::System *VerseMgr::getVersificationSystem(const char *name) const { + map<SWBuf, System>::const_iterator it = p->systems.find(name); + return (it != p->systems.end()) ? &(it->second) : 0; +} + + +void VerseMgr::registerVersificationSystem(const char *name, const sbook *ot, const sbook *nt, int *chMax) { + p->systems[name] = name; + System &s = p->systems[name]; + s.loadFromSBook(ot, nt, chMax); +} + + +void VerseMgr::registerVersificationSystem(const char *name, const TreeKey *tk) { +} + + +const StringList VerseMgr::getVersificationSystems() const { + StringList retVal; + for (map<SWBuf, System>::const_iterator it = p->systems.begin(); it != p->systems.end(); it++) { + retVal.push_back(it->first); + } + return retVal; +} + + +SWORD_NAMESPACE_END diff --git a/src/modules/comments/hrefcom/hrefcom.cpp b/src/modules/comments/hrefcom/hrefcom.cpp index 7791da2..7035b08 100644 --- a/src/modules/comments/hrefcom/hrefcom.cpp +++ b/src/modules/comments/hrefcom/hrefcom.cpp @@ -2,6 +2,22 @@ * hrefcom.cpp - code for class 'HREFCom'- a module that produces HTML HREFs * pointing to actual text desired. Uses standard * files: ot and nt using indexs ??.bks ??.cps ??.vss + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ @@ -56,14 +72,9 @@ SWBuf &HREFCom::getRawEntryBuf() { unsigned short size; VerseKey *key = 0; - SWTRY { - key = SWDYNAMIC_CAST(VerseKey, this->key); - } - SWCATCH ( ... ) {} - if (!key) - key = new VerseKey(this->key); + key = &getVerseKey(); - findOffset(key->Testament(), key->Index(), &start, &size); + findOffset(key->Testament(), key->TestamentIndex(), &start, &size); entrySize = size; // support getEntrySize call SWBuf tmpbuf; diff --git a/src/modules/comments/rawcom/rawcom.cpp b/src/modules/comments/rawcom/rawcom.cpp index fd01c24..c0404ae 100644 --- a/src/modules/comments/rawcom/rawcom.cpp +++ b/src/modules/comments/rawcom/rawcom.cpp @@ -1,6 +1,22 @@ /****************************************************************************** * rawcom.cpp - code for class 'RawCom'- a module that reads raw commentary * files: ot and nt using indexs ??.bks ??.cps ??.vss + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ @@ -23,9 +39,9 @@ SWORD_NAMESPACE_START * idisp - Display object to use for displaying */ -RawCom::RawCom(const char *ipath, const char *iname, const char *idesc, SWDisplay *idisp, SWTextEncoding encoding, SWTextDirection dir, SWTextMarkup markup, const char* ilang) +RawCom::RawCom(const char *ipath, const char *iname, const char *idesc, SWDisplay *idisp, SWTextEncoding encoding, SWTextDirection dir, SWTextMarkup markup, const char *ilang, const char *versification) : RawVerse(ipath), - SWCom(iname, idesc, idisp, encoding, dir, markup, ilang){ + SWCom(iname, idesc, idisp, encoding, dir, markup, ilang, versification) { } @@ -53,7 +69,7 @@ SWBuf &RawCom::getRawEntryBuf() { unsigned short size = 0; VerseKey *key = &getVerseKey(); - findOffset(key->Testament(), key->Index(), &start, &size); + findOffset(key->Testament(), key->TestamentIndex(), &start, &size); entrySize = size; // support getEntrySize call entryBuf = ""; @@ -82,21 +98,21 @@ void RawCom::increment(int steps) { unsigned short size; VerseKey *tmpkey = &getVerseKey(); - findOffset(tmpkey->Testament(), tmpkey->Index(), &start, &size); + findOffset(tmpkey->Testament(), tmpkey->TestamentIndex(), &start, &size); SWKey lastgood = *tmpkey; while (steps) { long laststart = start; unsigned short lastsize = size; SWKey lasttry = *tmpkey; - (steps > 0) ? (*key)++ : (*key)--; + (steps > 0) ? ++(*key) : --(*key); tmpkey = &getVerseKey(); if ((error = key->Error())) { *key = lastgood; break; } - long index = tmpkey->Index(); + long index = tmpkey->TestamentIndex(); findOffset(tmpkey->Testament(), index, &start, &size); if ( (((laststart != start) || (lastsize != size)) // we're a different entry @@ -113,24 +129,15 @@ void RawCom::increment(int steps) { void RawCom::setEntry(const char *inbuf, long len) { VerseKey *key = &getVerseKey(); - doSetText(key->Testament(), key->Index(), inbuf, len); + doSetText(key->Testament(), key->TestamentIndex(), inbuf, len); } void RawCom::linkEntry(const SWKey *inkey) { VerseKey *destkey = &getVerseKey(); - const VerseKey *srckey = 0; - - // see if we have a VerseKey * or decendant - SWTRY { - srckey = SWDYNAMIC_CAST(VerseKey, inkey); - } - SWCATCH ( ... ) {} - // if we don't have a VerseKey * decendant, create our own - if (!srckey) - srckey = new VerseKey(inkey); + const VerseKey *srckey = &getVerseKey(inkey); - doLinkEntry(destkey->Testament(), destkey->Index(), srckey->Index()); + doLinkEntry(destkey->Testament(), destkey->TestamentIndex(), srckey->TestamentIndex()); if (inkey != srckey) // free our key if we created a VerseKey delete srckey; @@ -146,8 +153,29 @@ void RawCom::linkEntry(const SWKey *inkey) { void RawCom::deleteEntry() { VerseKey *key = &getVerseKey(); - doSetText(key->Testament(), key->Index(), ""); + doSetText(key->Testament(), key->TestamentIndex(), ""); +} + +bool RawCom::isLinked(const SWKey *k1, const SWKey *k2) const { + long start1, start2; + unsigned short size1, size2; + VerseKey *vk1 = &getVerseKey(k1); + VerseKey *vk2 = &getVerseKey(k2); + if (vk1->Testament() != vk2->Testament()) return false; + + findOffset(vk1->Testament(), vk1->TestamentIndex(), &start1, &size1); + findOffset(vk2->Testament(), vk2->TestamentIndex(), &start2, &size2); + if (!size1 || !size2) return false; + return start1 == start2; } +bool RawCom::hasEntry(const SWKey *k) const { + long start; + unsigned short size; + VerseKey *vk = &getVerseKey(k); + + findOffset(vk->Testament(), vk->TestamentIndex(), &start, &size); + return size; +} SWORD_NAMESPACE_END diff --git a/src/modules/comments/rawcom4/rawcom4.cpp b/src/modules/comments/rawcom4/rawcom4.cpp index e59ee39..c0c4a1d 100644 --- a/src/modules/comments/rawcom4/rawcom4.cpp +++ b/src/modules/comments/rawcom4/rawcom4.cpp @@ -1,9 +1,24 @@ /****************************************************************************** * rawcom4.cpp - code for class 'RawCom4'- a module that reads raw commentary * files: ot and nt using indexs ??.bks ??.cps ??.vss + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <ctype.h> #include <stdio.h> #include <fcntl.h> @@ -23,9 +38,9 @@ SWORD_NAMESPACE_START * idisp - Display object to use for displaying */ -RawCom4::RawCom4(const char *ipath, const char *iname, const char *idesc, SWDisplay *idisp, SWTextEncoding encoding, SWTextDirection dir, SWTextMarkup markup, const char* ilang) +RawCom4::RawCom4(const char *ipath, const char *iname, const char *idesc, SWDisplay *idisp, SWTextEncoding encoding, SWTextDirection dir, SWTextMarkup markup, const char *ilang, const char *versification) : RawVerse4(ipath), - SWCom(iname, idesc, idisp, encoding, dir, markup, ilang){ + SWCom(iname, idesc, idisp, encoding, dir, markup, ilang, versification) { } @@ -53,7 +68,7 @@ SWBuf &RawCom4::getRawEntryBuf() { unsigned long size = 0; VerseKey *key = &getVerseKey(); - findOffset(key->Testament(), key->Index(), &start, &size); + findOffset(key->Testament(), key->TestamentIndex(), &start, &size); entrySize = size; // support getEntrySize call entryBuf = ""; @@ -82,21 +97,21 @@ void RawCom4::increment(int steps) { unsigned long size; VerseKey *tmpkey = &getVerseKey(); - findOffset(tmpkey->Testament(), tmpkey->Index(), &start, &size); + findOffset(tmpkey->Testament(), tmpkey->TestamentIndex(), &start, &size); SWKey lastgood = *tmpkey; while (steps) { long laststart = start; unsigned long lastsize = size; SWKey lasttry = *tmpkey; - (steps > 0) ? (*key)++ : (*key)--; + (steps > 0) ? ++(*key) : --(*key); tmpkey = &getVerseKey(); if ((error = key->Error())) { *key = lastgood; break; } - long index = tmpkey->Index(); + long index = tmpkey->TestamentIndex(); findOffset(tmpkey->Testament(), index, &start, &size); if ( (((laststart != start) || (lastsize != size)) // we're a different entry @@ -113,27 +128,14 @@ void RawCom4::increment(int steps) { void RawCom4::setEntry(const char *inbuf, long len) { VerseKey *key = &getVerseKey(); - doSetText(key->Testament(), key->Index(), inbuf, len); + doSetText(key->Testament(), key->TestamentIndex(), inbuf, len); } void RawCom4::linkEntry(const SWKey *inkey) { VerseKey *destkey = &getVerseKey(); - const VerseKey *srckey = 0; - - // see if we have a VerseKey * or decendant - SWTRY { - srckey = SWDYNAMIC_CAST(VerseKey, inkey); - } - SWCATCH ( ... ) {} - // if we don't have a VerseKey * decendant, create our own - if (!srckey) - srckey = new VerseKey(inkey); - - doLinkEntry(destkey->Testament(), destkey->Index(), srckey->Index()); - - if (inkey != srckey) // free our key if we created a VerseKey - delete srckey; + const VerseKey *srckey = &getVerseKey(inkey); + doLinkEntry(destkey->Testament(), destkey->TestamentIndex(), srckey->TestamentIndex()); } @@ -146,8 +148,29 @@ void RawCom4::linkEntry(const SWKey *inkey) { void RawCom4::deleteEntry() { VerseKey *key = &getVerseKey(); - doSetText(key->Testament(), key->Index(), ""); + doSetText(key->Testament(), key->TestamentIndex(), ""); +} + +bool RawCom4::isLinked(const SWKey *k1, const SWKey *k2) const { + long start1, start2; + unsigned long size1, size2; + VerseKey *vk1 = &getVerseKey(k1); + VerseKey *vk2 = &getVerseKey(k2); + if (vk1->Testament() != vk2->Testament()) return false; + + findOffset(vk1->Testament(), vk1->TestamentIndex(), &start1, &size1); + findOffset(vk2->Testament(), vk2->TestamentIndex(), &start2, &size2); + if (!size1 || !size2) return false; + return start1 == start2; } +bool RawCom4::hasEntry(const SWKey *k) const { + long start; + unsigned long size; + VerseKey *vk = &getVerseKey(k); + + findOffset(vk->Testament(), vk->TestamentIndex(), &start, &size); + return size; +} SWORD_NAMESPACE_END diff --git a/src/modules/comments/rawfiles/rawfiles.cpp b/src/modules/comments/rawfiles/rawfiles.cpp index 3b614d9..b0e24fc 100644 --- a/src/modules/comments/rawfiles/rawfiles.cpp +++ b/src/modules/comments/rawfiles/rawfiles.cpp @@ -2,9 +2,24 @@ * rawfiles.cpp - code for class 'RawFiles'- a module that produces HTML HREFs * pointing to actual text desired. Uses standard * files: ot and nt using indexs ??.bks ??.cps ??.vss + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <ctype.h> #include <stdio.h> #include <fcntl.h> @@ -13,6 +28,7 @@ #include <rawfiles.h> #include <filemgr.h> #include <versekey.h> +#include <sysdata.h> SWORD_NAMESPACE_START @@ -57,16 +73,9 @@ SWBuf &RawFiles::getRawEntryBuf() { FileDesc *datafile; long start = 0; unsigned short size = 0; - VerseKey *key = 0; - - SWTRY { - key = SWDYNAMIC_CAST(VerseKey, this->key); - } - SWCATCH ( ... ) {} - if (!key) - key = new VerseKey(this->key); + VerseKey *key = &getVerseKey(); - findOffset(key->Testament(), key->Index(), &start, &size); + findOffset(key->Testament(), key->TestamentIndex(), &start, &size); entryBuf = ""; if (size) { @@ -88,10 +97,6 @@ SWBuf &RawFiles::getRawEntryBuf() { } FileMgr::getSystemFileMgr()->close(datafile); } - - if (key != this->key) - delete key; - return entryBuf; } @@ -105,17 +110,11 @@ void RawFiles::setEntry(const char *inbuf, long len) { FileDesc *datafile; long start; unsigned short size; - VerseKey *key = 0; + VerseKey *key = &getVerseKey(); len = (len<0)?strlen(inbuf):len; - SWTRY { - key = SWDYNAMIC_CAST(VerseKey, this->key); - } - SWCATCH ( ... ) {} - if (!key) - key = new VerseKey(this->key); - findOffset(key->Testament(), key->Index(), &start, &size); + findOffset(key->Testament(), key->TestamentIndex(), &start, &size); if (size) { SWBuf tmpbuf; @@ -129,7 +128,7 @@ void RawFiles::setEntry(const char *inbuf, long len) { entryBuf = path; entryBuf += '/'; tmpbuf = getNextFilename(); - doSetText(key->Testament(), key->Index(), tmpbuf); + doSetText(key->Testament(), key->TestamentIndex(), tmpbuf); entryBuf += tmpbuf; } datafile = FileMgr::getSystemFileMgr()->open(entryBuf, FileMgr::CREAT|FileMgr::WRONLY|FileMgr::TRUNC); @@ -137,9 +136,6 @@ void RawFiles::setEntry(const char *inbuf, long len) { datafile->write(inbuf, len); } FileMgr::getSystemFileMgr()->close(datafile); - - if (key != this->key) - delete key; } @@ -154,36 +150,17 @@ void RawFiles::linkEntry(const SWKey *inkey) { long start; unsigned short size; - const VerseKey *key = 0; - - SWTRY { - key = SWDYNAMIC_CAST(VerseKey, inkey); - } - SWCATCH ( ... ) {} - if (!key) - key = new VerseKey(this->key); + const VerseKey *key = &getVerseKey(); - findOffset(key->Testament(), key->Index(), &start, &size); + findOffset(key->Testament(), key->TestamentIndex(), &start, &size); if (size) { SWBuf tmpbuf; readText(key->Testament(), start, size + 2, tmpbuf); - if (key != inkey) - delete key; - key = 0; - - SWTRY { - key = SWDYNAMIC_CAST(VerseKey, inkey); - } - SWCATCH ( ... ) {} - if (!key) - key = new VerseKey(this->key); - doSetText(key->Testament(), key->Index(), tmpbuf.c_str()); + key = &getVerseKey(inkey); + doSetText(key->Testament(), key->TestamentIndex(), tmpbuf.c_str()); } - - if (key != inkey) - delete key; } @@ -194,20 +171,8 @@ void RawFiles::linkEntry(const SWKey *inkey) { */ void RawFiles::deleteEntry() { - - VerseKey *key = 0; - - SWTRY { - key = SWDYNAMIC_CAST(VerseKey, this->key); - } - SWCATCH ( ... ) {} - if (!key) - key = new VerseKey(this->key); - - doSetText(key->Testament(), key->Index(), ""); - - if (key != this->key) - delete key; + VerseKey *key = &getVerseKey(); + doSetText(key->Testament(), key->TestamentIndex(), ""); } @@ -220,32 +185,40 @@ void RawFiles::deleteEntry() { char *RawFiles::getNextFilename() { static char incfile[255]; - long number; + __u32 number; FileDesc *datafile; sprintf(incfile, "%s/incfile", path); datafile = FileMgr::getSystemFileMgr()->open(incfile, FileMgr::RDONLY); - if (datafile->read(&number, 4) != 4) - number = 0; + + if (datafile->read(&number, 4) != 4) number = 0; + number = swordtoarch32(number); + number++; FileMgr::getSystemFileMgr()->close(datafile); datafile = FileMgr::getSystemFileMgr()->open(incfile, FileMgr::CREAT|FileMgr::WRONLY|FileMgr::TRUNC); + sprintf(incfile, "%.7d", number-1); + + number = archtosword32(number); datafile->write(&number, 4); + FileMgr::getSystemFileMgr()->close(datafile); - sprintf(incfile, "%.7ld", number-1); return incfile; } char RawFiles::createModule (const char *path) { char *incfile = new char [ strlen (path) + 16 ]; - static long zero = 0; + + __u32 zero = 0; + zero = archtosword32(zero); + FileDesc *datafile; sprintf(incfile, "%s/incfile", path); datafile = FileMgr::getSystemFileMgr()->open(incfile, FileMgr::CREAT|FileMgr::WRONLY|FileMgr::TRUNC); - delete [] incfile; + delete [] incfile; datafile->write(&zero, 4); FileMgr::getSystemFileMgr()->close(datafile); diff --git a/src/modules/comments/swcom.cpp b/src/modules/comments/swcom.cpp index 94f92c9..e82751b 100644 --- a/src/modules/comments/swcom.cpp +++ b/src/modules/comments/swcom.cpp @@ -1,14 +1,34 @@ /****************************************************************************** * swcom.cpp - code for base class 'SWCom'- The basis for all commentary * modules + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + +#include <utilstr.h> #include <swcom.h> #include <localemgr.h> #include <versekey.h> + SWORD_NAMESPACE_START + /****************************************************************************** * SWCom Constructor - Initializes data for instance of SWCom * @@ -17,10 +37,14 @@ SWORD_NAMESPACE_START * idisp - Display object to use for displaying */ -SWCom::SWCom(const char *imodname, const char *imoddesc, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang): SWModule(imodname, imoddesc, idisp, (char *)"Commentaries", enc, dir, mark, ilang) { +SWCom::SWCom(const char *imodname, const char *imoddesc, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char *ilang, const char *versification): SWModule(imodname, imoddesc, idisp, "Commentaries", enc, dir, mark, ilang) { + this->versification = 0; + stdstr(&(this->versification), versification); delete key; - key = CreateKey(); - tmpVK = new VerseKey(); + key = (VerseKey *)CreateKey(); + tmpVK1 = (VerseKey *)CreateKey(); + tmpVK2 = (VerseKey *)CreateKey(); + tmpSecond = false; } @@ -29,62 +53,53 @@ SWCom::SWCom(const char *imodname, const char *imoddesc, SWDisplay *idisp, SWTex */ SWCom::~SWCom() { - delete tmpVK; + delete tmpVK1; + delete tmpVK2; + delete [] versification; } -SWKey *SWCom::CreateKey() { return new VerseKey(); } - +SWKey *SWCom::CreateKey() const { + VerseKey *vk = new VerseKey(); -long SWCom::Index() const { - VerseKey *key = 0; - SWTRY { - key = SWDYNAMIC_CAST(VerseKey, this->key); - } - SWCATCH ( ... ) {} - if (!key) - key = new VerseKey(this->key); + vk->setVersificationSystem(versification); - entryIndex = key->NewIndex(); + return vk; +} - if (key != this->key) - delete key; +long SWCom::Index() const { + VerseKey *key = &getVerseKey(); + entryIndex = key->Index(); return entryIndex; } long SWCom::Index(long iindex) { - VerseKey *key = 0; - SWTRY { - key = SWDYNAMIC_CAST(VerseKey, this->key); - } - SWCATCH ( ... ) {} - if (!key) - key = new VerseKey(this->key); - + VerseKey *key = &getVerseKey(); key->Testament(1); key->Index(iindex); if (key != this->key) { this->key->copyFrom(*key); - delete key; } return Index(); } -VerseKey &SWCom::getVerseKey() const { - VerseKey *key = NULL; +VerseKey &SWCom::getVerseKey(const SWKey *keyToConvert) const { + const SWKey *thisKey = keyToConvert ? keyToConvert : this->key; + + VerseKey *key = 0; // see if we have a VerseKey * or decendant SWTRY { - key = SWDYNAMIC_CAST(VerseKey, this->key); + key = SWDYNAMIC_CAST(VerseKey, thisKey); } SWCATCH ( ... ) { } if (!key) { ListKey *lkTest = 0; SWTRY { - lkTest = SWDYNAMIC_CAST(ListKey, this->key); + lkTest = SWDYNAMIC_CAST(ListKey, thisKey); } SWCATCH ( ... ) { } if (lkTest) { @@ -95,11 +110,14 @@ VerseKey &SWCom::getVerseKey() const { } } if (!key) { - tmpVK->setLocale(LocaleMgr::getSystemLocaleMgr()->getDefaultLocaleName()); - (*tmpVK) = *(this->key); - return (*tmpVK); + VerseKey *retKey = (tmpSecond) ? tmpVK1 : tmpVK2; + tmpSecond = !tmpSecond; + retKey->setLocale(LocaleMgr::getSystemLocaleMgr()->getDefaultLocaleName()); + (*retKey) = *(thisKey); + return (*retKey); } else return *key; } + SWORD_NAMESPACE_END diff --git a/src/modules/comments/zcom/zcom.cpp b/src/modules/comments/zcom/zcom.cpp index cdaea02..35b8946 100644 --- a/src/modules/comments/zcom/zcom.cpp +++ b/src/modules/comments/zcom/zcom.cpp @@ -1,9 +1,24 @@ /****************************************************************************** * rawcom.cpp - code for class 'zCom'- a module that reads raw commentary * files: ot and nt using indexs ??.bks ??.cps ??.vss + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <ctype.h> #include <stdio.h> #include <fcntl.h> @@ -26,7 +41,7 @@ SWORD_NAMESPACE_START * idisp - Display object to use for displaying */ -zCom::zCom(const char *ipath, const char *iname, const char *idesc, int iblockType, SWCompress *icomp, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang) : zVerse(ipath, -1, iblockType, icomp), SWCom(iname, idesc, idisp, enc, dir, mark, ilang)/*, SWCompress()*/ +zCom::zCom(const char *ipath, const char *iname, const char *idesc, int iblockType, SWCompress *icomp, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char *ilang, const char *versification) : zVerse(ipath, -1, iblockType, icomp), SWCom(iname, idesc, idisp, enc, dir, mark, ilang, versification)/*, SWCompress()*/ { blockType = iblockType; lastWriteKey = 0; @@ -58,13 +73,14 @@ bool zCom::isWritable() { SWBuf &zCom::getRawEntryBuf() { long start = 0; unsigned short size = 0; + unsigned long buffnum; VerseKey *key = &getVerseKey(); - findOffset(key->Testament(), key->Index(), &start, &size); + findOffset(key->Testament(), key->TestamentIndex(), &start, &size, &buffnum); entrySize = size; // support getEntrySize call entryBuf = ""; - zReadText(key->Testament(), start, size, entryBuf); + zReadText(key->Testament(), start, size, buffnum, entryBuf); rawFilter(entryBuf, key); @@ -104,7 +120,7 @@ void zCom::setEntry(const char *inbuf, long len) { delete lastWriteKey; } - doSetText(key->Testament(), key->Index(), inbuf, len); + doSetText(key->Testament(), key->TestamentIndex(), inbuf, len); lastWriteKey = (VerseKey *)key->clone(); // must delete } @@ -112,19 +128,9 @@ void zCom::setEntry(const char *inbuf, long len) { void zCom::linkEntry(const SWKey *inkey) { VerseKey *destkey = &getVerseKey(); - const VerseKey *srckey = 0; - - // see if we have a VerseKey * or decendant - SWTRY { - srckey = (const VerseKey *) SWDYNAMIC_CAST(VerseKey, inkey); - } - SWCATCH ( ... ) { - } - // if we don't have a VerseKey * decendant, create our own - if (!srckey) - srckey = new VerseKey(inkey); + const VerseKey *srckey = &getVerseKey(inkey); - doLinkEntry(destkey->Testament(), destkey->Index(), srckey->Index()); + doLinkEntry(destkey->Testament(), destkey->TestamentIndex(), srckey->TestamentIndex()); if (inkey != srckey) // free our key if we created a VerseKey delete srckey; @@ -139,7 +145,7 @@ void zCom::linkEntry(const SWKey *inkey) { void zCom::deleteEntry() { VerseKey *key = &getVerseKey(); - doSetText(key->Testament(), key->Index(), ""); + doSetText(key->Testament(), key->TestamentIndex(), ""); } @@ -154,24 +160,25 @@ void zCom::deleteEntry() { void zCom::increment(int steps) { long start; unsigned short size; + unsigned long buffnum; VerseKey *tmpkey = &getVerseKey(); - findOffset(tmpkey->Testament(), tmpkey->Index(), &start, &size); + findOffset(tmpkey->Testament(), tmpkey->TestamentIndex(), &start, &size, &buffnum); SWKey lastgood = *tmpkey; while (steps) { long laststart = start; unsigned short lastsize = size; SWKey lasttry = *tmpkey; - (steps > 0) ? (*key)++ : (*key)--; + (steps > 0) ? ++(*key) : --(*key); tmpkey = &getVerseKey(); if ((error = key->Error())) { *key = lastgood; break; } - long index = tmpkey->Index(); - findOffset(tmpkey->Testament(), index, &start, &size); + long index = tmpkey->TestamentIndex(); + findOffset(tmpkey->Testament(), index, &start, &size, &buffnum); if ( (((laststart != start) || (lastsize != size)) // we're a different entry // && (start > 0) @@ -184,5 +191,27 @@ void zCom::increment(int steps) { error = (error) ? KEYERR_OUTOFBOUNDS : 0; } +bool zCom::isLinked(const SWKey *k1, const SWKey *k2) const { + long start1, start2; + unsigned short size1, size2; + unsigned long buffnum1, buffnum2; + VerseKey *vk1 = &getVerseKey(k1); + VerseKey *vk2 = &getVerseKey(k2); + if (vk1->Testament() != vk2->Testament()) return false; + + findOffset(vk1->Testament(), vk1->TestamentIndex(), &start1, &size1, &buffnum1); + findOffset(vk2->Testament(), vk2->TestamentIndex(), &start2, &size2, &buffnum2); + return start1 == start2 && buffnum1 == buffnum2; +} + +bool zCom::hasEntry(const SWKey *k) const { + long start; + unsigned short size; + unsigned long buffnum; + VerseKey *vk = &getVerseKey(k); + + findOffset(vk->Testament(), vk->TestamentIndex(), &start, &size, &buffnum); + return size; +} SWORD_NAMESPACE_END diff --git a/src/modules/common/entriesblk.cpp b/src/modules/common/entriesblk.cpp index 216abd8..6e4c9aa 100644 --- a/src/modules/common/entriesblk.cpp +++ b/src/modules/common/entriesblk.cpp @@ -1,3 +1,20 @@ +/* + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + #include <entriesblk.h> #include <stdlib.h> #include <string.h> diff --git a/src/modules/common/lzsscomprs.cpp b/src/modules/common/lzsscomprs.cpp index bd8f768..00177db 100644 --- a/src/modules/common/lzsscomprs.cpp +++ b/src/modules/common/lzsscomprs.cpp @@ -1,6 +1,22 @@ /****************************************************************************** * lzsscomprs.cpp - code for class 'LZSSCompress'- a driver class that * provides LZSS compression + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ #include <stdlib.h> diff --git a/src/modules/common/rawstr.cpp b/src/modules/common/rawstr.cpp index d2da1e9..6f17628 100644 --- a/src/modules/common/rawstr.cpp +++ b/src/modules/common/rawstr.cpp @@ -1,11 +1,26 @@ /****************************************************************************** * rawstr.cpp - code for class 'RawStr'- a module that reads raw text - * files: ot and nt using indexs ??.bks ??.cps ??.vss - * and provides lookup and parsing functions based on - * class StrKey + * files: ot and nt using indexs ??.bks ??.cps ??.vss + * and provides lookup and parsing functions based on + * class StrKey + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdio.h> #include <fcntl.h> #include <errno.h> @@ -27,6 +42,8 @@ SWORD_NAMESPACE_START int RawStr::instance = 0; char RawStr::nl = '\n'; +const int RawStr::IDXENTRYSIZE = 6; + /****************************************************************************** @@ -88,7 +105,7 @@ RawStr::~RawStr() * buf - address of pointer to allocate for storage of string */ -void RawStr::getIDXBufDat(long ioffset, char **buf) +void RawStr::getIDXBufDat(long ioffset, char **buf) const { int size; char ch; @@ -122,9 +139,9 @@ void RawStr::getIDXBufDat(long ioffset, char **buf) * buf - address of pointer to allocate for storage of string */ -void RawStr::getIDXBuf(long ioffset, char **buf) +void RawStr::getIDXBuf(long ioffset, char **buf) const { - long offset; + __u32 offset; if (idxfd > 0) { idxfd->seek(ioffset, SEEK_SET); @@ -149,17 +166,18 @@ void RawStr::getIDXBuf(long ioffset, char **buf) * RET: error status -1 general error; -2 new file */ -signed char RawStr::findOffset(const char *ikey, long *start, unsigned short *size, long away, long *idxoff) +signed char RawStr::findOffset(const char *ikey, __u32 *start, __u16 *size, long away, __u32 *idxoff) const { char *trybuf, *maxbuf, *key = 0, quitflag = 0; signed char retval = -1; long headoff, tailoff, tryoff = 0, maxoff = 0; int diff = 0; + bool awayFromSubstrCheck = false; if (idxfd->getFd() >=0) { tailoff = maxoff = idxfd->seek(0, SEEK_END) - 6; retval = (tailoff >= 0) ? 0 : -2; // if NOT new file - if (*ikey) { + if (*ikey && retval != -2) { headoff = 0; stdstr(&key, ikey, 3); @@ -203,6 +221,7 @@ signed char RawStr::findOffset(const char *ikey, long *start, unsigned short *si if (headoff >= tailoff) { tryoff = headoff; if (!substr && ((tryoff != maxoff)||(strncmp(key, maxbuf, keylen)<0))) { + awayFromSubstrCheck = true; away--; // if our entry doesn't startwith our key, prefer the previous entry over the next } } @@ -216,17 +235,19 @@ signed char RawStr::findOffset(const char *ikey, long *start, unsigned short *si idxfd->seek(tryoff, SEEK_SET); - *start = *size = 0; - idxfd->read(start, 4); - idxfd->read(size, 2); + __u32 tmpStart; + __u16 tmpSize; + *start = *size = tmpStart = tmpSize = 0; + idxfd->read(&tmpStart, 4); + idxfd->read(&tmpSize, 2); if (idxoff) *idxoff = tryoff; - *start = swordtoarch32(*start); - *size = swordtoarch16(*size); + *start = swordtoarch32(tmpStart); + *size = swordtoarch16(tmpSize); while (away) { - long laststart = *start; + unsigned long laststart = *start; unsigned short lastsize = *size; long lasttry = tryoff; tryoff += (away > 0) ? 6 : -6; @@ -237,7 +258,8 @@ signed char RawStr::findOffset(const char *ikey, long *start, unsigned short *si else if (idxfd->seek(tryoff, SEEK_SET) < 0) bad = true; if (bad) { - retval = -1; + if(!awayFromSubstrCheck) + retval = -1; *start = laststart; *size = lastsize; tryoff = lasttry; @@ -245,15 +267,15 @@ signed char RawStr::findOffset(const char *ikey, long *start, unsigned short *si *idxoff = tryoff; break; } - idxfd->read(start, 4); - idxfd->read(size, 2); + idxfd->read(&tmpStart, 4); + idxfd->read(&tmpSize, 2); if (idxoff) *idxoff = tryoff; - *start = swordtoarch32(*start); - *size = swordtoarch16(*size); + *start = swordtoarch32(tmpStart); + *size = swordtoarch16(tmpSize); - if (((laststart != *start) || (lastsize != *size)) && (*start >= 0) && (*size)) + if (((laststart != *start) || (lastsize != *size)) && (*size)) away += (away < 0) ? 1 : -1; } @@ -271,65 +293,6 @@ signed char RawStr::findOffset(const char *ikey, long *start, unsigned short *si /****************************************************************************** - * RawStr::preptext - Prepares the text before returning it to external - * objects - * - * ENT: buf - buffer where text is stored and where to store the prep'd - * text. - */ - -void RawStr::prepText(SWBuf &buf) { - unsigned int to, from; - char space = 0, cr = 0, realdata = 0, nlcnt = 0; - char *rawBuf = buf.getRawData(); - for (to = from = 0; rawBuf[from]; from++) { - switch (rawBuf[from]) { - case 10: - if (!realdata) - continue; - space = (cr) ? 0 : 1; - cr = 0; - nlcnt++; - if (nlcnt > 1) { -// *to++ = nl; - rawBuf[to++] = 10; -// *to++ = nl[1]; -// nlcnt = 0; - } - continue; - case 13: - if (!realdata) - continue; -// *to++ = nl[0]; - rawBuf[to++] = 10; - space = 0; - cr = 1; - continue; - } - realdata = 1; - nlcnt = 0; - if (space) { - space = 0; - if (rawBuf[from] != ' ') { - rawBuf[to++] = ' '; - from--; - continue; - } - } - rawBuf[to++] = rawBuf[from]; - } - buf.setSize(to); - - while (to > 1) { // remove trailing excess - to--; - if ((rawBuf[to] == 10) || (rawBuf[to] == ' ')) - buf.setSize(to); - else break; - } -} - - -/****************************************************************************** * RawStr::readtext - gets text at a given offset * * ENT: @@ -339,12 +302,12 @@ void RawStr::prepText(SWBuf &buf) { * */ -void RawStr::readText(long istart, unsigned short *isize, char **idxbuf, SWBuf &buf) +void RawStr::readText(__u32 istart, __u16 *isize, char **idxbuf, SWBuf &buf) { unsigned int ch; char *idxbuflocal = 0; getIDXBufDat(istart, &idxbuflocal); - long start = istart; + __u32 start = istart; do { if (*idxbuf) @@ -401,12 +364,12 @@ void RawStr::readText(long istart, unsigned short *isize, char **idxbuf, SWBuf & void RawStr::doSetText(const char *ikey, const char *buf, long len) { - long start, outstart; - long idxoff; - long endoff; - long shiftSize; - unsigned short size; - unsigned short outsize; + __u32 start, outstart; + __u32 idxoff; + __u32 endoff; + __s32 shiftSize; + __u16 size; + __u16 outsize; static const char nl[] = {13, 10}; char *tmpbuf = 0; char *key = 0; @@ -526,7 +489,6 @@ void RawStr::doLinkEntry(const char *destkey, const char *srckey) { delete [] text; } - /****************************************************************************** * RawLD::CreateModule - Creates new module files * diff --git a/src/modules/common/rawstr4.cpp b/src/modules/common/rawstr4.cpp index cbc8384..003b2fe 100644 --- a/src/modules/common/rawstr4.cpp +++ b/src/modules/common/rawstr4.cpp @@ -1,8 +1,24 @@ /****************************************************************************** * rawstr.cpp - code for class 'RawStr'- a module that reads raw text - * files: ot and nt using indexs ??.bks ??.cps ??.vss - * and provides lookup and parsing functions based on - * class StrKey + * files: ot and nt using indexs ??.bks ??.cps ??.vss + * and provides lookup and parsing functions based on + * class StrKey + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ #include <stdio.h> @@ -26,6 +42,7 @@ SWORD_NAMESPACE_START */ int RawStr4::instance = 0; +const int RawStr4::IDXENTRYSIZE = 8; /****************************************************************************** @@ -88,7 +105,8 @@ RawStr4::~RawStr4() * buf - address of pointer to allocate for storage of string */ -void RawStr4::getIDXBufDat(long ioffset, char **buf) { +void RawStr4::getIDXBufDat(long ioffset, char **buf) const +{ int size; char ch; if (datfd > 0) { @@ -121,14 +139,14 @@ void RawStr4::getIDXBufDat(long ioffset, char **buf) { * buf - address of pointer to allocate for storage of string */ -void RawStr4::getIDXBuf(long ioffset, char **buf) +void RawStr4::getIDXBuf(long ioffset, char **buf) const { - long offset; + __u32 offset; if (idxfd > 0) { idxfd->seek(ioffset, SEEK_SET); - idxfd->read(&offset, 4); + idxfd->read(&offset, 4); offset = swordtoarch32(offset); getIDXBufDat(offset, buf); @@ -157,17 +175,19 @@ void RawStr4::getIDXBuf(long ioffset, char **buf) * RET: error status -1 general error; -2 new file */ -signed char RawStr4::findOffset(const char *ikey, long *start, unsigned long *size, long away, long *idxoff) +signed char RawStr4::findOffset(const char *ikey, __u32 *start, __u32 *size, long away, __u32 *idxoff) const { char *trybuf, *maxbuf, *key = 0, quitflag = 0; signed char retval = -1; long headoff, tailoff, tryoff = 0, maxoff = 0; int diff = 0; + bool awayFromSubstrCheck = false; if (idxfd->getFd() >=0) { tailoff = maxoff = idxfd->seek(0, SEEK_END) - 8; + retval = (tailoff >= 0) ? 0 : -2; // if NOT new file - if (*ikey) { + if (*ikey && retval != -2) { headoff = 0; stdstr(&key, ikey, 3); @@ -211,6 +231,7 @@ signed char RawStr4::findOffset(const char *ikey, long *start, unsigned long *si if (headoff >= tailoff) { tryoff = headoff; if (!substr && ((tryoff != maxoff)||(strncmp(key, maxbuf, keylen)<0))) { + awayFromSubstrCheck = true; away--; // if our entry doesn't startwith our key, prefer the previous entry over the next } } @@ -224,17 +245,18 @@ signed char RawStr4::findOffset(const char *ikey, long *start, unsigned long *si idxfd->seek(tryoff, SEEK_SET); - *start = *size = 0; - idxfd->read(start, 4); - idxfd->read(size, 4); + __u32 tmpStart, tmpSize; + *start = *size = tmpStart = tmpSize = 0; + idxfd->read(&tmpStart, 4); + idxfd->read(&tmpSize, 4); if (idxoff) *idxoff = tryoff; - *start = swordtoarch32(*start); - *size = swordtoarch32(*size); + *start = swordtoarch32(tmpStart); + *size = swordtoarch32(tmpSize); while (away) { - long laststart = *start; + unsigned long laststart = *start; unsigned long lastsize = *size; long lasttry = tryoff; tryoff += (away > 0) ? 8 : -8; @@ -245,7 +267,8 @@ signed char RawStr4::findOffset(const char *ikey, long *start, unsigned long *si else if (idxfd->seek(tryoff, SEEK_SET) < 0) bad = true; if (bad) { - retval = -1; + if(!awayFromSubstrCheck) + retval = -1; *start = laststart; *size = lastsize; tryoff = lasttry; @@ -253,15 +276,15 @@ signed char RawStr4::findOffset(const char *ikey, long *start, unsigned long *si *idxoff = tryoff; break; } - idxfd->read(start, 4); - idxfd->read(size, 4); + idxfd->read(&tmpStart, 4); + idxfd->read(&tmpSize, 4); if (idxoff) *idxoff = tryoff; - *start = swordtoarch32(*start); - *size = swordtoarch32(*size); + *start = swordtoarch32(tmpStart); + *size = swordtoarch32(tmpSize); - if (((laststart != *start) || (lastsize != *size)) && (*start >= 0) && (*size)) + if (((laststart != *start) || (lastsize != *size)) && (*size)) away += (away < 0) ? 1 : -1; } @@ -279,65 +302,6 @@ signed char RawStr4::findOffset(const char *ikey, long *start, unsigned long *si /****************************************************************************** - * RawStr4::preptext - Prepares the text before returning it to external - * objects - * - * ENT: buf - buffer where text is stored and where to store the prep'd - * text. - */ - -void RawStr4::prepText(SWBuf &buf) { - unsigned int to, from; - char space = 0, cr = 0, realdata = 0, nlcnt = 0; - char *rawBuf = buf.getRawData(); - for (to = from = 0; rawBuf[from]; from++) { - switch (rawBuf[from]) { - case 10: - if (!realdata) - continue; - space = (cr) ? 0 : 1; - cr = 0; - nlcnt++; - if (nlcnt > 1) { -// *to++ = nl; - rawBuf[to++] = 10; -// *to++ = nl[1]; -// nlcnt = 0; - } - continue; - case 13: - if (!realdata) - continue; -// *to++ = nl[0]; - rawBuf[to++] = 10; - space = 0; - cr = 1; - continue; - } - realdata = 1; - nlcnt = 0; - if (space) { - space = 0; - if (rawBuf[from] != ' ') { - rawBuf[to++] = ' '; - from--; - continue; - } - } - rawBuf[to++] = rawBuf[from]; - } - buf.setSize(to); - - while (to > 1) { // remove trailing excess - to--; - if ((rawBuf[to] == 10) || (rawBuf[to] == ' ')) - buf.setSize(to); - else break; - } -} - - -/****************************************************************************** * RawStr4::readtext - gets text at a given offset * * ENT: @@ -347,12 +311,12 @@ void RawStr4::prepText(SWBuf &buf) { * */ -void RawStr4::readText(long istart, unsigned long *isize, char **idxbuf, SWBuf &buf) +void RawStr4::readText(__u32 istart, __u32 *isize, char **idxbuf, SWBuf &buf) { unsigned int ch; char *idxbuflocal = 0; getIDXBufDat(istart, &idxbuflocal); - long start = istart; + __u32 start = istart; do { if (*idxbuf) @@ -408,12 +372,12 @@ void RawStr4::readText(long istart, unsigned long *isize, char **idxbuf, SWBuf & void RawStr4::doSetText(const char *ikey, const char *buf, long len) { - long start, outstart; - long idxoff; - long endoff; - long shiftSize; - unsigned long size; - unsigned long outsize; + __u32 start, outstart; + __u32 idxoff; + __u32 endoff; + __s32 shiftSize; + __u32 size; + __u32 outsize; static const char nl[] = {13, 10}; char *tmpbuf = 0; char *key = 0; diff --git a/src/modules/common/rawverse.cpp b/src/modules/common/rawverse.cpp index 934082c..99beaa2 100644 --- a/src/modules/common/rawverse.cpp +++ b/src/modules/common/rawverse.cpp @@ -3,9 +3,26 @@ * files: ot and nt using indexs ??.bks ??.cps ??.vss * and provides lookup and parsing functions based on * class VerseKey + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <ctype.h> #include <stdio.h> #include <fcntl.h> @@ -96,18 +113,20 @@ RawVerse::~RawVerse() * size - address to store the size of the entry */ -void RawVerse::findOffset(char testmt, long idxoff, long *start, unsigned short *size) { +void RawVerse::findOffset(char testmt, long idxoff, long *start, unsigned short *size) const { idxoff *= 6; if (!testmt) testmt = ((idxfp[1]) ? 1:2); if (idxfp[testmt-1]->getFd() >= 0) { idxfp[testmt-1]->seek(idxoff, SEEK_SET); - idxfp[testmt-1]->read(start, 4); - long len = idxfp[testmt-1]->read(size, 2); // read size + __s32 tmpStart; + __u16 tmpSize; + idxfp[testmt-1]->read(&tmpStart, 4); + long len = idxfp[testmt-1]->read(&tmpSize, 2); // read size - *start = swordtoarch32(*start); - *size = swordtoarch16(*size); + *start = swordtoarch32(tmpStart); + *size = swordtoarch16(tmpSize); if (len < 2) { *size = (unsigned short)((*start) ? (textfp[testmt-1]->seek(0, SEEK_END) - (long)*start) : 0); // if for some reason we get an error reading size, make size to end of file @@ -121,65 +140,6 @@ void RawVerse::findOffset(char testmt, long idxoff, long *start, unsigned short /****************************************************************************** - * RawVerse::preptext - Prepares the text before returning it to external - * objects - * - * ENT: buf - buffer where text is stored and where to store the prep'd - * text. - */ - -void RawVerse::prepText(SWBuf &buf) { - unsigned int to, from; - char space = 0, cr = 0, realdata = 0, nlcnt = 0; - char *rawBuf = buf.getRawData(); - for (to = from = 0; rawBuf[from]; from++) { - switch (rawBuf[from]) { - case 10: - if (!realdata) - continue; - space = (cr) ? 0 : 1; - cr = 0; - nlcnt++; - if (nlcnt > 1) { -// *to++ = nl; - rawBuf[to++] = 10; -// *to++ = nl[1]; -// nlcnt = 0; - } - continue; - case 13: - if (!realdata) - continue; -// *to++ = nl[0]; - rawBuf[to++] = 10; - space = 0; - cr = 1; - continue; - } - realdata = 1; - nlcnt = 0; - if (space) { - space = 0; - if (rawBuf[from] != ' ') { - rawBuf[to++] = ' '; - from--; - continue; - } - } - rawBuf[to++] = rawBuf[from]; - } - buf.setSize(to); - - while (to > 1) { // remove trailing excess - to--; - if ((rawBuf[to] == 10) || (rawBuf[to] == ' ')) - buf.setSize(to); - else break; - } -} - - -/****************************************************************************** * RawVerse::readtext - gets text at a given offset * * ENT: testmt - testament file to search in (0 - Old; 1 - New) @@ -215,17 +175,16 @@ void RawVerse::readText(char testmt, long start, unsigned short size, SWBuf &buf void RawVerse::doSetText(char testmt, long idxoff, const char *buf, long len) { - long start, outstart; - unsigned short size; - unsigned short outsize; + __s32 start; + __u16 size; idxoff *= 6; if (!testmt) testmt = ((idxfp[1]) ? 1:2); - size = outsize = (len < 0) ? strlen(buf) : len; + size = (len < 0) ? strlen(buf) : len; - start = outstart = textfp[testmt-1]->seek(0, SEEK_END); + start = textfp[testmt-1]->seek(0, SEEK_END); idxfp[testmt-1]->seek(idxoff, SEEK_SET); if (size) { @@ -239,13 +198,11 @@ void RawVerse::doSetText(char testmt, long idxoff, const char *buf, long len) start = 0; } - outstart = archtosword32(start); - outsize = archtosword16(size); - - idxfp[testmt-1]->write(&outstart, 4); - idxfp[testmt-1]->write(&outsize, 2); - + start = archtosword32(start); + size = archtosword16(size); + idxfp[testmt-1]->write(&start, 4); + idxfp[testmt-1]->write(&size, 2); } @@ -258,8 +215,8 @@ void RawVerse::doSetText(char testmt, long idxoff, const char *buf, long len) */ void RawVerse::doLinkEntry(char testmt, long destidxoff, long srcidxoff) { - long start; - unsigned short size; + __s32 start; + __u16 size; destidxoff *= 6; srcidxoff *= 6; @@ -280,13 +237,13 @@ void RawVerse::doLinkEntry(char testmt, long destidxoff, long srcidxoff) { /****************************************************************************** - * RawVerse::CreateModule - Creates new module files + * RawVerse::createModule - Creates new module files * * ENT: path - directory to store module files * RET: error status */ -char RawVerse::createModule(const char *ipath) +char RawVerse::createModule(const char *ipath, const char *v11n) { char *path = 0; char *buf = new char [ strlen (ipath) + 20 ]; @@ -320,11 +277,16 @@ char RawVerse::createModule(const char *ipath) fd2->getFd(); VerseKey vk; + vk.setVersificationSystem(v11n); vk.Headings(1); - long offset = 0; - short size = 0; + + __s32 offset = 0; + __u16 size = 0; + offset = archtosword32(offset); + size = archtosword16(size); + for (vk = TOP; !vk.Error(); vk++) { - if (vk.Testament() == 1) { + if (vk.Testament() < 2) { fd->write(&offset, 4); fd->write(&size, 2); } @@ -333,16 +295,14 @@ char RawVerse::createModule(const char *ipath) fd2->write(&size, 2); } } + fd2->write(&offset, 4); + fd2->write(&size, 2); FileMgr::getSystemFileMgr()->close(fd); FileMgr::getSystemFileMgr()->close(fd2); delete [] path; delete [] buf; -/* - RawVerse rv(path); - VerseKey mykey("Rev 22:21"); -*/ return 0; } diff --git a/src/modules/common/rawverse4.cpp b/src/modules/common/rawverse4.cpp index bd438ec..ee0b207 100644 --- a/src/modules/common/rawverse4.cpp +++ b/src/modules/common/rawverse4.cpp @@ -3,9 +3,26 @@ * files: ot and nt using indexs ??.bks ??.cps ??.vss * and provides lookup and parsing functions based on * class VerseKey + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <ctype.h> #include <stdio.h> #include <fcntl.h> @@ -96,18 +113,20 @@ RawVerse4::~RawVerse4() * size - address to store the size of the entry */ -void RawVerse4::findOffset(char testmt, long idxoff, long *start, unsigned long *size) { +void RawVerse4::findOffset(char testmt, long idxoff, long *start, unsigned long *size) const { idxoff *= 8; if (!testmt) testmt = ((idxfp[1]) ? 1:2); if (idxfp[testmt-1]->getFd() >= 0) { idxfp[testmt-1]->seek(idxoff, SEEK_SET); - idxfp[testmt-1]->read(start, 4); - long len = idxfp[testmt-1]->read(size, 4); // read size + __u32 tmpStart; + __u32 tmpSize; + idxfp[testmt-1]->read(&tmpStart, 4); + long len = idxfp[testmt-1]->read(&tmpSize, 4); // read size - *start = swordtoarch32(*start); - *size = swordtoarch32(*size); + *start = swordtoarch32(tmpStart); + *size = swordtoarch32(tmpSize); if (len < 2) { *size = (unsigned long)((*start) ? (textfp[testmt-1]->seek(0, SEEK_END) - (long)*start) : 0); // if for some reason we get an error reading size, make size to end of file @@ -121,65 +140,6 @@ void RawVerse4::findOffset(char testmt, long idxoff, long *start, unsigned long /****************************************************************************** - * RawVerse4::preptext - Prepares the text before returning it to external - * objects - * - * ENT: buf - buffer where text is stored and where to store the prep'd - * text. - */ - -void RawVerse4::prepText(SWBuf &buf) { - unsigned int to, from; - char space = 0, cr = 0, realdata = 0, nlcnt = 0; - char *rawBuf = buf.getRawData(); - for (to = from = 0; rawBuf[from]; from++) { - switch (rawBuf[from]) { - case 10: - if (!realdata) - continue; - space = (cr) ? 0 : 1; - cr = 0; - nlcnt++; - if (nlcnt > 1) { -// *to++ = nl; - rawBuf[to++] = 10; -// *to++ = nl[1]; -// nlcnt = 0; - } - continue; - case 13: - if (!realdata) - continue; -// *to++ = nl[0]; - rawBuf[to++] = 10; - space = 0; - cr = 1; - continue; - } - realdata = 1; - nlcnt = 0; - if (space) { - space = 0; - if (rawBuf[from] != ' ') { - rawBuf[to++] = ' '; - from--; - continue; - } - } - rawBuf[to++] = rawBuf[from]; - } - buf.setSize(to); - - while (to > 1) { // remove trailing excess - to--; - if ((rawBuf[to] == 10) || (rawBuf[to] == ' ')) - buf.setSize(to); - else break; - } -} - - -/****************************************************************************** * RawVerse4::readtext - gets text at a given offset * * ENT: testmt - testament file to search in (0 - Old; 1 - New) @@ -215,17 +175,16 @@ void RawVerse4::readText(char testmt, long start, unsigned long size, SWBuf &buf void RawVerse4::doSetText(char testmt, long idxoff, const char *buf, long len) { - long start, outstart; - unsigned long size; - unsigned long outsize; + __u32 start; + __u32 size; idxoff *= 8; if (!testmt) testmt = ((idxfp[1]) ? 1:2); - size = outsize = (len < 0) ? strlen(buf) : len; + size = (len < 0) ? strlen(buf) : len; - start = outstart = textfp[testmt-1]->seek(0, SEEK_END); + start = textfp[testmt-1]->seek(0, SEEK_END); idxfp[testmt-1]->seek(idxoff, SEEK_SET); if (size) { @@ -239,13 +198,11 @@ void RawVerse4::doSetText(char testmt, long idxoff, const char *buf, long len) start = 0; } - outstart = archtosword32(start); - outsize = archtosword32(size); - - idxfp[testmt-1]->write(&outstart, 4); - idxfp[testmt-1]->write(&outsize, 4); - + start = archtosword32(start); + size = archtosword32(size); + idxfp[testmt-1]->write(&start, 4); + idxfp[testmt-1]->write(&size, 4); } @@ -258,8 +215,8 @@ void RawVerse4::doSetText(char testmt, long idxoff, const char *buf, long len) */ void RawVerse4::doLinkEntry(char testmt, long destidxoff, long srcidxoff) { - long start; - unsigned long size; + __u32 start; + __u32 size; destidxoff *= 8; srcidxoff *= 8; @@ -286,7 +243,7 @@ void RawVerse4::doLinkEntry(char testmt, long destidxoff, long srcidxoff) { * RET: error status */ -char RawVerse4::createModule(const char *ipath) +char RawVerse4::createModule(const char *ipath, const char *v11n) { char *path = 0; char *buf = new char [ strlen (ipath) + 20 ]; @@ -320,11 +277,15 @@ char RawVerse4::createModule(const char *ipath) fd2->getFd(); VerseKey vk; + vk.setVersificationSystem(v11n); vk.Headings(1); - long offset = 0; - long size = 0; + __u32 offset = 0; + __u32 size = 0; + offset = archtosword32(offset); + size = archtosword32(size); + for (vk = TOP; !vk.Error(); vk++) { - if (vk.Testament() == 1) { + if (vk.Testament() < 2) { fd->write(&offset, 4); fd->write(&size, 4); } @@ -333,16 +294,14 @@ char RawVerse4::createModule(const char *ipath) fd2->write(&size, 4); } } + fd2->write(&offset, 4); + fd2->write(&size, 4); FileMgr::getSystemFileMgr()->close(fd); FileMgr::getSystemFileMgr()->close(fd2); delete [] path; delete [] buf; -/* - RawVerse4 rv(path); - VerseKey mykey("Rev 22:21"); -*/ return 0; } diff --git a/src/modules/common/swcipher.cpp b/src/modules/common/swcipher.cpp index bd4d551..5ab91ea 100644 --- a/src/modules/common/swcipher.cpp +++ b/src/modules/common/swcipher.cpp @@ -1,8 +1,25 @@ /****************************************************************************** * swcipher.cpp - code for class 'SWCipher'- a driver class that provides * cipher utilities. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <stdlib.h> #include <string.h> #include <swcipher.h> diff --git a/src/modules/common/swcomprs.cpp b/src/modules/common/swcomprs.cpp index 02d7d7b..378c8b1 100644 --- a/src/modules/common/swcomprs.cpp +++ b/src/modules/common/swcomprs.cpp @@ -1,8 +1,25 @@ /****************************************************************************** * swcomprs.cpp - code for class 'SWCompress'- a driver class that provides * compression utilities. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <stdlib.h> #include <string.h> #include <swcomprs.h> diff --git a/src/modules/common/zipcomprs.cpp b/src/modules/common/zipcomprs.cpp index 21726bf..534d840 100644 --- a/src/modules/common/zipcomprs.cpp +++ b/src/modules/common/zipcomprs.cpp @@ -1,8 +1,25 @@ /****************************************************************************** * swcomprs.cpp - code for class 'ZipCompress'- a driver class that provides * compression utilities. - using zlib + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <stdlib.h> #include <string.h> #include <stdio.h> diff --git a/src/modules/common/zstr.cpp b/src/modules/common/zstr.cpp index 2539ff0..5b4da64 100644 --- a/src/modules/common/zstr.cpp +++ b/src/modules/common/zstr.cpp @@ -2,8 +2,25 @@ * zstr.cpp - code for class 'zStr'- a module that reads compressed text * files and provides lookup and parsing functions based on * class StrKey + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <stdio.h> #include <fcntl.h> #include <errno.h> @@ -111,7 +128,8 @@ zStr::~zStr() { * buf - address of pointer to allocate for storage of string */ -void zStr::getKeyFromDatOffset(long ioffset, char **buf) { +void zStr::getKeyFromDatOffset(long ioffset, char **buf) const +{ int size; char ch; if (datfd > 0) { @@ -144,12 +162,13 @@ void zStr::getKeyFromDatOffset(long ioffset, char **buf) { * buf - address of pointer to allocate for storage of string */ -void zStr::getKeyFromIdxOffset(long ioffset, char **buf) { +void zStr::getKeyFromIdxOffset(long ioffset, char **buf) const +{ __u32 offset; if (idxfd > 0) { idxfd->seek(ioffset, SEEK_SET); - idxfd->read(&offset, sizeof(__u32)); + idxfd->read(&offset, 4); offset = swordtoarch32(offset); getKeyFromDatOffset(offset, buf); } @@ -168,12 +187,14 @@ void zStr::getKeyFromIdxOffset(long ioffset, char **buf) { * RET: error status */ -signed char zStr::findKeyIndex(const char *ikey, long *idxoff, long away) { +signed char zStr::findKeyIndex(const char *ikey, long *idxoff, long away) const +{ char *maxbuf = 0, *trybuf = 0, *key = 0, quitflag = 0; signed char retval = 0; __s32 headoff, tailoff, tryoff = 0, maxoff = 0; __u32 start, size; int diff = 0; + bool awayFromSubstrCheck = false; if (idxfd->getFd() >= 0) { tailoff = maxoff = idxfd->seek(0, SEEK_END) - IDXENTRYSIZE; @@ -220,6 +241,7 @@ signed char zStr::findKeyIndex(const char *ikey, long *idxoff, long away) { if (headoff >= tailoff) { tryoff = headoff; if (!substr && ((tryoff != maxoff)||(strncmp(key, maxbuf, keylen)<0))) { + awayFromSubstrCheck = true; away--; // if our entry doesn't startwith our key, prefer the previous entry over the next } } @@ -234,8 +256,8 @@ signed char zStr::findKeyIndex(const char *ikey, long *idxoff, long away) { idxfd->seek(tryoff, SEEK_SET); start = size = 0; - retval = (idxfd->read(&start, sizeof(__u32))==sizeof(__u32)) ? retval : -1; - retval = (idxfd->read(&size, sizeof(__u32))==sizeof(__u32)) ? retval : -1; + retval = (idxfd->read(&start, 4) == 4) ? retval : -1; + retval = (idxfd->read(&size, 4) == 4) ? retval : -1; start = swordtoarch32(start); size = swordtoarch32(size); @@ -254,7 +276,8 @@ signed char zStr::findKeyIndex(const char *ikey, long *idxoff, long away) { else if (idxfd->seek(tryoff, SEEK_SET) < 0) bad = true; if (bad) { - retval = -1; + if(!awayFromSubstrCheck) + retval = -1; start = laststart; size = lastsize; tryoff = lasttry; @@ -262,8 +285,8 @@ signed char zStr::findKeyIndex(const char *ikey, long *idxoff, long away) { *idxoff = tryoff; break; } - idxfd->read(&start, sizeof(__u32)); - idxfd->read(&size, sizeof(__u32)); + idxfd->read(&start, 4); + idxfd->read(&size, 4); start = swordtoarch32(start); size = swordtoarch32(size); @@ -287,65 +310,6 @@ signed char zStr::findKeyIndex(const char *ikey, long *idxoff, long away) { /****************************************************************************** - * zStr::preptext - Prepares the text before returning it to external - * objects - * - * ENT: buf - buffer where text is stored and where to store the prep'd - * text. - */ - -void zStr::prepText(SWBuf &buf) { - unsigned int to, from; - char space = 0, cr = 0, realdata = 0, nlcnt = 0; - char *rawBuf = buf.getRawData(); - for (to = from = 0; rawBuf[from]; from++) { - switch (rawBuf[from]) { - case 10: - if (!realdata) - continue; - space = (cr) ? 0 : 1; - cr = 0; - nlcnt++; - if (nlcnt > 1) { -// *to++ = nl; - rawBuf[to++] = 10; -// *to++ = nl[1]; -// nlcnt = 0; - } - continue; - case 13: - if (!realdata) - continue; -// *to++ = nl[0]; - rawBuf[to++] = 10; - space = 0; - cr = 1; - continue; - } - realdata = 1; - nlcnt = 0; - if (space) { - space = 0; - if (rawBuf[from] != ' ') { - rawBuf[to++] = ' '; - from--; - continue; - } - } - rawBuf[to++] = rawBuf[from]; - } - buf.setSize(to); - - while (to > 1) { // remove trailing excess - to--; - if ((rawBuf[to] == 10) || (rawBuf[to] == ' ')) - buf.setSize(to); - else break; - } -} - - -/****************************************************************************** * zStr::getText - gets text at a given offset * * ENT: @@ -366,8 +330,8 @@ void zStr::getText(long offset, char **idxbuf, char **buf) { do { idxfd->seek(offset, SEEK_SET); - idxfd->read(&start, sizeof(__u32)); - idxfd->read(&size, sizeof(__u32)); + idxfd->read(&start, 4); + idxfd->read(&size, 4); start = swordtoarch32(start); size = swordtoarch32(size); @@ -430,8 +394,8 @@ void zStr::getCompressedText(long block, long entry, char **buf) { __u32 start = 0; zdxfd->seek(block * ZDXENTRYSIZE, SEEK_SET); - zdxfd->read(&start, sizeof(__u32)); - zdxfd->read(&size, sizeof(__u32)); + zdxfd->read(&start, 4); + zdxfd->read(&size, 4); start = swordtoarch32(start); size = swordtoarch32(size); @@ -496,8 +460,8 @@ void zStr::setText(const char *ikey, const char *buf, long len) { else if ((!diff) && (len > 0 /*we're not deleting*/)) { // got absolute entry do { idxfd->seek(idxoff, SEEK_SET); - idxfd->read(&start, sizeof(__u32)); - idxfd->read(&size, sizeof(__u32)); + idxfd->read(&start, 4); + idxfd->read(&size, 4); start = swordtoarch32(start); size = swordtoarch32(size); @@ -581,8 +545,8 @@ void zStr::setText(const char *ikey, const char *buf, long len) { // add a new line to make data file easier to read in an editor datfd->write(&nl, 2); - idxfd->write(&outstart, sizeof(__u32)); - idxfd->write(&outsize, sizeof(__u32)); + idxfd->write(&outstart, 4); + idxfd->write(&outsize, 4); if (idxBytes) { idxfd->write(idxBytes, shiftSize); } @@ -644,8 +608,8 @@ void zStr::flushCache() { } else { zdxfd->seek(cacheBlockIndex * ZDXENTRYSIZE, SEEK_SET); - zdxfd->read(&start, sizeof(__u32)); - zdxfd->read(&outsize, sizeof(__u32)); + zdxfd->read(&start, 4); + zdxfd->read(&outsize, 4); start = swordtoarch32(start); outsize = swordtoarch32(outsize); if (start + outsize >= zdtSize) { // last entry, just overwrite @@ -671,8 +635,8 @@ void zStr::flushCache() { // add a new line to make data file easier to read in an editor zdtfd->write(&nl, 2); - zdxfd->write(&outstart, sizeof(__u32)); - zdxfd->write(&outsize, sizeof(__u32)); + zdxfd->write(&outstart, 4); + zdxfd->write(&outsize, 4); } delete cacheBlock; cacheBlock = 0; diff --git a/src/modules/common/zverse.cpp b/src/modules/common/zverse.cpp index 3f91918..fa76467 100644 --- a/src/modules/common/zverse.cpp +++ b/src/modules/common/zverse.cpp @@ -1,11 +1,28 @@ /****************************************************************************** * zverse.h - code for class 'zVerse'- a module that reads raw text - * files: ot and nt using indexs ??.bks ??.cps ??.vss - * and provides lookup and parsing functions based on - * class VerseKey for compressed modules + * files: ot and nt using indexs ??.bks ??.cps ??.vss + * and provides lookup and parsing functions based on + * class VerseKey for compressed modules + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <ctype.h> #include <stdio.h> #include <fcntl.h> @@ -129,19 +146,15 @@ zVerse::~zVerse() * size - address to store the size of the entry */ -void zVerse::findOffset(char testmt, long idxoff, long *start, unsigned short *size) +void zVerse::findOffset(char testmt, long idxoff, long *start, unsigned short *size, unsigned long *buffnum) const { + __u32 ulBuffNum = 0; // buffer number + __u32 ulVerseStart = 0; // verse offset within buffer + __u16 usVerseSize = 0; // verse size // set start to offset in // set size to // set - unsigned long ulBuffNum=0; // buffer number - unsigned long ulVerseStart=0; // verse offset within buffer - unsigned short usVerseSize=0; // verse size - unsigned long ulCompOffset=0; // compressed buffer start - unsigned long ulCompSize=0; // buffer size compressed - unsigned long ulUnCompSize=0; // buffer size uncompressed - - *start = *size = 0; + *start = *size = *buffnum = 0; //printf ("Finding offset %ld\n", idxoff); idxoff *= 10; if (!testmt) { @@ -159,10 +172,8 @@ void zVerse::findOffset(char testmt, long idxoff, long *start, unsigned short *s return; } } - else return; - - ulBuffNum = swordtoarch32(ulBuffNum); - + else return; + if (compfp[testmt-1]->read(&ulVerseStart, 4) < 2) { printf ("Error reading ulVerseStart\n"); @@ -174,17 +185,39 @@ void zVerse::findOffset(char testmt, long idxoff, long *start, unsigned short *s return; } + *buffnum = swordtoarch32(ulBuffNum); *start = swordtoarch32(ulVerseStart); *size = swordtoarch16(usVerseSize); - if (*size) { - if (((long) ulBuffNum == cacheBufIdx) && (testmt == cacheTestament) && (cacheBuf)) { - // have the text buffered - return; - } +} - //printf ("Got buffer number{%ld} versestart{%ld} versesize{%d}\n", ulBuffNum, ulVerseStart, usVerseSize); +/****************************************************************************** + * zVerse::zreadtext - gets text at a given offset + * + * ENT: testmt - testament file to search in (0 - Old; 1 - New) + * start - starting offset where the text is located in the file + * size - size of text entry + 1 (null) + * buf - buffer to store text + * + */ + +void zVerse::zReadText(char testmt, long start, unsigned short size, unsigned long ulBuffNum, SWBuf &inBuf) { + __u32 ulCompOffset = 0; // compressed buffer start + __u32 ulCompSize = 0; // buffer size compressed + __u32 ulUnCompSize = 0; // buffer size uncompressed + + if (!testmt) { + testmt = ((idxfp[0]) ? 1:2); + } + + // assert we have and valid file descriptor + if (compfp[testmt-1]->getFd() < 1) + return; + + if (size && + !(((long) ulBuffNum == cacheBufIdx) && (testmt == cacheTestament) && (cacheBuf))) { + //printf ("Got buffer number{%ld} versestart{%ld} versesize{%d}\n", ulBuffNum, ulVerseStart, usVerseSize); if (idxfp[testmt-1]->seek(ulBuffNum*12, SEEK_SET)!=(long) ulBuffNum*12) { @@ -226,7 +259,8 @@ void zVerse::findOffset(char testmt, long idxoff, long *start, unsigned short *s pcCompText.setSize(ulCompSize); rawZFilter(pcCompText, 0); // 0 = decipher - compressor->zBuf(&ulCompSize, pcCompText.getRawData()); + unsigned long bufSize = ulCompSize; + compressor->zBuf(&bufSize, pcCompText.getRawData()); if (cacheBuf) { flushCache(); @@ -237,26 +271,13 @@ void zVerse::findOffset(char testmt, long idxoff, long *start, unsigned short *s compressor->Buf(0, &len); cacheBuf = (char *)calloc(len + 1, 1); memcpy(cacheBuf, compressor->Buf(), len); - + cacheBufSize = strlen(cacheBuf); // TODO: can we just use len? cacheTestament = testmt; cacheBufIdx = ulBuffNum; - } -} - - -/****************************************************************************** - * zVerse::zreadtext - gets text at a given offset - * - * ENT: testmt - testament file to search in (0 - Old; 1 - New) - * start - starting offset where the text is located in the file - * size - size of text entry + 1 (null) - * buf - buffer to store text - * - */ - -void zVerse::zReadText(char testmt, long start, unsigned short size, SWBuf &inBuf) { + } + inBuf = ""; - if ( (size > 0) && cacheBuf && ((unsigned)start < strlen(cacheBuf)) ){ //TODO: optimize this, remove strlen + if ((size > 0) && cacheBuf && ((unsigned)start < cacheBufSize)) { inBuf.setFillByte(0); inBuf.setSize(size+1); strncpy(inBuf.getRawData(), &(cacheBuf[start]), size); @@ -290,13 +311,12 @@ void zVerse::doSetText(char testmt, long idxoff, const char *buf, long len) { dirtyCache = true; - unsigned long start, outstart; - unsigned long outBufIdx = cacheBufIdx; - unsigned short size; - unsigned short outsize; + __u32 start; + __u16 size; + __u32 outBufIdx = cacheBufIdx; idxoff *= 10; - size = outsize = len; + size = len; start = strlen(cacheBuf); @@ -304,23 +324,23 @@ void zVerse::doSetText(char testmt, long idxoff, const char *buf, long len) { start = outBufIdx = 0; outBufIdx = archtosword32(outBufIdx); - outstart = archtosword32(start); - outsize = archtosword16(size); + start = archtosword32(start); + size = archtosword16(size); compfp[testmt-1]->seek(idxoff, SEEK_SET); compfp[testmt-1]->write(&outBufIdx, 4); - compfp[testmt-1]->write(&outstart, 4); - compfp[testmt-1]->write(&outsize, 2); + compfp[testmt-1]->write(&start, 4); + compfp[testmt-1]->write(&size, 2); strcat(cacheBuf, buf); } void zVerse::flushCache() { if (dirtyCache) { - unsigned long idxoff; - unsigned long start, outstart; - unsigned long size, outsize; - unsigned long zsize, outzsize; + __u32 idxoff; + __u32 start, outstart; + __u32 size, outsize; + __u32 zsize, outzsize; idxoff = cacheBufIdx * 12; if (cacheBuf) { @@ -331,12 +351,14 @@ void zVerse::flushCache() { // compressor = new LZSSCompress(); // } compressor->Buf(cacheBuf); - compressor->zBuf(&zsize); - outzsize = zsize; + unsigned long tmpSize; + compressor->zBuf(&tmpSize); + outzsize = zsize = tmpSize; SWBuf buf; buf.setSize(zsize + 5); - memcpy(buf.getRawData(), compressor->zBuf(&zsize), zsize); + memcpy(buf.getRawData(), compressor->zBuf(&tmpSize), tmpSize); + outzsize = zsize = tmpSize; buf.setSize(zsize); rawZFilter(buf, 1); // 1 = encipher @@ -369,9 +391,9 @@ void zVerse::flushCache() { */ void zVerse::doLinkEntry(char testmt, long destidxoff, long srcidxoff) { - long bufidx; - long start; - unsigned short size; + __s32 bufidx; + __s32 start; + __u16 size; destidxoff *= 10; srcidxoff *= 10; @@ -400,7 +422,7 @@ void zVerse::doLinkEntry(char testmt, long destidxoff, long srcidxoff) { * RET: error status */ -char zVerse::createModule(const char *ipath, int blockBound) +char zVerse::createModule(const char *ipath, int blockBound, const char *v11n) { char *path = 0; char *buf = new char [ strlen (ipath) + 20 ]; @@ -446,11 +468,16 @@ char zVerse::createModule(const char *ipath, int blockBound) fd2->getFd(); VerseKey vk; + vk.setVersificationSystem(v11n); vk.Headings(1); - long offset = 0; - short size = 0; + + __s32 offset = 0; + __s16 size = 0; + offset = archtosword32(offset); + size = archtosword16(size); + for (vk = TOP; !vk.Error(); vk++) { - if (vk.Testament() == 1) { + if (vk.Testament() < 2) { fd->write(&offset, 4); //compBufIdxOffset fd->write(&offset, 4); fd->write(&size, 2); @@ -461,78 +488,18 @@ char zVerse::createModule(const char *ipath, int blockBound) fd2->write(&size, 2); } } + fd2->write(&offset, 4); //compBufIdxOffset + fd2->write(&offset, 4); + fd2->write(&size, 2); FileMgr::getSystemFileMgr()->close(fd); FileMgr::getSystemFileMgr()->close(fd2); delete [] path; delete [] buf; -/* - RawVerse rv(path); - VerseKey mykey("Rev 22:21"); -*/ return 0; } -/****************************************************************************** - * zVerse::preptext - Prepares the text before returning it to external - * objects - * - * ENT: buf - buffer where text is stored and where to store the prep'd - * text. - */ - -void zVerse::prepText(SWBuf &buf) { - unsigned int to, from; - char space = 0, cr = 0, realdata = 0, nlcnt = 0; - char *rawBuf = buf.getRawData(); - for (to = from = 0; rawBuf[from]; from++) { - switch (rawBuf[from]) { - case 10: - if (!realdata) - continue; - space = (cr) ? 0 : 1; - cr = 0; - nlcnt++; - if (nlcnt > 1) { -// *to++ = nl; - rawBuf[to++] = 10; -// *to++ = nl[1]; -// nlcnt = 0; - } - continue; - case 13: - if (!realdata) - continue; -// *to++ = nl[0]; - rawBuf[to++] = 10; - space = 0; - cr = 1; - continue; - } - realdata = 1; - nlcnt = 0; - if (space) { - space = 0; - if (rawBuf[from] != ' ') { - rawBuf[to++] = ' '; - from--; - continue; - } - } - rawBuf[to++] = rawBuf[from]; - } - buf.setSize(to); - - while (to > 1) { // remove trailing excess - to--; - if ((rawBuf[to] == 10) || (rawBuf[to] == ' ')) - buf.setSize(to); - else break; - } -} - - SWORD_NAMESPACE_END diff --git a/src/modules/filters/Makefile.am b/src/modules/filters/Makefile.am index 7092c73..f212cbf 100644 --- a/src/modules/filters/Makefile.am +++ b/src/modules/filters/Makefile.am @@ -53,17 +53,18 @@ OSISFIL += $(filtersdir)/osisscripref.cpp OSISFIL += $(filtersdir)/osisvariants.cpp OSISFIL += $(filtersdir)/osiswordjs.cpp OSISFIL += $(filtersdir)/osismorphsegmentation.cpp +OSISFIL += $(filtersdir)/osisruby.cpp libsword_la_SOURCES += $(filtersdir)/latin1utf8.cpp libsword_la_SOURCES += $(filtersdir)/latin1utf16.cpp libsword_la_SOURCES += $(filtersdir)/utf8utf16.cpp libsword_la_SOURCES += $(filtersdir)/utf16utf8.cpp -libsword_la_SOURCES += $(filtersdir)/scsuutf8.cpp libsword_la_SOURCES += $(filtersdir)/utf8html.cpp libsword_la_SOURCES += $(filtersdir)/utf8latin1.cpp libsword_la_SOURCES += $(filtersdir)/utf8cantillation.cpp libsword_la_SOURCES += $(filtersdir)/utf8hebrewpoints.cpp +libsword_la_SOURCES += $(filtersdir)/utf8arabicpoints.cpp libsword_la_SOURCES += $(filtersdir)/utf8greekaccents.cpp libsword_la_SOURCES += $(filtersdir)/cipherfil.cpp diff --git a/src/modules/filters/cipherfil.cpp b/src/modules/filters/cipherfil.cpp index 24c665e..34d0465 100644 --- a/src/modules/filters/cipherfil.cpp +++ b/src/modules/filters/cipherfil.cpp @@ -1,6 +1,21 @@ /****************************************************************************** * * cipherfil - SWFilter descendant to decipher a module + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ diff --git a/src/modules/filters/gbffootnotes.cpp b/src/modules/filters/gbffootnotes.cpp index bef29b8..a5384cb 100644 --- a/src/modules/filters/gbffootnotes.cpp +++ b/src/modules/filters/gbffootnotes.cpp @@ -2,6 +2,21 @@ * * gbffootnotes - SWFilter descendant to hide or show footnotes * in a GBF module. + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ @@ -33,7 +48,7 @@ GBFFootnotes::~GBFFootnotes() { char GBFFootnotes::processText (SWBuf &text, const SWKey *key, const SWModule *module) { - + SWBuf token; bool intoken = false; bool hide = false; @@ -42,11 +57,10 @@ char GBFFootnotes::processText (SWBuf &text, const SWKey *key, const SWModule *m SWBuf refs = ""; int footnoteNum = 1; char buf[254]; - VerseKey parser = key->getText(); SWBuf orig = text; const char *from = orig.c_str(); - + //XMLTag tag; for (text = ""; *from; from++) { @@ -61,7 +75,7 @@ char GBFFootnotes::processText (SWBuf &text, const SWKey *key, const SWModule *m //XMLTag tag(token); if (!strncmp(token, "RF",2)) { // tag = token; - + refs = ""; startTag = token; hide = true; @@ -71,7 +85,7 @@ char GBFFootnotes::processText (SWBuf &text, const SWKey *key, const SWModule *m else if (!strncmp(token, "Rf",2)) { if (module->isProcessEntryAttributes()) { //tag = token; - + if((tagText.length() == 1) || !strcmp(module->Name(), "IGNT")) { if (option) { // for ASV marks text in verse then put explanation at end of verse text.append(" <FS>["); @@ -93,7 +107,7 @@ char GBFFootnotes::processText (SWBuf &text, const SWKey *key, const SWModule *m startTag.setAttribute("swordFootnote", buf); } hide = false; - if (option) { + if (option) { text.append(startTag); text.append(tagText); } @@ -120,7 +134,7 @@ char GBFFootnotes::processText (SWBuf &text, const SWKey *key, const SWModule *m else tagText.append(*from); } return 0; - + /* if (!option) { // if we don't want footnotes char token[4096]; // cheese. Fix. diff --git a/src/modules/filters/gbfheadings.cpp b/src/modules/filters/gbfheadings.cpp index 81a4d94..122445e 100644 --- a/src/modules/filters/gbfheadings.cpp +++ b/src/modules/filters/gbfheadings.cpp @@ -2,9 +2,23 @@ * * gbfheadings - SWFilter descendant to hide or show headings * in a GBF module. + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <gbfheadings.h> diff --git a/src/modules/filters/gbfhtml.cpp b/src/modules/filters/gbfhtml.cpp index a9d8434..2467e36 100644 --- a/src/modules/filters/gbfhtml.cpp +++ b/src/modules/filters/gbfhtml.cpp @@ -1,18 +1,24 @@ /*************************************************************************** - gbfhtml.cpp - GBF to HTML filter - ------------------- - begin : 2001-09-03 - copyright : 2001 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ + * gbfhtml.cpp - GBF to HTML filter + * ------------------- + * begin : 2001-09-03 + * copyright : 2001 by CrossWire Bible Society + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <gbfhtml.h> diff --git a/src/modules/filters/gbfhtmlhref.cpp b/src/modules/filters/gbfhtmlhref.cpp index 7f1c254..b4cdde0 100644 --- a/src/modules/filters/gbfhtmlhref.cpp +++ b/src/modules/filters/gbfhtmlhref.cpp @@ -1,20 +1,27 @@ /*************************************************************************** - gbfhtmlhref.cpp - GBF to HTML filter with hrefs - for strongs and morph tags - ------------------- - begin : 2001-09-03 - copyright : 2001 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ + * gbfhtmlhref.cpp - GBF to HTML filter with hrefs + * for strongs and morph tags + * ------------------- + * begin : 2001-09-03 + * copyright : 2001 by CrossWire Bible Society + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + #include <stdlib.h> #include <gbfhtmlhref.h> #include <swmodule.h> diff --git a/src/modules/filters/gbfmorph.cpp b/src/modules/filters/gbfmorph.cpp index 5226db7..d7c8ab4 100644 --- a/src/modules/filters/gbfmorph.cpp +++ b/src/modules/filters/gbfmorph.cpp @@ -2,9 +2,24 @@ * * gbfmorph - SWFilter descendant to hide or show morph tags * in a GBF module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <gbfmorph.h> diff --git a/src/modules/filters/gbfosis.cpp b/src/modules/filters/gbfosis.cpp index 00443f9..526167a 100644 --- a/src/modules/filters/gbfosis.cpp +++ b/src/modules/filters/gbfosis.cpp @@ -2,9 +2,24 @@ * * gbfstrongs - SWFilter descendant to hide or show strongs number * in a GBF module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <stdarg.h> @@ -317,10 +332,10 @@ char GBFOSIS::processText(SWBuf &text, const SWKey *key, const SWModule *module) newWord = false; //fix this if required? - //memset(to, 0, 10); - + //memset(to, 0, 10); + } - + if (!suspendTextPassThru) { text += (*from); lastspace = (*from == ' '); @@ -335,29 +350,29 @@ char GBFOSIS::processText(SWBuf &text, const SWKey *key, const SWModule *module) if (vkey->Verse()) { ref.appendFormatted("\t\t<verse osisID=\"%s\">", vkey->getOSISRef()); } - + if (ref.length() > 0) { - + text = ref + text; - + if (vkey->Verse()) { - VerseKey tmp; - tmp = *vkey; - tmp.AutoNormalize(0); - tmp.Headings(1); - + VerseKey *tmp = (VerseKey *)vkey->clone(); + *tmp = *vkey; + tmp->AutoNormalize(0); + tmp->Headings(1); + text += "</verse>"; - - tmp = MAXVERSE; - if (*vkey == tmp) { - tmp.Verse(0); + + *tmp = MAXVERSE; + if (*vkey == *tmp) { + tmp->Verse(0); // sprintf(ref, "\t</div>"); // pushString(&to, ref); - tmp = MAXCHAPTER; - tmp = MAXVERSE; - if (*vkey == tmp) { - tmp.Chapter(0); - tmp.Verse(0); + *tmp = MAXCHAPTER; + *tmp = MAXVERSE; + if (*vkey == *tmp) { + tmp->Chapter(0); + tmp->Verse(0); // sprintf(ref, "\t</div>"); // pushString(&to, ref); /* @@ -368,6 +383,7 @@ char GBFOSIS::processText(SWBuf &text, const SWKey *key, const SWModule *module) */ } } + delete tmp; } // else if (vkey->Chapter()) { // sprintf(ref, "\t<div type=\"chapter\" osisID=\"%s\">", vkey->getOSISRef()); diff --git a/src/modules/filters/gbfplain.cpp b/src/modules/filters/gbfplain.cpp index 5657e20..e90bf94 100644 --- a/src/modules/filters/gbfplain.cpp +++ b/src/modules/filters/gbfplain.cpp @@ -2,9 +2,24 @@ * * gbfplain - SWFilter descendant to strip out all GBF tags or convert to * ASCII rendered symbols. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <gbfplain.h> #include <swbuf.h> diff --git a/src/modules/filters/gbfredletterwords.cpp b/src/modules/filters/gbfredletterwords.cpp index a79802d..7397781 100644 --- a/src/modules/filters/gbfredletterwords.cpp +++ b/src/modules/filters/gbfredletterwords.cpp @@ -2,9 +2,24 @@ * * GBFRedLetterWords - SWFilter descendant to toggle red coloring of words of * Christ in a GBF module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <gbfredletterwords.h> #include <swmodule.h> diff --git a/src/modules/filters/gbfrtf.cpp b/src/modules/filters/gbfrtf.cpp index eb39612..7471d0b 100644 --- a/src/modules/filters/gbfrtf.cpp +++ b/src/modules/filters/gbfrtf.cpp @@ -1,9 +1,24 @@ /****************************************************************************** * * gbfrtf - SWFilter descendant to convert all GBF tags to RTF tags + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <gbfrtf.h> #include <utilstr.h> #include <ctype.h> diff --git a/src/modules/filters/gbfstrongs.cpp b/src/modules/filters/gbfstrongs.cpp index 610edb5..c7cf6c5 100644 --- a/src/modules/filters/gbfstrongs.cpp +++ b/src/modules/filters/gbfstrongs.cpp @@ -2,9 +2,24 @@ * * gbfstrongs - SWFilter descendant to hide or show strongs number * in a GBF module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <gbfstrongs.h> diff --git a/src/modules/filters/gbfthml.cpp b/src/modules/filters/gbfthml.cpp index 2664f48..4feb1fa 100644 --- a/src/modules/filters/gbfthml.cpp +++ b/src/modules/filters/gbfthml.cpp @@ -1,18 +1,24 @@ /*************************************************************************** - gbfthml.cpp - GBF to ThML filter - ------------------- - begin : 1999-10-27 - copyright : 2001 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ + * gbfthml.cpp - GBF to ThML filter + * ------------------- + * begin : 1999-10-27 + * copyright : 2001 by CrossWire Bible Society + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <gbfthml.h> diff --git a/src/modules/filters/gbfwebif.cpp b/src/modules/filters/gbfwebif.cpp index e651db6..b5ff798 100644 --- a/src/modules/filters/gbfwebif.cpp +++ b/src/modules/filters/gbfwebif.cpp @@ -1,19 +1,26 @@ /*************************************************************************** - GBFWEBIF.cpp - GBF to HTML filter with hrefs - for strongs and morph tags - ------------------- - begin : 2001-09-03 - copyright : 2001 by CrossWire Bible Society - ***************************************************************************/ + * GBFWEBIF.cpp - GBF to HTML filter with hrefs + * for strongs and morph tags + * ------------------- + * begin : 2001-09-03 + * copyright : 2001 by CrossWire Bible Society + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ #include <gbfwebif.h> #include <ctype.h> diff --git a/src/modules/filters/gbfwordjs.cpp b/src/modules/filters/gbfwordjs.cpp index f81ffac..c3ab166 100644 --- a/src/modules/filters/gbfwordjs.cpp +++ b/src/modules/filters/gbfwordjs.cpp @@ -2,9 +2,24 @@ * * gbfstrongs - SWFilter descendant to hide or show strongs number * in a GBF module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <gbfwordjs.h> diff --git a/src/modules/filters/greeklexattribs.cpp b/src/modules/filters/greeklexattribs.cpp index 1e82305..e1a60a2 100644 --- a/src/modules/filters/greeklexattribs.cpp +++ b/src/modules/filters/greeklexattribs.cpp @@ -2,9 +2,24 @@ * * greeklexattribs - SWFilter descendant to set entry attributes for greek * lexicons + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <ctype.h> diff --git a/src/modules/filters/latin1utf16.cpp b/src/modules/filters/latin1utf16.cpp index 1392750..bf2f3f8 100644 --- a/src/modules/filters/latin1utf16.cpp +++ b/src/modules/filters/latin1utf16.cpp @@ -1,10 +1,25 @@ /****************************************************************************** * - * Latin1UTF16 - SWFilter descendant to convert a Latin-1 character to UTF-16 + * Latin1UTF16 - SWFilter descendant to convert a Latin-1 character to UTF-16 + * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. * */ - #include <stdlib.h> #include <stdio.h> #include <latin1utf16.h> diff --git a/src/modules/filters/latin1utf8.cpp b/src/modules/filters/latin1utf8.cpp index 6c0d7f1..784aafe 100644 --- a/src/modules/filters/latin1utf8.cpp +++ b/src/modules/filters/latin1utf8.cpp @@ -2,9 +2,24 @@ * * Latin1UTF8 - SWFilter descendant to convert a Latin-1 character to UTF-8 * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <latin1utf8.h> diff --git a/src/modules/filters/osisfootnotes.cpp b/src/modules/filters/osisfootnotes.cpp index 89c9c40..3d0d2d4 100644 --- a/src/modules/filters/osisfootnotes.cpp +++ b/src/modules/filters/osisfootnotes.cpp @@ -2,9 +2,24 @@ * * osisfootnotes - SWFilter descendant to hide or show footnotes * in an OSIS module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <osisfootnotes.h> @@ -41,11 +56,17 @@ char OSISFootnotes::processText(SWBuf &text, const SWKey *key, const SWModule *m SWBuf refs = ""; int footnoteNum = 1; char buf[254]; - VerseKey parser(key->getText()); + SWKey *p = (module) ? module->CreateKey() : (key) ? key->clone() : new VerseKey(); + VerseKey *parser = SWDYNAMIC_CAST(VerseKey, p); + if (!parser) { + delete p; + parser = new VerseKey(); + } + *parser = key->getText(); SWBuf orig = text; const char *from = orig.c_str(); - + XMLTag tag; bool strongsMarkup = false; @@ -59,20 +80,20 @@ char OSISFootnotes::processText(SWBuf &text, const SWKey *key, const SWModule *m continue; } - + if (*from == '<') { intoken = true; token = ""; continue; } - - - + + + if (*from == '>') { // process tokens - intoken = false; + intoken = false; if (!strncmp(token, "note", 4) || !strncmp(token.c_str(), "/note", 5)) { tag = token; - + if (!tag.isEndTag()) { if (tag.getAttribute("type") && (!strcmp("x-strongsMarkup", tag.getAttribute("type")) || !strcmp("strongsMarkup", tag.getAttribute("type"))) // deprecated @@ -80,7 +101,7 @@ char OSISFootnotes::processText(SWBuf &text, const SWKey *key, const SWModule *m tag.setEmpty(false); // handle bug in KJV2003 module where some note open tags were <note ... /> strongsMarkup = true; } - + if (!tag.isEmpty()) { // if ((!tag.isEmpty()) || (SWBuf("strongsMarkup") == tag.getAttribute("type"))) { refs = ""; @@ -101,7 +122,7 @@ char OSISFootnotes::processText(SWBuf &text, const SWKey *key, const SWModule *m startTag.setAttribute("swordFootnote", buf); if ((startTag.getAttribute("type")) && (!strcmp(startTag.getAttribute("type"), "crossReference"))) { if (!refs.length()) - refs = parser.ParseVerseList(tagText.c_str(), parser, true).getRangeText(); + refs = parser->ParseVerseList(tagText.c_str(), *parser, true).getRangeText(); module->getEntryAttributes()["Footnote"][buf]["refList"] = refs.c_str(); } } @@ -122,7 +143,7 @@ char OSISFootnotes::processText(SWBuf &text, const SWKey *key, const SWModule *m if (refs.length()) { refs.append("; "); } - + const char* attr = strstr(token.c_str() + 9, "osisRef=\""); const char* end = attr ? strchr(attr+9, '"') : 0; @@ -150,6 +171,7 @@ char OSISFootnotes::processText(SWBuf &text, const SWKey *key, const SWModule *m } else tagText.append(*from); } + delete parser; return 0; } diff --git a/src/modules/filters/osisheadings.cpp b/src/modules/filters/osisheadings.cpp index a072335..8872f24 100644 --- a/src/modules/filters/osisheadings.cpp +++ b/src/modules/filters/osisheadings.cpp @@ -2,9 +2,24 @@ * *osisheadings - SWFilter descendant to hide or show headings * in an OSIS module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <osisheadings.h> @@ -35,6 +50,9 @@ char OSISHeadings::processText(SWBuf &text, const SWKey *key, const SWModule *mo bool hide = false; bool preverse = false; bool withinTitle = false; + bool withinPreverseDiv = false; + SWBuf preverseDivID = ""; + const char *pvDID = 0; bool canonical = false; SWBuf header; int headerNum = 0; @@ -56,27 +74,41 @@ char OSISHeadings::processText(SWBuf &text, const SWKey *key, const SWModule *mo } if (*from == '>') { // process tokens intoken = false; - - if (!strncmp(token.c_str(), "title", 5) || !strncmp(token.c_str(), "/title", 6)) { - withinTitle = (!strnicmp(token.c_str(), "title", 5)); - tag = token; + tag = token; + + // <title> </title> <div subType="x-preverse"> (</div> ## when in previous) + if ( (!withinPreverseDiv && !strcmp(tag.getName(), "title")) || + (!strcmp(tag.getName(), "div") && + ((withinPreverseDiv && (tag.isEndTag(pvDID))) || + (tag.getAttribute("subType") && !strcmp(tag.getAttribute("subType"), "x-preverse"))) + )) { + + withinTitle = (!tag.isEndTag(pvDID)); + if (!strcmp(tag.getName(), "div")) { + withinPreverseDiv = (!tag.isEndTag(pvDID)); + if (!pvDID) { + preverseDivID = tag.getAttribute("sID"); + pvDID = (preverseDivID.length())? preverseDivID.c_str() : 0; + } + } - if (!tag.isEndTag()) { //start tag - if (!tag.isEmpty()) { + if (!tag.isEndTag(pvDID)) { //start tag + if (!tag.isEmpty() || pvDID) { startTag = tag; } } - if ( (tag.getAttribute("subType") && !stricmp(tag.getAttribute("subType"), "x-preverse")) - || (tag.getAttribute("subtype") && !stricmp(tag.getAttribute("subtype"), "x-preverse")) // deprecated - ) { + if ( !tag.isEndTag(pvDID) && (withinPreverseDiv + || (tag.getAttribute("subType") && !stricmp(tag.getAttribute("subType"), "x-preverse")) + || (tag.getAttribute("subtype") && !stricmp(tag.getAttribute("subtype"), "x-preverse")) // deprecated + )) { hide = true; preverse = true; header = ""; canonical = (tag.getAttribute("canonical") && (!stricmp(tag.getAttribute("canonical"), "true"))); continue; } - if (!tag.isEndTag()) { //start tag + if (!tag.isEndTag(pvDID)) { //start tag hide = true; header = ""; if (option || canonical) { // we want the tag in the text @@ -86,7 +118,7 @@ char OSISHeadings::processText(SWBuf &text, const SWKey *key, const SWModule *mo } continue; } - if (hide && tag.isEndTag()) { + if (hide && tag.isEndTag(pvDID)) { if (module->isProcessEntryAttributes() && ((option || canonical) || (!preverse))) { if (preverse) { sprintf(buf, "%i", pvHeaderNum++); @@ -112,6 +144,7 @@ char OSISHeadings::processText(SWBuf &text, const SWKey *key, const SWModule *mo continue; } preverse = false; + pvDID = 0; } } diff --git a/src/modules/filters/osishtmlhref.cpp b/src/modules/filters/osishtmlhref.cpp index fe3e058..6fce987 100644 --- a/src/modules/filters/osishtmlhref.cpp +++ b/src/modules/filters/osishtmlhref.cpp @@ -1,17 +1,25 @@ /*************************************************************************** - osishtmlhref.cpp - OSIS to HTML with hrefs filter - ------------------- - begin : 2003-06-24 - copyright : 2003 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation version 2 of the License. * - * * - ***************************************************************************/ + * osishtmlhref.cpp - OSIS to HTML with hrefs filter + * ------------------- + * begin : 2003-06-24 + * copyright : 2003 by CrossWire Bible Society + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <ctype.h> @@ -111,7 +119,7 @@ void processLemma(bool suspendTextPassThru, XMLTag &tag, SWBuf &buf) { if (!suspendTextPassThru) { buf.appendFormatted("<small><em><<a href=\"passagestudy.jsp?action=showStrongs&type=%s&value=%s\">%s</a>></em></small>", (gh.length()) ? gh.c_str() : "", - URL::encode(val2).c_str(), + URL::encode(val2).c_str(), val2); } //} @@ -188,8 +196,9 @@ bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat if ((attrib = tag.getAttribute("gloss"))) { val = strchr(attrib, ':'); val = (val) ? (val + 1) : attrib; - outText(" ", buf, u); + outText("(", buf, u); outText(val, buf, u); + outText(")", buf, u); } if (!morphFirst) { processLemma(u->suspendTextPassThru, tag, buf); @@ -278,49 +287,71 @@ bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat } } + // Milestoned paragraphs, created by osis2mod + // <div type="paragraph" sID.../> + // <div type="paragraph" eID.../> + else if (tag.isEmpty() && !strcmp(tag.getName(), "div") && tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "paragraph")) { + // <div type="paragraph" sID... /> + if (tag.getAttribute("sID")) { // non-empty start tag + outText("<!P><br />", buf, u); + } + // <div type="paragraph" eID... /> + else if (tag.getAttribute("eID")) { + outText("<!/P><br />", buf, u); + userData->supressAdjacentWhitespace = true; + } + } + // <reference> tag else if (!strcmp(tag.getName(), "reference")) { if (!u->inXRefNote) { // only show these if we're not in an xref note - if ((!tag.isEndTag()) && (!tag.isEmpty())) { - u->suspendTextPassThru = (++u->suspendLevel); - } - if (tag.isEndTag()) { - if (!u->BiblicalText) { - SWBuf refList = tag.getAttribute("passage"); - if (!refList.length()) - refList = u->lastTextNode; - SWBuf version = tag.getAttribute("version"); - - buf.appendFormatted(" <a href=\"passagestudy.jsp?action=showRef&type=scripRef&value=%s&module=%s\">", - (refList.length()) ? URL::encode(refList.c_str()).c_str() : "", - (version.length()) ? URL::encode(version.c_str()).c_str() : ""); - buf += u->lastTextNode.c_str(); - buf += "</a> "; + if (!tag.isEndTag()) { + SWBuf target; + SWBuf work; + SWBuf ref; + bool is_scripRef = false; + + target = tag.getAttribute("osisRef"); + const char* the_ref = strchr(target, ':'); + + if(!the_ref) { + // No work + ref = target; + is_scripRef = true; } else { - SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); - VerseKey *vkey = NULL; - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) {} - if (vkey) { - // leave this special osis type in for crossReference notes types? Might thml use this some day? Doesn't hurt. - //buf.appendFormatted("<a href=\"noteID=%s.x.%s\"><small><sup>*x</sup></small></a> ", vkey->getText(), footnoteNumber.c_str()); - buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=x&value=%s&module=%s&passage=%s\"><small><sup>*x</sup></small></a>", - URL::encode(footnoteNumber.c_str()).c_str(), - URL::encode(u->version.c_str()).c_str(), - URL::encode(vkey->getText()).c_str()); - - } + // Compensate for starting : + ref = the_ref + 1; + + int size = target.size() - ref.size() - 1; + work.setSize(size); + strncpy(work.getRawData(), target, size); + + // For Bible:Gen.3.15 or Bible.vulgate:Gen.3.15 + if(!strncmp(work, "Bible", 5)) + is_scripRef = true; + } + + if(is_scripRef) + { + buf.appendFormatted("<a href=\"passagestudy.jsp?action=showRef&type=scripRef&value=%s&module=\">", + URL::encode(ref.c_str()).c_str() +// (work.size()) ? URL::encode(work.c_str()).c_str() : "") + ); + } + else + { + // Dictionary link, or something + buf.appendFormatted("<a href=\"sword://%s/%s\">", + URL::encode(work.c_str()).c_str(), + URL::encode(ref.c_str()).c_str() + ); } - u->suspendTextPassThru = (--u->suspendLevel); } - }/* - if (tag.isEndTag()) { - u->suspendTextPassThru = false; - }*/ + else { + outText("</a>", buf, u); + } + } } // <l> poetry, etc @@ -383,7 +414,26 @@ bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat outText("</b><br />", buf, u); } } + + // <list> + else if (!strcmp(tag.getName(), "list")) { + if((!tag.isEndTag()) && (!tag.isEmpty())) { + outText("<ul>", buf, u); + } + else if (tag.isEndTag()) { + outText("</ul>", buf, u); + } + } + // <item> + else if (!strcmp(tag.getName(), "item")) { + if((!tag.isEndTag()) && (!tag.isEmpty())) { + outText("<li>", buf, u); + } + else if (tag.isEndTag()) { + outText("</li>", buf, u); + } + } // <catchWord> & <rdg> tags (italicize) else if (!strcmp(tag.getName(), "rdg") || !strcmp(tag.getName(), "catchWord")) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { @@ -405,6 +455,16 @@ bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat if (lastText.size()) { toupperstr(lastText); scratch.setFormatted("%c<font size=\"-1\">%s</font>", lastText[0], lastText.c_str()+1); + + const unsigned char *tmpBuf = (const unsigned char *)lastText.c_str(); + getUniCharFromUTF8(&tmpBuf); + int char_length = (tmpBuf - (const unsigned char *)lastText.c_str()); + scratch.setFormatted("%.*s<font size=\"-1\">%s</font>", + char_length, + lastText.c_str(), + lastText.c_str() + char_length + ); + outText(scratch.c_str(), buf, u); } } @@ -542,8 +602,7 @@ bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat outText(URL::encode(u->version.c_str()).c_str(), buf, u); outText("\">", buf, u); -// we do this because BibleCS looks for this EXACT format for an image tag - outText("<image border=0 src=\"", buf, u); + outText("<img border=\"0\" src=\"", buf, u); outText(filepath, buf, u); outText("\" />", buf, u); diff --git a/src/modules/filters/osislemma.cpp b/src/modules/filters/osislemma.cpp index f5e6ff6..7b56024 100644 --- a/src/modules/filters/osislemma.cpp +++ b/src/modules/filters/osislemma.cpp @@ -2,9 +2,24 @@ * * osislemma - SWFilter descendant to hide or show lemmata * in a OSIS module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <osislemma.h> #include <utilxml.h> diff --git a/src/modules/filters/osismorph.cpp b/src/modules/filters/osismorph.cpp index 69d44d5..7ceec79 100644 --- a/src/modules/filters/osismorph.cpp +++ b/src/modules/filters/osismorph.cpp @@ -2,9 +2,24 @@ * * osismorph - SWFilter descendant to hide or show morph tags * in a OSIS module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <osismorph.h> diff --git a/src/modules/filters/osismorphsegmentation.cpp b/src/modules/filters/osismorphsegmentation.cpp index bf32581..fef7af7 100644 --- a/src/modules/filters/osismorphsegmentation.cpp +++ b/src/modules/filters/osismorphsegmentation.cpp @@ -2,9 +2,24 @@ * * osismorphsegmentation - SWFilter descendant to toggle splitting of morphemes * (for morpheme segmented Hebrew in the WLC) + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <osismorphsegmentation.h> #include <stdlib.h> #include <utilxml.h> diff --git a/src/modules/filters/osisosis.cpp b/src/modules/filters/osisosis.cpp index 7da6089..82a6bfc 100644 --- a/src/modules/filters/osisosis.cpp +++ b/src/modules/filters/osisosis.cpp @@ -1,17 +1,24 @@ /*************************************************************************** - osisosis.cpp - internal OSIS to public OSIS filter - ------------------- - begin : 2004-03-13 - copyright : 2003 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation version 2 of the License. - * * - ***************************************************************************/ + * osisosis.cpp - internal OSIS to public OSIS filter + * ------------------- + * begin : 2004-03-13 + * copyright : 2003 by CrossWire Bible Society + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <osisosis.h> @@ -55,33 +62,34 @@ char OSISOSIS::processText(SWBuf &text, const SWKey *key, const SWModule *module if (vkey->Verse()) { ref.appendFormatted("\t\t<verse osisID=\"%s\">", vkey->getOSISRef()); } - + if (ref.length() > 0) { - + text = ref + text; - + if (vkey->Verse()) { - VerseKey tmp; - tmp = *vkey; - tmp.AutoNormalize(0); - tmp.Headings(1); - + VerseKey *tmp = (VerseKey *)vkey->clone(); + *tmp = *vkey; + tmp->AutoNormalize(0); + tmp->Headings(1); + text += "</verse>"; - - tmp = MAXVERSE; - if (*vkey == tmp) { - tmp.Verse(0); + + *tmp = MAXVERSE; + if (*vkey == *tmp) { + tmp->Verse(0); // sprintf(ref, "\t</div>"); // pushString(&to, ref); - tmp = MAXCHAPTER; - tmp = MAXVERSE; - if (*vkey == tmp) { - tmp.Chapter(0); - tmp.Verse(0); + *tmp = MAXCHAPTER; + *tmp = MAXVERSE; + if (*vkey == *tmp) { + tmp->Chapter(0); + tmp->Verse(0); // sprintf(ref, "\t</div>"); // pushString(&to, ref); } } + delete tmp; } // diff --git a/src/modules/filters/osisplain.cpp b/src/modules/filters/osisplain.cpp index 62841a6..57105f0 100644 --- a/src/modules/filters/osisplain.cpp +++ b/src/modules/filters/osisplain.cpp @@ -1,18 +1,24 @@ -/*************************************************************************** - osisplain.cpp - OSIS to Plaintext filter - ------------------- - begin : 2003-02-15 - copyright : 2003 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/****************************************************************************** + * osisplain.cpp - An SWFilter + * impl that provides stripping of OSIS tags + * + * $Id: osisplain.cpp 2334 2009-04-24 00:14:12Z scribe $ + * + * Copyright 2001 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <osisplain.h> @@ -22,6 +28,17 @@ SWORD_NAMESPACE_START +namespace { +class MyUserData : public BasicFilterUserData { +public: + SWBuf w; + XMLTag tag; + VerseKey *vk; + char testament; + MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) {} +}; +} + OSISPlain::OSISPlain() { setTokenStart("<"); setTokenEnd(">"); @@ -45,13 +62,18 @@ OSISPlain::OSISPlain() { addTokenSubstitute("/lg", "\n"); } +BasicFilterUserData *OSISPlain::createUserData(const SWModule *module, const SWKey *key) { + MyUserData *u = new MyUserData(module, key); + u->vk = SWDYNAMIC_CAST(VerseKey, u->key); + u->testament = (u->vk) ? u->vk->Testament() : 2; // default to NT + return u; +} + bool OSISPlain::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) { // manually process if it wasn't a simple substitution if (!substituteToken(buf, token)) { MyUserData *u = (MyUserData *)userData; - VerseKey *vk = SWDYNAMIC_CAST(VerseKey, u->key); - char testament = (vk) ? vk ->Testament() : 2; // default to NT if (((*token == 'w') && (token[1] == ' ')) || ((*token == '/') && (token[1] == 'w') && (!token[2]))) { u->tag = token; @@ -99,7 +121,7 @@ bool OSISPlain::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * val++; } else { - gh = (testament>1) ? 'G' : 'H'; + gh = (u->testament>1) ? 'G' : 'H'; } if ((!strcmp(val, "3588")) && (lastText.length() < 1)) show = false; @@ -139,13 +161,13 @@ bool OSISPlain::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * // <note> tag else if (!strncmp(token, "note", 4)) { if (!strstr(token, "strongsMarkup")) { // leave strong's markup notes out, in the future we'll probably have different option filters to turn different note types on or off - buf.append(" ("); + buf.append(" ["); } else u->suspendTextPassThru = true; } else if (!strncmp(token, "/note", 5)) { if (!u->suspendTextPassThru) - buf.append(')'); + buf.append("] "); else u->suspendTextPassThru = false; } @@ -156,6 +178,15 @@ bool OSISPlain::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * buf.append('\n'); } + // Milestoned paragraph, created by osis2mod + // <div type="paragraph" sID... /> + // <div type="paragraph" eID... /> + else if (!strcmp(u->tag.getName(), "div") && u->tag.getAttribute("type") && !strcmp(u->tag.getAttribute("type"), "paragraph") && + (u->tag.isEmpty() && (u->tag.getAttribute("sID") || u->tag.getAttribute("eID")))) { + userData->supressAdjacentWhitespace = true; + buf.append('\n'); + } + // <lb .../> else if (!strncmp(token, "lb", 2)) { userData->supressAdjacentWhitespace = true; diff --git a/src/modules/filters/osisredletterwords.cpp b/src/modules/filters/osisredletterwords.cpp index 727332d..9075fd8 100644 --- a/src/modules/filters/osisredletterwords.cpp +++ b/src/modules/filters/osisredletterwords.cpp @@ -2,9 +2,24 @@ * * OSISRedLetterWords - SWFilter descendant to toggle red coloring for words * of Christ in an OSIS module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <osisredletterwords.h> #include <swmodule.h> diff --git a/src/modules/filters/osisrtf.cpp b/src/modules/filters/osisrtf.cpp index 0352335..84801e3 100644 --- a/src/modules/filters/osisrtf.cpp +++ b/src/modules/filters/osisrtf.cpp @@ -1,17 +1,25 @@ /*************************************************************************** - osisrtf.cpp - OSIS to RTF filter - ------------------- - begin : 2003-02-15 - copyright : 2003 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation version 2 of the License. * - * * - ***************************************************************************/ + * osisrtf.cpp - OSIS to RTF filter + * ------------------- + * begin : 2003-02-15 + * copyright : 2003 by CrossWire Bible Society + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <ctype.h> @@ -272,6 +280,21 @@ bool OSISRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *us } } + // Milestoned paragraphs, created by osis2mod + // <div type="paragraph" sID.../> + // <div type="paragraph" eID.../> + else if (tag.isEmpty() && !strcmp(tag.getName(), "div") && tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "paragraph")) { + // <div type="paragraph" sID... /> + if (tag.getAttribute("sID")) { // non-empty start tag + outText("{\\fi200\\par}", buf, u); + } + // <div type="paragraph" eID... /> + else if (tag.getAttribute("eID")) { + outText("{\\par}", buf, u); + userData->supressAdjacentWhitespace = true; + } + } + // <reference> tag else if (!strcmp(tag.getName(), "reference")) { if (!u->inXRefNote) { // only show these if we're not in an xref note @@ -316,6 +339,25 @@ bool OSISRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *us outText("\\par}", buf, u); } } + // <list> - how do we support these better in RTF? + else if (!strcmp(tag.getName(), "list")) { + if((!tag.isEndTag()) && (!tag.isEmpty())) { + outText("\\par\\pard", buf, u); + } + else if (tag.isEndTag()) { + outText("\\par\\pard", buf, u); + } + } + + // <item> - support better + else if (!strcmp(tag.getName(), "item")) { + if((!tag.isEndTag()) && (!tag.isEmpty())) { + outText("* ", buf, u); + } + else if (tag.isEndTag()) { + outText("\\par", buf, u); + } + } // <catchWord> & <rdg> tags (italicize) else if (!strcmp(tag.getName(), "rdg") || !strcmp(tag.getName(), "catchWord")) { @@ -445,16 +487,10 @@ bool OSISRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *us else if (!strcmp(tag.getName(), "divineName")) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { - u->suspendTextPassThru = (++u->suspendLevel); + outText("{\\scaps ", buf, u); } else if (tag.isEndTag()) { - SWBuf lastText = u->lastSuspendSegment.c_str(); - u->suspendTextPassThru = (--u->suspendLevel); - if (lastText.size()) { - toupperstr(lastText); - scratch.setFormatted("{\\fs19%c\\fs16%s}", lastText[0], lastText.c_str()+1); - outText(scratch.c_str(), buf, u); - } + outText("}", buf, u); } } @@ -462,10 +498,11 @@ bool OSISRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *us else if (!strcmp(tag.getName(), "div")) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { - outText("\\par\\par\\pard ", buf, u); + outText("\\pard ", buf, u); } else if (tag.isEndTag()) { - } + outText("\\par ", buf, u); + } } // image diff --git a/src/modules/filters/osisruby.cpp b/src/modules/filters/osisruby.cpp new file mode 100644 index 0000000..c17ea43 --- /dev/null +++ b/src/modules/filters/osisruby.cpp @@ -0,0 +1,93 @@ +/******************************************************************************
+ *
+ * osisruby - SWFilter descendant to hide or show ruby
+ * in a OSIS module.
+ *
+ *
+ * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org)
+ * CrossWire Bible Society
+ * P. O. Box 2528
+ * Tempe, AZ 85280-2528
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#include <stdlib.h>
+#include <osisruby.h>
+#include <utilxml.h>
+
+SWORD_NAMESPACE_START
+
+const char oName[] = "Ruby";
+const char oTip[] = "Toggles Ruby On and Off if they exist";
+
+const SWBuf choices[3] = {"Off", "On", ""};
+const StringList oValues(&choices[0], &choices[2]);
+
+OSISRuby::OSISRuby() : SWOptionFilter(oName, oTip, &oValues) {
+ setOptionValue("Off");
+}
+
+
+OSISRuby::~OSISRuby() {
+}
+
+
+char OSISRuby::processText(SWBuf &text, const SWKey *key, const SWModule *module) {
+ SWBuf token;
+ bool intoken = false;
+ bool lastspace = false;
+
+ const SWBuf orig = text;
+ const char * from = orig.c_str();
+
+ if (!option) {
+ for (text = ""; *from; ++from) {
+ if (*from == '<') {
+ intoken = true;
+ token = "";
+ continue;
+ }
+ if (*from == '>') { // process tokens
+ intoken = false;
+ if (token.startsWith("w ")) { // Word
+ XMLTag wtag(token);
+ const char *l = wtag.getAttribute("gloss");
+ if (l) {
+ wtag.setAttribute("gloss", 0);
+ token = wtag;
+ token.trim();
+ // drop <>
+ token << 1;
+ token--;
+ }
+ }
+
+ // keep token in text
+ text.append('<');
+ text.append(token);
+ text.append('>');
+
+ continue;
+ }
+ if (intoken) {
+ token += *from;
+ }
+ else {
+ text.append(*from);
+ lastspace = (*from == ' ');
+ }
+ }
+ }
+ return 0;
+}
+
+SWORD_NAMESPACE_END
diff --git a/src/modules/filters/osisscripref.cpp b/src/modules/filters/osisscripref.cpp index 437f5f5..73c7309 100644 --- a/src/modules/filters/osisscripref.cpp +++ b/src/modules/filters/osisscripref.cpp @@ -2,9 +2,24 @@ * * OSISScripref - SWFilter descendant to hide or show scripture references * in an OSIS module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <osisscripref.h> #include <swmodule.h> diff --git a/src/modules/filters/osisstrongs.cpp b/src/modules/filters/osisstrongs.cpp index 922f7fd..8c06b07 100644 --- a/src/modules/filters/osisstrongs.cpp +++ b/src/modules/filters/osisstrongs.cpp @@ -2,9 +2,24 @@ * * osisstrongs - SWFilter descendant to hide or show strongs number * in a OSIS module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <ctype.h> @@ -38,6 +53,7 @@ char OSISStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *mod int wordNum = 1; char wordstr[5]; const char *wordStart = 0; + SWBuf page = ""; // some modules include <seg> page info, so we add these to the words const SWBuf orig = text; const char * from = orig.c_str(); @@ -50,6 +66,20 @@ char OSISStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *mod } if (*from == '>') { // process tokens intoken = false; + + // possible page seg -------------------------------- + if (token.startsWith("seg ")) { + XMLTag stag(token); + SWBuf type = stag.getAttribute("type"); + if (type == "page") { + SWBuf number = stag.getAttribute("subtype"); + if (number.length()) { + page = number; + } + } + } + // --------------------------------------------------- + if (token.startsWith("w ")) { // Word XMLTag wtag(token); if (module->isProcessEntryAttributes()) { @@ -167,15 +197,17 @@ char OSISStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *mod if (lemma.length()) - module->getEntryAttributes()["Word"][wordstr]["Lemma"] = lemma; + module->getEntryAttributes()["Word"][wordstr]["Lemma"] = lemma; if (lemmaClass.length()) - module->getEntryAttributes()["Word"][wordstr]["LemmaClass"] = lemmaClass; + module->getEntryAttributes()["Word"][wordstr]["LemmaClass"] = lemmaClass; if (morph.length()) - module->getEntryAttributes()["Word"][wordstr]["Morph"] = morph; + module->getEntryAttributes()["Word"][wordstr]["Morph"] = morph; if (morphClass.length()) - module->getEntryAttributes()["Word"][wordstr]["MorphClass"] = morphClass; + module->getEntryAttributes()["Word"][wordstr]["MorphClass"] = morphClass; if (src.length()) module->getEntryAttributes()["Word"][wordstr]["Src"] = src; + if (page.length()) + module->getEntryAttributes()["Word"][wordstr]["Page"] = page; if (wtag.isEmpty()) { int j; diff --git a/src/modules/filters/osisvariants.cpp b/src/modules/filters/osisvariants.cpp index 91d700c..16e0cfb 100644 --- a/src/modules/filters/osisvariants.cpp +++ b/src/modules/filters/osisvariants.cpp @@ -2,9 +2,24 @@ * * osisvariants - SWFilter descendant to hide or show textual variants * in an OSIS module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <osisvariants.h> #include <utilstr.h> diff --git a/src/modules/filters/osiswebif.cpp b/src/modules/filters/osiswebif.cpp index ecc58f7..e313836 100644 --- a/src/modules/filters/osiswebif.cpp +++ b/src/modules/filters/osiswebif.cpp @@ -1,19 +1,25 @@ /*************************************************************************** - OSISWEBIF.cpp - OSIS to HTML filter with hrefs - for strongs and morph tags - ------------------- - begin : 2003-10-23 - copyright : 2003 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ + * OSISWEBIF.cpp - OSIS to HTML filter with hrefs + * for strongs and morph tags + * ------------------- + * begin : 2003-10-23 + * copyright : 2003 by CrossWire Bible Society + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <osiswebif.h> @@ -169,6 +175,14 @@ bool OSISWEBIF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * } } + // Milestoned paragraphs, created by osis2mod + // <div type="paragraph" sID.../> + // <div type="paragraph" eID.../> + else if (tag.isEmpty() && !strcmp(tag.getName(), "div") && tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "paragraph")) { + // This is properly handled by base class. + return OSISHTMLHREF::handleToken(buf, token, userData); + } + // ok to leave these in else if (!strcmp(tag.getName(), "div")) { buf += tag; diff --git a/src/modules/filters/osiswordjs.cpp b/src/modules/filters/osiswordjs.cpp index dc805b4..da573d3 100644 --- a/src/modules/filters/osiswordjs.cpp +++ b/src/modules/filters/osiswordjs.cpp @@ -2,9 +2,24 @@ * * osisstrongs - SWFilter descendant to hide or show strongs number * in a OSIS module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <osiswordjs.h> @@ -76,8 +91,11 @@ char OSISWordJS::processText(SWBuf &text, const SWKey *key, const SWModule *modu SWBuf lemmaClass; SWBuf lemma; SWBuf morph; + SWBuf page; SWBuf src; char gh = 0; + page = module->getEntryAttributes()["Word"][wordstr]["Page"].c_str(); + if (page.length()) page = (SWBuf)"p:" + page; int count = atoi(module->getEntryAttributes()["Word"][wordstr]["PartCount"].c_str()); for (int i = 0; i < count; i++) { @@ -146,7 +164,7 @@ char OSISWordJS::processText(SWBuf &text, const SWKey *key, const SWModule *modu } } // 'p' = 'fillpop' to save bandwidth - text.appendFormatted("<span class=\"clk\" onclick=\"p('%s','%s','%s','%s','','%s');\" >", lexName.c_str(), lemma.c_str(), wordID.c_str(), morph.c_str(), modName.c_str()); + text.appendFormatted("<span class=\"clk\" onclick=\"p('%s','%s','%s','%s','%s','%s');\" >", lexName.c_str(), lemma.c_str(), wordID.c_str(), morph.c_str(), page.c_str(), modName.c_str()); wordNum++; } if ((*token == '/') && (token[1] == 'w') && option) { // Word diff --git a/src/modules/filters/papyriplain.cpp b/src/modules/filters/papyriplain.cpp index 423bfda..782b52a 100644 --- a/src/modules/filters/papyriplain.cpp +++ b/src/modules/filters/papyriplain.cpp @@ -1,9 +1,24 @@ /****************************************************************************** * * papyriplain - SWFilter descendant to strip out all Papyri tags + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <papyriplain.h> diff --git a/src/modules/filters/plainfootnotes.cpp b/src/modules/filters/plainfootnotes.cpp index 0baf313..449f7da 100644 --- a/src/modules/filters/plainfootnotes.cpp +++ b/src/modules/filters/plainfootnotes.cpp @@ -1,19 +1,25 @@ /*************************************************************************** - plainfootnotes.cpp - description - ------------------- - begin : Wed Oct 13 1999 - copyright : (C) 1999 by The team of BibleTime - email : info@bibletime.de - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ + * plainfootnotes.cpp - description + * ------------------- + * begin : Wed Oct 13 1999 + * copyright : (C) 1999 by The team of BibleTime + * email : info@bibletime.de + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <plainfootnotes.h> #include <swkey.h> diff --git a/src/modules/filters/plainhtml.cpp b/src/modules/filters/plainhtml.cpp index f5f2a5c..3f989fa 100644 --- a/src/modules/filters/plainhtml.cpp +++ b/src/modules/filters/plainhtml.cpp @@ -1,19 +1,25 @@ /*************************************************************************** - plainhtml.cpp - description - ------------------- - begin : Thu Jun 24 1999 - copyright : (C) 1999 by Torsten Uhlmann - email : TUhlmann@gmx.de - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ + * plainhtml.cpp - description + * ------------------- + * begin : Thu Jun 24 1999 + * copyright : (C) 1999 by Torsten Uhlmann + * email : TUhlmann@gmx.de + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <plainhtml.h> #include <swbuf.h> diff --git a/src/modules/filters/rtfhtml.cpp b/src/modules/filters/rtfhtml.cpp index cac5068..7b55721 100644 --- a/src/modules/filters/rtfhtml.cpp +++ b/src/modules/filters/rtfhtml.cpp @@ -1,19 +1,25 @@ /*************************************************************************** - rtfhtml.cpp - description - ------------------- - begin : Wed Oct 13 1999 - copyright : (C) 1999 by The team of BibleTime - email : info@bibletime.de - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ + * rtfhtml.cpp - description + * ------------------- + * begin : Wed Oct 13 1999 + * copyright : (C) 1999 by The team of BibleTime + * email : info@bibletime.de + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <rtfhtml.h> diff --git a/src/modules/filters/scsuutf8.cpp b/src/modules/filters/scsuutf8.cpp deleted file mode 100644 index 0daff4a..0000000 --- a/src/modules/filters/scsuutf8.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/****************************************************************************** - * - * SCSUUTF8 - SWFilter descendant to convert a SCSU character to UTF-8 - * - */ - - -/* This class is based on: - * http://czyborra.com/scsu/scsu.c written by Roman Czyborra@dds.nl - * on Andrea's balcony in North Amsterdam on 1998-08-04 - * Thanks to Richard Verhoeven <rcb5@win.tue.nl> for his suggestion - * to correct the haphazard "if" after UQU to "else if" on 1998-10-01 - * - * This is a deflator to UTF-8 output for input compressed in SCSU, - * the (Reuters) Standard Compression Scheme for Unicode as described - * in http://www.unicode.org/unicode/reports/tr6.html - */ - -#include <stdlib.h> -#include <stdio.h> -#include <swmodule.h> - -#include <scsuutf8.h> - -SWORD_NAMESPACE_START - -SCSUUTF8::SCSUUTF8() { -} - - -unsigned char* SCSUUTF8::UTF8Output(unsigned long uchar, unsigned char* text) -{ - /* join UTF-16 surrogates without any pairing sanity checks */ - - static int d; - - if (uchar >= 0xd800 && uchar <= 0xdbff) { d = uchar & 0x3f; return text; } - if (uchar >= 0xdc00 && uchar <= 0xdfff) { uchar = uchar + 0x2400 + d * 0x400; } - - /* output one character as UTF-8 multibyte sequence */ - - if (uchar < 0x80) { - *text++ = c; - } - else if (uchar < 0x800) { - *text++ = 0xc0 | uchar >> 6; - *text++ = 0x80 | (uchar & 0x3f); - } - else if (uchar < 0x10000) { - *text++ = 0xe0 | uchar >> 12; - *text++ = 0x80 | (uchar >> 6 & 0x3f); - *text++ = 0x80 | (uchar & 0x3f); - } - else if (uchar < 0x200000) { - *text++ = 0xf0 | uchar >> 18; - *text++ = 0x80 | (uchar >> 12 & 0x3f); - *text++ = 0x80 | (uchar >> 6 & 0x3f); - *text++ = 0x80 | (uchar & 0x3f); - } - - return text; -} - -char SCSUUTF8::processText(SWBuf &text, const SWKey *key, const SWModule *module) { -/* - unsigned char *to, *from; - unsigned long buflen = len * FILTERPAD; - char active = 0, mode = 0; - if ((unsigned long)key < 2) // hack, we're en(1)/de(0)ciphering - return -1; - - static unsigned short start[8] = {0x0000,0x0080,0x0100,0x0300,0x2000,0x2080,0x2100,0x3000}; - static unsigned short slide[8] = {0x0080,0x00C0,0x0400,0x0600,0x0900,0x3040,0x30A0,0xFF00}; - static unsigned short win[256] = { - 0x0000, 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, - 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, - 0x0800, 0x0880, 0x0900, 0x0980, 0x0A00, 0x0A80, 0x0B00, 0x0B80, - 0x0C00, 0x0C80, 0x0D00, 0x0D80, 0x0E00, 0x0E80, 0x0F00, 0x0F80, - 0x1000, 0x1080, 0x1100, 0x1180, 0x1200, 0x1280, 0x1300, 0x1380, - 0x1400, 0x1480, 0x1500, 0x1580, 0x1600, 0x1680, 0x1700, 0x1780, - 0x1800, 0x1880, 0x1900, 0x1980, 0x1A00, 0x1A80, 0x1B00, 0x1B80, - 0x1C00, 0x1C80, 0x1D00, 0x1D80, 0x1E00, 0x1E80, 0x1F00, 0x1F80, - 0x2000, 0x2080, 0x2100, 0x2180, 0x2200, 0x2280, 0x2300, 0x2380, - 0x2400, 0x2480, 0x2500, 0x2580, 0x2600, 0x2680, 0x2700, 0x2780, - 0x2800, 0x2880, 0x2900, 0x2980, 0x2A00, 0x2A80, 0x2B00, 0x2B80, - 0x2C00, 0x2C80, 0x2D00, 0x2D80, 0x2E00, 0x2E80, 0x2F00, 0x2F80, - 0x3000, 0x3080, 0x3100, 0x3180, 0x3200, 0x3280, 0x3300, 0x3800, - 0xE000, 0xE080, 0xE100, 0xE180, 0xE200, 0xE280, 0xE300, 0xE380, - 0xE400, 0xE480, 0xE500, 0xE580, 0xE600, 0xE680, 0xE700, 0xE780, - 0xE800, 0xE880, 0xE900, 0xE980, 0xEA00, 0xEA80, 0xEB00, 0xEB80, - 0xEC00, 0xEC80, 0xED00, 0xED80, 0xEE00, 0xEE80, 0xEF00, 0xEF80, - 0xF000, 0xF080, 0xF100, 0xF180, 0xF200, 0xF280, 0xF300, 0xF380, - 0xF400, 0xF480, 0xF500, 0xF580, 0xF600, 0xF680, 0xF700, 0xF780, - 0xF800, 0xF880, 0xF900, 0xF980, 0xFA00, 0xFA80, 0xFB00, 0xFB80, - 0xFC00, 0xFC80, 0xFD00, 0xFD80, 0xFE00, 0xFE80, 0xFF00, 0xFF80, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x00C0, 0x0250, 0x0370, 0x0530, 0x3040, 0x30A0, 0xFF60 - }; - - if (!len) - return 0; - - memmove(&text[buflen - len], text, len); - from = (unsigned char*)&text[buflen - len]; - to = (unsigned char *)text; - - // ------------------------------- - - for (int i = 0; i < len;) { - - - if (i >= len) break; - c = from[i++]; - - if (c >= 0x80) - { - to = UTF8Output (c - 0x80 + slide[active], to); - } - else if (c >= 0x20 && c <= 0x7F) - { - to = UTF8Output (c, to); - } - else if (c == 0x0 || c == 0x9 || c == 0xA || c == 0xC || c == 0xD) - { - to = UTF8Output (c, to); - } - else if (c >= 0x1 && c <= 0x8) // SQn - { - if (i >= len) break; - d = from[i++]; // single quote - - to = UTF8Output (d < 0x80 ? d + start [c - 0x1] : - d - 0x80 + slide [c - 0x1], to); - } - else if (c >= 0x10 && c <= 0x17) // SCn - { - active = c - 0x10; // change window - } - else if (c >= 0x18 && c <= 0x1F) // SDn - { - active = c - 0x18; // define window - if (i >= len) break; - slide [active] = win [from[i++]]; - } - else if (c == 0xB) // SDX - { - if (i >= len) break; - c = from[i++]; - - if (i >= len) break; - d = from[i++]; - - slide [active = c>>5] = 0x10000 + (((c & 0x1F) << 8 | d) << 7); - } - else if (c == 0xE) // SQU - { - if (i >= len) break; - c = from[i++]; // SQU - - if (i >= len) break; - to = UTF8Output (c << 8 | from[i++], to); - } - else if (c == 0xF) // SCU - { - mode = 1; // change to Unicode mode - - while (mode) - { - if (i >= len) break; - c = from[i++]; - - if (c <= 0xDF || c >= 0xF3) - { - if (i >= len) break; - to = UTF8Output (c << 8 | from[i++], to); - } - else if (c == 0xF0) // UQU - { - if (i >= len) break; - c = from[i++]; - - if (i >= len) break; - to = UTF8Output (c << 8 | from[i++], to); - } - else if (c >= 0xE0 && c <= 0xE7) // UCn - { - active = c - 0xE0; mode = 0; - } - else if (c >= 0xE8 && c <= 0xEF) // UDn - { - if (i >= len) break; - slide [active=c-0xE8] = win [from[i++]]; mode = 0; - } - else if (c == 0xF1) // UDX - { - if (i >= len) break; - c = from[i++]; - - if (i >= len) break; - d = from[i++]; - - slide [active = c>>5] = - 0x10000 + (((c & 0x1F) << 8 | d) << 7); mode = 0; - } - } - } - - - } - - *to++ = 0; - *to = 0; -*/ - return 0; -} - -SWORD_NAMESPACE_END diff --git a/src/modules/filters/swoptfilter.cpp b/src/modules/filters/swoptfilter.cpp index 6921190..9d6dac4 100644 --- a/src/modules/filters/swoptfilter.cpp +++ b/src/modules/filters/swoptfilter.cpp @@ -1,9 +1,24 @@ /****************************************************************************** * - * swoptfilter - SWFilter descendant and base class for all option filters + * swoptfilter - SWFilter descendant and base class for all option filters + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <swoptfilter.h> #include <utilstr.h> diff --git a/src/modules/filters/teihtmlhref.cpp b/src/modules/filters/teihtmlhref.cpp index 1d213f4..7e27667 100644 --- a/src/modules/filters/teihtmlhref.cpp +++ b/src/modules/filters/teihtmlhref.cpp @@ -1,18 +1,24 @@ /*************************************************************************** - teirtf.cpp - TEI to HTMLHREF filter - ------------------- - begin : 2006-07-03 - copyright : 2006 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ + * teirtf.cpp - TEI to HTMLHREF filter + * ------------------- + * begin : 2006-07-03 + * copyright : 2006 by CrossWire Bible Society + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <ctype.h> @@ -20,6 +26,7 @@ #include <utilxml.h> #include <swmodule.h> #include <url.h> +#include <iostream> SWORD_NAMESPACE_START @@ -137,8 +144,8 @@ bool TEIHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData !strcmp(tag.getName(), "case") || !strcmp(tag.getName(), "gram") || !strcmp(tag.getName(), "number") || - !strcmp(tag.getName(), "pron") || - !strcmp(tag.getName(), "def")) { + !strcmp(tag.getName(), "pron") /*|| + !strcmp(tag.getName(), "def")*/) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { buf += "<i>"; } @@ -172,6 +179,67 @@ bool TEIHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData !strcmp(tag.getName(), "usg")) { // do nothing here } + else if (!strcmp(tag.getName(), "ref")) { + if (!tag.isEndTag()) { + u->suspendTextPassThru = true; + SWBuf target; + SWBuf work; + SWBuf ref; + + int was_osisref = false; + if(tag.getAttribute("osisRef")) + { + target += tag.getAttribute("osisRef"); + was_osisref=true; + } + else if(tag.getAttribute("target")) + target += tag.getAttribute("target"); + + if(target.size()) + { + const char* the_ref = strchr(target, ':'); + + if(!the_ref) { + // No work + ref = target; + } + else { + // Compensate for starting : + ref = the_ref + 1; + + int size = target.size() - ref.size() - 1; + work.setSize(size); + strncpy(work.getRawData(), target, size); + } + + if(was_osisref) + { + buf.appendFormatted("<a href=\"passagestudy.jsp?action=showRef&type=scripRef&value=%s&module=%s\">", + (ref) ? URL::encode(ref.c_str()).c_str() : "", + (work.size()) ? URL::encode(work.c_str()).c_str() : ""); + } + else + { + // Dictionary link, or something + buf.appendFormatted("<a href=\"sword://%s/%s\">", + (work.size()) ? URL::encode(work.c_str()).c_str() : u->version.c_str(), + (ref) ? URL::encode(ref.c_str()).c_str() : "" + ); + } + } + else + { + //std::cout << "TARGET WASN'T\n"; + } + + } + else { + buf += u->lastTextNode.c_str(); + buf += "</a>"; + + u->suspendTextPassThru = false; + } + } // <note> tag else if (!strcmp(tag.getName(), "note")) { diff --git a/src/modules/filters/teiplain.cpp b/src/modules/filters/teiplain.cpp index c721d84..90b7c7c 100644 --- a/src/modules/filters/teiplain.cpp +++ b/src/modules/filters/teiplain.cpp @@ -1,18 +1,24 @@ /*************************************************************************** - teiplain.cpp - TEI to Plaintext filter - ------------------- - begin : 2006-07-05 - copyright : 2006 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ + * teiplain.cpp - TEI to Plaintext filter + * ------------------- + * begin : 2006-07-05 + * copyright : 2006 by CrossWire Bible Society + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <teiplain.h> diff --git a/src/modules/filters/teirtf.cpp b/src/modules/filters/teirtf.cpp index 006f099..8560f5c 100644 --- a/src/modules/filters/teirtf.cpp +++ b/src/modules/filters/teirtf.cpp @@ -1,18 +1,24 @@ /***************************************************************************
- teirtf.cpp - TEI to RTF filter
- -------------------
- begin : 2006-07-03
- copyright : 2006 by CrossWire Bible Society
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
+ * teirtf.cpp - TEI to RTF filter
+ * -------------------
+ * begin : 2006-07-03
+ * copyright : 2006 by CrossWire Bible Society
+ *
+ * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org)
+ * CrossWire Bible Society
+ * P. O. Box 2528
+ * Tempe, AZ 85280-2528
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
#include <stdlib.h>
#include <ctype.h>
@@ -26,6 +32,7 @@ SWORD_NAMESPACE_START TEIRTF::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) {
BiblicalText = false;
+ inOsisRef = false;
if (module) {
version = module->Name();
BiblicalText = (!strcmp(module->Type(), "Biblical Texts"));
@@ -66,10 +73,10 @@ bool TEIRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *use }
// <hi>
- else if (!strcmp(tag.getName(), "hi")) {
+ else if (!strcmp(tag.getName(), "hi") || !strcmp(tag.getName(), "emph")) {
SWBuf rend = tag.getAttribute("rend");
if ((!tag.isEndTag()) && (!tag.isEmpty())) {
- if (rend == "ital")
+ if (rend == "ital" || rend == "italic")
buf += "{\\i1 ";
else if (rend == "bold")
buf += "{\\b1 ";
@@ -169,6 +176,25 @@ bool TEIRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *use }
}
+ // <lb/> tag
+ else if (!strcmp(tag.getName(), "lb")) {
+ buf += "{\\par}";
+ userData->supressAdjacentWhitespace = true;
+ }
+
+ // <ref> tag
+ else if (!strcmp(tag.getName(), "ref")) {
+ if (!tag.isEndTag() && tag.getAttribute("osisRef")) {
+ buf += "{<a href=\"\">";
+ u->inOsisRef = true;
+ }
+ else if (tag.isEndTag() && u->inOsisRef) {
+ buf += "</a>}";
+ u->inOsisRef = false;
+ }
+ }
+
+
else {
return false; // we still didn't handle token
}
diff --git a/src/modules/filters/thmlfootnotes.cpp b/src/modules/filters/thmlfootnotes.cpp index 23c43b4..e75311a 100644 --- a/src/modules/filters/thmlfootnotes.cpp +++ b/src/modules/filters/thmlfootnotes.cpp @@ -2,9 +2,26 @@ * * thmlfootnotes - SWFilter descendant to hide or show footnotes * in a ThML module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <stdlib.h> #include <stdio.h> #include <thmlfootnotes.h> @@ -39,7 +56,13 @@ char ThMLFootnotes::processText(SWBuf &text, const SWKey *key, const SWModule *m SWBuf refs = ""; int footnoteNum = 1; char buf[254]; - VerseKey parser = key->getText(); + SWKey *p = (module) ? module->CreateKey() : (key) ? key->clone() : new VerseKey(); + VerseKey *parser = SWDYNAMIC_CAST(VerseKey, p); + if (!parser) { + delete p; + parser = new VerseKey(); + } + *parser = key->getText(); SWBuf orig = text; const char *from = orig.c_str(); @@ -78,7 +101,7 @@ char ThMLFootnotes::processText(SWBuf &text, const SWKey *key, const SWModule *m startTag.setAttribute("swordFootnote", buf); if ((startTag.getAttribute("type")) && (!strcmp(startTag.getAttribute("type"), "crossReference"))) { if (!refs.length()) - refs = parser.ParseVerseList(tagText.c_str(), parser, true).getRangeText(); + refs = parser->ParseVerseList(tagText.c_str(), *parser, true).getRangeText(); module->getEntryAttributes()["Footnote"][buf]["refList"] = refs.c_str(); } } @@ -118,6 +141,7 @@ char ThMLFootnotes::processText(SWBuf &text, const SWKey *key, const SWModule *m } else tagText += *from; } + delete parser; return 0; } diff --git a/src/modules/filters/thmlgbf.cpp b/src/modules/filters/thmlgbf.cpp index f8703b1..e2e8e1c 100644 --- a/src/modules/filters/thmlgbf.cpp +++ b/src/modules/filters/thmlgbf.cpp @@ -1,18 +1,25 @@ /*************************************************************************** - thmlgbf.cpp - ThML to GBF filter - ------------------- - begin : 1999-10-28 - copyright : 2001 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ + * thmlgbf.cpp - ThML to GBF filter + * ------------------- + * begin : 1999-10-28 + * copyright : 2001 by CrossWire Bible Society + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <thmlgbf.h> diff --git a/src/modules/filters/thmlheadings.cpp b/src/modules/filters/thmlheadings.cpp index 4d6134f..e2b7c97 100644 --- a/src/modules/filters/thmlheadings.cpp +++ b/src/modules/filters/thmlheadings.cpp @@ -2,9 +2,24 @@ * * thmlheadings - SWFilter descendant to hide or show headings * in a ThML module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <thmlheadings.h> diff --git a/src/modules/filters/thmlhtml.cpp b/src/modules/filters/thmlhtml.cpp index efb09cd..4c66b87 100644 --- a/src/modules/filters/thmlhtml.cpp +++ b/src/modules/filters/thmlhtml.cpp @@ -1,18 +1,25 @@ /*************************************************************************** - thmlhtml.cpp - ThML to HTML filter - ------------------- - begin : 1999-10-27 - copyright : 2001 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ + * thmlhtml.cpp - ThML to HTML filter + * ------------------- + * begin : 1999-10-27 + * copyright : 2001 by CrossWire Bible Society + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <thmlhtml.h> diff --git a/src/modules/filters/thmlhtmlhref.cpp b/src/modules/filters/thmlhtmlhref.cpp index 0596f75..83f5a80 100644 --- a/src/modules/filters/thmlhtmlhref.cpp +++ b/src/modules/filters/thmlhtmlhref.cpp @@ -1,18 +1,26 @@ /*************************************************************************** - thmlhtmlhref.cpp - ThML to HTML filter with hrefs - ------------------- - begin : 2001-09-03 - copyright : 2001 by CrossWire Bible Society - ***************************************************************************/ + * thmlhtmlhref.cpp - ThML to HTML filter with hrefs + * ------------------- + * begin : 2001-09-03 + * copyright : 2001 by CrossWire Bible Society + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ #include <stdlib.h> #include <thmlhtmlhref.h> #include <swmodule.h> @@ -320,8 +328,8 @@ bool ThMLHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat URL::encode(u->version.c_str()).c_str()); for (c = token; *c; c++) { - if ((*c == '/') && (*(c+1) == '\0')) - continue; + if ((*c == '/') && (*(c+1) == '\0')) + continue; if (c == src) { for (;((*c) && (*c != '"')); c++) buf += *c; diff --git a/src/modules/filters/thmllemma.cpp b/src/modules/filters/thmllemma.cpp index 3e5761d..53eec58 100644 --- a/src/modules/filters/thmllemma.cpp +++ b/src/modules/filters/thmllemma.cpp @@ -2,9 +2,24 @@ * * thmllemma - SWFilter descendant to hide or show lemmas * in a ThML module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <thmllemma.h> diff --git a/src/modules/filters/thmlmorph.cpp b/src/modules/filters/thmlmorph.cpp index 0fbef56..d3cf597 100644 --- a/src/modules/filters/thmlmorph.cpp +++ b/src/modules/filters/thmlmorph.cpp @@ -2,9 +2,24 @@ * * thmlmorph - SWFilter descendant to hide or show morph tags * in a ThML module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <thmlmorph.h> diff --git a/src/modules/filters/thmlosis.cpp b/src/modules/filters/thmlosis.cpp index 939be82..25fdf23 100644 --- a/src/modules/filters/thmlosis.cpp +++ b/src/modules/filters/thmlosis.cpp @@ -2,9 +2,24 @@ * * thmlstrongs - SWFilter descendant to hide or show strongs number * in a ThML module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <stdarg.h> @@ -326,7 +341,7 @@ char ThMLOSIS::processText(SWBuf &text, const SWKey *key, const SWModule *module } // Footnote - if (!strcmp(token, "note")) { + if (!strncmp(token, "note", 4)) { //pushString(&to, "<note>"); text.append("<note>"); newText = true; @@ -534,23 +549,23 @@ char ThMLOSIS::processText(SWBuf &text, const SWKey *key, const SWModule *module text = ref + text; if (vkey->Verse()) { - VerseKey tmp; - tmp = *vkey; - tmp.AutoNormalize(0); - tmp.Headings(1); - + VerseKey *tmp = (VerseKey *)vkey->clone(); + *tmp = *vkey; + tmp->AutoNormalize(0); + tmp->Headings(1); + text += "</verse>"; - - tmp = MAXVERSE; - if (*vkey == tmp) { - tmp.Verse(0); + + *tmp = MAXVERSE; + if (*vkey == *tmp) { + tmp->Verse(0); // sprintf(ref, "\t</div>"); // pushString(&to, ref); - tmp = MAXCHAPTER; - tmp = MAXVERSE; - if (*vkey == tmp) { - tmp.Chapter(0); - tmp.Verse(0); + *tmp = MAXCHAPTER; + *tmp = MAXVERSE; + if (*vkey == *tmp) { + tmp->Chapter(0); + tmp->Verse(0); // sprintf(ref, "\t</div>"); // pushString(&to, ref); /* @@ -561,6 +576,7 @@ char ThMLOSIS::processText(SWBuf &text, const SWKey *key, const SWModule *module */ } } + delete tmp; } // else if (vkey->Chapter()) { // sprintf(ref, "\t<div type=\"chapter\" osisID=\"%s\">", vkey->getOSISRef()); diff --git a/src/modules/filters/thmlplain.cpp b/src/modules/filters/thmlplain.cpp index 8f8379a..8c9358f 100644 --- a/src/modules/filters/thmlplain.cpp +++ b/src/modules/filters/thmlplain.cpp @@ -2,9 +2,24 @@ * * thmlplain - SWFilter descendant to strip out all ThML tags or convert to * ASCII rendered symbols. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <thmlplain.h> #include <swbuf.h> @@ -55,104 +70,104 @@ char ThMLPlain::processText(SWBuf &text, const SWKey *key, const SWModule *modul else if (!strncmp("amp", token, 3)) text += '&'; else if (!strncmp("lt", token, 2)) text += '<'; else if (!strncmp("gt", token, 2)) text += '>'; - else if (!strncmp("brvbar", token, 6)) text += '¦'; - else if (!strncmp("sect", token, 4)) text += '§'; - else if (!strncmp("copy", token, 4)) text += '©'; - else if (!strncmp("laquo", token, 5)) text += '«'; - else if (!strncmp("reg", token, 3)) text += '®'; - else if (!strncmp("acute", token, 5)) text += '´'; - else if (!strncmp("para", token, 4)) text += '¶'; - else if (!strncmp("raquo", token, 5)) text += '»'; + else if (!strncmp("brvbar", token, 6)) text += "¦"; + else if (!strncmp("sect", token, 4)) text += "§"; + else if (!strncmp("copy", token, 4)) text += "©"; + else if (!strncmp("laquo", token, 5)) text += "«"; + else if (!strncmp("reg", token, 3)) text += "®"; + else if (!strncmp("acute", token, 5)) text += "´"; + else if (!strncmp("para", token, 4)) text += "¶"; + else if (!strncmp("raquo", token, 5)) text += "»"; - else if (!strncmp("Aacute", token, 6)) text += 'Á'; - else if (!strncmp("Agrave", token, 6)) text += 'À'; - else if (!strncmp("Acirc", token, 5)) text += 'Â'; - else if (!strncmp("Auml", token, 4)) text += 'Ä'; - else if (!strncmp("Atilde", token, 6)) text += 'Ã'; - else if (!strncmp("Aring", token, 5)) text += 'Å'; - else if (!strncmp("aacute", token, 6)) text += 'á'; - else if (!strncmp("agrave", token, 6)) text += 'à'; - else if (!strncmp("acirc", token, 5)) text += 'â'; - else if (!strncmp("auml", token, 4)) text += 'ä'; - else if (!strncmp("atilde", token, 6)) text += 'ã'; - else if (!strncmp("aring", token, 5)) text += 'å'; - else if (!strncmp("Eacute", token, 6)) text += 'É'; - else if (!strncmp("Egrave", token, 6)) text += 'È'; - else if (!strncmp("Ecirc", token, 5)) text += 'Ê'; - else if (!strncmp("Euml", token, 4)) text += 'Ë'; - else if (!strncmp("eacute", token, 6)) text += 'é'; - else if (!strncmp("egrave", token, 6)) text += 'è'; - else if (!strncmp("ecirc", token, 5)) text += 'ê'; - else if (!strncmp("euml", token, 4)) text += 'ë'; - else if (!strncmp("Iacute", token, 6)) text += 'Í'; - else if (!strncmp("Igrave", token, 6)) text += 'Ì'; - else if (!strncmp("Icirc", token, 5)) text += 'Î'; - else if (!strncmp("Iuml", token, 4)) text += 'Ï'; - else if (!strncmp("iacute", token, 6)) text += 'í'; - else if (!strncmp("igrave", token, 6)) text += 'ì'; - else if (!strncmp("icirc", token, 5)) text += 'î'; - else if (!strncmp("iuml", token, 4)) text += 'ï'; - else if (!strncmp("Oacute", token, 6)) text += 'Ó'; - else if (!strncmp("Ograve", token, 6)) text += 'Ò'; - else if (!strncmp("Ocirc", token, 5)) text += 'Ô'; - else if (!strncmp("Ouml", token, 4)) text += 'Ö'; - else if (!strncmp("Otilde", token, 6)) text += 'Õ'; - else if (!strncmp("oacute", token, 6)) text += 'ó'; - else if (!strncmp("ograve", token, 6)) text += 'ò'; - else if (!strncmp("ocirc", token, 5)) text += 'ô'; - else if (!strncmp("ouml", token, 4)) text += 'ö'; - else if (!strncmp("otilde", token, 6)) text += 'õ'; - else if (!strncmp("Uacute", token, 6)) text += 'Ú'; - else if (!strncmp("Ugrave", token, 6)) text += 'Ù'; - else if (!strncmp("Ucirc", token, 5)) text += 'Û'; - else if (!strncmp("Uuml", token, 4)) text += 'Ü'; - else if (!strncmp("uacute", token, 6)) text += 'ú'; - else if (!strncmp("ugrave", token, 6)) text += 'ù'; - else if (!strncmp("ucirc", token, 5)) text += 'û'; - else if (!strncmp("uuml", token, 4)) text += 'ü'; - else if (!strncmp("Yacute", token, 6)) text += 'Ý'; - else if (!strncmp("yacute", token, 6)) text += 'ý'; - else if (!strncmp("yuml", token, 4)) text += 'ÿ'; + else if (!strncmp("Aacute", token, 6)) text += "Ã"; + else if (!strncmp("Agrave", token, 6)) text += "À"; + else if (!strncmp("Acirc", token, 5)) text += "Â"; + else if (!strncmp("Auml", token, 4)) text += "Ä"; + else if (!strncmp("Atilde", token, 6)) text += "Ã"; + else if (!strncmp("Aring", token, 5)) text += "Ã…"; + else if (!strncmp("aacute", token, 6)) text += "á"; + else if (!strncmp("agrave", token, 6)) text += "à "; + else if (!strncmp("acirc", token, 5)) text += "â"; + else if (!strncmp("auml", token, 4)) text += "ä"; + else if (!strncmp("atilde", token, 6)) text += "ã"; + else if (!strncmp("aring", token, 5)) text += "Ã¥"; + else if (!strncmp("Eacute", token, 6)) text += "É"; + else if (!strncmp("Egrave", token, 6)) text += "È"; + else if (!strncmp("Ecirc", token, 5)) text += "Ê"; + else if (!strncmp("Euml", token, 4)) text += "Ë"; + else if (!strncmp("eacute", token, 6)) text += "é"; + else if (!strncmp("egrave", token, 6)) text += "è"; + else if (!strncmp("ecirc", token, 5)) text += "ê"; + else if (!strncmp("euml", token, 4)) text += "ë"; + else if (!strncmp("Iacute", token, 6)) text += "Ã"; + else if (!strncmp("Igrave", token, 6)) text += "ÃŒ"; + else if (!strncmp("Icirc", token, 5)) text += "ÃŽ"; + else if (!strncmp("Iuml", token, 4)) text += "Ã"; + else if (!strncmp("iacute", token, 6)) text += "Ã"; + else if (!strncmp("igrave", token, 6)) text += "ì"; + else if (!strncmp("icirc", token, 5)) text += "î"; + else if (!strncmp("iuml", token, 4)) text += "ï"; + else if (!strncmp("Oacute", token, 6)) text += "Ó"; + else if (!strncmp("Ograve", token, 6)) text += "Ã’"; + else if (!strncmp("Ocirc", token, 5)) text += "Ô"; + else if (!strncmp("Ouml", token, 4)) text += "Ö"; + else if (!strncmp("Otilde", token, 6)) text += "Õ"; + else if (!strncmp("oacute", token, 6)) text += "ó"; + else if (!strncmp("ograve", token, 6)) text += "ò"; + else if (!strncmp("ocirc", token, 5)) text += "ô"; + else if (!strncmp("ouml", token, 4)) text += "ö"; + else if (!strncmp("otilde", token, 6)) text += "õ"; + else if (!strncmp("Uacute", token, 6)) text += "Ú"; + else if (!strncmp("Ugrave", token, 6)) text += "Ù"; + else if (!strncmp("Ucirc", token, 5)) text += "Û"; + else if (!strncmp("Uuml", token, 4)) text += "Ãœ"; + else if (!strncmp("uacute", token, 6)) text += "ú"; + else if (!strncmp("ugrave", token, 6)) text += "ù"; + else if (!strncmp("ucirc", token, 5)) text += "û"; + else if (!strncmp("uuml", token, 4)) text += "ü"; + else if (!strncmp("Yacute", token, 6)) text += "Ã"; + else if (!strncmp("yacute", token, 6)) text += "ý"; + else if (!strncmp("yuml", token, 4)) text += "ÿ"; - else if (!strncmp("deg", token, 3)) text += '°'; - else if (!strncmp("plusmn", token, 6)) text += '±'; - else if (!strncmp("sup2", token, 4)) text += '²'; - else if (!strncmp("sup3", token, 4)) text += '³'; - else if (!strncmp("sup1", token, 4)) text += '¹'; - else if (!strncmp("nbsp", token, 4)) text += 'º'; - else if (!strncmp("pound", token, 5)) text += '£'; - else if (!strncmp("cent", token, 4)) text += '¢'; - else if (!strncmp("frac14", token, 6)) text += '¼'; - else if (!strncmp("frac12", token, 6)) text += '½'; - else if (!strncmp("frac34", token, 6)) text += '¾'; - else if (!strncmp("iquest", token, 6)) text += '¿'; - else if (!strncmp("iexcl", token, 5)) text += '¡'; - else if (!strncmp("ETH", token, 3)) text += 'Ð'; - else if (!strncmp("eth", token, 3)) text += 'ð'; - else if (!strncmp("THORN", token, 5)) text += 'Þ'; - else if (!strncmp("thorn", token, 5)) text += 'þ'; - else if (!strncmp("AElig", token, 5)) text += 'Æ'; - else if (!strncmp("aelig", token, 5)) text += 'æ'; - else if (!strncmp("Oslash", token, 6)) text += 'Ø'; - else if (!strncmp("curren", token, 6)) text += '¤'; - else if (!strncmp("Ccedil", token, 6)) text += 'Ç'; - else if (!strncmp("ccedil", token, 6)) text += 'ç'; - else if (!strncmp("szlig", token, 5)) text += 'ß'; - else if (!strncmp("Ntilde", token, 6)) text += 'Ñ'; - else if (!strncmp("ntilde", token, 6)) text += 'ñ'; - else if (!strncmp("yen", token, 3)) text += '¥'; - else if (!strncmp("not", token, 3)) text += '¬'; - else if (!strncmp("ordf", token, 4)) text += 'ª'; - else if (!strncmp("uml", token, 3)) text += '¨'; - else if (!strncmp("shy", token, 3)) text += ''; - else if (!strncmp("macr", token, 4)) text += '¯'; - else if (!strncmp("micro", token, 5)) text += "µ"; - else if (!strncmp("middot", token, 6)) text +="·"; - else if (!strncmp("cedil", token, 5)) text += "¸"; - else if (!strncmp("ordm", token, 4)) text += "º"; - else if (!strncmp("times", token, 5)) text += "×"; - else if (!strncmp("divide", token, 6)) text +="÷"; - else if (!strncmp("oslash", token, 6)) text +="ø"; + else if (!strncmp("deg", token, 3)) text += "°"; + else if (!strncmp("plusmn", token, 6)) text += "±"; + else if (!strncmp("sup2", token, 4)) text += "²"; + else if (!strncmp("sup3", token, 4)) text += "³"; + else if (!strncmp("sup1", token, 4)) text += "¹"; + else if (!strncmp("nbsp", token, 4)) text += "º"; + else if (!strncmp("pound", token, 5)) text += "£"; + else if (!strncmp("cent", token, 4)) text += "¢"; + else if (!strncmp("frac14", token, 6)) text += "¼"; + else if (!strncmp("frac12", token, 6)) text += "½"; + else if (!strncmp("frac34", token, 6)) text += "¾"; + else if (!strncmp("iquest", token, 6)) text += "¿"; + else if (!strncmp("iexcl", token, 5)) text += "¡"; + else if (!strncmp("ETH", token, 3)) text += "Ã"; + else if (!strncmp("eth", token, 3)) text += "ð"; + else if (!strncmp("THORN", token, 5)) text += "Þ"; + else if (!strncmp("thorn", token, 5)) text += "þ"; + else if (!strncmp("AElig", token, 5)) text += "Æ"; + else if (!strncmp("aelig", token, 5)) text += "æ"; + else if (!strncmp("Oslash", token, 6)) text += "Ø"; + else if (!strncmp("curren", token, 6)) text += "¤"; + else if (!strncmp("Ccedil", token, 6)) text += "Ç"; + else if (!strncmp("ccedil", token, 6)) text += "ç"; + else if (!strncmp("szlig", token, 5)) text += "ß"; + else if (!strncmp("Ntilde", token, 6)) text += "Ñ"; + else if (!strncmp("ntilde", token, 6)) text += "ñ"; + else if (!strncmp("yen", token, 3)) text += "Â¥"; + else if (!strncmp("not", token, 3)) text += "¬"; + else if (!strncmp("ordf", token, 4)) text += "ª"; + else if (!strncmp("uml", token, 3)) text += "¨"; + else if (!strncmp("shy", token, 3)) text += "Â"; + else if (!strncmp("macr", token, 4)) text += "¯"; + else if (!strncmp("micro", token, 5)) text += "µ"; + else if (!strncmp("middot", token, 6)) text += "·"; + else if (!strncmp("cedil", token, 5)) text += "¸"; + else if (!strncmp("ordm", token, 4)) text += "º"; + else if (!strncmp("times", token, 5)) text += "×"; + else if (!strncmp("divide", token, 6)) text += "÷"; + else if (!strncmp("oslash", token, 6)) text += "ø"; continue; } @@ -177,14 +192,14 @@ char ThMLPlain::processText(SWBuf &text, const SWKey *key, const SWModule *modul } if (!strncmp("note", token, 4)) { text += ' '; - text += '('; + text += '['; } else if (!strncmp("br", token, 2)) text += '\n'; else if (!strncmp("/p", token, 2)) text += '\n'; else if (!strncmp("/note", token, 5)) { - text += ')'; + text += ']'; text += ' '; } continue; diff --git a/src/modules/filters/thmlrtf.cpp b/src/modules/filters/thmlrtf.cpp index 23e4a90..fdb41df 100644 --- a/src/modules/filters/thmlrtf.cpp +++ b/src/modules/filters/thmlrtf.cpp @@ -1,18 +1,25 @@ /*************************************************************************** - thmlrtf.cpp - ThML to RTF filter - ------------------- - begin : 1999-10-27 - copyright : 2001 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ + * thmlrtf.cpp - ThML to RTF filter + * ------------------- + * begin : 1999-10-27 + * copyright : 2001 by CrossWire Bible Society + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <thmlrtf.h> diff --git a/src/modules/filters/thmlscripref.cpp b/src/modules/filters/thmlscripref.cpp index df2b3d2..e46d679 100644 --- a/src/modules/filters/thmlscripref.cpp +++ b/src/modules/filters/thmlscripref.cpp @@ -2,9 +2,24 @@ * * thmlscripref - SWFilter descendant to hide or show scripture * referebces in a ThML module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <thmlscripref.h> @@ -38,7 +53,13 @@ char ThMLScripref::processText(SWBuf &text, const SWKey *key, const SWModule *mo SWBuf refs = ""; int footnoteNum = 1; char buf[254]; - VerseKey parser = key->getText(); + SWKey *p = (module) ? module->CreateKey() : (key) ? key->clone() : new VerseKey(); + VerseKey *parser = SWDYNAMIC_CAST(VerseKey, p); + if (!parser) { + delete p; + parser = new VerseKey(); + } + *parser = key->getText(); SWBuf orig = text; const char *from = orig.c_str(); @@ -77,8 +98,8 @@ char ThMLScripref::processText(SWBuf &text, const SWKey *key, const SWModule *mo startTag.setAttribute("swordFootnote", buf); SWBuf passage = startTag.getAttribute("passage"); if (passage.length()) - refs = parser.ParseVerseList(passage.c_str(), parser, true).getRangeText(); - else refs = parser.ParseVerseList(tagText.c_str(), parser, true).getRangeText(); + refs = parser->ParseVerseList(passage.c_str(), *parser, true).getRangeText(); + else refs = parser->ParseVerseList(tagText.c_str(), *parser, true).getRangeText(); module->getEntryAttributes()["Footnote"][buf]["refList"] = refs.c_str(); } hide = false; @@ -117,6 +138,7 @@ char ThMLScripref::processText(SWBuf &text, const SWKey *key, const SWModule *mo } else tagText += *from; } + delete parser; return 0; } diff --git a/src/modules/filters/thmlstrongs.cpp b/src/modules/filters/thmlstrongs.cpp index c1ab08c..457e28b 100644 --- a/src/modules/filters/thmlstrongs.cpp +++ b/src/modules/filters/thmlstrongs.cpp @@ -2,9 +2,24 @@ * * thmlstrongs - SWFilter descendant to hide or show strongs number * in a ThML module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <thmlstrongs.h> diff --git a/src/modules/filters/thmlvariants.cpp b/src/modules/filters/thmlvariants.cpp index 49f9b65..4f28dbe 100644 --- a/src/modules/filters/thmlvariants.cpp +++ b/src/modules/filters/thmlvariants.cpp @@ -2,9 +2,24 @@ * * thmlvariants - SWFilter descendant to hide or show textual variants * in a ThML module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <thmlvariants.h> #include <utilstr.h> diff --git a/src/modules/filters/thmlwebif.cpp b/src/modules/filters/thmlwebif.cpp index 7428754..0192703 100644 --- a/src/modules/filters/thmlwebif.cpp +++ b/src/modules/filters/thmlwebif.cpp @@ -1,18 +1,25 @@ /*************************************************************************** - ThMLWEBIF.cpp - ThML to HTML filter with hrefs - ------------------- - begin : 2001-09-03 - copyright : 2001 by CrossWire Bible Society - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ + * ThMLWEBIF.cpp - ThML to HTML filter with hrefs + * ------------------- + * begin : 2001-09-03 + * copyright : 2001 by CrossWire Bible Society + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #include <stdlib.h> #include <thmlwebif.h> diff --git a/src/modules/filters/thmlwordjs.cpp b/src/modules/filters/thmlwordjs.cpp index ad8eef0..12fbeb1 100644 --- a/src/modules/filters/thmlwordjs.cpp +++ b/src/modules/filters/thmlwordjs.cpp @@ -2,9 +2,24 @@ * * thmlstrongs - SWFilter descendant to hide or show strongs number * in a ThML module. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <thmlwordjs.h> diff --git a/src/modules/filters/unicodertf.cpp b/src/modules/filters/unicodertf.cpp index 8c2a1f6..768aecc 100644 --- a/src/modules/filters/unicodertf.cpp +++ b/src/modules/filters/unicodertf.cpp @@ -2,9 +2,24 @@ * * unicodertf - SWFilter descendant to convert a double byte unicode file * to RTF tags + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <unicodertf.h> diff --git a/src/modules/filters/utf16utf8.cpp b/src/modules/filters/utf16utf8.cpp index ae0845f..a488e18 100644 --- a/src/modules/filters/utf16utf8.cpp +++ b/src/modules/filters/utf16utf8.cpp @@ -2,8 +2,25 @@ * * UTF16UTF8 - SWFilter descendant to convert UTF-16 to UTF-8 * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <stdlib.h> #include <stdio.h> diff --git a/src/modules/filters/utf8arabicpoints.cpp b/src/modules/filters/utf8arabicpoints.cpp new file mode 100644 index 0000000..bd3169b --- /dev/null +++ b/src/modules/filters/utf8arabicpoints.cpp @@ -0,0 +1,61 @@ +/****************************************************************************** + * + * UTF8ArabicPoints - SWFilter descendant to remove UTF-8 Arabic vowel points + * + * $Id: utf8arabicpoints.h 1688 2008-11-30 04:42:26Z refdoc $ + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + + +#include <stdlib.h> +#include <stdio.h> +#include <utf8arabicpoints.h> + +SWORD_NAMESPACE_START + +const char oName[] = "Arabic Vowel Points"; +const char oTip[] = "Toggles Arabic Vowel Points"; + +const SWBuf choices[3] = {"On", "Off", ""}; +const StringList oValues(&choices[0], &choices[2]); + +UTF8ArabicPoints::UTF8ArabicPoints() : SWOptionFilter(oName, oTip, &oValues) { + setOptionValue("On"); +} + +UTF8ArabicPoints::~UTF8ArabicPoints(){}; + + +char UTF8ArabicPoints::processText(SWBuf &text, const SWKey *key, const SWModule *module) { + if (!option) { + //The UTF-8 range 0xFC 0xE5 to 0xFC 0x63 consist of Arabic vowel marks so block those out. + // Also ranges 0xFE70 til OxFE7F and 0x064b-0x0655 + SWBuf orig = text; + const unsigned char* from = (unsigned char*)orig.c_str(); + for (text = ""; *from; from++) { + if (((*from == 0xFC) && (*(from + 1) >= 0xE5 && *(from + 1) <= 0x63)) || ((*from == 0xFE) && (*(from + 1) >= 0x70 && *(from + 1) <= 0x7F)) || ((*from == 0x06) && (*(from + 1) >= 0x4B && *(from + 1) <= 0x55))){ + from++; + } + else { + text += *from; + } + } + } + return 0; +} + +SWORD_NAMESPACE_END diff --git a/src/modules/filters/utf8arshaping.cpp b/src/modules/filters/utf8arshaping.cpp index 702fb62..09d8973 100644 --- a/src/modules/filters/utf8arshaping.cpp +++ b/src/modules/filters/utf8arshaping.cpp @@ -1,8 +1,24 @@ /****************************************************************************** -* -* utf8arshaping - SWFilter descendant to perform Arabic shaping on -* UTF-8 text -*/ + * + * utf8arshaping - SWFilter descendant to perform Arabic shaping on + * UTF-8 text + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #ifdef _ICU_ diff --git a/src/modules/filters/utf8bidireorder.cpp b/src/modules/filters/utf8bidireorder.cpp index 783602c..71dc804 100644 --- a/src/modules/filters/utf8bidireorder.cpp +++ b/src/modules/filters/utf8bidireorder.cpp @@ -1,8 +1,24 @@ /****************************************************************************** -* -* utf8cnormalizer - SWFilter descendant to perform reordering of UTF-8 -* text to visual order according to Unicode BiDi -*/ + * + * utf8bidireorder - SWFilter descendant to perform reordering of UTF-8 + * text to visual order according to Unicode BiDi + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #ifdef _ICU_ diff --git a/src/modules/filters/utf8cantillation.cpp b/src/modules/filters/utf8cantillation.cpp index 6213620..73785b4 100644 --- a/src/modules/filters/utf8cantillation.cpp +++ b/src/modules/filters/utf8cantillation.cpp @@ -2,9 +2,24 @@ * * UTF8Cantillation - SWFilter descendant to remove UTF-8 Hebrew cantillation * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <utf8cantillation.h> diff --git a/src/modules/filters/utf8greekaccents.cpp b/src/modules/filters/utf8greekaccents.cpp index df85968..5fdb047 100644 --- a/src/modules/filters/utf8greekaccents.cpp +++ b/src/modules/filters/utf8greekaccents.cpp @@ -2,9 +2,24 @@ * * UTF8GreekAccents - SWFilter descendant to remove UTF-8 Greek accents * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <utf8greekaccents.h> diff --git a/src/modules/filters/utf8hebrewpoints.cpp b/src/modules/filters/utf8hebrewpoints.cpp index 0476db8..ba7c746 100644 --- a/src/modules/filters/utf8hebrewpoints.cpp +++ b/src/modules/filters/utf8hebrewpoints.cpp @@ -2,9 +2,24 @@ * * UTF8HebrewPoints - SWFilter descendant to remove UTF-8 Hebrew vowel points * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <utf8hebrewpoints.h> diff --git a/src/modules/filters/utf8html.cpp b/src/modules/filters/utf8html.cpp index 088f669..0d1dce3 100644 --- a/src/modules/filters/utf8html.cpp +++ b/src/modules/filters/utf8html.cpp @@ -2,9 +2,24 @@ * * utf8html - SWFilter descendant to convert a UTF-8 stream to HTML escapes * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdlib.h> #include <stdio.h> #include <utf8html.h> diff --git a/src/modules/filters/utf8latin1.cpp b/src/modules/filters/utf8latin1.cpp index 08b288d..25df0c1 100644 --- a/src/modules/filters/utf8latin1.cpp +++ b/src/modules/filters/utf8latin1.cpp @@ -2,6 +2,22 @@ * * UTF8Latin1 - SWFilter descendant to convert UTF-8 to Latin-1 * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ #include <stdlib.h> diff --git a/src/modules/filters/utf8nfc.cpp b/src/modules/filters/utf8nfc.cpp index 15b76b5..82d404e 100644 --- a/src/modules/filters/utf8nfc.cpp +++ b/src/modules/filters/utf8nfc.cpp @@ -1,8 +1,24 @@ /****************************************************************************** -* -* utf8nfc - SWFilter descendant to perform NFC (canonical composition -* normalization) on UTF-8 text -*/ + * + * utf8nfc - SWFilter descendant to perform NFC (canonical composition + * normalization) on UTF-8 text + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #ifdef _ICU_ diff --git a/src/modules/filters/utf8nfkd.cpp b/src/modules/filters/utf8nfkd.cpp index a19d36b..1d6acf3 100644 --- a/src/modules/filters/utf8nfkd.cpp +++ b/src/modules/filters/utf8nfkd.cpp @@ -1,8 +1,24 @@ /****************************************************************************** -* -* utf8nfkd - SWFilter descendant to perform NFKD (compatability decomposition -* normalization) on UTF-8 text -*/ + * + * utf8nfkd - SWFilter descendant to perform NFKD (compatability decomposition + * normalization) on UTF-8 text + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #ifdef _ICU_ diff --git a/src/modules/filters/utf8transliterator.cpp b/src/modules/filters/utf8transliterator.cpp index d99741b..552ec3e 100644 --- a/src/modules/filters/utf8transliterator.cpp +++ b/src/modules/filters/utf8transliterator.cpp @@ -1,8 +1,24 @@ /****************************************************************************** -* -* utf8transliterators - SWFilter descendant to transliterate between -* ICU-supported scripts. -*/ + * + * utf8transliterators - SWFilter descendant to transliterate between + * ICU-supported scripts. + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ #ifdef _ICU_ @@ -25,51 +41,48 @@ SWORD_NAMESPACE_START const char UTF8Transliterator::optionstring[NUMTARGETSCRIPTS][16] = { "Off", "Latin", - "IPA", - "Basic Latin", - "SBL", - "TC", - "Beta", - "BGreek", - "SERA", - "Hugoye", - "UNGEGN", - "ISO", - "ALA-LC", - "BGN-PCGN", - "Greek", - "Hebrew", - "Cyrillic", - "Arabic", - "Syriac", - "Katakana", - "Hiragana", - "Hangul", - "Devanagari", - "Tamil", - "Bengali", - "Gurmukhi", - "Gujarati", - "Oriya", - "Telugu", - "Kannada", - "Malayalam", - "Thai", - "Georgian", - "Armenian", - "Ethiopic", - "Gothic", - "Ugaritic", - "Coptic", - "Meroitic", - "Linear B", - "Cypriot", - "Runic", - "Ogham", - "Thaana", - "Glagolitic", -// "Tengwar", -// "Cirth" + // "IPA", + // "Basic Latin", + // "SBL", + // "TC", + // "Beta", + // "BGreek", + // "SERA", + // "Hugoye", + // "UNGEGN", + // "ISO", + // "ALA-LC", + // "BGN", + // "Greek", + // "Hebrew", + // "Cyrillic", + // "Arabic", + // "Syriac", + // "Katakana", + // "Hiragana", + // "Hangul", + // "Devanagari", + // "Tamil", + // "Bengali", + // "Gurmukhi", + // "Gujarati", + // "Oriya", + // "Telugu", + // "Kannada", + // "Malayalam", + // "Thai", + // "Georgian", + // "Armenian", + // "Ethiopic", + // "Gothic", + // "Ugaritic", + // "Coptic", + // "Linear B", + // "Cypriot", + // "Runic", + // "Ogham", + // "Thaana", + // "Glagolitic", }; const char UTF8Transliterator::optName[] = "Transliteration"; @@ -128,6 +141,11 @@ UTF8Transliterator::UTF8Transliterator() { #endif } + +UTF8Transliterator::~UTF8Transliterator() { +} + + void UTF8Transliterator::Load(UErrorCode &status) { #ifndef _ICUSWORD_ @@ -374,19 +392,19 @@ char UTF8Transliterator::processText(SWBuf &text, const SWKey *key, const SWModu case UBLOCK_MALAYALAM: scripts[SE_MALAYALAM] = true; break; case UBLOCK_THAI: scripts[SE_THAI] = true; break; case UBLOCK_GEORGIAN: scripts[SE_GEORGIAN] = true; break; - case UBLOCK_ARMENIAN: scripts[SE_ARMENIAN] = true; break; - case UBLOCK_ETHIOPIC: scripts[SE_ETHIOPIC] = true; break; - case UBLOCK_GOTHIC: scripts[SE_GOTHIC] = true; break; - case UBLOCK_UGARITIC: scripts[SE_UGARITIC] = true; break; -// case UBLOCK_MEROITIC: scripts[SE_MEROITIC] = true; break; -// case UBLOCK_LINEARB: scripts[SE_LINEARB] = true; break; -// case UBLOCK_CYPRIOT: scripts[SE_CYPRIOT] = true; break; - case UBLOCK_RUNIC: scripts[SE_RUNIC] = true; break; - case UBLOCK_OGHAM: scripts[SE_OGHAM] = true; break; - case UBLOCK_THAANA: scripts[SE_THAANA] = true; break; -// case UBLOCK_GLAGOLITIC: scripts[SE_GLAGOLITIC] = true; break; -// case UBLOCK_TENGWAR: scripts[SE_TENGWAR] = true; break; -// case UBLOCK_CIRTH: scripts[SE_CIRTH] = true; break; + case UBLOCK_ARMENIAN: scripts[SE_ARMENIAN] = true; break; + case UBLOCK_ETHIOPIC: scripts[SE_ETHIOPIC] = true; break; + case UBLOCK_GOTHIC: scripts[SE_GOTHIC] = true; break; + case UBLOCK_UGARITIC: scripts[SE_UGARITIC] = true; break; +// case UBLOCK_MEROITIC: scripts[SE_MEROITIC] = true; break; + case UBLOCK_LINEAR_B_SYLLABARY: scripts[SE_LINEARB] = true; break; + case UBLOCK_CYPRIOT_SYLLABARY: scripts[SE_CYPRIOT] = true; break; + case UBLOCK_RUNIC: scripts[SE_RUNIC] = true; break; + case UBLOCK_OGHAM: scripts[SE_OGHAM] = true; break; + case UBLOCK_THAANA: scripts[SE_THAANA] = true; break; + case UBLOCK_GLAGOLITIC: scripts[SE_GLAGOLITIC] = true; break; +// case UBLOCK_TENGWAR: scripts[SE_TENGWAR] = true; break; +// case UBLOCK_CIRTH: scripts[SE_CIRTH] = true; break; case UBLOCK_CJK_RADICALS_SUPPLEMENT: case UBLOCK_KANGXI_RADICALS: case UBLOCK_IDEOGRAPHIC_DESCRIPTION_CHARACTERS: @@ -445,8 +463,8 @@ char UTF8Transliterator::processText(SWBuf &text, const SWKey *key, const SWModu addTrans("Greek-Latin/ISO", &ID); else if (option == SE_ALALC) addTrans("Greek-Latin/ALALC", &ID); - else if (option == SE_BGNPCGN) - addTrans("Greek-Latin/BGNPCGN", &ID); + else if (option == SE_BGN) + addTrans("Greek-Latin/BGN", &ID); else if (option == SE_IPA) addTrans("Greek-IPA/Ancient", &ID); else { @@ -522,8 +540,8 @@ char UTF8Transliterator::processText(SWBuf &text, const SWKey *key, const SWModu addTrans("Georgian-Latin/ISO", &ID); else if (option == SE_ALALC) addTrans("Georgian-Latin/ALALC", &ID); - else if (option == SE_BGNPCGN) - addTrans("Georgian-Latin/BGNPCGN", &ID); + else if (option == SE_BGN) + addTrans("Georgian-Latin/BGN", &ID); else if (option == SE_IPA) addTrans("Georgian-IPA", &ID); else { @@ -536,8 +554,8 @@ char UTF8Transliterator::processText(SWBuf &text, const SWKey *key, const SWModu addTrans("Armenian-Latin/ISO", &ID); else if (option == SE_ALALC) addTrans("Armenian-Latin/ALALC", &ID); - else if (option == SE_BGNPCGN) - addTrans("Armenian-Latin/BGNPCGN", &ID); + else if (option == SE_BGN) + addTrans("Armenian-Latin/BGN", &ID); else if (option == SE_IPA) addTrans("Armenian-IPA", &ID); else { @@ -600,8 +618,8 @@ char UTF8Transliterator::processText(SWBuf &text, const SWKey *key, const SWModu if (scripts[SE_THAANA]) { if (option == SE_ALALC) addTrans("Thaana-Latin/ALALC", &ID); - else if (option == SE_BGNPCGN) - addTrans("Thaana-Latin/BGNPCGN", &ID); + else if (option == SE_BGN) + addTrans("Thaana-Latin/BGN", &ID); else { addTrans("Thaana-Latin", &ID); scripts[SE_LATIN] = true; diff --git a/src/modules/filters/utf8utf16.cpp b/src/modules/filters/utf8utf16.cpp index 5c1614c..a770d5f 100644 --- a/src/modules/filters/utf8utf16.cpp +++ b/src/modules/filters/utf8utf16.cpp @@ -2,12 +2,30 @@ * * UTF8UTF16 - SWFilter descendant to convert UTF-8 to UTF-16 * + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ #include <stdlib.h> #include <stdio.h> +#include <sysdata.h> #include <utf8utf16.h> +#include <utilstr.h> #include <swbuf.h> SWORD_NAMESPACE_START @@ -15,61 +33,36 @@ SWORD_NAMESPACE_START UTF8UTF16::UTF8UTF16() { } + char UTF8UTF16::processText(SWBuf &text, const SWKey *key, const SWModule *module) { const unsigned char *from; - unsigned long ch; - signed short utf16; - unsigned char from2[7]; - SWBuf orig = text; from = (const unsigned char *)orig.c_str(); // ------------------------------- - for (text = ""; *from; from++) { - ch = 0; - //case: ANSI - if ((*from & 128) != 128) { + text = ""; + while (*from) { + + __u32 ch = getUniCharFromUTF8(&from); + + if (!ch) continue; // invalid char + + if (ch < 0x10000) { text.setSize(text.size()+2); - *((unsigned short *)(text.getRawData()+(text.size()-2))) = (unsigned short)*from; - continue; - } - //case: Invalid UTF-8 (illegal continuing byte in initial position) - if ((*from & 128) && ((*from & 64) != 64)) { - continue; + *((__u16 *)(text.getRawData()+(text.size()-2))) = (__u16)ch; } - //case: 2+ byte codepoint - from2[0] = *from; - from2[0] <<= 1; - int subsequent; - for (subsequent = 1; (from2[0] & 128) && (subsequent < 7); subsequent++) { - from2[0] <<= 1; - from2[subsequent] = from[subsequent]; - from2[subsequent] &= 63; - ch <<= 6; - ch |= from2[subsequent]; + else { + __u16 utf16; + utf16 = (__s16)((ch - 0x10000) / 0x400 + 0xD800); + text.setSize(text.size()+4); + *((__u16 *)(text.getRawData()+(text.size()-4))) = utf16; + utf16 = (__s16)((ch - 0x10000) % 0x400 + 0xDC00); + *((__u16 *)(text.getRawData()+(text.size()-2))) = utf16; } - subsequent--; - from2[0] <<= 1; - char significantFirstBits = 8 - (2+subsequent); - - ch |= (((short)from2[0]) << (((6*subsequent)+significantFirstBits)-8)); - from += subsequent; - if (ch < 0x10000) { - text.setSize(text.size()+2); - *((unsigned short *)(text.getRawData()+(text.size()-2))) = (unsigned short)ch; - } - else { - utf16 = (signed short)((ch - 0x10000) / 0x400 + 0xD800); - text.setSize(text.size()+2); - *((unsigned short *)(text.getRawData()+(text.size()-2))) = (unsigned short)utf16; - utf16 = (signed short)((ch - 0x10000) % 0x400 + 0xDC00); - text.setSize(text.size()+2); - *((unsigned short *)(text.getRawData()+(text.size()-2))) = (unsigned short)utf16; - } } text.setSize(text.size()+2); - *((unsigned short *)(text.getRawData()+(text.size()-2))) = (unsigned short)0; + *((__u16 *)(text.getRawData()+(text.size()-2))) = (__u16)0; return 0; diff --git a/src/modules/genbook/rawgenbook/rawgenbook.cpp b/src/modules/genbook/rawgenbook/rawgenbook.cpp index 22cc51f..eff68f5 100644 --- a/src/modules/genbook/rawgenbook/rawgenbook.cpp +++ b/src/modules/genbook/rawgenbook/rawgenbook.cpp @@ -1,9 +1,26 @@ /****************************************************************************** - * rawtext.cpp - code for class 'RawGenBook'- a module that reads raw text files: - * ot and nt using indexs ??.bks ??.cps ??.vss + * rawtext.cpp - code for class 'RawGenBook'- a module that reads raw text + * files: ot and nt using indexs ??.bks ??.cps ??.vss + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <stdio.h> #include <fcntl.h> @@ -82,34 +99,16 @@ SWBuf &RawGenBook::getRawEntryBuf() { __u32 offset = 0; __u32 size = 0; - TreeKey *key = 0; - SWTRY { - key = SWDYNAMIC_CAST(TreeKey, (this->key)); - } - SWCATCH ( ... ) {} - - if (!key) { - VerseTreeKey *tkey = 0; - SWTRY { - tkey = SWDYNAMIC_CAST(VerseTreeKey, (this->key)); - } - SWCATCH ( ... ) {} - if (tkey) key = tkey->getTreeKey(); - } - - if (!key) { - key = (TreeKeyIdx *)CreateKey(); - (*key) = *(this->key); - } + const TreeKey &key = getTreeKey(); int dsize; - key->getUserData(&dsize); + key.getUserData(&dsize); entryBuf = ""; if (dsize > 7) { - memcpy(&offset, key->getUserData(), 4); + memcpy(&offset, key.getUserData(), 4); offset = swordtoarch32(offset); - memcpy(&size, key->getUserData() + 4, 4); + memcpy(&size, key.getUserData() + 4, 4); size = swordtoarch32(size); entrySize = size; // support getEntrySize call @@ -120,15 +119,12 @@ SWBuf &RawGenBook::getRawEntryBuf() { bdtfd->read(entryBuf.getRawData(), size); rawFilter(entryBuf, 0); // hack, decipher - rawFilter(entryBuf, key); + rawFilter(entryBuf, &key); // if (!isUnicode()) - RawStr::prepText(entryBuf); + SWModule::prepText(entryBuf); } - if (key != this->key) // free our key if we created a VerseKey - delete key; - return entryBuf; } @@ -137,7 +133,7 @@ void RawGenBook::setEntry(const char *inbuf, long len) { __u32 offset = archtosword32(bdtfd->seek(0, SEEK_END)); __u32 size = 0; - TreeKeyIdx *key = ((TreeKeyIdx *)this->key); + TreeKeyIdx *key = ((TreeKeyIdx *)&(getTreeKey())); char userData[8]; @@ -156,7 +152,7 @@ void RawGenBook::setEntry(const char *inbuf, long len) { void RawGenBook::linkEntry(const SWKey *inkey) { TreeKeyIdx *srckey = 0; - TreeKeyIdx *key = ((TreeKeyIdx *)this->key); + TreeKeyIdx *key = ((TreeKeyIdx *)&(getTreeKey())); // see if we have a VerseKey * or decendant SWTRY { srckey = SWDYNAMIC_CAST(TreeKeyIdx, inkey); @@ -183,7 +179,7 @@ void RawGenBook::linkEntry(const SWKey *inkey) { */ void RawGenBook::deleteEntry() { - TreeKeyIdx *key = ((TreeKeyIdx *)this->key); + TreeKeyIdx *key = ((TreeKeyIdx *)&(getTreeKey())); key->remove(); } @@ -211,9 +207,18 @@ char RawGenBook::createModule(const char *ipath) { } -SWKey *RawGenBook::CreateKey() { - TreeKeyIdx *newKey = new TreeKeyIdx(path); - return (verseKey) ? (SWKey *)new VerseTreeKey(newKey) : newKey; +SWKey *RawGenBook::CreateKey() const { + TreeKey *tKey = new TreeKeyIdx(path); + if (verseKey) { SWKey *vtKey = new VerseTreeKey(tKey); delete tKey; return vtKey; } + return tKey; +} + +bool RawGenBook::hasEntry(const SWKey *k) const { + TreeKey &key = getTreeKey(k); + + int dsize; + key.getUserData(&dsize); + return (dsize > 7) && key.Error() == '\x00'; } SWORD_NAMESPACE_END diff --git a/src/modules/genbook/swgenbook.cpp b/src/modules/genbook/swgenbook.cpp index 0ce16aa..e7feea2 100644 --- a/src/modules/genbook/swgenbook.cpp +++ b/src/modules/genbook/swgenbook.cpp @@ -1,9 +1,27 @@ /****************************************************************************** * swld.cpp - code for base class 'SWLD'. SWLD is the basis for all - * types of Lexicon and Dictionary modules (hence the 'LD'). + * types of Lexicon and Dictionary modules (hence the 'LD'). + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <swgenbook.h> +#include <versetreekey.h> SWORD_NAMESPACE_START @@ -16,14 +34,66 @@ SWORD_NAMESPACE_START */ SWGenBook::SWGenBook(const char *imodname, const char *imoddesc, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang) : SWModule(imodname, imoddesc, idisp, (char *)"Generic Books", enc, dir, mark, ilang) { + tmpTreeKey = 0; } /****************************************************************************** - * SWLD Destructor - Cleans up instance of SWLD + * SWLD Destructor - Cleans up instance of SWGenBook */ SWGenBook::~SWGenBook() { + delete tmpTreeKey; +} + + +TreeKey &SWGenBook::getTreeKey(const SWKey *k) const { + const SWKey* thiskey = k?k:this->key; + + TreeKey *key = 0; + + SWTRY { + key = SWDYNAMIC_CAST(TreeKey, (thiskey)); + } + SWCATCH ( ... ) {} + + if (!key) { + ListKey *lkTest = 0; + SWTRY { + lkTest = SWDYNAMIC_CAST(ListKey, thiskey); + } + SWCATCH ( ... ) { } + if (lkTest) { + SWTRY { + key = SWDYNAMIC_CAST(TreeKey, lkTest->GetElement()); + if (!key) { + VerseTreeKey *tkey = 0; + SWTRY { + tkey = SWDYNAMIC_CAST(VerseTreeKey, lkTest->GetElement()); + } + SWCATCH ( ... ) {} + if (tkey) key = tkey->getTreeKey(); + } + } + SWCATCH ( ... ) { } + } + } + if (!key) { + VerseTreeKey *tkey = 0; + SWTRY { + tkey = SWDYNAMIC_CAST(VerseTreeKey, (thiskey)); + } + SWCATCH ( ... ) {} + if (tkey) key = tkey->getTreeKey(); + } + + if (!key) { + delete tmpTreeKey; + tmpTreeKey = (TreeKey *)CreateKey(); + (*tmpTreeKey) = *(thiskey); + return (*tmpTreeKey); + } + else return *key; } SWORD_NAMESPACE_END diff --git a/src/modules/lexdict/rawld/rawld.cpp b/src/modules/lexdict/rawld/rawld.cpp index 08be215..e6a4d57 100644 --- a/src/modules/lexdict/rawld/rawld.cpp +++ b/src/modules/lexdict/rawld/rawld.cpp @@ -1,11 +1,24 @@ /****************************************************************************** * rawld.cpp - code for class 'RawLD'- a module that reads raw lexicon and * dictionary files: *.dat *.idx + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - -#include <ctype.h> -#include <stdio.h> #include <fcntl.h> #include <utilstr.h> @@ -13,6 +26,8 @@ #include <rawld.h> #include <filemgr.h> +#include <stdio.h> + SWORD_NAMESPACE_START /****************************************************************************** @@ -44,50 +59,6 @@ bool RawLD::isWritable() { /****************************************************************************** - * RawLD::strongsPad - Pads a key if (it-1) is 100% digits to 5 places - * allows for final to be alpha, e.g. '123B' - * - * ENT: buf - buffer to check and pad - */ - -void RawLD::strongsPad(char *buf) -{ - char *check; - int size = 0; - int len = strlen(buf); - char subLet = 0; - bool bang = false; - if ((len < 8) && (len > 0)) { - for (check = buf; *(check+1); check++) { - if (!isdigit(*check)) - break; - else size++; - } - - if (size && ((size == (len-1)) || (size == (len-2)))) { - if (*check == '!') { - bang = true; - check++; - } - if (isalpha(*check)) { - subLet = toupper(*check); - *(check-(bang?1:0)) = 0; - } - sprintf(buf, "%.5d", atoi(buf)); - if (subLet) { - check = buf+(strlen(buf)); - if (bang) { - *check++ = '!'; - } - *check++ = subLet; - *check = 0; - } - } - } -} - - -/****************************************************************************** * RawLD::getEntry - Looks up entry from data file. 'Snaps' to closest * entry and sets 'entrybuf'. * @@ -98,8 +69,8 @@ void RawLD::strongsPad(char *buf) char RawLD::getEntry(long away) { - long start = 0; - unsigned short size = 0; + __u32 start = 0; + __u16 size = 0; char *idxbuf = 0; char retval = 0; @@ -191,4 +162,34 @@ void RawLD::deleteEntry() { doSetText(*key, ""); } + +long RawLD::getEntryCount() const { + if (idxfd < 0) return 0; + return idxfd->seek(0, SEEK_END) / IDXENTRYSIZE; +} + + +long RawLD::getEntryForKey(const char *key) const { + __u32 start, offset; + __u16 size; + + char *buf = new char [ strlen(key) + 6 ]; + strcpy(buf, key); + + strongsPad(buf); + + findOffset(buf, &start, &size, 0, &offset); + + delete [] buf; + + return offset / IDXENTRYSIZE; +} + + +char *RawLD::getKeyForEntry(long entry) const { + char *key = 0; + getIDXBuf(entry * IDXENTRYSIZE, &key); + return key; +} + SWORD_NAMESPACE_END diff --git a/src/modules/lexdict/rawld4/rawld4.cpp b/src/modules/lexdict/rawld4/rawld4.cpp index 0fd1058..6d60d9a 100644 --- a/src/modules/lexdict/rawld4/rawld4.cpp +++ b/src/modules/lexdict/rawld4/rawld4.cpp @@ -1,11 +1,24 @@ /****************************************************************************** * rawld.cpp - code for class 'RawLD'- a module that reads raw lexicon and - * dictionary files: *.dat *.idx + * dictionary files: *.dat *.idx + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - -#include <ctype.h> -#include <stdio.h> #include <fcntl.h> #include <filemgr.h> @@ -13,6 +26,8 @@ #include <rawstr4.h> #include <rawld4.h> +#include <stdio.h> + SWORD_NAMESPACE_START /****************************************************************************** @@ -44,50 +59,6 @@ bool RawLD4::isWritable() { /****************************************************************************** - * RawLD4::strongsPad - Pads a key if (it-1) is 100% digits to 5 places - * allows for final to be alpha, e.g. '123B' - * - * ENT: buf - buffer to check and pad - */ - -void RawLD4::strongsPad(char *buf) -{ - char *check; - int size = 0; - int len = strlen(buf); - char subLet = 0; - bool bang = false; - if ((len < 8) && (len > 0)) { - for (check = buf; *(check+1); check++) { - if (!isdigit(*check)) - break; - else size++; - } - - if (size && ((size == (len-1)) || (size == (len-2)))) { - if (*check == '!') { - bang = true; - check++; - } - if (isalpha(*check)) { - subLet = toupper(*check); - *(check-(bang?1:0)) = 0; - } - sprintf(buf, "%.5d", atoi(buf)); - if (subLet) { - check = buf+(strlen(buf)); - if (bang) { - *check++ = '!'; - } - *check++ = subLet; - *check = 0; - } - } - } -} - - -/****************************************************************************** * RawLD4::getEntry - Looks up entry from data file. 'Snaps' to closest * entry and sets 'entrybuf'. * @@ -98,10 +69,10 @@ void RawLD4::strongsPad(char *buf) char RawLD4::getEntry(long away) { - long start = 0; - unsigned long size = 0; + __u32 start = 0; + __u32 size = 0; char *idxbuf = 0; - char retval = 0; + char retval = 0; char *buf = new char [ strlen(*key) + 6 ]; strcpy(buf, *key); @@ -189,4 +160,31 @@ void RawLD4::deleteEntry() { doSetText(*key, ""); } +long RawLD4::getEntryCount() const { + if (idxfd < 0) return 0; + return idxfd->seek(0, SEEK_END) / IDXENTRYSIZE; +} + +long RawLD4::getEntryForKey(const char *key) const { + __u32 start, offset; + __u32 size; + + char *buf = new char [ strlen(key) + 6 ]; + strcpy(buf, key); + + strongsPad(buf); + + findOffset(buf, &start, &size, 0, &offset); + + delete [] buf; + + return offset / IDXENTRYSIZE; +} + +char *RawLD4::getKeyForEntry(long entry) const { + char *key = 0; + getIDXBuf(entry * IDXENTRYSIZE, &key); + return key; +} + SWORD_NAMESPACE_END diff --git a/src/modules/lexdict/swld.cpp b/src/modules/lexdict/swld.cpp index 518e5c0..bccf5d8 100644 --- a/src/modules/lexdict/swld.cpp +++ b/src/modules/lexdict/swld.cpp @@ -1,8 +1,26 @@ /****************************************************************************** * swld.cpp - code for base class 'SWLD'. SWLD is the basis for all - * types of Lexicon and Dictionary modules (hence the 'LD'). + * types of Lexicon and Dictionary modules (hence the 'LD'). + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ +#include <ctype.h> +#include <stdio.h> #include <swld.h> #include <strkey.h> @@ -36,7 +54,7 @@ SWLD::~SWLD() } -SWKey *SWLD::CreateKey() { return new StrKey(); } +SWKey *SWLD::CreateKey() const { return new StrKey(); } /****************************************************************************** @@ -78,5 +96,68 @@ void SWLD::setPosition(SW_POSITION p) { getRawEntryBuf(); } +bool SWLD::hasEntry(const SWKey *key) const { + const char *key_str = *key; + char *buf = new char [ strlen(key_str) + 6 ]; + strcpy(buf, key_str); + + strongsPad(buf); + + bool retVal = !strcmp(buf, getKeyForEntry(getEntryForKey(buf))); + delete buf; + + return retVal; +} + +/****************************************************************************** + * SWLD::strongsPad - Pads a key if (it-1) is 100% digits to 5 places + * allows for final to be alpha, e.g. '123B' + * + * ENT: buf - buffer to check and pad + */ + +void SWLD::strongsPad(char *buf) +{ + char *check; + int size = 0; + int len = strlen(buf); + char subLet = 0; + bool bang = false, prefix=false; + if ((len < 9) && (len > 0)) { + // Handle initial G or H + if (*buf == 'G' || *buf == 'H' || *buf == 'g' || *buf == 'h') { + buf += 1; + len -= 1; + prefix = true; + } + + for (check = buf; *(check); check++) { + if (!isdigit(*check)) + break; + else size++; + } + + if (size && ((size == len) || (size == len - 1) || (size == (len-2)))) { + if (*check == '!') { + bang = true; + check++; + } + if (isalpha(*check)) { + subLet = toupper(*check); + *(check-(bang?1:0)) = 0; + } + sprintf(buf, prefix?"%.4d":"%.5d", atoi(buf)); + if (subLet) { + check = buf+(strlen(buf)); + if (bang) { + *check++ = '!'; + } + *check++ = subLet; + *check = 0; + } + } + } +} + SWORD_NAMESPACE_END diff --git a/src/modules/lexdict/zld/zld.cpp b/src/modules/lexdict/zld/zld.cpp index bcb51ab..4e786bc 100644 --- a/src/modules/lexdict/zld/zld.cpp +++ b/src/modules/lexdict/zld/zld.cpp @@ -1,11 +1,23 @@ /****************************************************************************** * rawld.cpp - code for class 'RawLD'- a module that reads raw lexicon and - * dictionary files: *.dat *.idx + * dictionary files: *.dat *.idx + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - -#include <ctype.h> -#include <stdio.h> #include <fcntl.h> #include <utilstr.h> @@ -13,6 +25,8 @@ #include <zld.h> #include <filemgr.h> +#include <stdio.h> + SWORD_NAMESPACE_START /****************************************************************************** @@ -44,48 +58,6 @@ bool zLD::isWritable() { /****************************************************************************** - * zLD::strongsPad - Pads a key if it is 100% digits to 5 places - * - * ENT: buf - buffer to check and pad - */ - -void zLD::strongsPad(char *buf) { - char *check; - int size = 0; - int len = strlen(buf); - char subLet = 0; - bool bang = false; - if ((len < 8) && (len > 0)) { - for (check = buf; *(check+1); check++) { - if (!isdigit(*check)) - break; - else size++; - } - - if (size && ((size == (len-1)) || (size == (len-2)))) { - if (*check == '!') { - bang = true; - check++; - } - if (isalpha(*check)) { - subLet = toupper(*check); - *(check-(bang?1:0)) = 0; - } - sprintf(buf, "%.5d", atoi(buf)); - if (subLet) { - check = buf+(strlen(buf)); - if (bang) { - *check++ = '!'; - } - *check++ = subLet; - *check = 0; - } - } - } -} - - -/****************************************************************************** * zLD::getEntry - Looks up entry from data file. 'Snaps' to closest * entry and sets 'entrybuf'. * @@ -186,4 +158,36 @@ void zLD::deleteEntry() { setText(*key, ""); } + +long zLD::getEntryCount() const +{ + if (idxfd < 0) return 0; + return idxfd->seek(0, SEEK_END) / IDXENTRYSIZE; +} + + +long zLD::getEntryForKey(const char* key) const +{ + long offset; + char *buf = new char [ strlen(key) + 6 ]; + strcpy(buf, key); + + strongsPad(buf); + + findKeyIndex(buf, &offset); + + delete [] buf; + + return offset/IDXENTRYSIZE; +} + + +char *zLD::getKeyForEntry(long entry) const +{ + char *key = 0; + getKeyFromIdxOffset(entry * IDXENTRYSIZE, &key); + return key; +} + + SWORD_NAMESPACE_END diff --git a/src/modules/swmodule.cpp b/src/modules/swmodule.cpp index 8461953..3eb7ce1 100644 --- a/src/modules/swmodule.cpp +++ b/src/modules/swmodule.cpp @@ -1,11 +1,29 @@ /****************************************************************************** - * swmodule.cpp -code for base class 'module'. Module is the basis for all - * types of modules (e.g. texts, commentaries, maps, lexicons, - * etc.) + * swmodule.cpp - code for base class 'module'. Module is the basis for all + * types of modules (e.g. texts, commentaries, maps, lexicons, + * etc.) + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ + #include <vector> +#include <swlog.h> #include <sysdata.h> #include <swmodule.h> #include <utilstr.h> @@ -58,7 +76,7 @@ typedef std::list<SWBuf> StringList; * unicode - if this module is unicode */ -SWModule::SWModule(const char *imodname, const char *imoddesc, SWDisplay *idisp, char *imodtype, SWTextEncoding encoding, SWTextDirection direction, SWTextMarkup markup, const char* imodlang) { +SWModule::SWModule(const char *imodname, const char *imoddesc, SWDisplay *idisp, const char *imodtype, SWTextEncoding encoding, SWTextDirection direction, SWTextMarkup markup, const char *imodlang) { key = CreateKey(); entryBuf = ""; config = &ownConfig; @@ -127,7 +145,7 @@ SWModule::~SWModule() * RET: pointer to allocated key */ -SWKey *SWModule::CreateKey() +SWKey *SWModule::CreateKey() const { return new SWKey(); } @@ -255,7 +273,8 @@ char SWModule::Markup(signed char newmark) { char *SWModule::Lang(const char *imodlang) { - return stdstr(&modlang, imodlang); + if (imodlang) stdstr(&modlang, imodlang); + return modlang; } @@ -395,8 +414,9 @@ void SWModule::decrement(int steps) { * >=0 - regex * -1 - phrase * -2 - multiword - * -3 - entryAttrib (eg. Word//Lemma/G1234/) + * -3 - entryAttrib (eg. Word//Lemma./G1234/) (Lemma with dot means check components (Lemma.[1-9]) also) * -4 - clucene + * -5 - multilemma window; flags = window size * flags - options flags for search * justCheckIfSupported - if set, don't search, only tell if this * function supports requested search. @@ -408,6 +428,7 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc listKey.ClearList(); SWBuf term = istr; + bool includeComponents = false; // for entryAttrib e.g., /Lemma.1/ #ifdef USELUCENE SWBuf target = getConfigEntry("AbsoluteDataPath"); @@ -431,12 +452,16 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc SWKey *resultKey = CreateKey(); regex_t preg; vector<SWBuf> words; + vector<SWBuf> window; const char *sres; terminateSearch = false; char perc = 1; bool savePEA = isProcessEntryAttributes(); - // determine if we might be doing special strip searches. useful for knowing if we can use shortcuts - bool specialStrips = (getConfigEntry("LocalStripFilter") || strchr(istr, '<')); + + // determine if we might be doing special strip searches. useful for knowing if we can use shortcuts + bool specialStrips = (getConfigEntry("LocalStripFilter") + || (getConfig().has("GlobalOptionFilter", "UTF8GreekAccents")) + || (strchr(istr, '<'))); processEntryAttributes(searchType == -3); @@ -454,19 +479,9 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc } (*percent)(perc, percentUserData); - // MAJOR KLUDGE: VerseKey::Index still return index within testament. - // VerseKey::NewIndex should be moved to Index and Index should be some - // VerseKey specific name - VerseKey *vkcheck = 0; - SWTRY { - vkcheck = SWDYNAMIC_CAST(VerseKey, key); - } - SWCATCH (...) {} - // end MAJOR KLUDGE *this = BOTTOM; - // fix below when we find out the bug - long highIndex = (vkcheck)?32300/*vkcheck->NewIndex()*/:key->Index(); + long highIndex = key->Index(); if (!highIndex) highIndex = 1; // avoid division by zero errors. *this = TOP; @@ -502,6 +517,7 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc (*percent)(80, percentUserData); // iterate thru each good module position that meets the search + bool checkBounds = getKey()->isBoundSet(); for (long i = 0; i < h->length(); i++) { Document &doc = h->doc(i); @@ -509,12 +525,15 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc lucene_wcstoutf8(utfBuffer, doc.get(_T("key")), MAX_CONV_SIZE); *resultKey = utfBuffer; //TODO Does a key always accept utf8? - // check to see if it sets ok (in our range?) and if so, add to our return list - *getKey() = *resultKey; - if (*getKey() == *resultKey) { - listKey << *resultKey; - listKey.GetElement()->userData = (void *)((__u32)(h->score(i)*100)); + // check to see if it sets ok (within our bounds) and if not, skip + if (checkBounds) { + *getKey() = *resultKey; + if (*getKey() != *resultKey) { + continue; + } } + listKey << *resultKey; + listKey.GetElement()->userData = (void *)((__u32)(h->score(i)*100)); } (*percent)(98, percentUserData); } @@ -543,6 +562,7 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc // multi-word case -2: + case -5: // let's break the term down into our words vector while (1) { const char *word = term.stripPrefix(' '); @@ -570,6 +590,10 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc } words.push_back(word); } + if ((words.size()>2) && words[2].endsWith(".")) { + includeComponents = true; + words[2]--; + } break; } @@ -579,16 +603,12 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc (*percent)(perc, percentUserData); - while ((searchType > -4) && !Error() && !terminateSearch) { - long mindex = 0; - if (vkcheck) - mindex = vkcheck->NewIndex(); - else mindex = key->Index(); + while ((searchType != -4) && !Error() && !terminateSearch) { + long mindex = key->Index(); float per = (float)mindex / highIndex; per *= 93; per += 5; char newperc = (char)per; -// char newperc = (char)(5+(93*(((float)((vkcheck)?vkcheck->NewIndex():key->Index()))/highIndex))); if (newperc > perc) { perc = newperc; (*percent)(perc, percentUserData); @@ -596,8 +616,7 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc else if (newperc < perc) { #ifndef _MSC_VER std::cerr << "Serious error: new percentage complete is less than previous value\n"; - std::cerr << "using vk? " << ((vkcheck)?"yes":"no") << "\n"; - std::cerr << "index: " << ((vkcheck)?vkcheck->NewIndex():key->Index()) << "\n"; + std::cerr << "index: " << (key->Index()) << "\n"; std::cerr << "highIndex: " << highIndex << "\n"; std::cerr << "newperc ==" << (int)newperc << "%" << "is smaller than\n"; std::cerr << "perc == " << (int )perc << "% \n"; @@ -656,7 +675,7 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc } break; // entry attributes - case -3: + case -3: { RenderText(); // force parse AttributeTypeList &entryAttribs = getEntryAttributes(); AttributeTypeList::iterator i1Start, i1End; @@ -685,7 +704,7 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc i2End = i1Start->second.end(); } for (;i2Start != i2End; i2Start++) { - if ((words.size()>2) && (words[2].length())) { + if ((words.size()>2) && (words[2].length()) && (!includeComponents)) { i3Start = i2Start->second.find(words[2]); i3End = i3Start; if (i3End != i2Start->second.end()) @@ -697,6 +716,13 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc } for (;i3Start != i3End; i3Start++) { if ((words.size()>3) && (words[3].length())) { + if (includeComponents) { + SWBuf key = i3Start->first.c_str(); + key = key.stripPrefix('.', true); + // we're iterating all 3 level keys, so be sure we match our + // prefix (e.g., Lemma, Lemma.1, Lemma.2, etc.) + if (key != words[2]) continue; + } if (flags & SEARCHFLAG_MATCHWHOLEENTRY) { bool found = !(((flags & REG_ICASE) == REG_ICASE) ? sword::stricmp(i3Start->second.c_str(), words[3]) : strcmp(i3Start->second.c_str(), words[3])); sres = (found) ? i3Start->second.c_str() : 0; @@ -719,6 +745,54 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc break; } break; + } + case -5: + AttributeList &words = getEntryAttributes()["Word"]; + SWBuf kjvWord = ""; + SWBuf bibWord = ""; + for (AttributeList::iterator it = words.begin(); it != words.end(); it++) { + int parts = atoi(it->second["PartCount"]); + SWBuf lemma = ""; + SWBuf morph = ""; + for (int i = 1; i <= parts; i++) { + SWBuf key = ""; + key = (parts == 1) ? "Lemma" : SWBuf().setFormatted("Lemma.%d", i).c_str(); + AttributeValue::iterator li = it->second.find(key); + if (li != it->second.end()) { + if (i > 1) lemma += " "; + key = (parts == 1) ? "LemmaClass" : SWBuf().setFormatted("LemmaClass.%d", i).c_str(); + AttributeValue::iterator lci = it->second.find(key); + if (lci != it->second.end()) { + lemma += lci->second + ":"; + } + lemma += li->second; + } + key = (parts == 1) ? "Morph" : SWBuf().setFormatted("Morph.%d", i).c_str(); + li = it->second.find(key); + // silly. sometimes morph counts don't equal lemma counts + if (i == 1 && parts != 1 && li == it->second.end()) { + li = it->second.find("Morph"); + } + if (li != it->second.end()) { + if (i > 1) morph += " "; + key = (parts == 1) ? "MorphClass" : SWBuf().setFormatted("MorphClass.%d", i).c_str(); + AttributeValue::iterator lci = it->second.find(key); + // silly. sometimes morph counts don't equal lemma counts + if (i == 1 && parts != 1 && lci == it->second.end()) { + lci = it->second.find("MorphClass"); + } + if (lci != it->second.end()) { + morph += lci->second + ":"; + } + morph += li->second; + } + // TODO: add src tags and maybe other attributes + } + while (window.size() < (unsigned)flags) { + + } + } + break; } // end switch } (*this)++; @@ -812,7 +886,7 @@ const char *SWModule::StripText(const char *buf, int len) { * RET: this module's text at current key location massaged by RenderFilers */ - const char *SWModule::RenderText(SWKey *tmpKey) { + const char *SWModule::RenderText(const SWKey *tmpKey) { SWKey *saveKey; const char *retVal; @@ -843,7 +917,7 @@ const char *SWModule::StripText(const char *buf, int len) { * RET: this module's text at specified key location massaged by Strip filters */ -const char *SWModule::StripText(SWKey *tmpKey) { +const char *SWModule::StripText(const SWKey *tmpKey) { SWKey *saveKey; const char *retVal; @@ -919,8 +993,8 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void } } - - // be sure we give CLucene enough file handles + + // be sure we give CLucene enough file handles FileMgr::getSystemFileMgr()->flush(); // save key information so as not to disrupt original @@ -941,7 +1015,7 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void IndexWriter *coreWriter = NULL; IndexWriter *fsWriter = NULL; Directory *d = NULL; - + standard::StandardAnalyzer *an = new standard::StandardAnalyzer(); SWBuf target = getConfigEntry("AbsoluteDataPath"); bool includeKeyInSearch = getConfig().has("SearchOption", "IncludeKeyInSearch"); @@ -953,19 +1027,21 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void ramDir = new RAMDirectory(); coreWriter = new IndexWriter(ramDir, an, true); - - + + char perc = 1; VerseKey *vkcheck = 0; vkcheck = SWDYNAMIC_CAST(VerseKey, key); + VerseKey *chapMax = 0; + if (vkcheck) chapMax = (VerseKey *)vkcheck->clone(); TreeKeyIdx *tkcheck = 0; tkcheck = SWDYNAMIC_CAST(TreeKeyIdx, key); *this = BOTTOM; - long highIndex = (vkcheck)?32300/*vkcheck->NewIndex()*/:key->Index(); + long highIndex = key->Index(); if (!highIndex) highIndex = 1; // avoid division by zero errors. @@ -976,20 +1052,16 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void // position module at the beginning *this = TOP; - VerseKey chapMax; SWBuf proxBuf; SWBuf proxLem; SWBuf strong; const short int MAX_CONV_SIZE = 2047; wchar_t wcharBuffer[MAX_CONV_SIZE + 1]; - + char err = Error(); while (!err) { - long mindex = 0; - if (vkcheck) - mindex = vkcheck->NewIndex(); - else mindex = key->Index(); + long mindex = key->Index(); proxBuf = ""; proxLem = ""; @@ -1016,7 +1088,7 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void if (content && *content) { good = true; - + // build "strong" field AttributeTypeList::iterator words; AttributeList::iterator word; @@ -1046,8 +1118,10 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void } lucene_utf8towcs(wcharBuffer, keyText, MAX_CONV_SIZE); //keyText must be utf8 +// doc->add( *(new Field("key", wcharBuffer, Field::STORE_YES | Field::INDEX_TOKENIZED))); doc->add( *Field::Text(_T("key"), wcharBuffer ) ); + if (includeKeyInSearch) { c = keyText; c += " "; @@ -1071,12 +1145,12 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void // for VerseKeys use chapter if (vkcheck) { - chapMax = *vkcheck; + *chapMax = *vkcheck; // we're the first verse in a chapter if (vkcheck->Verse() == 1) { - chapMax = MAXVERSE; + *chapMax = MAXVERSE; VerseKey saveKey = *vkcheck; - while ((!err) && (*vkcheck <= chapMax)) { + while ((!err) && (*vkcheck <= *chapMax)) { //printf("building proxBuf from (%s).\nproxBuf.c_str(): %s\n", (const char *)*key, proxBuf.c_str()); //printf("building proxBuf from (%s).\n", (const char *)*key); @@ -1112,7 +1186,7 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void proxBuf += content; proxBuf.append(' '); proxLem += strong; - if (proxLem.length()) + if (proxLem.length()) proxLem.append("\n"); } (*this)++; @@ -1122,7 +1196,7 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void *vkcheck = saveKey; } } - + // for TreeKeys use siblings if we have no children else if (tkcheck) { if (!tkcheck->hasChildren()) { @@ -1164,7 +1238,7 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void proxBuf += content; proxBuf.append(' '); proxLem += strong; - if (proxLem.length()) + if (proxLem.length()) proxLem.append("\n"); } } while (tkcheck->nextSibling()); @@ -1174,11 +1248,11 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void else tkcheck->nextSibling(); // reposition from our previousSibling test } } - + if (proxBuf.length() > 0) { - + lucene_utf8towcs(wcharBuffer, proxBuf, MAX_CONV_SIZE); //keyText must be utf8 - + //printf("proxBuf after (%s).\nprox: %s\nproxLem: %s\n", (const char *)*key, proxBuf.c_str(), proxLem.c_str()); doc->add( *Field::UnStored(_T("prox"), wcharBuffer) ); @@ -1209,7 +1283,7 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void if (IndexReader::isLocked(d)) { IndexReader::unlock(d); } - + fsWriter = new IndexWriter( d, an, false); } else { d = FSDirectory::getDirectory(target.c_str(), true); @@ -1234,6 +1308,8 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void if (searchKey) delete searchKey; + delete chapMax; + processEntryAttributes(savePEA); // reset option filters back to original values @@ -1253,7 +1329,7 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void * @param buf the buffer to filter * @param key key location from where this buffer was extracted */ -void SWModule::filterBuffer(OptionFilterList *filters, SWBuf &buf, SWKey *key) { +void SWModule::filterBuffer(OptionFilterList *filters, SWBuf &buf, const SWKey *key) { OptionFilterList::iterator it; for (it = filters->begin(); it != filters->end(); it++) { (*it)->processText(buf, key, this); @@ -1265,7 +1341,7 @@ void SWModule::filterBuffer(OptionFilterList *filters, SWBuf &buf, SWKey *key) { * @param buf the buffer to filter * @param key key location from where this buffer was extracted */ -void SWModule::filterBuffer(FilterList *filters, SWBuf &buf, SWKey *key) { +void SWModule::filterBuffer(FilterList *filters, SWBuf &buf, const SWKey *key) { FilterList::iterator it; for (it = filters->begin(); it != filters->end(); it++) { (*it)->processText(buf, key, this); @@ -1282,4 +1358,63 @@ void SWModule::setEntry(const char*, long) { void SWModule::linkEntry(const SWKey*) { } + +/****************************************************************************** + * SWModule::prepText - Prepares the text before returning it to external + * objects + * + * ENT: buf - buffer where text is stored and where to store the prep'd + * text. + */ + +void SWModule::prepText(SWBuf &buf) { + unsigned int to, from; + char space = 0, cr = 0, realdata = 0, nlcnt = 0; + char *rawBuf = buf.getRawData(); + for (to = from = 0; rawBuf[from]; from++) { + switch (rawBuf[from]) { + case 10: + if (!realdata) + continue; + space = (cr) ? 0 : 1; + cr = 0; + nlcnt++; + if (nlcnt > 1) { +// *to++ = nl; + rawBuf[to++] = 10; +// *to++ = nl[1]; +// nlcnt = 0; + } + continue; + case 13: + if (!realdata) + continue; +// *to++ = nl[0]; + rawBuf[to++] = 10; + space = 0; + cr = 1; + continue; + } + realdata = 1; + nlcnt = 0; + if (space) { + space = 0; + if (rawBuf[from] != ' ') { + rawBuf[to++] = ' '; + from--; + continue; + } + } + rawBuf[to++] = rawBuf[from]; + } + buf.setSize(to); + + while (to > 1) { // remove trailing excess + to--; + if ((rawBuf[to] == 10) || (rawBuf[to] == ' ')) + buf.setSize(to); + else break; + } +} + SWORD_NAMESPACE_END diff --git a/src/modules/tests/echomod.cpp b/src/modules/tests/echomod.cpp index 2640773..99b00cd 100644 --- a/src/modules/tests/echomod.cpp +++ b/src/modules/tests/echomod.cpp @@ -1,6 +1,22 @@ /****************************************************************************** * echomod.cpp - code for class 'echomod'- a dummy test text module that just * echos back the key + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ #include <echomod.h> diff --git a/src/modules/texts/rawtext/rawtext.cpp b/src/modules/texts/rawtext/rawtext.cpp index 3245da6..8641a45 100644 --- a/src/modules/texts/rawtext/rawtext.cpp +++ b/src/modules/texts/rawtext/rawtext.cpp @@ -1,9 +1,24 @@ /****************************************************************************** * rawtext.cpp - code for class 'RawText'- a module that reads raw text files: * ot and nt using indexs ??.bks ??.cps ??.vss + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdio.h> #include <fcntl.h> #include <sysdata.h> @@ -42,27 +57,9 @@ typedef list<long> longlist; * idisp - Display object to use for displaying */ -RawText::RawText(const char *ipath, const char *iname, const char *idesc, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang) - : SWText(iname, idesc, idisp, enc, dir, mark, ilang), +RawText::RawText(const char *ipath, const char *iname, const char *idesc, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang, const char *versification) + : SWText(iname, idesc, idisp, enc, dir, mark, ilang, versification), RawVerse(ipath) { - -#ifndef USELUCENE - SWBuf fname; - fname = path; - char ch = fname.c_str()[strlen(fname.c_str())-1]; - if ((ch != '/') && (ch != '\\')) - fname += "/"; - - for (int loop = 0; loop < 2; loop++) { - fastSearch[loop] = 0; - SWBuf fastidxname =(fname + ((loop)?"ntwords.dat":"otwords.dat")); - if (FileMgr::existsFile(fastidxname.c_str())) { - fastidxname = (fname + ((loop)?"ntwords.idx":"otwords.idx")); - if (FileMgr::existsFile(fastidxname.c_str())) - fastSearch[loop] = new RawStr((fname + ((loop)?"ntwords":"otwords")).c_str()); - } - } -#endif } @@ -71,13 +68,6 @@ RawText::RawText(const char *ipath, const char *iname, const char *idesc, SWDisp */ RawText::~RawText() { -#ifndef USELUCENE - if (fastSearch[0]) - delete fastSearch[0]; - - if (fastSearch[1]) - delete fastSearch[1]; -#endif } @@ -98,7 +88,7 @@ SWBuf &RawText::getRawEntryBuf() { unsigned short size = 0; VerseKey &key = getVerseKey(); - findOffset(key.Testament(), key.Index(), &start, &size); + findOffset(key.Testament(), key.TestamentIndex(), &start, &size); entrySize = size; // support getEntrySize call entryBuf = ""; @@ -114,382 +104,16 @@ SWBuf &RawText::getRawEntryBuf() { } -signed char RawText::createSearchFramework(void (*percent)(char, void *), void *percentUserData) { -#ifndef USELUCENE - SWKey *savekey = 0; - SWKey *searchkey = 0; - SWKey textkey; - char *word = 0; - char *wordBuf = 0; - - // dictionary holds words associated with a list - // containing every module position that contains - // the word. [0] Old Testament; [1] NT - map < SWBuf, list<long> > dictionary[2]; - - - // save key information so as not to disrupt original - // module position - if (!key->Persist()) { - savekey = CreateKey(); - *savekey = *key; - } - else savekey = key; - - searchkey = (key->Persist())?key->clone():0; - if (searchkey) { - searchkey->Persist(1); - setKey(*searchkey); - } - - // position module at the beginning - *this = TOP; - - VerseKey *lkey = (VerseKey *)key; - - // iterate thru each entry in module - while (!Error()) { - long index = lkey->Index(); - wordBuf = (char *)calloc(sizeof(char), strlen(StripText()) + 1); - strcpy(wordBuf, StripText()); - - // grab each word from the text - word = strtok(wordBuf, " !.,?;:()-=+/\\|{}[]\"<>"); - while (word) { - - // make word upper case - toupperstr(word); - - // lookup word in dictionary (or make entry in dictionary - // for this word) and add this module position (index) to - // the word's associated list of module positions - dictionary[lkey->Testament()-1][word].push_back(index); - word = strtok(NULL, " !.,?;:()-=+/\\|{}[]\"<>"); - } - free(wordBuf); - (*this)++; - } - - // reposition module back to where it was before we were called - setKey(*savekey); - - if (!savekey->Persist()) - delete savekey; - - if (searchkey) - delete searchkey; - - - // --------- Let's output an index from our dictionary ----------- - FileDesc *datfd; - FileDesc *idxfd; - strlist::iterator it; - longlist::iterator it2; - unsigned long offset, entryoff; - unsigned short size; - - SWBuf fname; - fname = path; - char ch = fname.c_str()[strlen(fname.c_str())-1]; - if ((ch != '/') && (ch != '\\')) - fname += "/"; - - // for old and new testament do... - for (int loop = 0; loop < 2; loop++) { - datfd = FileMgr::getSystemFileMgr()->open((fname + ((loop)?"ntwords.dat":"otwords.dat")).c_str(), FileMgr::CREAT|FileMgr::WRONLY, 00644); - if (datfd->getFd() == -1) - return -1; - idxfd = FileMgr::getSystemFileMgr()->open((fname + ((loop)?"ntwords.idx":"otwords.idx")).c_str(), FileMgr::CREAT|FileMgr::WRONLY, 00644); - if (idxfd->getFd() == -1) { - FileMgr::getSystemFileMgr()->close(datfd); - return -1; - } - - // iterate thru each word in the dictionary - for (it = dictionary[loop].begin(); it != dictionary[loop].end(); it++) { - printf("%s: ", it->first.c_str()); - - // get our current offset in our word.dat file and write this as the start - // of the next entry in our database - offset = datfd->seek(0, SEEK_CUR); - idxfd->write(&offset, 4); - - // write our word out to the word.dat file, delineating with a \n - datfd->write(it->first.c_str(), strlen(it->first.c_str())); - datfd->write("\n", 1); - - // force our mod position list for this word to be unique (remove - // duplicates that may exist if the word was found more than once - // in the verse - it->second.unique(); - - // iterate thru each mod position for this word and output it to - // our database - unsigned short count = 0; - for (it2 = it->second.begin(); it2 != it->second.end(); it2++) { - entryoff= *it2; - datfd->write(&entryoff, 4); - count++; - } - - // now see what our new position is in our word.dat file and - // determine the size of this database entry - size = datfd->seek(0, SEEK_CUR) - offset; - - // store the size of this database entry - idxfd->write(&size, 2); - printf("%d entries (size: %d)\n", count, size); - } - FileMgr::getSystemFileMgr()->close(datfd); - FileMgr::getSystemFileMgr()->close(idxfd); - } - return 0; -#else - return SWModule::createSearchFramework(percent, percentUserData); -#endif -} - - -void RawText::deleteSearchFramework() { -#ifndef USELUCENE - SWBuf target = path; - char ch = target.c_str()[strlen(target.c_str())-1]; - if ((ch != '/') && (ch != '\\')) - target += "/lucene"; - FileMgr::removeFile(target + "ntwords.dat"); - FileMgr::removeFile(target + "otwords.dat"); - FileMgr::removeFile(target + "ntwords.idx"); - FileMgr::removeFile(target + "otwords.idx"); -#else - SWModule::deleteSearchFramework(); -#endif -} - - -/****************************************************************************** - * SWModule::search - Searches a module for a string - * - * ENT: istr - string for which to search - * searchType - type of search to perform - * >=0 - regex - * -1 - phrase - * -2 - multiword - * flags - options flags for search - * justCheckIfSupported - if set, don't search, only tell if this - * function supports requested search. - * - * RET: ListKey set to verses that contain istr - */ - -ListKey &RawText::search(const char *istr, int searchType, int flags, SWKey *scope, bool *justCheckIfSupported, void (*percent)(char, void *), void *percentUserData) { -#ifndef USELUCENE - listKey.ClearList(); - - if ((fastSearch[0]) && (fastSearch[1])) { - - switch (searchType) { - case -2: { - - if ((flags & REG_ICASE) != REG_ICASE) // if haven't chosen to - // ignore case - break; // can't handle fast case sensitive searches - - // test to see if our scope for this search is bounded by a - // VerseKey - VerseKey *testKeyType = 0; - SWTRY { - testKeyType = SWDYNAMIC_CAST(VerseKey, ((scope)?scope:key)); - } - SWCATCH ( ... ) {} - // if we don't have a VerseKey * decendant we can't handle - // because of scope. - // In the future, add bool SWKey::isValid(const char *tryString); - if (!testKeyType) - break; - - - // check if we just want to see if search is supported. - // If we've gotten this far, then it is supported. - if (justCheckIfSupported) { - *justCheckIfSupported = true; - return listKey; - } - - SWKey saveKey = *testKeyType; // save current place - - char error = 0; - char **words = 0; - char *wordBuf = 0; - int wordCount = 0; - long start; - unsigned short size; - char *idxbuf = 0; - SWBuf datBuf; - list <long> indexes; - list <long> indexes2; - VerseKey vk; - vk = TOP; - - (*percent)(10, percentUserData); - - // toupper our copy of search string - stdstr(&wordBuf, istr); - toupperstr(wordBuf); - - // get list of individual words - words = (char **)calloc(sizeof(char *), 10); - int allocWords = 10; - words[wordCount] = strtok(wordBuf, " "); - while (words[wordCount]) { - wordCount++; - if (wordCount == allocWords) { - allocWords+=10; - words = (char **)realloc(words, sizeof(char *)*allocWords); - } - words[wordCount] = strtok(NULL, " "); - } - - (*percent)(20, percentUserData); - - // clear our result set - indexes.erase(indexes.begin(), indexes.end()); - - // search both old and new testament indexes - for (int j = 0; j < 2; j++) { - // iterate thru each word the user passed to us. - for (int i = 0; i < wordCount; i++) { - - // clear this word's result set - indexes2.erase(indexes2.begin(), indexes2.end()); - error = 0; - - // iterate thru every word in the database that starts - // with our search word - for (int away = 0; !error; away++) { - idxbuf = 0; - - // find our word in the database and jump ahead _away_ - error = fastSearch[j]->findOffset(words[i], &start, &size, away); - - // get the word from the database - fastSearch[j]->getIDXBufDat(start, &idxbuf); - - // check to see if it starts with our target word - if (strlen(idxbuf) > strlen(words[i])) - idxbuf[strlen(words[i])] = 0; -// else words[i][strlen(idxbuf)] = 0; - if (!strcmp(idxbuf, words[i])) { - - // get data for this word from database - delete [] idxbuf; - idxbuf = 0; - datBuf = ""; - fastSearch[j]->readText(start, &size, &idxbuf, datBuf); - - // we know that the data consists of sizof(long) - // records each a valid module position that constains - // this word - // - // iterate thru each of these module positions - long *keyindex = (long *)datBuf.getRawData(); - while (keyindex < (long *)(datBuf.getRawData() + size - (strlen(idxbuf) + 1))) { - if (i) { // if we're not on our first word - - // check to see if this word is already in the result set. - // This is our AND functionality - if (find(indexes.begin(), indexes.end(), *keyindex) != indexes.end()) - // add to new result set - indexes2.push_back(*keyindex); - } - else indexes2.push_back(*keyindex); - keyindex++; - } - } - else error = 1; // no more matches - free(idxbuf); - } - - // make new result set final result set - indexes = indexes2; - - percent((char)(20 + (float)((j*wordCount)+i)/(wordCount * 2) * 78), percentUserData); - } - - // indexes contains our good verses, lets return them in a listKey - indexes.sort(); - - // iterate thru each good module position that meets the search - for (longlist::iterator it = indexes.begin(); it != indexes.end(); it++) { - - // set a temporary verse key to this module position - vk.Testament(j+1); - vk.Error(); - vk.Index(*it); - - // check scope - // Try to set our scope key to this verse key - if (scope) { - *testKeyType = vk; - - // check to see if it set ok and if so, add to our return list - if (*testKeyType == vk) - listKey << (const char *) vk; - } - else listKey << (const char*) vk; - } - } - (*percent)(98, percentUserData); - - free(words); - free(wordBuf); - - *testKeyType = saveKey; // set current place back to original - - listKey = TOP; - (*percent)(100, percentUserData); - return listKey; - } - - default: - break; - } - } - - // check if we just want to see if search is supported - if (justCheckIfSupported) { - *justCheckIfSupported = false; - return listKey; - } - -#endif - // if we don't support this search, fall back to base class - return SWModule::search(istr, searchType, flags, scope, justCheckIfSupported, percent, percentUserData); -} - - void RawText::setEntry(const char *inbuf, long len) { VerseKey &key = getVerseKey(); - doSetText(key.Testament(), key.Index(), inbuf, len); + doSetText(key.Testament(), key.TestamentIndex(), inbuf, len); } void RawText::linkEntry(const SWKey *inkey) { VerseKey &destkey = getVerseKey(); - const VerseKey *srckey = 0; - - // see if we have a VerseKey * or decendant - SWTRY { - srckey = SWDYNAMIC_CAST(VerseKey, inkey); - } - SWCATCH ( ... ) {} - // if we don't have a VerseKey * decendant, create our own - if (!srckey) - srckey = new VerseKey(inkey); - - doLinkEntry(destkey.Testament(), destkey.Index(), srckey->Index()); - - if (inkey != srckey) // free our key if we created a VerseKey - delete srckey; + const VerseKey *srckey = &getVerseKey(inkey); + doLinkEntry(destkey.Testament(), destkey.TestamentIndex(), srckey->TestamentIndex()); } @@ -501,7 +125,7 @@ void RawText::linkEntry(const SWKey *inkey) { void RawText::deleteEntry() { VerseKey &key = getVerseKey(); - doSetText(key.Testament(), key.Index(), ""); + doSetText(key.Testament(), key.TestamentIndex(), ""); } /****************************************************************************** @@ -517,21 +141,21 @@ void RawText::increment(int steps) { unsigned short size; VerseKey *tmpkey = &getVerseKey(); - findOffset(tmpkey->Testament(), tmpkey->Index(), &start, &size); + findOffset(tmpkey->Testament(), tmpkey->TestamentIndex(), &start, &size); SWKey lastgood = *tmpkey; while (steps) { long laststart = start; unsigned short lastsize = size; SWKey lasttry = *tmpkey; - (steps > 0) ? (*key)++ : (*key)--; + (steps > 0) ? ++(*key) : --(*key); tmpkey = &getVerseKey(); if ((error = key->Error())) { *key = lastgood; break; } - long index = tmpkey->Index(); + long index = tmpkey->TestamentIndex(); findOffset(tmpkey->Testament(), index, &start, &size); if ( (((laststart != start) || (lastsize != size)) // we're a different entry @@ -545,4 +169,28 @@ void RawText::increment(int steps) { error = (error) ? KEYERR_OUTOFBOUNDS : 0; } +bool RawText::isLinked(const SWKey *k1, const SWKey *k2) const { + long start1, start2; + unsigned short size1, size2; + VerseKey *vk1 = &getVerseKey(k1); + VerseKey *vk2 = &getVerseKey(k2); + if (vk1->Testament() != vk2->Testament()) return false; + + findOffset(vk1->Testament(), vk1->TestamentIndex(), &start1, &size1); + findOffset(vk2->Testament(), vk2->TestamentIndex(), &start2, &size2); + if (!size1 || !size2) return false; + return start1 == start2; +} + +bool RawText::hasEntry(const SWKey *k) const { + long start; + unsigned short size; + VerseKey *vk = &getVerseKey(k); + + findOffset(vk->Testament(), vk->TestamentIndex(), &start, &size); + return size; +} + + + SWORD_NAMESPACE_END diff --git a/src/modules/texts/rawtext4/rawtext4.cpp b/src/modules/texts/rawtext4/rawtext4.cpp index a06691e..65f5cef 100644 --- a/src/modules/texts/rawtext4/rawtext4.cpp +++ b/src/modules/texts/rawtext4/rawtext4.cpp @@ -1,9 +1,24 @@ /****************************************************************************** - * rawtext4.cpp - code for class 'RawText4'- a module that reads raw text files: - * ot and nt using indexs ??.bks ??.cps ??.vss + * rawtext4.cpp - code for class 'RawText4'- a module that reads raw text + * files: ot and nt using indexs ??.bks ??.cps ??.vss + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <stdio.h> #include <fcntl.h> #include <sysdata.h> @@ -42,27 +57,9 @@ typedef list<long> longlist; * idisp - Display object to use for displaying */ -RawText4::RawText4(const char *ipath, const char *iname, const char *idesc, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang) - : SWText(iname, idesc, idisp, enc, dir, mark, ilang), +RawText4::RawText4(const char *ipath, const char *iname, const char *idesc, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang, const char *versification) + : SWText(iname, idesc, idisp, enc, dir, mark, ilang, versification), RawVerse4(ipath) { - -#ifndef USELUCENE - SWBuf fname; - fname = path; - char ch = fname.c_str()[strlen(fname.c_str())-1]; - if ((ch != '/') && (ch != '\\')) - fname += "/"; - - for (int loop = 0; loop < 2; loop++) { - fastSearch[loop] = 0; - SWBuf fastidxname =(fname + ((loop)?"ntwords.dat":"otwords.dat")); - if (FileMgr::existsFile(fastidxname.c_str())) { - fastidxname = (fname + ((loop)?"ntwords.idx":"otwords.idx")); - if (FileMgr::existsFile(fastidxname.c_str())) - fastSearch[loop] = new RawStr4((fname + ((loop)?"ntwords":"otwords")).c_str()); - } - } -#endif } @@ -71,13 +68,6 @@ RawText4::RawText4(const char *ipath, const char *iname, const char *idesc, SWDi */ RawText4::~RawText4() { -#ifndef USELUCENE - if (fastSearch[0]) - delete fastSearch[0]; - - if (fastSearch[1]) - delete fastSearch[1]; -#endif } @@ -98,7 +88,7 @@ SWBuf &RawText4::getRawEntryBuf() { unsigned long size = 0; VerseKey &key = getVerseKey(); - findOffset(key.Testament(), key.Index(), &start, &size); + findOffset(key.Testament(), key.TestamentIndex(), &start, &size); entrySize = size; // support getEntrySize call entryBuf = ""; @@ -114,382 +104,16 @@ SWBuf &RawText4::getRawEntryBuf() { } -signed char RawText4::createSearchFramework(void (*percent)(char, void *), void *percentUserData) { -#ifndef USELUCENE - SWKey *savekey = 0; - SWKey *searchkey = 0; - SWKey textkey; - char *word = 0; - char *wordBuf = 0; - - // dictionary holds words associated with a list - // containing every module position that contains - // the word. [0] Old Testament; [1] NT - map < SWBuf, list<long> > dictionary[2]; - - - // save key information so as not to disrupt original - // module position - if (!key->Persist()) { - savekey = CreateKey(); - *savekey = *key; - } - else savekey = key; - - searchkey = (key->Persist())?key->clone():0; - if (searchkey) { - searchkey->Persist(1); - setKey(*searchkey); - } - - // position module at the beginning - *this = TOP; - - VerseKey *lkey = (VerseKey *)key; - - // iterate thru each entry in module - while (!Error()) { - long index = lkey->Index(); - wordBuf = (char *)calloc(sizeof(char), strlen(StripText()) + 1); - strcpy(wordBuf, StripText()); - - // grab each word from the text - word = strtok(wordBuf, " !.,?;:()-=+/\\|{}[]\"<>"); - while (word) { - - // make word upper case - toupperstr(word); - - // lookup word in dictionary (or make entry in dictionary - // for this word) and add this module position (index) to - // the word's associated list of module positions - dictionary[lkey->Testament()-1][word].push_back(index); - word = strtok(NULL, " !.,?;:()-=+/\\|{}[]\"<>"); - } - free(wordBuf); - (*this)++; - } - - // reposition module back to where it was before we were called - setKey(*savekey); - - if (!savekey->Persist()) - delete savekey; - - if (searchkey) - delete searchkey; - - - // --------- Let's output an index from our dictionary ----------- - FileDesc *datfd; - FileDesc *idxfd; - strlist::iterator it; - longlist::iterator it2; - unsigned long offset, entryoff; - unsigned long size; - - SWBuf fname; - fname = path; - char ch = fname.c_str()[strlen(fname.c_str())-1]; - if ((ch != '/') && (ch != '\\')) - fname += "/"; - - // for old and new testament do... - for (int loop = 0; loop < 2; loop++) { - datfd = FileMgr::getSystemFileMgr()->open((fname + ((loop)?"ntwords.dat":"otwords.dat")).c_str(), FileMgr::CREAT|FileMgr::WRONLY, 00644); - if (datfd->getFd() == -1) - return -1; - idxfd = FileMgr::getSystemFileMgr()->open((fname + ((loop)?"ntwords.idx":"otwords.idx")).c_str(), FileMgr::CREAT|FileMgr::WRONLY, 00644); - if (idxfd->getFd() == -1) { - FileMgr::getSystemFileMgr()->close(datfd); - return -1; - } - - // iterate thru each word in the dictionary - for (it = dictionary[loop].begin(); it != dictionary[loop].end(); it++) { - printf("%s: ", it->first.c_str()); - - // get our current offset in our word.dat file and write this as the start - // of the next entry in our database - offset = datfd->seek(0, SEEK_CUR); - idxfd->write(&offset, 4); - - // write our word out to the word.dat file, delineating with a \n - datfd->write(it->first.c_str(), strlen(it->first.c_str())); - datfd->write("\n", 1); - - // force our mod position list for this word to be unique (remove - // duplicates that may exist if the word was found more than once - // in the verse - it->second.unique(); - - // iterate thru each mod position for this word and output it to - // our database - unsigned short count = 0; - for (it2 = it->second.begin(); it2 != it->second.end(); it2++) { - entryoff= *it2; - datfd->write(&entryoff, 4); - count++; - } - - // now see what our new position is in our word.dat file and - // determine the size of this database entry - size = datfd->seek(0, SEEK_CUR) - offset; - - // store the size of this database entry - idxfd->write(&size, 4); - printf("%d entries (size: %d)\n", count, size); - } - FileMgr::getSystemFileMgr()->close(datfd); - FileMgr::getSystemFileMgr()->close(idxfd); - } - return 0; -#else - return SWModule::createSearchFramework(percent, percentUserData); -#endif -} - - -void RawText4::deleteSearchFramework() { -#ifndef USELUCENE - SWBuf target = path; - char ch = target.c_str()[strlen(target.c_str())-1]; - if ((ch != '/') && (ch != '\\')) - target += "/lucene"; - FileMgr::removeFile(target + "ntwords.dat"); - FileMgr::removeFile(target + "otwords.dat"); - FileMgr::removeFile(target + "ntwords.idx"); - FileMgr::removeFile(target + "otwords.idx"); -#else - SWModule::deleteSearchFramework(); -#endif -} - - -/****************************************************************************** - * SWModule::search - Searches a module for a string - * - * ENT: istr - string for which to search - * searchType - type of search to perform - * >=0 - regex - * -1 - phrase - * -2 - multiword - * flags - options flags for search - * justCheckIfSupported - if set, don't search, only tell if this - * function supports requested search. - * - * RET: ListKey set to verses that contain istr - */ - -ListKey &RawText4::search(const char *istr, int searchType, int flags, SWKey *scope, bool *justCheckIfSupported, void (*percent)(char, void *), void *percentUserData) { -#ifndef USELUCENE - listKey.ClearList(); - - if ((fastSearch[0]) && (fastSearch[1])) { - - switch (searchType) { - case -2: { - - if ((flags & REG_ICASE) != REG_ICASE) // if haven't chosen to - // ignore case - break; // can't handle fast case sensitive searches - - // test to see if our scope for this search is bounded by a - // VerseKey - VerseKey *testKeyType = 0; - SWTRY { - testKeyType = SWDYNAMIC_CAST(VerseKey, ((scope)?scope:key)); - } - SWCATCH ( ... ) {} - // if we don't have a VerseKey * decendant we can't handle - // because of scope. - // In the future, add bool SWKey::isValid(const char *tryString); - if (!testKeyType) - break; - - - // check if we just want to see if search is supported. - // If we've gotten this far, then it is supported. - if (justCheckIfSupported) { - *justCheckIfSupported = true; - return listKey; - } - - SWKey saveKey = *testKeyType; // save current place - - char error = 0; - char **words = 0; - char *wordBuf = 0; - int wordCount = 0; - long start; - unsigned long size; - char *idxbuf = 0; - SWBuf datBuf; - list <long> indexes; - list <long> indexes2; - VerseKey vk; - vk = TOP; - - (*percent)(10, percentUserData); - - // toupper our copy of search string - stdstr(&wordBuf, istr); - toupperstr(wordBuf); - - // get list of individual words - words = (char **)calloc(sizeof(char *), 10); - int allocWords = 10; - words[wordCount] = strtok(wordBuf, " "); - while (words[wordCount]) { - wordCount++; - if (wordCount == allocWords) { - allocWords+=10; - words = (char **)realloc(words, sizeof(char *)*allocWords); - } - words[wordCount] = strtok(NULL, " "); - } - - (*percent)(20, percentUserData); - - // clear our result set - indexes.erase(indexes.begin(), indexes.end()); - - // search both old and new testament indexes - for (int j = 0; j < 2; j++) { - // iterate thru each word the user passed to us. - for (int i = 0; i < wordCount; i++) { - - // clear this word's result set - indexes2.erase(indexes2.begin(), indexes2.end()); - error = 0; - - // iterate thru every word in the database that starts - // with our search word - for (int away = 0; !error; away++) { - idxbuf = 0; - - // find our word in the database and jump ahead _away_ - error = fastSearch[j]->findOffset(words[i], &start, &size, away); - - // get the word from the database - fastSearch[j]->getIDXBufDat(start, &idxbuf); - - // check to see if it starts with our target word - if (strlen(idxbuf) > strlen(words[i])) - idxbuf[strlen(words[i])] = 0; -// else words[i][strlen(idxbuf)] = 0; - if (!strcmp(idxbuf, words[i])) { - - // get data for this word from database - delete [] idxbuf; - idxbuf = 0; - datBuf = ""; - fastSearch[j]->readText(start, &size, &idxbuf, datBuf); - - // we know that the data consists of sizof(long) - // records each a valid module position that constains - // this word - // - // iterate thru each of these module positions - long *keyindex = (long *)datBuf.getRawData(); - while (keyindex < (long *)(datBuf.getRawData() + size - (strlen(idxbuf) + 1))) { - if (i) { // if we're not on our first word - - // check to see if this word is already in the result set. - // This is our AND functionality - if (find(indexes.begin(), indexes.end(), *keyindex) != indexes.end()) - // add to new result set - indexes2.push_back(*keyindex); - } - else indexes2.push_back(*keyindex); - keyindex++; - } - } - else error = 1; // no more matches - free(idxbuf); - } - - // make new result set final result set - indexes = indexes2; - - percent((char)(20 + (float)((j*wordCount)+i)/(wordCount * 2) * 78), percentUserData); - } - - // indexes contains our good verses, lets return them in a listKey - indexes.sort(); - - // iterate thru each good module position that meets the search - for (longlist::iterator it = indexes.begin(); it != indexes.end(); it++) { - - // set a temporary verse key to this module position - vk.Testament(j+1); - vk.Error(); - vk.Index(*it); - - // check scope - // Try to set our scope key to this verse key - if (scope) { - *testKeyType = vk; - - // check to see if it set ok and if so, add to our return list - if (*testKeyType == vk) - listKey << (const char *) vk; - } - else listKey << (const char*) vk; - } - } - (*percent)(98, percentUserData); - - free(words); - free(wordBuf); - - *testKeyType = saveKey; // set current place back to original - - listKey = TOP; - (*percent)(100, percentUserData); - return listKey; - } - - default: - break; - } - } - - // check if we just want to see if search is supported - if (justCheckIfSupported) { - *justCheckIfSupported = false; - return listKey; - } - -#endif - // if we don't support this search, fall back to base class - return SWModule::search(istr, searchType, flags, scope, justCheckIfSupported, percent, percentUserData); -} - - void RawText4::setEntry(const char *inbuf, long len) { VerseKey &key = getVerseKey(); - doSetText(key.Testament(), key.Index(), inbuf, len); + doSetText(key.Testament(), key.TestamentIndex(), inbuf, len); } void RawText4::linkEntry(const SWKey *inkey) { VerseKey &destkey = getVerseKey(); - const VerseKey *srckey = 0; - - // see if we have a VerseKey * or decendant - SWTRY { - srckey = SWDYNAMIC_CAST(VerseKey, inkey); - } - SWCATCH ( ... ) {} - // if we don't have a VerseKey * decendant, create our own - if (!srckey) - srckey = new VerseKey(inkey); - - doLinkEntry(destkey.Testament(), destkey.Index(), srckey->Index()); - - if (inkey != srckey) // free our key if we created a VerseKey - delete srckey; + const VerseKey *srckey = &getVerseKey(inkey); + doLinkEntry(destkey.Testament(), destkey.TestamentIndex(), srckey->TestamentIndex()); } @@ -501,7 +125,7 @@ void RawText4::linkEntry(const SWKey *inkey) { void RawText4::deleteEntry() { VerseKey &key = getVerseKey(); - doSetText(key.Testament(), key.Index(), ""); + doSetText(key.Testament(), key.TestamentIndex(), ""); } /****************************************************************************** @@ -517,21 +141,21 @@ void RawText4::increment(int steps) { unsigned long size; VerseKey *tmpkey = &getVerseKey(); - findOffset(tmpkey->Testament(), tmpkey->Index(), &start, &size); + findOffset(tmpkey->Testament(), tmpkey->TestamentIndex(), &start, &size); SWKey lastgood = *tmpkey; while (steps) { long laststart = start; unsigned long lastsize = size; SWKey lasttry = *tmpkey; - (steps > 0) ? (*key)++ : (*key)--; + (steps > 0) ? ++(*key) : --(*key); tmpkey = &getVerseKey(); if ((error = key->Error())) { *key = lastgood; break; } - long index = tmpkey->Index(); + long index = tmpkey->TestamentIndex(); findOffset(tmpkey->Testament(), index, &start, &size); if ( (((laststart != start) || (lastsize != size)) // we're a different entry @@ -545,4 +169,25 @@ void RawText4::increment(int steps) { error = (error) ? KEYERR_OUTOFBOUNDS : 0; } +bool RawText4::isLinked(const SWKey *k1, const SWKey *k2) const { + long start1, start2; + unsigned long size1, size2; + VerseKey *vk1 = &getVerseKey(k1); + VerseKey *vk2 = &getVerseKey(k2); + if (vk1->Testament() != vk2->Testament()) return false; + + findOffset(vk1->Testament(), vk1->TestamentIndex(), &start1, &size1); + findOffset(vk2->Testament(), vk2->TestamentIndex(), &start2, &size2); + return start1 == start2; +} + +bool RawText4::hasEntry(const SWKey *k) const { + long start; + unsigned long size; + VerseKey *vk = &getVerseKey(k); + + findOffset(vk->Testament(), vk->TestamentIndex(), &start, &size); + return size; +} + SWORD_NAMESPACE_END diff --git a/src/modules/texts/swtext.cpp b/src/modules/texts/swtext.cpp index d0ff386..a7f5f92 100644 --- a/src/modules/texts/swtext.cpp +++ b/src/modules/texts/swtext.cpp @@ -1,7 +1,24 @@ /****************************************************************************** * swtext.cpp - code for base class 'SWText'- The basis for all text modules + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ +#include <utilstr.h> #include <swtext.h> #include <listkey.h> #include <localemgr.h> @@ -17,10 +34,14 @@ SWORD_NAMESPACE_START * idisp - Display object to use for displaying */ -SWText::SWText(const char *imodname, const char *imoddesc, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang): SWModule(imodname, imoddesc, idisp, (char *)"Biblical Texts", enc, dir, mark, ilang) { - tmpVK = new VerseKey(); +SWText::SWText(const char *imodname, const char *imoddesc, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang, const char *versification): SWModule(imodname, imoddesc, idisp, "Biblical Texts", enc, dir, mark, ilang) { + this->versification = 0; + stdstr(&(this->versification), versification); delete key; - key = CreateKey(); + key = (VerseKey *)CreateKey(); + tmpVK1 = (VerseKey *)CreateKey(); + tmpVK2 = (VerseKey *)CreateKey(); + tmpSecond = false; skipConsecutiveLinks = false; } @@ -30,7 +51,9 @@ SWText::SWText(const char *imodname, const char *imoddesc, SWDisplay *idisp, SWT */ SWText::~SWText() { - delete tmpVK; + delete tmpVK1; + delete tmpVK2; + delete [] versification; } @@ -38,60 +61,49 @@ SWText::~SWText() { * SWText CreateKey - Create the correct key (VerseKey) for use with SWText */ -SWKey *SWText::CreateKey() { - return new VerseKey(); -} +SWKey *SWText::CreateKey() const { + VerseKey *vk = new VerseKey(); + vk->setVersificationSystem(versification); -long SWText::Index() const { - VerseKey *key = 0; - SWTRY { - key = SWDYNAMIC_CAST(VerseKey, this->key); - } - SWCATCH ( ... ) {} - if (!key) - key = new VerseKey(this->key); + return vk; +} - entryIndex = key->NewIndex(); - if (key != this->key) - delete key; +long SWText::Index() const { + VerseKey *key = &getVerseKey(); + entryIndex = key->Index(); return entryIndex; } long SWText::Index(long iindex) { - VerseKey *key = 0; - SWTRY { - key = SWDYNAMIC_CAST(VerseKey, this->key); - } - SWCATCH ( ... ) {} - if (!key) - key = new VerseKey(this->key); + VerseKey *key = &getVerseKey(); key->Testament(1); key->Index(iindex); if (key != this->key) { this->key->copyFrom(*key); - delete key; } return Index(); } -VerseKey &SWText::getVerseKey() const { - VerseKey *key = NULL; +VerseKey &SWText::getVerseKey(const SWKey *keyToConvert) const { + const SWKey *thisKey = keyToConvert ? keyToConvert : this->key; + + VerseKey *key = 0; // see if we have a VerseKey * or decendant SWTRY { - key = SWDYNAMIC_CAST(VerseKey, this->key); + key = SWDYNAMIC_CAST(VerseKey, thisKey); } SWCATCH ( ... ) { } if (!key) { ListKey *lkTest = 0; SWTRY { - lkTest = SWDYNAMIC_CAST(ListKey, this->key); + lkTest = SWDYNAMIC_CAST(ListKey, thisKey); } SWCATCH ( ... ) { } if (lkTest) { @@ -102,9 +114,11 @@ VerseKey &SWText::getVerseKey() const { } } if (!key) { - tmpVK->setLocale(LocaleMgr::getSystemLocaleMgr()->getDefaultLocaleName()); - (*tmpVK) = *(this->key); - return (*tmpVK); + VerseKey *retKey = (tmpSecond) ? tmpVK1 : tmpVK2; + tmpSecond = !tmpSecond; + retKey->setLocale(LocaleMgr::getSystemLocaleMgr()->getDefaultLocaleName()); + (*retKey) = *(thisKey); + return (*retKey); } else return *key; } diff --git a/src/modules/texts/ztext/ztext.cpp b/src/modules/texts/ztext/ztext.cpp index b461d49..61b3008 100644 --- a/src/modules/texts/ztext/ztext.cpp +++ b/src/modules/texts/ztext/ztext.cpp @@ -1,9 +1,24 @@ /****************************************************************************** * ztext.cpp - code for class 'zText'- a module that reads compressed text * files: ot and nt using indexs ??.vss + * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ - #include <ctype.h> #include <stdio.h> #include <fcntl.h> @@ -29,8 +44,8 @@ SWORD_NAMESPACE_START * idisp - Display object to use for displaying */ -zText::zText(const char *ipath, const char *iname, const char *idesc, int iblockType, SWCompress *icomp, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang) - : zVerse(ipath, FileMgr::RDWR, iblockType, icomp), SWText(iname, idesc, idisp, enc, dir, mark, ilang) { +zText::zText(const char *ipath, const char *iname, const char *idesc, int iblockType, SWCompress *icomp, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char *ilang, const char *versification) + : zVerse(ipath, FileMgr::RDWR, iblockType, icomp), SWText(iname, idesc, idisp, enc, dir, mark, ilang, versification) { blockType = iblockType; lastWriteKey = 0; } @@ -62,14 +77,15 @@ bool zText::isWritable() { return ((idxfp[0]->getFd() > 0) && ((idxfp[0]->mode & SWBuf &zText::getRawEntryBuf() { long start = 0; unsigned short size = 0; + unsigned long buffnum = 0; VerseKey &key = getVerseKey(); - findOffset(key.Testament(), key.Index(), &start, &size); + findOffset(key.Testament(), key.TestamentIndex(), &start, &size, &buffnum); entrySize = size; // support getEntrySize call entryBuf = ""; - zReadText(key.Testament(), start, size, entryBuf); - + + zReadText(key.Testament(), start, size, buffnum, entryBuf); rawFilter(entryBuf, &key); // if (!isUnicode()) @@ -109,7 +125,7 @@ void zText::setEntry(const char *inbuf, long len) { delete lastWriteKey; } - doSetText(key.Testament(), key.Index(), inbuf, len); + doSetText(key.Testament(), key.TestamentIndex(), inbuf, len); lastWriteKey = (VerseKey *)key.clone(); // must delete } @@ -117,22 +133,8 @@ void zText::setEntry(const char *inbuf, long len) { void zText::linkEntry(const SWKey *inkey) { VerseKey &destkey = getVerseKey(); - const VerseKey *srckey = 0; - - // see if we have a VerseKey * or decendant - SWTRY { - srckey = (const VerseKey *) SWDYNAMIC_CAST(VerseKey, inkey); - } - SWCATCH ( ... ) { - } - // if we don't have a VerseKey * decendant, create our own - if (!srckey) - srckey = new VerseKey(inkey); - - doLinkEntry(destkey.Testament(), destkey.Index(), srckey->Index()); - - if (inkey != srckey) // free our key if we created a VerseKey - delete srckey; + const VerseKey *srckey = &getVerseKey(inkey); + doLinkEntry(destkey.Testament(), destkey.TestamentIndex(), srckey->TestamentIndex()); } @@ -145,7 +147,7 @@ void zText::deleteEntry() { VerseKey &key = getVerseKey(); - doSetText(key.Testament(), key.Index(), ""); + doSetText(key.Testament(), key.TestamentIndex(), ""); } @@ -157,26 +159,27 @@ void zText::deleteEntry() { */ void zText::increment(int steps) { - long start; + long start; unsigned short size; + unsigned long buffnum; VerseKey *tmpkey = &getVerseKey(); - findOffset(tmpkey->Testament(), tmpkey->Index(), &start, &size); + findOffset(tmpkey->Testament(), tmpkey->TestamentIndex(), &start, &size, &buffnum); SWKey lastgood = *tmpkey; while (steps) { long laststart = start; unsigned short lastsize = size; SWKey lasttry = *tmpkey; - (steps > 0) ? (*key)++ : (*key)--; + (steps > 0) ? ++(*key) : --(*key); tmpkey = &getVerseKey(); if ((error = key->Error())) { *key = lastgood; break; } - long index = tmpkey->Index(); - findOffset(tmpkey->Testament(), index, &start, &size); + long index = tmpkey->TestamentIndex(); + findOffset(tmpkey->Testament(), index, &start, &size, &buffnum); if ( (((laststart != start) || (lastsize != size)) // we're a different entry @@ -190,6 +193,28 @@ void zText::increment(int steps) { error = (error) ? KEYERR_OUTOFBOUNDS : 0; } +bool zText::isLinked(const SWKey *k1, const SWKey *k2) const { + long start1, start2; + unsigned short size1, size2; + unsigned long buffnum1, buffnum2; + VerseKey *vk1 = &getVerseKey(k1); + VerseKey *vk2 = &getVerseKey(k2); + if (vk1->Testament() != vk2->Testament()) return false; + + findOffset(vk1->Testament(), vk1->TestamentIndex(), &start1, &size1, &buffnum1); + findOffset(vk2->Testament(), vk2->TestamentIndex(), &start2, &size2, &buffnum2); + return start1 == start2 && buffnum1 == buffnum2; +} + +bool zText::hasEntry(const SWKey *k) const { + long start; + unsigned short size; + unsigned long buffnum; + VerseKey *vk = &getVerseKey(k); + + findOffset(vk->Testament(), vk->TestamentIndex(), &start, &size, &buffnum); + return size; +} SWORD_NAMESPACE_END diff --git a/src/utilfuns/Makefile.am b/src/utilfuns/Makefile.am index 4160db0..e0fc031 100644 --- a/src/utilfuns/Makefile.am +++ b/src/utilfuns/Makefile.am @@ -1,7 +1,7 @@ if HAVE_VSNPRINTF else -CXXFLAGS += -DNO_VSNPRINTF +AM_CXXFLAGS += -DNO_VSNPRINTF endif utilfunsdir = $(top_srcdir)/src/utilfuns diff --git a/src/utilfuns/regex.c b/src/utilfuns/regex.c deleted file mode 100644 index 09743d2..0000000 --- a/src/utilfuns/regex.c +++ /dev/null @@ -1,5721 +0,0 @@ -/* Extended regular expression matching and search library, - version 0.12. - (Implements POSIX draft P1003.2/D11.2, except for some of the - internationalization features.) - - Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. - - the C library, however. The master source lives in /gd/gnu/lib. - -NOTE: The canonical source of this file is maintained with the -GNU C Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software Foundation, -Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* AIX requires this to be the first thing in the file. */ -#if defined (_AIX) && !defined (REGEX_MALLOC) - #pragma alloca -#endif - -#undef _GNU_SOURCE -#define _GNU_SOURCE - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if defined(STDC_HEADERS) && !defined(emacs) -#include <stddef.h> -#else -/* We need this for `regex.h', and perhaps for the Emacs include files. */ -#include <sys/types.h> -#endif -#include <stdlib.h> // sword - -/* For platform which support the ISO C amendement 1 functionality we - support user defined character classes. */ -#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) -# include <wctype.h> -# include <wchar.h> -#endif - -/* This is for other GNU distributions with internationalized messages. */ -#if HAVE_LIBINTL_H || defined (_LIBC) -# include <libintl.h> -#else -# define gettext(msgid) (msgid) -#endif - -#ifndef gettext_noop -/* This define is so xgettext can find the internationalizable - strings. */ -#define gettext_noop(String) String -#endif - -/* The `emacs' switch turns on certain matching commands - that make sense only in Emacs. */ -#ifdef emacs - -#include "lisp.h" -#include "buffer.h" -#include "syntax.h" - -#else /* not emacs */ - -/* If we are not linking with Emacs proper, - we can't use the relocating allocator - even if config.h says that we can. */ -#undef REL_ALLOC - -#if defined (STDC_HEADERS) || defined (_LIBC) -#include <stdlib.h> -#else -//sword char *malloc (); -//sword char *realloc (); -#endif - -/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow. - If nothing else has been done, use the method below. */ -#ifdef INHIBIT_STRING_HEADER -#if !(defined (HAVE_BZERO) && defined (HAVE_BCOPY)) -#if !defined (bzero) && !defined (bcopy) -#undef INHIBIT_STRING_HEADER -#endif -#endif -#endif - -/* This is the normal way of making sure we have a bcopy and a bzero. - This is used in most programs--a few other programs avoid this - by defining INHIBIT_STRING_HEADER. */ -#define HAVE_STRING_H // for SWORD Project -#ifndef INHIBIT_STRING_HEADER -#if defined (HAVE_STRING_H) || defined (STDC_HEADERS) || defined (_LIBC) -#include <string.h> -#ifndef bcmp -#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) -#endif -#ifndef bcopy -#define bcopy(s, d, n) memcpy ((d), (s), (n)) -#endif -#ifndef bzero -#define bzero(s, n) memset ((s), 0, (n)) -#endif -#else -#include <strings.h> -#endif -#endif - -/* Define the syntax stuff for \<, \>, etc. */ - -/* This must be nonzero for the wordchar and notwordchar pattern - commands in re_match_2. */ -#ifndef Sword -#define Sword 1 -#endif - -#ifdef SWITCH_ENUM_BUG -#define SWITCH_ENUM_CAST(x) ((int)(x)) -#else -#define SWITCH_ENUM_CAST(x) (x) -#endif - -#ifdef SYNTAX_TABLE - -extern char *re_syntax_table; - -#else /* not SYNTAX_TABLE */ - -/* How many characters in the character set. */ -#define CHAR_SET_SIZE 256 - -static char re_syntax_table[CHAR_SET_SIZE]; - -static void -init_syntax_once () -{ - register int c; - static int done = 0; - - if (done) - return; - - bzero (re_syntax_table, sizeof re_syntax_table); - - for (c = 'a'; c <= 'z'; c++) - re_syntax_table[c] = Sword; - - for (c = 'A'; c <= 'Z'; c++) - re_syntax_table[c] = Sword; - - for (c = '0'; c <= '9'; c++) - re_syntax_table[c] = Sword; - - re_syntax_table['_'] = Sword; - - done = 1; -} - -#endif /* not SYNTAX_TABLE */ - -#define SYNTAX(c) re_syntax_table[c] - -#endif /* not emacs */ - -/* Get the interface, including the syntax bits. */ -#include "regex.h" - -/* isalpha etc. are used for the character classes. */ -#include <ctype.h> - -/* Jim Meyering writes: - - "... Some ctype macros are valid only for character codes that - isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when - using /bin/cc or gcc but without giving an ansi option). So, all - ctype uses should be through macros like ISPRINT... If - STDC_HEADERS is defined, then autoconf has verified that the ctype - macros don't need to be guarded with references to isascii. ... - Defining isascii to 1 should let any compiler worth its salt - eliminate the && through constant folding." */ - -#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) -#define ISASCII(c) 1 -#else -#define ISASCII(c) isascii(c) -#endif - -#ifdef isblank -#define ISBLANK(c) (ISASCII (c) && isblank (c)) -#else -#define ISBLANK(c) ((c) == ' ' || (c) == '\t') -#endif -#ifdef isgraph -#define ISGRAPH(c) (ISASCII (c) && isgraph (c)) -#else -#define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) -#endif - -#define ISPRINT(c) (ISASCII (c) && isprint (c)) -#define ISDIGIT(c) (ISASCII (c) && isdigit (c)) -#define ISALNUM(c) (ISASCII (c) && isalnum (c)) -#define ISALPHA(c) (ISASCII (c) && isalpha (c)) -#define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) -#define ISLOWER(c) (ISASCII (c) && islower (c)) -#define ISPUNCT(c) (ISASCII (c) && ispunct (c)) -#define ISSPACE(c) (ISASCII (c) && isspace (c)) -#define ISUPPER(c) (ISASCII (c) && isupper (c)) -#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) - -#ifndef NULL -#define NULL (void *)0 -#endif - -/* We remove any previous definition of `SIGN_EXTEND_CHAR', - since ours (we hope) works properly with all combinations of - machines, compilers, `char' and `unsigned char' argument types. - (Per Bothner suggested the basic approach.) */ -#undef SIGN_EXTEND_CHAR -#if __STDC__ -#define SIGN_EXTEND_CHAR(c) ((signed char) (c)) -#else /* not __STDC__ */ -/* As in Harbison and Steele. */ -#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) -#endif - -/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we - use `alloca' instead of `malloc'. This is because using malloc in - re_search* or re_match* could cause memory leaks when C-g is used in - Emacs; also, malloc is slower and causes storage fragmentation. On - the other hand, malloc is more portable, and easier to debug. - - Because we sometimes use alloca, some routines have to be macros, - not functions -- `alloca'-allocated space disappears at the end of the - function it is called in. */ - -#ifdef REGEX_MALLOC - -#define REGEX_ALLOCATE malloc -#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) -#define REGEX_FREE free - -#else /* not REGEX_MALLOC */ - -/* Emacs already defines alloca, sometimes. */ -#ifndef alloca - -/* Make alloca work the best possible way. */ -#ifdef __GNUC__ -#define alloca __builtin_alloca -#else /* not __GNUC__ */ -#if HAVE_ALLOCA_H -#include <alloca.h> -#else /* not __GNUC__ or HAVE_ALLOCA_H */ -#if 0 /* It is a bad idea to declare alloca. We always cast the result. */ -#ifndef _AIX /* Already did AIX, up at the top. */ -char *alloca (); -#endif /* not _AIX */ -#endif -#endif /* not HAVE_ALLOCA_H */ -#endif /* not __GNUC__ */ - -#endif /* not alloca */ - -#define REGEX_ALLOCATE alloca - -/* Assumes a `char *destination' variable. */ -#define REGEX_REALLOCATE(source, osize, nsize) \ - (destination = (char *) alloca (nsize), \ - bcopy (source, destination, osize), \ - destination) - -/* No need to do anything to free, after alloca. */ -#define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */ - -#endif /* not REGEX_MALLOC */ - -/* Define how to allocate the failure stack. */ - -#if defined (REL_ALLOC) && defined (REGEX_MALLOC) - -#define REGEX_ALLOCATE_STACK(size) \ - r_alloc (&failure_stack_ptr, (size)) -#define REGEX_REALLOCATE_STACK(source, osize, nsize) \ - r_re_alloc (&failure_stack_ptr, (nsize)) -#define REGEX_FREE_STACK(ptr) \ - r_alloc_free (&failure_stack_ptr) - -#else /* not using relocating allocator */ - -#ifdef REGEX_MALLOC - -#define REGEX_ALLOCATE_STACK malloc -#define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) -#define REGEX_FREE_STACK free - -#else /* not REGEX_MALLOC */ - -#define REGEX_ALLOCATE_STACK alloca - -#define REGEX_REALLOCATE_STACK(source, osize, nsize) \ - REGEX_REALLOCATE (source, osize, nsize) -/* No need to explicitly free anything. */ -#define REGEX_FREE_STACK(arg) - -#endif /* not REGEX_MALLOC */ -#endif /* not using relocating allocator */ - - -/* True if `size1' is non-NULL and PTR is pointing anywhere inside - `string1' or just past its end. This works if PTR is NULL, which is - a good thing. */ -#define FIRST_STRING_P(ptr) \ - (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) - -/* (Re)Allocate N items of type T using malloc, or fail. */ -#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) -#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) -#define RETALLOC_IF(addr, n, t) \ - if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t) -#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) - -#define BYTEWIDTH 8 /* In bits. */ - -#define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) - -#undef MAX -#undef MIN -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -typedef char boolean; -#define false 0 -#define true 1 - -static int re_match_2_internal (); - -/* These are the command codes that appear in compiled regular - expressions. Some opcodes are followed by argument bytes. A - command code can specify any interpretation whatsoever for its - arguments. Zero bytes may appear in the compiled regular expression. */ - -typedef enum -{ - no_op = 0, - - /* Succeed right away--no more backtracking. */ - succeed, - - /* Followed by one byte giving n, then by n literal bytes. */ - exactn, - - /* Matches any (more or less) character. */ - anychar, - - /* Matches any one char belonging to specified set. First - following byte is number of bitmap bytes. Then come bytes - for a bitmap saying which chars are in. Bits in each byte - are ordered low-bit-first. A character is in the set if its - bit is 1. A character too large to have a bit in the map is - automatically not in the set. */ - charset, - - /* Same parameters as charset, but match any character that is - not one of those specified. */ - charset_not, - - /* Start remembering the text that is matched, for storing in a - register. Followed by one byte with the register number, in - the range 0 to one less than the pattern buffer's re_nsub - field. Then followed by one byte with the number of groups - inner to this one. (This last has to be part of the - start_memory only because we need it in the on_failure_jump - of re_match_2.) */ - start_memory, - - /* Stop remembering the text that is matched and store it in a - memory register. Followed by one byte with the register - number, in the range 0 to one less than `re_nsub' in the - pattern buffer, and one byte with the number of inner groups, - just like `start_memory'. (We need the number of inner - groups here because we don't have any easy way of finding the - corresponding start_memory when we're at a stop_memory.) */ - stop_memory, - - /* Match a duplicate of something remembered. Followed by one - byte containing the register number. */ - duplicate, - - /* Fail unless at beginning of line. */ - begline, - - /* Fail unless at end of line. */ - endline, - - /* Succeeds if at beginning of buffer (if emacs) or at beginning - of string to be matched (if not). */ - begbuf, - - /* Analogously, for end of buffer/string. */ - endbuf, - - /* Followed by two byte relative address to which to jump. */ - jump, - - /* Same as jump, but marks the end of an alternative. */ - jump_past_alt, - - /* Followed by two-byte relative address of place to resume at - in case of failure. */ - on_failure_jump, - - /* Like on_failure_jump, but pushes a placeholder instead of the - current string position when executed. */ - on_failure_keep_string_jump, - - /* Throw away latest failure point and then jump to following - two-byte relative address. */ - pop_failure_jump, - - /* Change to pop_failure_jump if know won't have to backtrack to - match; otherwise change to jump. This is used to jump - back to the beginning of a repeat. If what follows this jump - clearly won't match what the repeat does, such that we can be - sure that there is no use backtracking out of repetitions - already matched, then we change it to a pop_failure_jump. - Followed by two-byte address. */ - maybe_pop_jump, - - /* Jump to following two-byte address, and push a dummy failure - point. This failure point will be thrown away if an attempt - is made to use it for a failure. A `+' construct makes this - before the first repeat. Also used as an intermediary kind - of jump when compiling an alternative. */ - dummy_failure_jump, - - /* Push a dummy failure point and continue. Used at the end of - alternatives. */ - push_dummy_failure, - - /* Followed by two-byte relative address and two-byte number n. - After matching N times, jump to the address upon failure. */ - succeed_n, - - /* Followed by two-byte relative address, and two-byte number n. - Jump to the address N times, then fail. */ - jump_n, - - /* Set the following two-byte relative address to the - subsequent two-byte number. The address *includes* the two - bytes of number. */ - set_number_at, - - wordchar, /* Matches any word-constituent character. */ - notwordchar, /* Matches any char that is not a word-constituent. */ - - wordbeg, /* Succeeds if at word beginning. */ - wordend, /* Succeeds if at word end. */ - - wordbound, /* Succeeds if at a word boundary. */ - notwordbound /* Succeeds if not at a word boundary. */ - -#ifdef emacs - ,before_dot, /* Succeeds if before point. */ - at_dot, /* Succeeds if at point. */ - after_dot, /* Succeeds if after point. */ - - /* Matches any character whose syntax is specified. Followed by - a byte which contains a syntax code, e.g., Sword. */ - syntaxspec, - - /* Matches any character whose syntax is not that specified. */ - notsyntaxspec -#endif /* emacs */ -} re_opcode_t; - -/* Common operations on the compiled pattern. */ - -/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ - -#define STORE_NUMBER(destination, number) \ - do { \ - (destination)[0] = (number) & 0377; \ - (destination)[1] = (number) >> 8; \ - } while (0) - -/* Same as STORE_NUMBER, except increment DESTINATION to - the byte after where the number is stored. Therefore, DESTINATION - must be an lvalue. */ - -#define STORE_NUMBER_AND_INCR(destination, number) \ - do { \ - STORE_NUMBER (destination, number); \ - (destination) += 2; \ - } while (0) - -/* Put into DESTINATION a number stored in two contiguous bytes starting - at SOURCE. */ - -#define EXTRACT_NUMBER(destination, source) \ - do { \ - (destination) = *(source) & 0377; \ - (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ - } while (0) - -#ifdef DEBUG -static void extract_number _RE_ARGS ((int *dest, unsigned char *source)); -static void -extract_number (dest, source) - int *dest; - unsigned char *source; -{ - int temp = SIGN_EXTEND_CHAR (*(source + 1)); - *dest = *source & 0377; - *dest += temp << 8; -} - -#ifndef EXTRACT_MACROS /* To debug the macros. */ -#undef EXTRACT_NUMBER -#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src) -#endif /* not EXTRACT_MACROS */ - -#endif /* DEBUG */ - -/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. - SOURCE must be an lvalue. */ - -#define EXTRACT_NUMBER_AND_INCR(destination, source) \ - do { \ - EXTRACT_NUMBER (destination, source); \ - (source) += 2; \ - } while (0) - -#ifdef DEBUG -static void extract_number_and_incr _RE_ARGS ((int *destination, - unsigned char **source)); -static void -extract_number_and_incr (destination, source) - int *destination; - unsigned char **source; -{ - extract_number (destination, *source); - *source += 2; -} - -#ifndef EXTRACT_MACROS -#undef EXTRACT_NUMBER_AND_INCR -#define EXTRACT_NUMBER_AND_INCR(dest, src) \ - extract_number_and_incr (&dest, &src) -#endif /* not EXTRACT_MACROS */ - -#endif /* DEBUG */ - -/* If DEBUG is defined, Regex prints many voluminous messages about what - it is doing (if the variable `debug' is nonzero). If linked with the - main program in `iregex.c', you can enter patterns and strings - interactively. And if linked with the main program in `main.c' and - the other test files, you can run the already-written tests. */ - -#ifdef DEBUG - -/* We use standard I/O for debugging. */ -#include <stdio.h> - -/* It is useful to test things that ``must'' be true when debugging. */ -#include <assert.h> - -static int debug = 0; - -#define DEBUG_STATEMENT(e) e -#define DEBUG_PRINT1(x) if (debug) printf (x) -#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) -#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) -#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) -#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ - if (debug) print_partial_compiled_pattern (s, e) -#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ - if (debug) print_double_string (w, s1, sz1, s2, sz2) - - -/* Print the fastmap in human-readable form. */ - -void -print_fastmap (fastmap) - char *fastmap; -{ - unsigned was_a_range = 0; - unsigned i = 0; - - while (i < (1 << BYTEWIDTH)) - { - if (fastmap[i++]) - { - was_a_range = 0; - putchar (i - 1); - while (i < (1 << BYTEWIDTH) && fastmap[i]) - { - was_a_range = 1; - i++; - } - if (was_a_range) - { - printf ("-"); - putchar (i - 1); - } - } - } - putchar ('\n'); -} - - -/* Print a compiled pattern string in human-readable form, starting at - the START pointer into it and ending just before the pointer END. */ - -void -print_partial_compiled_pattern (start, end) - unsigned char *start; - unsigned char *end; -{ - int mcnt, mcnt2; - unsigned char *p1; - unsigned char *p = start; - unsigned char *pend = end; - - if (start == NULL) - { - printf ("(null)\n"); - return; - } - - /* Loop over pattern commands. */ - while (p < pend) - { - printf ("%d:\t", p - start); - - switch ((re_opcode_t) *p++) - { - case no_op: - printf ("/no_op"); - break; - - case exactn: - mcnt = *p++; - printf ("/exactn/%d", mcnt); - do - { - putchar ('/'); - putchar (*p++); - } - while (--mcnt); - break; - - case start_memory: - mcnt = *p++; - printf ("/start_memory/%d/%d", mcnt, *p++); - break; - - case stop_memory: - mcnt = *p++; - printf ("/stop_memory/%d/%d", mcnt, *p++); - break; - - case duplicate: - printf ("/duplicate/%d", *p++); - break; - - case anychar: - printf ("/anychar"); - break; - - case charset: - case charset_not: - { - register int c, last = -100; - register int in_range = 0; - - printf ("/charset [%s", - (re_opcode_t) *(p - 1) == charset_not ? "^" : ""); - - assert (p + *p < pend); - - for (c = 0; c < 256; c++) - if (c / 8 < *p - && (p[1 + (c/8)] & (1 << (c % 8)))) - { - /* Are we starting a range? */ - if (last + 1 == c && ! in_range) - { - putchar ('-'); - in_range = 1; - } - /* Have we broken a range? */ - else if (last + 1 != c && in_range) - { - putchar (last); - in_range = 0; - } - - if (! in_range) - putchar (c); - - last = c; - } - - if (in_range) - putchar (last); - - putchar (']'); - - p += 1 + *p; - } - break; - - case begline: - printf ("/begline"); - break; - - case endline: - printf ("/endline"); - break; - - case on_failure_jump: - extract_number_and_incr (&mcnt, &p); - printf ("/on_failure_jump to %d", p + mcnt - start); - break; - - case on_failure_keep_string_jump: - extract_number_and_incr (&mcnt, &p); - printf ("/on_failure_keep_string_jump to %d", p + mcnt - start); - break; - - case dummy_failure_jump: - extract_number_and_incr (&mcnt, &p); - printf ("/dummy_failure_jump to %d", p + mcnt - start); - break; - - case push_dummy_failure: - printf ("/push_dummy_failure"); - break; - - case maybe_pop_jump: - extract_number_and_incr (&mcnt, &p); - printf ("/maybe_pop_jump to %d", p + mcnt - start); - break; - - case pop_failure_jump: - extract_number_and_incr (&mcnt, &p); - printf ("/pop_failure_jump to %d", p + mcnt - start); - break; - - case jump_past_alt: - extract_number_and_incr (&mcnt, &p); - printf ("/jump_past_alt to %d", p + mcnt - start); - break; - - case jump: - extract_number_and_incr (&mcnt, &p); - printf ("/jump to %d", p + mcnt - start); - break; - - case succeed_n: - extract_number_and_incr (&mcnt, &p); - p1 = p + mcnt; - extract_number_and_incr (&mcnt2, &p); - printf ("/succeed_n to %d, %d times", p1 - start, mcnt2); - break; - - case jump_n: - extract_number_and_incr (&mcnt, &p); - p1 = p + mcnt; - extract_number_and_incr (&mcnt2, &p); - printf ("/jump_n to %d, %d times", p1 - start, mcnt2); - break; - - case set_number_at: - extract_number_and_incr (&mcnt, &p); - p1 = p + mcnt; - extract_number_and_incr (&mcnt2, &p); - printf ("/set_number_at location %d to %d", p1 - start, mcnt2); - break; - - case wordbound: - printf ("/wordbound"); - break; - - case notwordbound: - printf ("/notwordbound"); - break; - - case wordbeg: - printf ("/wordbeg"); - break; - - case wordend: - printf ("/wordend"); - -#ifdef emacs - case before_dot: - printf ("/before_dot"); - break; - - case at_dot: - printf ("/at_dot"); - break; - - case after_dot: - printf ("/after_dot"); - break; - - case syntaxspec: - printf ("/syntaxspec"); - mcnt = *p++; - printf ("/%d", mcnt); - break; - - case notsyntaxspec: - printf ("/notsyntaxspec"); - mcnt = *p++; - printf ("/%d", mcnt); - break; -#endif /* emacs */ - - case wordchar: - printf ("/wordchar"); - break; - - case notwordchar: - printf ("/notwordchar"); - break; - - case begbuf: - printf ("/begbuf"); - break; - - case endbuf: - printf ("/endbuf"); - break; - - default: - printf ("?%d", *(p-1)); - } - - putchar ('\n'); - } - - printf ("%d:\tend of pattern.\n", p - start); -} - - -void -print_compiled_pattern (bufp) - struct re_pattern_buffer *bufp; -{ - unsigned char *buffer = bufp->buffer; - - print_partial_compiled_pattern (buffer, buffer + bufp->used); - printf ("%ld bytes used/%ld bytes allocated.\n", - bufp->used, bufp->allocated); - - if (bufp->fastmap_accurate && bufp->fastmap) - { - printf ("fastmap: "); - print_fastmap (bufp->fastmap); - } - - printf ("re_nsub: %d\t", bufp->re_nsub); - printf ("regs_alloc: %d\t", bufp->regs_allocated); - printf ("can_be_null: %d\t", bufp->can_be_null); - printf ("newline_anchor: %d\n", bufp->newline_anchor); - printf ("no_sub: %d\t", bufp->no_sub); - printf ("not_bol: %d\t", bufp->not_bol); - printf ("not_eol: %d\t", bufp->not_eol); - printf ("syntax: %lx\n", bufp->syntax); - /* Perhaps we should print the translate table? */ -} - - -void -print_double_string (where, string1, size1, string2, size2) - const char *where; - const char *string1; - const char *string2; - int size1; - int size2; -{ - int this_char; - - if (where == NULL) - printf ("(null)"); - else - { - if (FIRST_STRING_P (where)) - { - for (this_char = where - string1; this_char < size1; this_char++) - putchar (string1[this_char]); - - where = string2; - } - - for (this_char = where - string2; this_char < size2; this_char++) - putchar (string2[this_char]); - } -} - -void -printchar (c) - int c; -{ - putc (c, stderr); -} - -#else /* not DEBUG */ - -#undef assert -#define assert(e) - -#define DEBUG_STATEMENT(e) -#define DEBUG_PRINT1(x) -#define DEBUG_PRINT2(x1, x2) -#define DEBUG_PRINT3(x1, x2, x3) -#define DEBUG_PRINT4(x1, x2, x3, x4) -#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) -#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) - -#endif /* not DEBUG */ - -/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can - also be assigned to arbitrarily: each pattern buffer stores its own - syntax, so it can be changed between regex compilations. */ -/* This has no initializer because initialized variables in Emacs - become read-only after dumping. */ -reg_syntax_t re_syntax_options; - - -/* Specify the precise syntax of regexps for compilation. This provides - for compatibility for various utilities which historically have - different, incompatible syntaxes. - - The argument SYNTAX is a bit mask comprised of the various bits - defined in regex.h. We return the old syntax. */ - -reg_syntax_t -re_set_syntax (syntax) - reg_syntax_t syntax; -{ - reg_syntax_t ret = re_syntax_options; - - re_syntax_options = syntax; -#ifdef DEBUG - if (syntax & RE_DEBUG) - debug = 1; - else if (debug) /* was on but now is not */ - debug = 0; -#endif /* DEBUG */ - return ret; -} - -/* This table gives an error message for each of the error codes listed - in regex.h. Obviously the order here has to be same as there. - POSIX doesn't require that we do anything for REG_NOERROR, - but why not be nice? */ - -static const char *re_error_msgid[] = - { - gettext_noop ("Success"), /* REG_NOERROR */ - gettext_noop ("No match"), /* REG_NOMATCH */ - gettext_noop ("Invalid regular expression"), /* REG_BADPAT */ - gettext_noop ("Invalid collation character"), /* REG_ECOLLATE */ - gettext_noop ("Invalid character class name"), /* REG_ECTYPE */ - gettext_noop ("Trailing backslash"), /* REG_EESCAPE */ - gettext_noop ("Invalid back reference"), /* REG_ESUBREG */ - gettext_noop ("Unmatched [ or [^"), /* REG_EBRACK */ - gettext_noop ("Unmatched ( or \\("), /* REG_EPAREN */ - gettext_noop ("Unmatched \\{"), /* REG_EBRACE */ - gettext_noop ("Invalid content of \\{\\}"), /* REG_BADBR */ - gettext_noop ("Invalid range end"), /* REG_ERANGE */ - gettext_noop ("Memory exhausted"), /* REG_ESPACE */ - gettext_noop ("Invalid preceding regular expression"), /* REG_BADRPT */ - gettext_noop ("Premature end of regular expression"), /* REG_EEND */ - gettext_noop ("Regular expression too big"), /* REG_ESIZE */ - gettext_noop ("Unmatched ) or \\)"), /* REG_ERPAREN */ - }; - -/* Avoiding alloca during matching, to placate r_alloc. */ - -/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the - searching and matching functions should not call alloca. On some - systems, alloca is implemented in terms of malloc, and if we're - using the relocating allocator routines, then malloc could cause a - relocation, which might (if the strings being searched are in the - ralloc heap) shift the data out from underneath the regexp - routines. - - Here's another reason to avoid allocation: Emacs - processes input from X in a signal handler; processing X input may - call malloc; if input arrives while a matching routine is calling - malloc, then we're scrod. But Emacs can't just block input while - calling matching routines; then we don't notice interrupts when - they come in. So, Emacs blocks input around all regexp calls - except the matching calls, which it leaves unprotected, in the - faith that they will not malloc. */ - -/* Normally, this is fine. */ -#define MATCH_MAY_ALLOCATE - -/* When using GNU C, we are not REALLY using the C alloca, no matter - what config.h may say. So don't take precautions for it. */ -#ifdef __GNUC__ -#undef C_ALLOCA -#endif - -/* The match routines may not allocate if (1) they would do it with malloc - and (2) it's not safe for them to use malloc. - Note that if REL_ALLOC is defined, matching would not use malloc for the - failure stack, but we would still use it for the register vectors; - so REL_ALLOC should not affect this. */ -#if (defined (C_ALLOCA) || defined (REGEX_MALLOC)) && defined (emacs) -#undef MATCH_MAY_ALLOCATE -#endif - - -/* Failure stack declarations and macros; both re_compile_fastmap and - re_match_2 use a failure stack. These have to be macros because of - REGEX_ALLOCATE_STACK. */ - - -/* Number of failure points for which to initially allocate space - when matching. If this number is exceeded, we allocate more - space, so it is not a hard limit. */ -#ifndef INIT_FAILURE_ALLOC -#define INIT_FAILURE_ALLOC 5 -#endif - -/* Roughly the maximum number of failure points on the stack. Would be - exactly that if always used MAX_FAILURE_ITEMS items each time we failed. - This is a variable only so users of regex can assign to it; we never - change it ourselves. */ - -#ifdef INT_IS_16BIT - -#if defined (MATCH_MAY_ALLOCATE) -/* 4400 was enough to cause a crash on Alpha OSF/1, - whose default stack limit is 2mb. */ -long int re_max_failures = 4000; -#else -long int re_max_failures = 2000; -#endif - -union fail_stack_elt -{ - unsigned char *pointer; - long int integer; -}; - -typedef union fail_stack_elt fail_stack_elt_t; - -typedef struct -{ - fail_stack_elt_t *stack; - unsigned long int size; - unsigned long int avail; /* Offset of next open position. */ -} fail_stack_type; - -#else /* not INT_IS_16BIT */ - -#if defined (MATCH_MAY_ALLOCATE) -/* 4400 was enough to cause a crash on Alpha OSF/1, - whose default stack limit is 2mb. */ -int re_max_failures = 20000; -#else -int re_max_failures = 2000; -#endif - -union fail_stack_elt -{ - unsigned char *pointer; - int integer; -}; - -typedef union fail_stack_elt fail_stack_elt_t; - -typedef struct -{ - fail_stack_elt_t *stack; - unsigned size; - unsigned avail; /* Offset of next open position. */ -} fail_stack_type; - -#endif /* INT_IS_16BIT */ - -#define FAIL_STACK_EMPTY() (fail_stack.avail == 0) -#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) -#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) - - -/* Define macros to initialize and free the failure stack. - Do `return -2' if the alloc fails. */ - -#ifdef MATCH_MAY_ALLOCATE -#define INIT_FAIL_STACK() \ - do { \ - fail_stack.stack = (fail_stack_elt_t *) \ - REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ - \ - if (fail_stack.stack == NULL) \ - return -2; \ - \ - fail_stack.size = INIT_FAILURE_ALLOC; \ - fail_stack.avail = 0; \ - } while (0) - -#define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack) -#else -#define INIT_FAIL_STACK() \ - do { \ - fail_stack.avail = 0; \ - } while (0) - -#define RESET_FAIL_STACK() -#endif - - -/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. - - Return 1 if succeeds, and 0 if either ran out of memory - allocating space for it or it was already too large. - - REGEX_REALLOCATE_STACK requires `destination' be declared. */ - -#define DOUBLE_FAIL_STACK(fail_stack) \ - ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \ - ? 0 \ - : ((fail_stack).stack = (fail_stack_elt_t *) \ - REGEX_REALLOCATE_STACK ((fail_stack).stack, \ - (fail_stack).size * sizeof (fail_stack_elt_t), \ - ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ - \ - (fail_stack).stack == NULL \ - ? 0 \ - : ((fail_stack).size <<= 1, \ - 1))) - - -/* Push pointer POINTER on FAIL_STACK. - Return 1 if was able to do so and 0 if ran out of memory allocating - space to do so. */ -#define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \ - ((FAIL_STACK_FULL () \ - && !DOUBLE_FAIL_STACK (FAIL_STACK)) \ - ? 0 \ - : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \ - 1)) - -/* Push a pointer value onto the failure stack. - Assumes the variable `fail_stack'. Probably should only - be called from within `PUSH_FAILURE_POINT'. */ -#define PUSH_FAILURE_POINTER(item) \ - fail_stack.stack[fail_stack.avail++].pointer = (unsigned char *) (item) - -/* This pushes an integer-valued item onto the failure stack. - Assumes the variable `fail_stack'. Probably should only - be called from within `PUSH_FAILURE_POINT'. */ -#define PUSH_FAILURE_INT(item) \ - fail_stack.stack[fail_stack.avail++].integer = (item) - -/* Push a fail_stack_elt_t value onto the failure stack. - Assumes the variable `fail_stack'. Probably should only - be called from within `PUSH_FAILURE_POINT'. */ -#define PUSH_FAILURE_ELT(item) \ - fail_stack.stack[fail_stack.avail++] = (item) - -/* These three POP... operations complement the three PUSH... operations. - All assume that `fail_stack' is nonempty. */ -#define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer -#define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer -#define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail] - -/* Used to omit pushing failure point id's when we're not debugging. */ -#ifdef DEBUG -#define DEBUG_PUSH PUSH_FAILURE_INT -#define DEBUG_POP(item_addr) (item_addr)->integer = POP_FAILURE_INT () -#else -#define DEBUG_PUSH(item) -#define DEBUG_POP(item_addr) -#endif - - -/* Push the information about the state we will need - if we ever fail back to it. - - Requires variables fail_stack, regstart, regend, reg_info, and - num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be - declared. - - Does `return FAILURE_CODE' if runs out of memory. */ - -#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ - do { \ - char *destination; \ - /* Must be int, so when we don't save any registers, the arithmetic \ - of 0 + -1 isn't done as unsigned. */ \ - /* Can't be int, since there is not a shred of a guarantee that int \ - is wide enough to hold a value of something to which pointer can \ - be assigned */ \ - s_reg_t this_reg; \ - \ - DEBUG_STATEMENT (failure_id++); \ - DEBUG_STATEMENT (nfailure_points_pushed++); \ - DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ - DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ - DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ - \ - DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \ - DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ - \ - /* Ensure we have enough space allocated for what we will push. */ \ - while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ - { \ - if (!DOUBLE_FAIL_STACK (fail_stack)) \ - return failure_code; \ - \ - DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ - (fail_stack).size); \ - DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ - } \ - \ - /* Push the info, starting with the registers. */ \ - DEBUG_PRINT1 ("\n"); \ - \ - if (1) \ - for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ - this_reg++) \ - { \ - DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \ - DEBUG_STATEMENT (num_regs_pushed++); \ - \ - DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ - PUSH_FAILURE_POINTER (regstart[this_reg]); \ - \ - DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ - PUSH_FAILURE_POINTER (regend[this_reg]); \ - \ - DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \ - DEBUG_PRINT2 (" match_null=%d", \ - REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ - DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ - DEBUG_PRINT2 (" matched_something=%d", \ - MATCHED_SOMETHING (reg_info[this_reg])); \ - DEBUG_PRINT2 (" ever_matched=%d", \ - EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ - DEBUG_PRINT1 ("\n"); \ - PUSH_FAILURE_ELT (reg_info[this_reg].word); \ - } \ - \ - DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\ - PUSH_FAILURE_INT (lowest_active_reg); \ - \ - DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\ - PUSH_FAILURE_INT (highest_active_reg); \ - \ - DEBUG_PRINT2 (" Pushing pattern 0x%x:\n", pattern_place); \ - DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ - PUSH_FAILURE_POINTER (pattern_place); \ - \ - DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \ - DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ - size2); \ - DEBUG_PRINT1 ("'\n"); \ - PUSH_FAILURE_POINTER (string_place); \ - \ - DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ - DEBUG_PUSH (failure_id); \ - } while (0) - -/* This is the number of items that are pushed and popped on the stack - for each register. */ -#define NUM_REG_ITEMS 3 - -/* Individual items aside from the registers. */ -#ifdef DEBUG -#define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ -#else -#define NUM_NONREG_ITEMS 4 -#endif - -/* We push at most this many items on the stack. */ -/* We used to use (num_regs - 1), which is the number of registers - this regexp will save; but that was changed to 5 - to avoid stack overflow for a regexp with lots of parens. */ -#define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS) - -/* We actually push this many items. */ -#define NUM_FAILURE_ITEMS \ - (((0 \ - ? 0 : highest_active_reg - lowest_active_reg + 1) \ - * NUM_REG_ITEMS) \ - + NUM_NONREG_ITEMS) - -/* How many items can still be added to the stack without overflowing it. */ -#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) - - -/* Pops what PUSH_FAIL_STACK pushes. - - We restore into the parameters, all of which should be lvalues: - STR -- the saved data position. - PAT -- the saved pattern position. - LOW_REG, HIGH_REG -- the highest and lowest active registers. - REGSTART, REGEND -- arrays of string positions. - REG_INFO -- array of information about each subexpression. - - Also assumes the variables `fail_stack' and (if debugging), `bufp', - `pend', `string1', `size1', `string2', and `size2'. */ - -#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ -{ \ - DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \ - s_reg_t this_reg; \ - const unsigned char *string_temp; \ - \ - assert (!FAIL_STACK_EMPTY ()); \ - \ - /* Remove failure points and point to how many regs pushed. */ \ - DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ - DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ - DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ - \ - assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ - \ - DEBUG_POP (&failure_id); \ - DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ - \ - /* If the saved string location is NULL, it came from an \ - on_failure_keep_string_jump opcode, and we want to throw away the \ - saved NULL, thus retaining our current position in the string. */ \ - string_temp = POP_FAILURE_POINTER (); \ - if (string_temp != NULL) \ - str = (const char *) string_temp; \ - \ - DEBUG_PRINT2 (" Popping string 0x%x: `", str); \ - DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ - DEBUG_PRINT1 ("'\n"); \ - \ - pat = (unsigned char *) POP_FAILURE_POINTER (); \ - DEBUG_PRINT2 (" Popping pattern 0x%x:\n", pat); \ - DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ - \ - /* Restore register info. */ \ - high_reg = (active_reg_t) POP_FAILURE_INT (); \ - DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \ - \ - low_reg = (active_reg_t) POP_FAILURE_INT (); \ - DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \ - \ - if (1) \ - for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ - { \ - DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \ - \ - reg_info[this_reg].word = POP_FAILURE_ELT (); \ - DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \ - \ - regend[this_reg] = (const char *) POP_FAILURE_POINTER (); \ - DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ - \ - regstart[this_reg] = (const char *) POP_FAILURE_POINTER (); \ - DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ - } \ - else \ - { \ - for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \ - { \ - reg_info[this_reg].word.integer = 0; \ - regend[this_reg] = 0; \ - regstart[this_reg] = 0; \ - } \ - highest_active_reg = high_reg; \ - } \ - \ - set_regs_matched_done = 0; \ - DEBUG_STATEMENT (nfailure_points_popped++); \ -} /* POP_FAILURE_POINT */ - - - -/* Structure for per-register (a.k.a. per-group) information. - Other register information, such as the - starting and ending positions (which are addresses), and the list of - inner groups (which is a bits list) are maintained in separate - variables. - - We are making a (strictly speaking) nonportable assumption here: that - the compiler will pack our bit fields into something that fits into - the type of `word', i.e., is something that fits into one item on the - failure stack. */ - - -/* Declarations and macros for re_match_2. */ - -typedef union -{ - fail_stack_elt_t word; - struct - { - /* This field is one if this group can match the empty string, - zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ -#define MATCH_NULL_UNSET_VALUE 3 - unsigned match_null_string_p : 2; - unsigned is_active : 1; - unsigned matched_something : 1; - unsigned ever_matched_something : 1; - } bits; -} register_info_type; - -#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) -#define IS_ACTIVE(R) ((R).bits.is_active) -#define MATCHED_SOMETHING(R) ((R).bits.matched_something) -#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) - - -/* Call this when have matched a real character; it sets `matched' flags - for the subexpressions which we are currently inside. Also records - that those subexprs have matched. */ -#define SET_REGS_MATCHED() \ - do \ - { \ - if (!set_regs_matched_done) \ - { \ - active_reg_t r; \ - set_regs_matched_done = 1; \ - for (r = lowest_active_reg; r <= highest_active_reg; r++) \ - { \ - MATCHED_SOMETHING (reg_info[r]) \ - = EVER_MATCHED_SOMETHING (reg_info[r]) \ - = 1; \ - } \ - } \ - } \ - while (0) - -/* Registers are set to a sentinel when they haven't yet matched. */ -static char reg_unset_dummy; -#define REG_UNSET_VALUE (®_unset_dummy) -#define REG_UNSET(e) ((e) == REG_UNSET_VALUE) - -/* Subroutine declarations and macros for regex_compile. */ - -static reg_errcode_t regex_compile _RE_ARGS ((const char *pattern, size_t size, - reg_syntax_t syntax, - struct re_pattern_buffer *bufp)); -static void store_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, int arg)); -static void store_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc, - int arg1, int arg2)); -static void insert_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, - int arg, unsigned char *end)); -static void insert_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc, - int arg1, int arg2, unsigned char *end)); -static boolean at_begline_loc_p _RE_ARGS ((const char *pattern, const char *p, - reg_syntax_t syntax)); -static boolean at_endline_loc_p _RE_ARGS ((const char *p, const char *pend, - reg_syntax_t syntax)); -static reg_errcode_t compile_range _RE_ARGS ((const char **p_ptr, - const char *pend, - char *translate, - reg_syntax_t syntax, - unsigned char *b)); - -/* Fetch the next character in the uncompiled pattern---translating it - if necessary. Also cast from a signed character in the constant - string passed to us by the user to an unsigned char that we can use - as an array index (in, e.g., `translate'). */ -#ifndef PATFETCH -#define PATFETCH(c) \ - do {if (p == pend) return REG_EEND; \ - c = (unsigned char) *p++; \ - if (translate) c = (unsigned char) translate[c]; \ - } while (0) -#endif - -/* Fetch the next character in the uncompiled pattern, with no - translation. */ -#define PATFETCH_RAW(c) \ - do {if (p == pend) return REG_EEND; \ - c = (unsigned char) *p++; \ - } while (0) - -/* Go backwards one character in the pattern. */ -#define PATUNFETCH p-- - - -/* If `translate' is non-null, return translate[D], else just D. We - cast the subscript to translate because some data is declared as - `char *', to avoid warnings when a string constant is passed. But - when we use a character as a subscript we must make it unsigned. */ -#ifndef TRANSLATE -#define TRANSLATE(d) \ - (translate ? (char) translate[(unsigned char) (d)] : (d)) -#endif - - -/* Macros for outputting the compiled pattern into `buffer'. */ - -/* If the buffer isn't allocated when it comes in, use this. */ -#define INIT_BUF_SIZE 32 - -/* Make sure we have at least N more bytes of space in buffer. */ -#define GET_BUFFER_SPACE(n) \ - while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \ - EXTEND_BUFFER () - -/* Make sure we have one more byte of buffer space and then add C to it. */ -#define BUF_PUSH(c) \ - do { \ - GET_BUFFER_SPACE (1); \ - *b++ = (unsigned char) (c); \ - } while (0) - - -/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ -#define BUF_PUSH_2(c1, c2) \ - do { \ - GET_BUFFER_SPACE (2); \ - *b++ = (unsigned char) (c1); \ - *b++ = (unsigned char) (c2); \ - } while (0) - - -/* As with BUF_PUSH_2, except for three bytes. */ -#define BUF_PUSH_3(c1, c2, c3) \ - do { \ - GET_BUFFER_SPACE (3); \ - *b++ = (unsigned char) (c1); \ - *b++ = (unsigned char) (c2); \ - *b++ = (unsigned char) (c3); \ - } while (0) - - -/* Store a jump with opcode OP at LOC to location TO. We store a - relative address offset by the three bytes the jump itself occupies. */ -#define STORE_JUMP(op, loc, to) \ - store_op1 (op, loc, (int) ((to) - (loc) - 3)) - -/* Likewise, for a two-argument jump. */ -#define STORE_JUMP2(op, loc, to, arg) \ - store_op2 (op, loc, (int) ((to) - (loc) - 3), arg) - -/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ -#define INSERT_JUMP(op, loc, to) \ - insert_op1 (op, loc, (int) ((to) - (loc) - 3), b) - -/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ -#define INSERT_JUMP2(op, loc, to, arg) \ - insert_op2 (op, loc, (int) ((to) - (loc) - 3), arg, b) - - -/* This is not an arbitrary limit: the arguments which represent offsets - into the pattern are two bytes long. So if 2^16 bytes turns out to - be too small, many things would have to change. */ -/* Any other compiler which, like MSC, has allocation limit below 2^16 - bytes will have to use approach similar to what was done below for - MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up - reallocating to 0 bytes. Such thing is not going to work too well. - You have been warned!! */ -#if defined(_MSC_VER) && !defined(WIN32) -/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes. - The REALLOC define eliminates a flurry of conversion warnings, - but is not required. */ -#define MAX_BUF_SIZE 65500L -#define REALLOC(p,s) realloc ((p), (size_t) (s)) -#else -#define MAX_BUF_SIZE (1L << 16) -#define REALLOC(p,s) realloc ((p), (s)) -#endif - -/* Extend the buffer by twice its current size via realloc and - reset the pointers that pointed into the old block to point to the - correct places in the new one. If extending the buffer results in it - being larger than MAX_BUF_SIZE, then flag memory exhausted. */ -#define EXTEND_BUFFER() \ - do { \ - unsigned char *old_buffer = bufp->buffer; \ - if (bufp->allocated == MAX_BUF_SIZE) \ - return REG_ESIZE; \ - bufp->allocated <<= 1; \ - if (bufp->allocated > MAX_BUF_SIZE) \ - bufp->allocated = MAX_BUF_SIZE; \ - bufp->buffer = (unsigned char *) REALLOC (bufp->buffer, bufp->allocated);\ - if (bufp->buffer == NULL) \ - return REG_ESPACE; \ - /* If the buffer moved, move all the pointers into it. */ \ - if (old_buffer != bufp->buffer) \ - { \ - b = (b - old_buffer) + bufp->buffer; \ - begalt = (begalt - old_buffer) + bufp->buffer; \ - if (fixup_alt_jump) \ - fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ - if (laststart) \ - laststart = (laststart - old_buffer) + bufp->buffer; \ - if (pending_exact) \ - pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ - } \ - } while (0) - - -/* Since we have one byte reserved for the register number argument to - {start,stop}_memory, the maximum number of groups we can report - things about is what fits in that byte. */ -#define MAX_REGNUM 255 - -/* But patterns can have more than `MAX_REGNUM' registers. We just - ignore the excess. */ -typedef unsigned regnum_t; - - -/* Macros for the compile stack. */ - -/* Since offsets can go either forwards or backwards, this type needs to - be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ -/* int may be not enough when sizeof(int) == 2. */ -typedef long pattern_offset_t; - -typedef struct -{ - pattern_offset_t begalt_offset; - pattern_offset_t fixup_alt_jump; - pattern_offset_t inner_group_offset; - pattern_offset_t laststart_offset; - regnum_t regnum; -} compile_stack_elt_t; - - -typedef struct -{ - compile_stack_elt_t *stack; - unsigned size; - unsigned avail; /* Offset of next open position. */ -} compile_stack_type; - - -#define INIT_COMPILE_STACK_SIZE 32 - -#define COMPILE_STACK_EMPTY (compile_stack.avail == 0) -#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) - -/* The next available element. */ -#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) - - -/* Set the bit for character C in a list. */ -#define SET_LIST_BIT(c) \ - (b[((unsigned char) (c)) / BYTEWIDTH] \ - |= 1 << (((unsigned char) c) % BYTEWIDTH)) - - -/* Get the next unsigned number in the uncompiled pattern. */ -#define GET_UNSIGNED_NUMBER(num) \ - { if (p != pend) \ - { \ - PATFETCH (c); \ - while (ISDIGIT (c)) \ - { \ - if (num < 0) \ - num = 0; \ - num = num * 10 + c - '0'; \ - if (p == pend) \ - break; \ - PATFETCH (c); \ - } \ - } \ - } - -#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) -/* The GNU C library provides support for user-defined character classes - and the functions from ISO C amendement 1. */ -# ifdef CHARCLASS_NAME_MAX -# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX -# else -/* This shouldn't happen but some implementation might still have this - problem. Use a reasonable default value. */ -# define CHAR_CLASS_MAX_LENGTH 256 -# endif - -# define IS_CHAR_CLASS(string) wctype (string) -#else -# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ - -# define IS_CHAR_CLASS(string) \ - (STREQ (string, "alpha") || STREQ (string, "upper") \ - || STREQ (string, "lower") || STREQ (string, "digit") \ - || STREQ (string, "alnum") || STREQ (string, "xdigit") \ - || STREQ (string, "space") || STREQ (string, "print") \ - || STREQ (string, "punct") || STREQ (string, "graph") \ - || STREQ (string, "cntrl") || STREQ (string, "blank")) -#endif - -#ifndef MATCH_MAY_ALLOCATE - -/* If we cannot allocate large objects within re_match_2_internal, - we make the fail stack and register vectors global. - The fail stack, we grow to the maximum size when a regexp - is compiled. - The register vectors, we adjust in size each time we - compile a regexp, according to the number of registers it needs. */ - -static fail_stack_type fail_stack; - -/* Size with which the following vectors are currently allocated. - That is so we can make them bigger as needed, - but never make them smaller. */ -static int regs_allocated_size; - -static const char ** regstart, ** regend; -static const char ** old_regstart, ** old_regend; -static const char **best_regstart, **best_regend; -static register_info_type *reg_info; -static const char **reg_dummy; -static register_info_type *reg_info_dummy; - -/* Make the register vectors big enough for NUM_REGS registers, - but don't make them smaller. */ - -static -regex_grow_registers (num_regs) - int num_regs; -{ - if (num_regs > regs_allocated_size) - { - RETALLOC_IF (regstart, num_regs, const char *); - RETALLOC_IF (regend, num_regs, const char *); - RETALLOC_IF (old_regstart, num_regs, const char *); - RETALLOC_IF (old_regend, num_regs, const char *); - RETALLOC_IF (best_regstart, num_regs, const char *); - RETALLOC_IF (best_regend, num_regs, const char *); - RETALLOC_IF (reg_info, num_regs, register_info_type); - RETALLOC_IF (reg_dummy, num_regs, const char *); - RETALLOC_IF (reg_info_dummy, num_regs, register_info_type); - - regs_allocated_size = num_regs; - } -} - -#endif /* not MATCH_MAY_ALLOCATE */ - -static boolean group_in_compile_stack _RE_ARGS ((compile_stack_type - compile_stack, - regnum_t regnum)); - -/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. - Returns one of error codes defined in `regex.h', or zero for success. - - Assumes the `allocated' (and perhaps `buffer') and `translate' - fields are set in BUFP on entry. - - If it succeeds, results are put in BUFP (if it returns an error, the - contents of BUFP are undefined): - `buffer' is the compiled pattern; - `syntax' is set to SYNTAX; - `used' is set to the length of the compiled pattern; - `fastmap_accurate' is zero; - `re_nsub' is the number of subexpressions in PATTERN; - `not_bol' and `not_eol' are zero; - - The `fastmap' and `newline_anchor' fields are neither - examined nor set. */ - -/* Return, freeing storage we allocated. */ -#define FREE_STACK_RETURN(value) \ - return (free (compile_stack.stack), value) - -static reg_errcode_t -regex_compile (pattern, size, syntax, bufp) - const char *pattern; - size_t size; - reg_syntax_t syntax; - struct re_pattern_buffer *bufp; -{ - /* We fetch characters from PATTERN here. Even though PATTERN is - `char *' (i.e., signed), we declare these variables as unsigned, so - they can be reliably used as array indices. */ - register unsigned char c, c1; - - /* A random temporary spot in PATTERN. */ - const char *p1; - - /* Points to the end of the buffer, where we should append. */ - register unsigned char *b; - - /* Keeps track of unclosed groups. */ - compile_stack_type compile_stack; - - /* Points to the current (ending) position in the pattern. */ - const char *p = pattern; - const char *pend = pattern + size; - - /* How to translate the characters in the pattern. */ - RE_TRANSLATE_TYPE translate = bufp->translate; - - /* Address of the count-byte of the most recently inserted `exactn' - command. This makes it possible to tell if a new exact-match - character can be added to that command or if the character requires - a new `exactn' command. */ - unsigned char *pending_exact = 0; - - /* Address of start of the most recently finished expression. - This tells, e.g., postfix * where to find the start of its - operand. Reset at the beginning of groups and alternatives. */ - unsigned char *laststart = 0; - - /* Address of beginning of regexp, or inside of last group. */ - unsigned char *begalt; - - /* Place in the uncompiled pattern (i.e., the {) to - which to go back if the interval is invalid. */ - const char *beg_interval; - - /* Address of the place where a forward jump should go to the end of - the containing expression. Each alternative of an `or' -- except the - last -- ends with a forward jump of this sort. */ - unsigned char *fixup_alt_jump = 0; - - /* Counts open-groups as they are encountered. Remembered for the - matching close-group on the compile stack, so the same register - number is put in the stop_memory as the start_memory. */ - regnum_t regnum = 0; - -#ifdef DEBUG - DEBUG_PRINT1 ("\nCompiling pattern: "); - if (debug) - { - unsigned debug_count; - - for (debug_count = 0; debug_count < size; debug_count++) - putchar (pattern[debug_count]); - putchar ('\n'); - } -#endif /* DEBUG */ - - /* Initialize the compile stack. */ - compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); - if (compile_stack.stack == NULL) - return REG_ESPACE; - - compile_stack.size = INIT_COMPILE_STACK_SIZE; - compile_stack.avail = 0; - - /* Initialize the pattern buffer. */ - bufp->syntax = syntax; - bufp->fastmap_accurate = 0; - bufp->not_bol = bufp->not_eol = 0; - - /* Set `used' to zero, so that if we return an error, the pattern - printer (for debugging) will think there's no pattern. We reset it - at the end. */ - bufp->used = 0; - - /* Always count groups, whether or not bufp->no_sub is set. */ - bufp->re_nsub = 0; - -#if !defined (emacs) && !defined (SYNTAX_TABLE) - /* Initialize the syntax table. */ - init_syntax_once (); -#endif - - if (bufp->allocated == 0) - { - if (bufp->buffer) - { /* If zero allocated, but buffer is non-null, try to realloc - enough space. This loses if buffer's address is bogus, but - that is the user's responsibility. */ - RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char); - } - else - { /* Caller did not allocate a buffer. Do it for them. */ - bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char); - } - if (!bufp->buffer) FREE_STACK_RETURN (REG_ESPACE); - - bufp->allocated = INIT_BUF_SIZE; - } - - begalt = b = bufp->buffer; - - /* Loop through the uncompiled pattern until we're at the end. */ - while (p != pend) - { - PATFETCH (c); - - switch (c) - { - case '^': - { - if ( /* If at start of pattern, it's an operator. */ - p == pattern + 1 - /* If context independent, it's an operator. */ - || syntax & RE_CONTEXT_INDEP_ANCHORS - /* Otherwise, depends on what's come before. */ - || at_begline_loc_p (pattern, p, syntax)) - BUF_PUSH (begline); - else - goto normal_char; - } - break; - - - case '$': - { - if ( /* If at end of pattern, it's an operator. */ - p == pend - /* If context independent, it's an operator. */ - || syntax & RE_CONTEXT_INDEP_ANCHORS - /* Otherwise, depends on what's next. */ - || at_endline_loc_p (p, pend, syntax)) - BUF_PUSH (endline); - else - goto normal_char; - } - break; - - - case '+': - case '?': - if ((syntax & RE_BK_PLUS_QM) - || (syntax & RE_LIMITED_OPS)) - goto normal_char; - handle_plus: - case '*': - /* If there is no previous pattern... */ - if (!laststart) - { - if (syntax & RE_CONTEXT_INVALID_OPS) - FREE_STACK_RETURN (REG_BADRPT); - else if (!(syntax & RE_CONTEXT_INDEP_OPS)) - goto normal_char; - } - - { - /* Are we optimizing this jump? */ - boolean keep_string_p = false; - - /* 1 means zero (many) matches is allowed. */ - char zero_times_ok = 0, many_times_ok = 0; - - /* If there is a sequence of repetition chars, collapse it - down to just one (the right one). We can't combine - interval operators with these because of, e.g., `a{2}*', - which should only match an even number of `a's. */ - - for (;;) - { - zero_times_ok |= c != '+'; - many_times_ok |= c != '?'; - - if (p == pend) - break; - - PATFETCH (c); - - if (c == '*' - || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) - ; - - else if (syntax & RE_BK_PLUS_QM && c == '\\') - { - if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); - - PATFETCH (c1); - if (!(c1 == '+' || c1 == '?')) - { - PATUNFETCH; - PATUNFETCH; - break; - } - - c = c1; - } - else - { - PATUNFETCH; - break; - } - - /* If we get here, we found another repeat character. */ - } - - /* Star, etc. applied to an empty pattern is equivalent - to an empty pattern. */ - if (!laststart) - break; - - /* Now we know whether or not zero matches is allowed - and also whether or not two or more matches is allowed. */ - if (many_times_ok) - { /* More than one repetition is allowed, so put in at the - end a backward relative jump from `b' to before the next - jump we're going to put in below (which jumps from - laststart to after this jump). - - But if we are at the `*' in the exact sequence `.*\n', - insert an unconditional jump backwards to the ., - instead of the beginning of the loop. This way we only - push a failure point once, instead of every time - through the loop. */ - assert (p - 1 > pattern); - - /* Allocate the space for the jump. */ - GET_BUFFER_SPACE (3); - - /* We know we are not at the first character of the pattern, - because laststart was nonzero. And we've already - incremented `p', by the way, to be the character after - the `*'. Do we have to do something analogous here - for null bytes, because of RE_DOT_NOT_NULL? */ - if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') - && zero_times_ok - && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') - && !(syntax & RE_DOT_NEWLINE)) - { /* We have .*\n. */ - STORE_JUMP (jump, b, laststart); - keep_string_p = true; - } - else - /* Anything else. */ - STORE_JUMP (maybe_pop_jump, b, laststart - 3); - - /* We've added more stuff to the buffer. */ - b += 3; - } - - /* On failure, jump from laststart to b + 3, which will be the - end of the buffer after this jump is inserted. */ - GET_BUFFER_SPACE (3); - INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump - : on_failure_jump, - laststart, b + 3); - pending_exact = 0; - b += 3; - - if (!zero_times_ok) - { - /* At least one repetition is required, so insert a - `dummy_failure_jump' before the initial - `on_failure_jump' instruction of the loop. This - effects a skip over that instruction the first time - we hit that loop. */ - GET_BUFFER_SPACE (3); - INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6); - b += 3; - } - } - break; - - - case '.': - laststart = b; - BUF_PUSH (anychar); - break; - - - case '[': - { - boolean had_char_class = false; - - if (p == pend) FREE_STACK_RETURN (REG_EBRACK); - - /* Ensure that we have enough space to push a charset: the - opcode, the length count, and the bitset; 34 bytes in all. */ - GET_BUFFER_SPACE (34); - - laststart = b; - - /* We test `*p == '^' twice, instead of using an if - statement, so we only need one BUF_PUSH. */ - BUF_PUSH (*p == '^' ? charset_not : charset); - if (*p == '^') - p++; - - /* Remember the first position in the bracket expression. */ - p1 = p; - - /* Push the number of bytes in the bitmap. */ - BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); - - /* Clear the whole map. */ - bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); - - /* charset_not matches newline according to a syntax bit. */ - if ((re_opcode_t) b[-2] == charset_not - && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) - SET_LIST_BIT ('\n'); - - /* Read in characters and ranges, setting map bits. */ - for (;;) - { - if (p == pend) FREE_STACK_RETURN (REG_EBRACK); - - PATFETCH (c); - - /* \ might escape characters inside [...] and [^...]. */ - if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') - { - if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); - - PATFETCH (c1); - SET_LIST_BIT (c1); - continue; - } - - /* Could be the end of the bracket expression. If it's - not (i.e., when the bracket expression is `[]' so - far), the ']' character bit gets set way below. */ - if (c == ']' && p != p1 + 1) - break; - - /* Look ahead to see if it's a range when the last thing - was a character class. */ - if (had_char_class && c == '-' && *p != ']') - FREE_STACK_RETURN (REG_ERANGE); - - /* Look ahead to see if it's a range when the last thing - was a character: if this is a hyphen not at the - beginning or the end of a list, then it's the range - operator. */ - if (c == '-' - && !(p - 2 >= pattern && p[-2] == '[') - && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') - && *p != ']') - { - reg_errcode_t ret - = compile_range (&p, pend, translate, syntax, b); - if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); - } - - else if (p[0] == '-' && p[1] != ']') - { /* This handles ranges made up of characters only. */ - reg_errcode_t ret; - - /* Move past the `-'. */ - PATFETCH (c1); - - ret = compile_range (&p, pend, translate, syntax, b); - if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); - } - - /* See if we're at the beginning of a possible character - class. */ - - else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') - { /* Leave room for the null. */ - char str[CHAR_CLASS_MAX_LENGTH + 1]; - - PATFETCH (c); - c1 = 0; - - /* If pattern is `[[:'. */ - if (p == pend) FREE_STACK_RETURN (REG_EBRACK); - - for (;;) - { - PATFETCH (c); - if (c == ':' || c == ']' || p == pend - || c1 == CHAR_CLASS_MAX_LENGTH) - break; - str[c1++] = c; - } - str[c1] = '\0'; - - /* If isn't a word bracketed by `[:' and:`]': - undo the ending character, the letters, and leave - the leading `:' and `[' (but set bits for them). */ - if (c == ':' && *p == ']') - { -#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) - boolean is_lower = STREQ (str, "lower"); - boolean is_upper = STREQ (str, "upper"); - wctype_t wt; - int ch; - - wt = wctype (str); - if (wt == 0) - FREE_STACK_RETURN (REG_ECTYPE); - - /* Throw away the ] at the end of the character - class. */ - PATFETCH (c); - - if (p == pend) FREE_STACK_RETURN (REG_EBRACK); - - for (ch = 0; ch < 1 << BYTEWIDTH; ++ch) - { - if (iswctype (btowc (ch), wt)) - SET_LIST_BIT (ch); - - if (translate && (is_upper || is_lower) - && (ISUPPER (ch) || ISLOWER (ch))) - SET_LIST_BIT (ch); - } - - had_char_class = true; -#else - int ch; - boolean is_alnum = STREQ (str, "alnum"); - boolean is_alpha = STREQ (str, "alpha"); - boolean is_blank = STREQ (str, "blank"); - boolean is_cntrl = STREQ (str, "cntrl"); - boolean is_digit = STREQ (str, "digit"); - boolean is_graph = STREQ (str, "graph"); - boolean is_lower = STREQ (str, "lower"); - boolean is_print = STREQ (str, "print"); - boolean is_punct = STREQ (str, "punct"); - boolean is_space = STREQ (str, "space"); - boolean is_upper = STREQ (str, "upper"); - boolean is_xdigit = STREQ (str, "xdigit"); - - if (!IS_CHAR_CLASS (str)) - FREE_STACK_RETURN (REG_ECTYPE); - - /* Throw away the ] at the end of the character - class. */ - PATFETCH (c); - - if (p == pend) FREE_STACK_RETURN (REG_EBRACK); - - for (ch = 0; ch < (1 << BYTEWIDTH); ch++) - { - /* This was split into 3 if's to - avoid an arbitrary limit in some compiler. */ - if ( (is_alnum && ISALNUM (ch)) - || (is_alpha && ISALPHA (ch)) - || (is_blank && ISBLANK (ch)) - || (is_cntrl && ISCNTRL (ch))) - SET_LIST_BIT (ch); - if ( (is_digit && ISDIGIT (ch)) - || (is_graph && ISGRAPH (ch)) - || (is_lower && ISLOWER (ch)) - || (is_print && ISPRINT (ch))) - SET_LIST_BIT (ch); - if ( (is_punct && ISPUNCT (ch)) - || (is_space && ISSPACE (ch)) - || (is_upper && ISUPPER (ch)) - || (is_xdigit && ISXDIGIT (ch))) - SET_LIST_BIT (ch); - if ( translate && (is_upper || is_lower) - && (ISUPPER (ch) || ISLOWER (ch))) - SET_LIST_BIT (ch); - } - had_char_class = true; -#endif /* libc || wctype.h */ - } - else - { - c1++; - while (c1--) - PATUNFETCH; - SET_LIST_BIT ('['); - SET_LIST_BIT (':'); - had_char_class = false; - } - } - else - { - had_char_class = false; - SET_LIST_BIT (c); - } - } - - /* Discard any (non)matching list bytes that are all 0 at the - end of the map. Decrease the map-length byte too. */ - while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) - b[-1]--; - b += b[-1]; - } - break; - - - case '(': - if (syntax & RE_NO_BK_PARENS) - goto handle_open; - else - goto normal_char; - - - case ')': - if (syntax & RE_NO_BK_PARENS) - goto handle_close; - else - goto normal_char; - - - case '\n': - if (syntax & RE_NEWLINE_ALT) - goto handle_alt; - else - goto normal_char; - - - case '|': - if (syntax & RE_NO_BK_VBAR) - goto handle_alt; - else - goto normal_char; - - - case '{': - if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) - goto handle_interval; - else - goto normal_char; - - - case '\\': - if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); - - /* Do not translate the character after the \, so that we can - distinguish, e.g., \B from \b, even if we normally would - translate, e.g., B to b. */ - PATFETCH_RAW (c); - - switch (c) - { - case '(': - if (syntax & RE_NO_BK_PARENS) - goto normal_backslash; - - handle_open: - bufp->re_nsub++; - regnum++; - - if (COMPILE_STACK_FULL) - { - RETALLOC (compile_stack.stack, compile_stack.size << 1, - compile_stack_elt_t); - if (compile_stack.stack == NULL) return REG_ESPACE; - - compile_stack.size <<= 1; - } - - /* These are the values to restore when we hit end of this - group. They are all relative offsets, so that if the - whole pattern moves because of realloc, they will still - be valid. */ - COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer; - COMPILE_STACK_TOP.fixup_alt_jump - = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0; - COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer; - COMPILE_STACK_TOP.regnum = regnum; - - /* We will eventually replace the 0 with the number of - groups inner to this one. But do not push a - start_memory for groups beyond the last one we can - represent in the compiled pattern. */ - if (regnum <= MAX_REGNUM) - { - COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2; - BUF_PUSH_3 (start_memory, regnum, 0); - } - - compile_stack.avail++; - - fixup_alt_jump = 0; - laststart = 0; - begalt = b; - /* If we've reached MAX_REGNUM groups, then this open - won't actually generate any code, so we'll have to - clear pending_exact explicitly. */ - pending_exact = 0; - break; - - - case ')': - if (syntax & RE_NO_BK_PARENS) goto normal_backslash; - - if (COMPILE_STACK_EMPTY) { - if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) - goto normal_backslash; - } - else FREE_STACK_RETURN (REG_ERPAREN); - - handle_close: - if (fixup_alt_jump) - { /* Push a dummy failure point at the end of the - alternative for a possible future - `pop_failure_jump' to pop. See comments at - `push_dummy_failure' in `re_match_2'. */ - BUF_PUSH (push_dummy_failure); - - /* We allocated space for this jump when we assigned - to `fixup_alt_jump', in the `handle_alt' case below. */ - STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); - } - - /* See similar code for backslashed left paren above. */ - if (COMPILE_STACK_EMPTY) { - if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) - goto normal_char; - } - else FREE_STACK_RETURN (REG_ERPAREN); - - /* Since we just checked for an empty stack above, this - ``can't happen''. */ - assert (compile_stack.avail != 0); - { - /* We don't just want to restore into `regnum', because - later groups should continue to be numbered higher, - as in `(ab)c(de)' -- the second group is #2. */ - regnum_t this_group_regnum; - - compile_stack.avail--; - begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset; - fixup_alt_jump - = COMPILE_STACK_TOP.fixup_alt_jump - ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1 - : 0; - laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset; - this_group_regnum = COMPILE_STACK_TOP.regnum; - /* If we've reached MAX_REGNUM groups, then this open - won't actually generate any code, so we'll have to - clear pending_exact explicitly. */ - pending_exact = 0; - - /* We're at the end of the group, so now we know how many - groups were inside this one. */ - if (this_group_regnum <= MAX_REGNUM) - { - unsigned char *inner_group_loc - = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset; - - *inner_group_loc = regnum - this_group_regnum; - BUF_PUSH_3 (stop_memory, this_group_regnum, - regnum - this_group_regnum); - } - } - break; - - - case '|': /* `\|'. */ - if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) - goto normal_backslash; - handle_alt: - if (syntax & RE_LIMITED_OPS) - goto normal_char; - - /* Insert before the previous alternative a jump which - jumps to this alternative if the former fails. */ - GET_BUFFER_SPACE (3); - INSERT_JUMP (on_failure_jump, begalt, b + 6); - pending_exact = 0; - b += 3; - - /* The alternative before this one has a jump after it - which gets executed if it gets matched. Adjust that - jump so it will jump to this alternative's analogous - jump (put in below, which in turn will jump to the next - (if any) alternative's such jump, etc.). The last such - jump jumps to the correct final destination. A picture: - _____ _____ - | | | | - | v | v - a | b | c - - If we are at `b', then fixup_alt_jump right now points to a - three-byte space after `a'. We'll put in the jump, set - fixup_alt_jump to right after `b', and leave behind three - bytes which we'll fill in when we get to after `c'. */ - - if (fixup_alt_jump) - STORE_JUMP (jump_past_alt, fixup_alt_jump, b); - - /* Mark and leave space for a jump after this alternative, - to be filled in later either by next alternative or - when know we're at the end of a series of alternatives. */ - fixup_alt_jump = b; - GET_BUFFER_SPACE (3); - b += 3; - - laststart = 0; - begalt = b; - break; - - - case '{': - /* If \{ is a literal. */ - if (!(syntax & RE_INTERVALS) - /* If we're at `\{' and it's not the open-interval - operator. */ - || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) - || (p - 2 == pattern && p == pend)) - goto normal_backslash; - - handle_interval: - { - /* If got here, then the syntax allows intervals. */ - - /* At least (most) this many matches must be made. */ - int lower_bound = -1, upper_bound = -1; - - beg_interval = p - 1; - - if (p == pend) - { - if (syntax & RE_NO_BK_BRACES) - goto unfetch_interval; - else - FREE_STACK_RETURN (REG_EBRACE); - } - - GET_UNSIGNED_NUMBER (lower_bound); - - if (c == ',') - { - GET_UNSIGNED_NUMBER (upper_bound); - if (upper_bound < 0) upper_bound = RE_DUP_MAX; - } - else - /* Interval such as `{1}' => match exactly once. */ - upper_bound = lower_bound; - - if (lower_bound < 0 || upper_bound > RE_DUP_MAX - || lower_bound > upper_bound) - { - if (syntax & RE_NO_BK_BRACES) - goto unfetch_interval; - else - FREE_STACK_RETURN (REG_BADBR); - } - - if (!(syntax & RE_NO_BK_BRACES)) - { - if (c != '\\') FREE_STACK_RETURN (REG_EBRACE); - - PATFETCH (c); - } - - if (c != '}') - { - if (syntax & RE_NO_BK_BRACES) - goto unfetch_interval; - else - FREE_STACK_RETURN (REG_BADBR); - } - - /* We just parsed a valid interval. */ - - /* If it's invalid to have no preceding re. */ - if (!laststart) - { - if (syntax & RE_CONTEXT_INVALID_OPS) - FREE_STACK_RETURN (REG_BADRPT); - else if (syntax & RE_CONTEXT_INDEP_OPS) - laststart = b; - else - goto unfetch_interval; - } - - /* If the upper bound is zero, don't want to succeed at - all; jump from `laststart' to `b + 3', which will be - the end of the buffer after we insert the jump. */ - if (upper_bound == 0) - { - GET_BUFFER_SPACE (3); - INSERT_JUMP (jump, laststart, b + 3); - b += 3; - } - - /* Otherwise, we have a nontrivial interval. When - we're all done, the pattern will look like: - set_number_at <jump count> <upper bound> - set_number_at <succeed_n count> <lower bound> - succeed_n <after jump addr> <succeed_n count> - <body of loop> - jump_n <succeed_n addr> <jump count> - (The upper bound and `jump_n' are omitted if - `upper_bound' is 1, though.) */ - else - { /* If the upper bound is > 1, we need to insert - more at the end of the loop. */ - unsigned nbytes = 10 + (upper_bound > 1) * 10; - - GET_BUFFER_SPACE (nbytes); - - /* Initialize lower bound of the `succeed_n', even - though it will be set during matching by its - attendant `set_number_at' (inserted next), - because `re_compile_fastmap' needs to know. - Jump to the `jump_n' we might insert below. */ - INSERT_JUMP2 (succeed_n, laststart, - b + 5 + (upper_bound > 1) * 5, - lower_bound); - b += 5; - - /* Code to initialize the lower bound. Insert - before the `succeed_n'. The `5' is the last two - bytes of this `set_number_at', plus 3 bytes of - the following `succeed_n'. */ - insert_op2 (set_number_at, laststart, 5, lower_bound, b); - b += 5; - - if (upper_bound > 1) - { /* More than one repetition is allowed, so - append a backward jump to the `succeed_n' - that starts this interval. - - When we've reached this during matching, - we'll have matched the interval once, so - jump back only `upper_bound - 1' times. */ - STORE_JUMP2 (jump_n, b, laststart + 5, - upper_bound - 1); - b += 5; - - /* The location we want to set is the second - parameter of the `jump_n'; that is `b-2' as - an absolute address. `laststart' will be - the `set_number_at' we're about to insert; - `laststart+3' the number to set, the source - for the relative address. But we are - inserting into the middle of the pattern -- - so everything is getting moved up by 5. - Conclusion: (b - 2) - (laststart + 3) + 5, - i.e., b - laststart. - - We insert this at the beginning of the loop - so that if we fail during matching, we'll - reinitialize the bounds. */ - insert_op2 (set_number_at, laststart, b - laststart, - upper_bound - 1, b); - b += 5; - } - } - pending_exact = 0; - beg_interval = NULL; - } - break; - - unfetch_interval: - /* If an invalid interval, match the characters as literals. */ - assert (beg_interval); - p = beg_interval; - beg_interval = NULL; - - /* normal_char and normal_backslash need `c'. */ - PATFETCH (c); - - if (!(syntax & RE_NO_BK_BRACES)) - { - if (p > pattern && p[-1] == '\\') - goto normal_backslash; - } - goto normal_char; - -#ifdef emacs - /* There is no way to specify the before_dot and after_dot - operators. rms says this is ok. --karl */ - case '=': - BUF_PUSH (at_dot); - break; - - case 's': - laststart = b; - PATFETCH (c); - BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); - break; - - case 'S': - laststart = b; - PATFETCH (c); - BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); - break; -#endif /* emacs */ - - - case 'w': - if (re_syntax_options & RE_NO_GNU_OPS) - goto normal_char; - laststart = b; - BUF_PUSH (wordchar); - break; - - - case 'W': - if (re_syntax_options & RE_NO_GNU_OPS) - goto normal_char; - laststart = b; - BUF_PUSH (notwordchar); - break; - - - case '<': - if (re_syntax_options & RE_NO_GNU_OPS) - goto normal_char; - BUF_PUSH (wordbeg); - break; - - case '>': - if (re_syntax_options & RE_NO_GNU_OPS) - goto normal_char; - BUF_PUSH (wordend); - break; - - case 'b': - if (re_syntax_options & RE_NO_GNU_OPS) - goto normal_char; - BUF_PUSH (wordbound); - break; - - case 'B': - if (re_syntax_options & RE_NO_GNU_OPS) - goto normal_char; - BUF_PUSH (notwordbound); - break; - - case '`': - if (re_syntax_options & RE_NO_GNU_OPS) - goto normal_char; - BUF_PUSH (begbuf); - break; - - case '\'': - if (re_syntax_options & RE_NO_GNU_OPS) - goto normal_char; - BUF_PUSH (endbuf); - break; - - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - if (syntax & RE_NO_BK_REFS) - goto normal_char; - - c1 = c - '0'; - - if (c1 > regnum) - FREE_STACK_RETURN (REG_ESUBREG); - - /* Can't back reference to a subexpression if inside of it. */ - if (group_in_compile_stack (compile_stack, (regnum_t) c1)) - goto normal_char; - - laststart = b; - BUF_PUSH_2 (duplicate, c1); - break; - - - case '+': - case '?': - if (syntax & RE_BK_PLUS_QM) - goto handle_plus; - else - goto normal_backslash; - - default: - normal_backslash: - /* You might think it would be useful for \ to mean - not to translate; but if we don't translate it - it will never match anything. */ - c = TRANSLATE (c); - goto normal_char; - } - break; - - - default: - /* Expects the character in `c'. */ - normal_char: - /* If no exactn currently being built. */ - if (!pending_exact - - /* If last exactn not at current position. */ - || pending_exact + *pending_exact + 1 != b - - /* We have only one byte following the exactn for the count. */ - || *pending_exact == (1 << BYTEWIDTH) - 1 - - /* If followed by a repetition operator. */ - || *p == '*' || *p == '^' - || ((syntax & RE_BK_PLUS_QM) - ? *p == '\\' && (p[1] == '+' || p[1] == '?') - : (*p == '+' || *p == '?')) - || ((syntax & RE_INTERVALS) - && ((syntax & RE_NO_BK_BRACES) - ? *p == '{' - : (p[0] == '\\' && p[1] == '{')))) - { - /* Start building a new exactn. */ - - laststart = b; - - BUF_PUSH_2 (exactn, 0); - pending_exact = b - 1; - } - - BUF_PUSH (c); - (*pending_exact)++; - break; - } /* switch (c) */ - } /* while p != pend */ - - - /* Through the pattern now. */ - - if (fixup_alt_jump) - STORE_JUMP (jump_past_alt, fixup_alt_jump, b); - - if (!COMPILE_STACK_EMPTY) - FREE_STACK_RETURN (REG_EPAREN); - - /* If we don't want backtracking, force success - the first time we reach the end of the compiled pattern. */ - if (syntax & RE_NO_POSIX_BACKTRACKING) - BUF_PUSH (succeed); - - free (compile_stack.stack); - - /* We have succeeded; set the length of the buffer. */ - bufp->used = b - bufp->buffer; - -#ifdef DEBUG - if (debug) - { - DEBUG_PRINT1 ("\nCompiled pattern: \n"); - print_compiled_pattern (bufp); - } -#endif /* DEBUG */ - -#ifndef MATCH_MAY_ALLOCATE - /* Initialize the failure stack to the largest possible stack. This - isn't necessary unless we're trying to avoid calling alloca in - the search and match routines. */ - { - int num_regs = bufp->re_nsub + 1; - - /* Since DOUBLE_FAIL_STACK refuses to double only if the current size - is strictly greater than re_max_failures, the largest possible stack - is 2 * re_max_failures failure points. */ - if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS)) - { - fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS); - -#ifdef emacs - if (! fail_stack.stack) - fail_stack.stack - = (fail_stack_elt_t *) xmalloc (fail_stack.size - * sizeof (fail_stack_elt_t)); - else - fail_stack.stack - = (fail_stack_elt_t *) xrealloc (fail_stack.stack, - (fail_stack.size - * sizeof (fail_stack_elt_t))); -#else /* not emacs */ - if (! fail_stack.stack) - fail_stack.stack - = (fail_stack_elt_t *) malloc (fail_stack.size - * sizeof (fail_stack_elt_t)); - else - fail_stack.stack - = (fail_stack_elt_t *) realloc (fail_stack.stack, - (fail_stack.size - * sizeof (fail_stack_elt_t))); -#endif /* not emacs */ - } - - regex_grow_registers (num_regs); - } -#endif /* not MATCH_MAY_ALLOCATE */ - - return REG_NOERROR; -} /* regex_compile */ - -/* Subroutines for `regex_compile'. */ - -/* Store OP at LOC followed by two-byte integer parameter ARG. */ - -static void -store_op1 (op, loc, arg) - re_opcode_t op; - unsigned char *loc; - int arg; -{ - *loc = (unsigned char) op; - STORE_NUMBER (loc + 1, arg); -} - - -/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ - -static void -store_op2 (op, loc, arg1, arg2) - re_opcode_t op; - unsigned char *loc; - int arg1, arg2; -{ - *loc = (unsigned char) op; - STORE_NUMBER (loc + 1, arg1); - STORE_NUMBER (loc + 3, arg2); -} - - -/* Copy the bytes from LOC to END to open up three bytes of space at LOC - for OP followed by two-byte integer parameter ARG. */ - -static void -insert_op1 (op, loc, arg, end) - re_opcode_t op; - unsigned char *loc; - int arg; - unsigned char *end; -{ - register unsigned char *pfrom = end; - register unsigned char *pto = end + 3; - - while (pfrom != loc) - *--pto = *--pfrom; - - store_op1 (op, loc, arg); -} - - -/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ - -static void -insert_op2 (op, loc, arg1, arg2, end) - re_opcode_t op; - unsigned char *loc; - int arg1, arg2; - unsigned char *end; -{ - register unsigned char *pfrom = end; - register unsigned char *pto = end + 5; - - while (pfrom != loc) - *--pto = *--pfrom; - - store_op2 (op, loc, arg1, arg2); -} - - -/* P points to just after a ^ in PATTERN. Return true if that ^ comes - after an alternative or a begin-subexpression. We assume there is at - least one character before the ^. */ - -static boolean -at_begline_loc_p (pattern, p, syntax) - const char *pattern, *p; - reg_syntax_t syntax; -{ - const char *prev = p - 2; - boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; - - return - /* After a subexpression? */ - (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) - /* After an alternative? */ - || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); -} - - -/* The dual of at_begline_loc_p. This one is for $. We assume there is - at least one character after the $, i.e., `P < PEND'. */ - -static boolean -at_endline_loc_p (p, pend, syntax) - const char *p, *pend; - reg_syntax_t syntax; -{ - const char *next = p; - boolean next_backslash = *next == '\\'; - const char *next_next = p + 1 < pend ? p + 1 : 0; - - return - /* Before a subexpression? */ - (syntax & RE_NO_BK_PARENS ? *next == ')' - : next_backslash && next_next && *next_next == ')') - /* Before an alternative? */ - || (syntax & RE_NO_BK_VBAR ? *next == '|' - : next_backslash && next_next && *next_next == '|'); -} - - -/* Returns true if REGNUM is in one of COMPILE_STACK's elements and - false if it's not. */ - -static boolean -group_in_compile_stack (compile_stack, regnum) - compile_stack_type compile_stack; - regnum_t regnum; -{ - int this_element; - - for (this_element = compile_stack.avail - 1; - this_element >= 0; - this_element--) - if (compile_stack.stack[this_element].regnum == regnum) - return true; - - return false; -} - - -/* Read the ending character of a range (in a bracket expression) from the - uncompiled pattern *P_PTR (which ends at PEND). We assume the - starting character is in `P[-2]'. (`P[-1]' is the character `-'.) - Then we set the translation of all bits between the starting and - ending characters (inclusive) in the compiled pattern B. - - Return an error code. - - We use these short variable names so we can use the same macros as - `regex_compile' itself. */ - -static reg_errcode_t -compile_range (p_ptr, pend, translate, syntax, b) - const char **p_ptr, *pend; - RE_TRANSLATE_TYPE translate; - reg_syntax_t syntax; - unsigned char *b; -{ - unsigned this_char; - - const char *p = *p_ptr; - unsigned int range_start, range_end; - - if (p == pend) - return REG_ERANGE; - - /* Even though the pattern is a signed `char *', we need to fetch - with unsigned char *'s; if the high bit of the pattern character - is set, the range endpoints will be negative if we fetch using a - signed char *. - - We also want to fetch the endpoints without translating them; the - appropriate translation is done in the bit-setting loop below. */ - /* The SVR4 compiler on the 3B2 had trouble with unsigned const char *. */ - range_start = ((const unsigned char *) p)[-2]; - range_end = ((const unsigned char *) p)[0]; - - /* Have to increment the pointer into the pattern string, so the - caller isn't still at the ending character. */ - (*p_ptr)++; - - /* If the start is after the end, the range is empty. */ - if (range_start > range_end) - return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; - - /* Here we see why `this_char' has to be larger than an `unsigned - char' -- the range is inclusive, so if `range_end' == 0xff - (assuming 8-bit characters), we would otherwise go into an infinite - loop, since all characters <= 0xff. */ - for (this_char = range_start; this_char <= range_end; this_char++) - { - SET_LIST_BIT (TRANSLATE (this_char)); - } - - return REG_NOERROR; -} - -/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in - BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible - characters can start a string that matches the pattern. This fastmap - is used by re_search to skip quickly over impossible starting points. - - The caller must supply the address of a (1 << BYTEWIDTH)-byte data - area as BUFP->fastmap. - - We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in - the pattern buffer. - - Returns 0 if we succeed, -2 if an internal error. */ - -int -re_compile_fastmap (bufp) - struct re_pattern_buffer *bufp; -{ - int j, k; -#ifdef MATCH_MAY_ALLOCATE - fail_stack_type fail_stack; -#endif -#ifndef REGEX_MALLOC - char *destination; -#endif - /* We don't push any register information onto the failure stack. */ -//sword unsigned num_regs = 0; - - register char *fastmap = bufp->fastmap; - unsigned char *pattern = bufp->buffer; - unsigned char *p = pattern; - register unsigned char *pend = pattern + bufp->used; - -#ifdef REL_ALLOC - /* This holds the pointer to the failure stack, when - it is allocated relocatably. */ - fail_stack_elt_t *failure_stack_ptr; -#endif - - /* Assume that each path through the pattern can be null until - proven otherwise. We set this false at the bottom of switch - statement, to which we get only if a particular path doesn't - match the empty string. */ - boolean path_can_be_null = true; - - /* We aren't doing a `succeed_n' to begin with. */ - boolean succeed_n_p = false; - - assert (fastmap != NULL && p != NULL); - - INIT_FAIL_STACK (); - bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ - bufp->fastmap_accurate = 1; /* It will be when we're done. */ - bufp->can_be_null = 0; - - while (1) - { - if (p == pend || *p == succeed) - { - /* We have reached the (effective) end of pattern. */ - if (!FAIL_STACK_EMPTY ()) - { - bufp->can_be_null |= path_can_be_null; - - /* Reset for next path. */ - path_can_be_null = true; - - p = fail_stack.stack[--fail_stack.avail].pointer; - - continue; - } - else - break; - } - - /* We should never be about to go beyond the end of the pattern. */ - assert (p < pend); - - switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) - { - - /* I guess the idea here is to simply not bother with a fastmap - if a backreference is used, since it's too hard to figure out - the fastmap for the corresponding group. Setting - `can_be_null' stops `re_search_2' from using the fastmap, so - that is all we do. */ - case duplicate: - bufp->can_be_null = 1; - goto done; - - - /* Following are the cases which match a character. These end - with `break'. */ - - case exactn: - fastmap[p[1]] = 1; - break; - - - case charset: - for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) - if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) - fastmap[j] = 1; - break; - - - case charset_not: - /* Chars beyond end of map must be allowed. */ - for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) - fastmap[j] = 1; - - for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) - if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) - fastmap[j] = 1; - break; - - - case wordchar: - for (j = 0; j < (1 << BYTEWIDTH); j++) - if (SYNTAX (j) == Sword) - fastmap[j] = 1; - break; - - - case notwordchar: - for (j = 0; j < (1 << BYTEWIDTH); j++) - if (SYNTAX (j) != Sword) - fastmap[j] = 1; - break; - - - case anychar: - { - int fastmap_newline = fastmap['\n']; - - /* `.' matches anything ... */ - for (j = 0; j < (1 << BYTEWIDTH); j++) - fastmap[j] = 1; - - /* ... except perhaps newline. */ - if (!(bufp->syntax & RE_DOT_NEWLINE)) - fastmap['\n'] = fastmap_newline; - - /* Return if we have already set `can_be_null'; if we have, - then the fastmap is irrelevant. Something's wrong here. */ - else if (bufp->can_be_null) - goto done; - - /* Otherwise, have to check alternative paths. */ - break; - } - -#ifdef emacs - case syntaxspec: - k = *p++; - for (j = 0; j < (1 << BYTEWIDTH); j++) - if (SYNTAX (j) == (enum syntaxcode) k) - fastmap[j] = 1; - break; - - - case notsyntaxspec: - k = *p++; - for (j = 0; j < (1 << BYTEWIDTH); j++) - if (SYNTAX (j) != (enum syntaxcode) k) - fastmap[j] = 1; - break; - - - /* All cases after this match the empty string. These end with - `continue'. */ - - - case before_dot: - case at_dot: - case after_dot: - continue; -#endif /* emacs */ - - - case no_op: - case begline: - case endline: - case begbuf: - case endbuf: - case wordbound: - case notwordbound: - case wordbeg: - case wordend: - case push_dummy_failure: - continue; - - - case jump_n: - case pop_failure_jump: - case maybe_pop_jump: - case jump: - case jump_past_alt: - case dummy_failure_jump: - EXTRACT_NUMBER_AND_INCR (j, p); - p += j; - if (j > 0) - continue; - - /* Jump backward implies we just went through the body of a - loop and matched nothing. Opcode jumped to should be - `on_failure_jump' or `succeed_n'. Just treat it like an - ordinary jump. For a * loop, it has pushed its failure - point already; if so, discard that as redundant. */ - if ((re_opcode_t) *p != on_failure_jump - && (re_opcode_t) *p != succeed_n) - continue; - - p++; - EXTRACT_NUMBER_AND_INCR (j, p); - p += j; - - /* If what's on the stack is where we are now, pop it. */ - if (!FAIL_STACK_EMPTY () - && fail_stack.stack[fail_stack.avail - 1].pointer == p) - fail_stack.avail--; - - continue; - - - case on_failure_jump: - case on_failure_keep_string_jump: - handle_on_failure_jump: - EXTRACT_NUMBER_AND_INCR (j, p); - - /* For some patterns, e.g., `(a?)?', `p+j' here points to the - end of the pattern. We don't want to push such a point, - since when we restore it above, entering the switch will - increment `p' past the end of the pattern. We don't need - to push such a point since we obviously won't find any more - fastmap entries beyond `pend'. Such a pattern can match - the null string, though. */ - if (p + j < pend) - { - if (!PUSH_PATTERN_OP (p + j, fail_stack)) - { - RESET_FAIL_STACK (); - return -2; - } - } - else - bufp->can_be_null = 1; - - if (succeed_n_p) - { - EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ - succeed_n_p = false; - } - - continue; - - - case succeed_n: - /* Get to the number of times to succeed. */ - p += 2; - - /* Increment p past the n for when k != 0. */ - EXTRACT_NUMBER_AND_INCR (k, p); - if (k == 0) - { - p -= 4; - succeed_n_p = true; /* Spaghetti code alert. */ - goto handle_on_failure_jump; - } - continue; - - - case set_number_at: - p += 4; - continue; - - - case start_memory: - case stop_memory: - p += 2; - continue; - - - default: - abort (); /* We have listed all the cases. */ - } /* switch *p++ */ - - /* Getting here means we have found the possible starting - characters for one path of the pattern -- and that the empty - string does not match. We need not follow this path further. - Instead, look at the next alternative (remembered on the - stack), or quit if no more. The test at the top of the loop - does these things. */ - path_can_be_null = false; - p = pend; - } /* while p */ - - /* Set `can_be_null' for the last path (also the first path, if the - pattern is empty). */ - bufp->can_be_null |= path_can_be_null; - - done: - RESET_FAIL_STACK (); - return 0; -} /* re_compile_fastmap */ - -/* Set REGS to hold NUM_REGS registers, storing them in STARTS and - ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use - this memory for recording register information. STARTS and ENDS - must be allocated using the malloc library routine, and must each - be at least NUM_REGS * sizeof (regoff_t) bytes long. - - If NUM_REGS == 0, then subsequent matches should allocate their own - register data. - - Unless this function is called, the first search or match using - PATTERN_BUFFER will allocate its own register data, without - freeing the old data. */ - -void -re_set_registers (bufp, regs, num_regs, starts, ends) - struct re_pattern_buffer *bufp; - struct re_registers *regs; - unsigned num_regs; - regoff_t *starts, *ends; -{ - if (num_regs) - { - bufp->regs_allocated = REGS_REALLOCATE; - regs->num_regs = num_regs; - regs->start = starts; - regs->end = ends; - } - else - { - bufp->regs_allocated = REGS_UNALLOCATED; - regs->num_regs = 0; - regs->start = regs->end = (regoff_t *) 0; - } -} - -/* Searching routines. */ - -/* Like re_search_2, below, but only one string is specified, and - doesn't let you say where to stop matching. */ - -int -re_search (bufp, string, size, startpos, range, regs) - struct re_pattern_buffer *bufp; - const char *string; - int size, startpos, range; - struct re_registers *regs; -{ - return re_search_2 (bufp, NULL, 0, string, size, startpos, range, - regs, size); -} - - -/* Using the compiled pattern in BUFP->buffer, first tries to match the - virtual concatenation of STRING1 and STRING2, starting first at index - STARTPOS, then at STARTPOS + 1, and so on. - - STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. - - RANGE is how far to scan while trying to match. RANGE = 0 means try - only at STARTPOS; in general, the last start tried is STARTPOS + - RANGE. - - In REGS, return the indices of the virtual concatenation of STRING1 - and STRING2 that matched the entire BUFP->buffer and its contained - subexpressions. - - Do not consider matching one past the index STOP in the virtual - concatenation of STRING1 and STRING2. - - We return either the position in the strings at which the match was - found, -1 if no match, or -2 if error (such as failure - stack overflow). */ - -int -re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - int size1, size2; - int startpos; - int range; - struct re_registers *regs; - int stop; -{ - int val; - register char *fastmap = bufp->fastmap; - register RE_TRANSLATE_TYPE translate = bufp->translate; - int total_size = size1 + size2; - int endpos = startpos + range; - - /* Check for out-of-range STARTPOS. */ - if (startpos < 0 || startpos > total_size) - return -1; - - /* Fix up RANGE if it might eventually take us outside - the virtual concatenation of STRING1 and STRING2. - Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */ - if (endpos < 0) - range = 0 - startpos; - else if (endpos > total_size) - range = total_size - startpos; - - /* If the search isn't to be a backwards one, don't waste time in a - search for a pattern that must be anchored. */ - if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0) - { - if (startpos > 0) - return -1; - else - range = 1; - } - -#ifdef emacs - /* In a forward search for something that starts with \=. - don't keep searching past point. */ - if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0) - { - range = PT - startpos; - if (range <= 0) - return -1; - } -#endif /* emacs */ - - /* Update the fastmap now if not correct already. */ - if (fastmap && !bufp->fastmap_accurate) - if (re_compile_fastmap (bufp) == -2) - return -2; - - /* Loop through the string, looking for a place to start matching. */ - for (;;) - { - /* If a fastmap is supplied, skip quickly over characters that - cannot be the start of a match. If the pattern can match the - null string, however, we don't need to skip characters; we want - the first null string. */ - if (fastmap && startpos < total_size && !bufp->can_be_null) - { - if (range > 0) /* Searching forwards. */ - { - register const char *d; - register int lim = 0; - int irange = range; - - if (startpos < size1 && startpos + range >= size1) - lim = range - (size1 - startpos); - - d = (startpos >= size1 ? string2 - size1 : string1) + startpos; - - /* Written out as an if-else to avoid testing `translate' - inside the loop. */ - if (translate) - while (range > lim - && !fastmap[(unsigned char) - translate[(unsigned char) *d++]]) - range--; - else - while (range > lim && !fastmap[(unsigned char) *d++]) - range--; - - startpos += irange - range; - } - else /* Searching backwards. */ - { - register char c = (size1 == 0 || startpos >= size1 - ? string2[startpos - size1] - : string1[startpos]); - - if (!fastmap[(unsigned char) TRANSLATE (c)]) - goto advance; - } - } - - /* If can't match the null string, and that's all we have left, fail. */ - if (range >= 0 && startpos == total_size && fastmap - && !bufp->can_be_null) - return -1; - - val = re_match_2_internal (bufp, string1, size1, string2, size2, - startpos, regs, stop); -#ifndef REGEX_MALLOC -#ifdef C_ALLOCA - alloca (0); -#endif -#endif - - if (val >= 0) - return startpos; - - if (val == -2) - return -2; - - advance: - if (!range) - break; - else if (range > 0) - { - range--; - startpos++; - } - else - { - range++; - startpos--; - } - } - return -1; -} /* re_search_2 */ - -/* This converts PTR, a pointer into one of the search strings `string1' - and `string2' into an offset from the beginning of that string. */ -#define POINTER_TO_OFFSET(ptr) \ - (FIRST_STRING_P (ptr) \ - ? ((regoff_t) ((ptr) - string1)) \ - : ((regoff_t) ((ptr) - string2 + size1))) - -/* Macros for dealing with the split strings in re_match_2. */ - -#define MATCHING_IN_FIRST_STRING (dend == end_match_1) - -/* Call before fetching a character with *d. This switches over to - string2 if necessary. */ -#define PREFETCH() \ - while (d == dend) \ - { \ - /* End of string2 => fail. */ \ - if (dend == end_match_2) \ - goto fail; \ - /* End of string1 => advance to string2. */ \ - d = string2; \ - dend = end_match_2; \ - } - - -/* Test if at very beginning or at very end of the virtual concatenation - of `string1' and `string2'. If only one string, it's `string2'. */ -#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) -#define AT_STRINGS_END(d) ((d) == end2) - - -/* Test if D points to a character which is word-constituent. We have - two special cases to check for: if past the end of string1, look at - the first character in string2; and if before the beginning of - string2, look at the last character in string1. */ -#define WORDCHAR_P(d) \ - (SYNTAX ((d) == end1 ? *string2 \ - : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ - == Sword) - -/* Disabled due to a compiler bug -- see comment at case wordbound */ -#if 0 -/* Test if the character before D and the one at D differ with respect - to being word-constituent. */ -#define AT_WORD_BOUNDARY(d) \ - (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ - || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) -#endif - -/* Free everything we malloc. */ -#ifdef MATCH_MAY_ALLOCATE -#define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL -#define FREE_VARIABLES() \ - do { \ - REGEX_FREE_STACK (fail_stack.stack); \ - FREE_VAR (regstart); \ - FREE_VAR (regend); \ - FREE_VAR (old_regstart); \ - FREE_VAR (old_regend); \ - FREE_VAR (best_regstart); \ - FREE_VAR (best_regend); \ - FREE_VAR (reg_info); \ - FREE_VAR (reg_dummy); \ - FREE_VAR (reg_info_dummy); \ - } while (0) -#else -#define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ -#endif /* not MATCH_MAY_ALLOCATE */ - -/* These values must meet several constraints. They must not be valid - register values; since we have a limit of 255 registers (because - we use only one byte in the pattern for the register number), we can - use numbers larger than 255. They must differ by 1, because of - NUM_FAILURE_ITEMS above. And the value for the lowest register must - be larger than the value for the highest register, so we do not try - to actually save any registers when none are active. */ -#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) -#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) - -/* Matching routines. */ - -#ifndef emacs /* Emacs never uses this. */ -/* re_match is like re_match_2 except it takes only a single string. */ - -int -re_match (bufp, string, size, pos, regs) - struct re_pattern_buffer *bufp; - const char *string; - int size, pos; - struct re_registers *regs; -{ - int result = re_match_2_internal (bufp, NULL, 0, string, size, - pos, regs, size); -#ifndef REGEX_MALLOC -#ifdef C_ALLOCA - alloca (0); -#endif -#endif - return result; -} -#endif /* not emacs */ - -static boolean group_match_null_string_p _RE_ARGS ((unsigned char **p, - unsigned char *end, - register_info_type *reg_info)); -static boolean alt_match_null_string_p _RE_ARGS ((unsigned char *p, - unsigned char *end, - register_info_type *reg_info)); -static boolean common_op_match_null_string_p _RE_ARGS ((unsigned char **p, - unsigned char *end, - register_info_type *reg_info)); -static int bcmp_translate _RE_ARGS ((const char *s1, const char *s2, - int len, char *translate)); - -/* re_match_2 matches the compiled pattern in BUFP against the - the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 - and SIZE2, respectively). We start matching at POS, and stop - matching at STOP. - - If REGS is non-null and the `no_sub' field of BUFP is nonzero, we - store offsets for the substring each group matched in REGS. See the - documentation for exactly how many groups we fill. - - We return -1 if no match, -2 if an internal error (such as the - failure stack overflowing). Otherwise, we return the length of the - matched substring. */ - -int -re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - int size1, size2; - int pos; - struct re_registers *regs; - int stop; -{ - int result = re_match_2_internal (bufp, string1, size1, string2, size2, - pos, regs, stop); -#ifndef REGEX_MALLOC -#ifdef C_ALLOCA - alloca (0); -#endif -#endif - return result; -} - -/* This is a separate function so that we can force an alloca cleanup - afterwards. */ -static int -re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - int size1, size2; - int pos; - struct re_registers *regs; - int stop; -{ - /* General temporaries. */ - int mcnt; - unsigned char *p1; - - /* Just past the end of the corresponding string. */ - const char *end1, *end2; - - /* Pointers into string1 and string2, just past the last characters in - each to consider matching. */ - const char *end_match_1, *end_match_2; - - /* Where we are in the data, and the end of the current string. */ - const char *d, *dend; - - /* Where we are in the pattern, and the end of the pattern. */ - unsigned char *p = bufp->buffer; - register unsigned char *pend = p + bufp->used; - - /* Mark the opcode just after a start_memory, so we can test for an - empty subpattern when we get to the stop_memory. */ - unsigned char *just_past_start_mem = 0; - - /* We use this to map every character in the string. */ - RE_TRANSLATE_TYPE translate = bufp->translate; - - /* Failure point stack. Each place that can handle a failure further - down the line pushes a failure point on this stack. It consists of - restart, regend, and reg_info for all registers corresponding to - the subexpressions we're currently inside, plus the number of such - registers, and, finally, two char *'s. The first char * is where - to resume scanning the pattern; the second one is where to resume - scanning the strings. If the latter is zero, the failure point is - a ``dummy''; if a failure happens and the failure point is a dummy, - it gets discarded and the next next one is tried. */ -#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ - fail_stack_type fail_stack; -#endif -#ifdef DEBUG - static unsigned failure_id = 0; - unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; -#endif - -#ifdef REL_ALLOC - /* This holds the pointer to the failure stack, when - it is allocated relocatably. */ - fail_stack_elt_t *failure_stack_ptr; -#endif - - /* We fill all the registers internally, independent of what we - return, for use in backreferences. The number here includes - an element for register zero. */ - size_t num_regs = bufp->re_nsub + 1; - - /* The currently active registers. */ - active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG; - active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG; - - /* Information on the contents of registers. These are pointers into - the input strings; they record just what was matched (on this - attempt) by a subexpression part of the pattern, that is, the - regnum-th regstart pointer points to where in the pattern we began - matching and the regnum-th regend points to right after where we - stopped matching the regnum-th subexpression. (The zeroth register - keeps track of what the whole pattern matches.) */ -#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ - const char **regstart, **regend; -#endif - - /* If a group that's operated upon by a repetition operator fails to - match anything, then the register for its start will need to be - restored because it will have been set to wherever in the string we - are when we last see its open-group operator. Similarly for a - register's end. */ -#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ - const char **old_regstart, **old_regend; -#endif - - /* The is_active field of reg_info helps us keep track of which (possibly - nested) subexpressions we are currently in. The matched_something - field of reg_info[reg_num] helps us tell whether or not we have - matched any of the pattern so far this time through the reg_num-th - subexpression. These two fields get reset each time through any - loop their register is in. */ -#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ - register_info_type *reg_info; -#endif - - /* The following record the register info as found in the above - variables when we find a match better than any we've seen before. - This happens as we backtrack through the failure points, which in - turn happens only if we have not yet matched the entire string. */ - unsigned best_regs_set = false; -#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ - const char **best_regstart, **best_regend; -#endif - - /* Logically, this is `best_regend[0]'. But we don't want to have to - allocate space for that if we're not allocating space for anything - else (see below). Also, we never need info about register 0 for - any of the other register vectors, and it seems rather a kludge to - treat `best_regend' differently than the rest. So we keep track of - the end of the best match so far in a separate variable. We - initialize this to NULL so that when we backtrack the first time - and need to test it, it's not garbage. */ - const char *match_end = NULL; - - /* This helps SET_REGS_MATCHED avoid doing redundant work. */ - int set_regs_matched_done = 0; - - /* Used when we pop values we don't care about. */ -#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ - const char **reg_dummy; - register_info_type *reg_info_dummy; -#endif - -#ifdef DEBUG - /* Counts the total number of registers pushed. */ - unsigned num_regs_pushed = 0; -#endif - - DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); - - INIT_FAIL_STACK (); - -#ifdef MATCH_MAY_ALLOCATE - /* Do not bother to initialize all the register variables if there are - no groups in the pattern, as it takes a fair amount of time. If - there are groups, we include space for register 0 (the whole - pattern), even though we never use it, since it simplifies the - array indexing. We should fix this. */ - if (bufp->re_nsub) - { - regstart = REGEX_TALLOC (num_regs, const char *); - regend = REGEX_TALLOC (num_regs, const char *); - old_regstart = REGEX_TALLOC (num_regs, const char *); - old_regend = REGEX_TALLOC (num_regs, const char *); - best_regstart = REGEX_TALLOC (num_regs, const char *); - best_regend = REGEX_TALLOC (num_regs, const char *); - reg_info = REGEX_TALLOC (num_regs, register_info_type); - reg_dummy = REGEX_TALLOC (num_regs, const char *); - reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type); - - if (!(regstart && regend && old_regstart && old_regend && reg_info - && best_regstart && best_regend && reg_dummy && reg_info_dummy)) - { - FREE_VARIABLES (); - return -2; - } - } - else - { - /* We must initialize all our variables to NULL, so that - `FREE_VARIABLES' doesn't try to free them. */ - regstart = regend = old_regstart = old_regend = best_regstart - = best_regend = reg_dummy = NULL; - reg_info = reg_info_dummy = (register_info_type *) NULL; - } -#endif /* MATCH_MAY_ALLOCATE */ - - /* The starting position is bogus. */ - if (pos < 0 || pos > size1 + size2) - { - FREE_VARIABLES (); - return -1; - } - - /* Initialize subexpression text positions to -1 to mark ones that no - start_memory/stop_memory has been seen for. Also initialize the - register information struct. */ - for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) - { - regstart[mcnt] = regend[mcnt] - = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; - - REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; - IS_ACTIVE (reg_info[mcnt]) = 0; - MATCHED_SOMETHING (reg_info[mcnt]) = 0; - EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; - } - - /* We move `string1' into `string2' if the latter's empty -- but not if - `string1' is null. */ - if (size2 == 0 && string1 != NULL) - { - string2 = string1; - size2 = size1; - string1 = 0; - size1 = 0; - } - end1 = string1 + size1; - end2 = string2 + size2; - - /* Compute where to stop matching, within the two strings. */ - if (stop <= size1) - { - end_match_1 = string1 + stop; - end_match_2 = string2; - } - else - { - end_match_1 = end1; - end_match_2 = string2 + stop - size1; - } - - /* `p' scans through the pattern as `d' scans through the data. - `dend' is the end of the input string that `d' points within. `d' - is advanced into the following input string whenever necessary, but - this happens before fetching; therefore, at the beginning of the - loop, `d' can be pointing at the end of a string, but it cannot - equal `string2'. */ - if (size1 > 0 && pos <= size1) - { - d = string1 + pos; - dend = end_match_1; - } - else - { - d = string2 + pos - size1; - dend = end_match_2; - } - - DEBUG_PRINT1 ("The compiled pattern is:\n"); - DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); - DEBUG_PRINT1 ("The string to match is: `"); - DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); - DEBUG_PRINT1 ("'\n"); - - /* This loops over pattern commands. It exits by returning from the - function if the match is complete, or it drops through if the match - fails at this starting point in the input data. */ - for (;;) - { -#ifdef _LIBC - DEBUG_PRINT2 ("\n%p: ", p); -#else - DEBUG_PRINT2 ("\n0x%x: ", p); -#endif - - if (p == pend) - { /* End of pattern means we might have succeeded. */ - DEBUG_PRINT1 ("end of pattern ... "); - - /* If we haven't matched the entire string, and we want the - longest match, try backtracking. */ - if (d != end_match_2) - { - /* 1 if this match ends in the same string (string1 or string2) - as the best previous match. */ - boolean same_str_p = (FIRST_STRING_P (match_end) - == MATCHING_IN_FIRST_STRING); - /* 1 if this match is the best seen so far. */ - boolean best_match_p; - - /* AIX compiler got confused when this was combined - with the previous declaration. */ - if (same_str_p) - best_match_p = d > match_end; - else - best_match_p = !MATCHING_IN_FIRST_STRING; - - DEBUG_PRINT1 ("backtracking.\n"); - - if (!FAIL_STACK_EMPTY ()) - { /* More failure points to try. */ - - /* If exceeds best match so far, save it. */ - if (!best_regs_set || best_match_p) - { - best_regs_set = true; - match_end = d; - - DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); - - for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) - { - best_regstart[mcnt] = regstart[mcnt]; - best_regend[mcnt] = regend[mcnt]; - } - } - goto fail; - } - - /* If no failure points, don't restore garbage. And if - last match is real best match, don't restore second - best one. */ - else if (best_regs_set && !best_match_p) - { - restore_best_regs: - /* Restore best match. It may happen that `dend == - end_match_1' while the restored d is in string2. - For example, the pattern `x.*y.*z' against the - strings `x-' and `y-z-', if the two strings are - not consecutive in memory. */ - DEBUG_PRINT1 ("Restoring best registers.\n"); - - d = match_end; - dend = ((d >= string1 && d <= end1) - ? end_match_1 : end_match_2); - - for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) - { - regstart[mcnt] = best_regstart[mcnt]; - regend[mcnt] = best_regend[mcnt]; - } - } - } /* d != end_match_2 */ - - succeed_label: - DEBUG_PRINT1 ("Accepting match.\n"); - - /* If caller wants register contents data back, do it. */ - if (regs && !bufp->no_sub) - { - /* Have the register data arrays been allocated? */ - if (bufp->regs_allocated == REGS_UNALLOCATED) - { /* No. So allocate them with malloc. We need one - extra element beyond `num_regs' for the `-1' marker - GNU code uses. */ - regs->num_regs = MAX (RE_NREGS, num_regs + 1); - regs->start = TALLOC (regs->num_regs, regoff_t); - regs->end = TALLOC (regs->num_regs, regoff_t); - if (regs->start == NULL || regs->end == NULL) - { - FREE_VARIABLES (); - return -2; - } - bufp->regs_allocated = REGS_REALLOCATE; - } - else if (bufp->regs_allocated == REGS_REALLOCATE) - { /* Yes. If we need more elements than were already - allocated, reallocate them. If we need fewer, just - leave it alone. */ - if (regs->num_regs < num_regs + 1) - { - regs->num_regs = num_regs + 1; - RETALLOC (regs->start, regs->num_regs, regoff_t); - RETALLOC (regs->end, regs->num_regs, regoff_t); - if (regs->start == NULL || regs->end == NULL) - { - FREE_VARIABLES (); - return -2; - } - } - } - else - { - /* These braces fend off a "empty body in an else-statement" - warning under GCC when assert expands to nothing. */ - assert (bufp->regs_allocated == REGS_FIXED); - } - - /* Convert the pointer data in `regstart' and `regend' to - indices. Register zero has to be set differently, - since we haven't kept track of any info for it. */ - if (regs->num_regs > 0) - { - regs->start[0] = pos; - regs->end[0] = (MATCHING_IN_FIRST_STRING - ? ((regoff_t) (d - string1)) - : ((regoff_t) (d - string2 + size1))); - } - - /* Go through the first `min (num_regs, regs->num_regs)' - registers, since that is all we initialized. */ - for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs); - mcnt++) - { - if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) - regs->start[mcnt] = regs->end[mcnt] = -1; - else - { - regs->start[mcnt] - = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); - regs->end[mcnt] - = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); - } - } - - /* If the regs structure we return has more elements than - were in the pattern, set the extra elements to -1. If - we (re)allocated the registers, this is the case, - because we always allocate enough to have at least one - -1 at the end. */ - for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++) - regs->start[mcnt] = regs->end[mcnt] = -1; - } /* regs && !bufp->no_sub */ - - DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", - nfailure_points_pushed, nfailure_points_popped, - nfailure_points_pushed - nfailure_points_popped); - DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); - - mcnt = d - pos - (MATCHING_IN_FIRST_STRING - ? string1 - : string2 - size1); - - DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); - - FREE_VARIABLES (); - return mcnt; - } - - /* Otherwise match next pattern command. */ - switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) - { - /* Ignore these. Used to ignore the n of succeed_n's which - currently have n == 0. */ - case no_op: - DEBUG_PRINT1 ("EXECUTING no_op.\n"); - break; - - case succeed: - DEBUG_PRINT1 ("EXECUTING succeed.\n"); - goto succeed_label; - - /* Match the next n pattern characters exactly. The following - byte in the pattern defines n, and the n bytes after that - are the characters to match. */ - case exactn: - mcnt = *p++; - DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); - - /* This is written out as an if-else so we don't waste time - testing `translate' inside the loop. */ - if (translate) - { - do - { - PREFETCH (); - if ((unsigned char) translate[(unsigned char) *d++] - != (unsigned char) *p++) - goto fail; - } - while (--mcnt); - } - else - { - do - { - PREFETCH (); - if (*d++ != (char) *p++) goto fail; - } - while (--mcnt); - } - SET_REGS_MATCHED (); - break; - - - /* Match any character except possibly a newline or a null. */ - case anychar: - DEBUG_PRINT1 ("EXECUTING anychar.\n"); - - PREFETCH (); - - if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') - || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) - goto fail; - - SET_REGS_MATCHED (); - DEBUG_PRINT2 (" Matched `%d'.\n", *d); - d++; - break; - - - case charset: - case charset_not: - { - register unsigned char c; - boolean not = (re_opcode_t) *(p - 1) == charset_not; - - DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); - - PREFETCH (); - c = TRANSLATE (*d); /* The character to match. */ - - /* Cast to `unsigned' instead of `unsigned char' in case the - bit list is a full 32 bytes long. */ - if (c < (unsigned) (*p * BYTEWIDTH) - && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) - not = !not; - - p += 1 + *p; - - if (!not) goto fail; - - SET_REGS_MATCHED (); - d++; - break; - } - - - /* The beginning of a group is represented by start_memory. - The arguments are the register number in the next byte, and the - number of groups inner to this one in the next. The text - matched within the group is recorded (in the internal - registers data structure) under the register number. */ - case start_memory: - DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]); - - /* Find out if this group can match the empty string. */ - p1 = p; /* To send to group_match_null_string_p. */ - - if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) - REG_MATCH_NULL_STRING_P (reg_info[*p]) - = group_match_null_string_p (&p1, pend, reg_info); - - /* Save the position in the string where we were the last time - we were at this open-group operator in case the group is - operated upon by a repetition operator, e.g., with `(a*)*b' - against `ab'; then we want to ignore where we are now in - the string in case this attempt to match fails. */ - old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) - ? REG_UNSET (regstart[*p]) ? d : regstart[*p] - : regstart[*p]; - DEBUG_PRINT2 (" old_regstart: %d\n", - POINTER_TO_OFFSET (old_regstart[*p])); - - regstart[*p] = d; - DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); - - IS_ACTIVE (reg_info[*p]) = 1; - MATCHED_SOMETHING (reg_info[*p]) = 0; - - /* Clear this whenever we change the register activity status. */ - set_regs_matched_done = 0; - - /* This is the new highest active register. */ - highest_active_reg = *p; - - /* If nothing was active before, this is the new lowest active - register. */ - if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) - lowest_active_reg = *p; - - /* Move past the register number and inner group count. */ - p += 2; - just_past_start_mem = p; - - break; - - - /* The stop_memory opcode represents the end of a group. Its - arguments are the same as start_memory's: the register - number, and the number of inner groups. */ - case stop_memory: - DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]); - - /* We need to save the string position the last time we were at - this close-group operator in case the group is operated - upon by a repetition operator, e.g., with `((a*)*(b*)*)*' - against `aba'; then we want to ignore where we are now in - the string in case this attempt to match fails. */ - old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) - ? REG_UNSET (regend[*p]) ? d : regend[*p] - : regend[*p]; - DEBUG_PRINT2 (" old_regend: %d\n", - POINTER_TO_OFFSET (old_regend[*p])); - - regend[*p] = d; - DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); - - /* This register isn't active anymore. */ - IS_ACTIVE (reg_info[*p]) = 0; - - /* Clear this whenever we change the register activity status. */ - set_regs_matched_done = 0; - - /* If this was the only register active, nothing is active - anymore. */ - if (lowest_active_reg == highest_active_reg) - { - lowest_active_reg = NO_LOWEST_ACTIVE_REG; - highest_active_reg = NO_HIGHEST_ACTIVE_REG; - } - else - { /* We must scan for the new highest active register, since - it isn't necessarily one less than now: consider - (a(b)c(d(e)f)g). When group 3 ends, after the f), the - new highest active register is 1. */ - unsigned char r = *p - 1; - while (r > 0 && !IS_ACTIVE (reg_info[r])) - r--; - - /* If we end up at register zero, that means that we saved - the registers as the result of an `on_failure_jump', not - a `start_memory', and we jumped to past the innermost - `stop_memory'. For example, in ((.)*) we save - registers 1 and 2 as a result of the *, but when we pop - back to the second ), we are at the stop_memory 1. - Thus, nothing is active. */ - if (r == 0) - { - lowest_active_reg = NO_LOWEST_ACTIVE_REG; - highest_active_reg = NO_HIGHEST_ACTIVE_REG; - } - else - highest_active_reg = r; - } - - /* If just failed to match something this time around with a - group that's operated on by a repetition operator, try to - force exit from the ``loop'', and restore the register - information for this group that we had before trying this - last match. */ - if ((!MATCHED_SOMETHING (reg_info[*p]) - || just_past_start_mem == p - 1) - && (p + 2) < pend) - { - boolean is_a_jump_n = false; - - p1 = p + 2; - mcnt = 0; - switch ((re_opcode_t) *p1++) - { - case jump_n: - is_a_jump_n = true; - case pop_failure_jump: - case maybe_pop_jump: - case jump: - case dummy_failure_jump: - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - if (is_a_jump_n) - p1 += 2; - break; - - default: - /* do nothing */ ; - } - p1 += mcnt; - - /* If the next operation is a jump backwards in the pattern - to an on_failure_jump right before the start_memory - corresponding to this stop_memory, exit from the loop - by forcing a failure after pushing on the stack the - on_failure_jump's jump in the pattern, and d. */ - if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump - && (re_opcode_t) p1[3] == start_memory && p1[4] == *p) - { - /* If this group ever matched anything, then restore - what its registers were before trying this last - failed match, e.g., with `(a*)*b' against `ab' for - regstart[1], and, e.g., with `((a*)*(b*)*)*' - against `aba' for regend[3]. - - Also restore the registers for inner groups for, - e.g., `((a*)(b*))*' against `aba' (register 3 would - otherwise get trashed). */ - - if (EVER_MATCHED_SOMETHING (reg_info[*p])) - { - unsigned r; - - EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; - - /* Restore this and inner groups' (if any) registers. */ - for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1); - r++) - { - regstart[r] = old_regstart[r]; - - /* xx why this test? */ - if (old_regend[r] >= regstart[r]) - regend[r] = old_regend[r]; - } - } - p1++; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - PUSH_FAILURE_POINT (p1 + mcnt, d, -2); - - goto fail; - } - } - - /* Move past the register number and the inner group count. */ - p += 2; - break; - - - /* \<digit> has been turned into a `duplicate' command which is - followed by the numeric value of <digit> as the register number. */ - case duplicate: - { - register const char *d2, *dend2; - int regno = *p++; /* Get which register to match against. */ - DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); - - /* Can't back reference a group which we've never matched. */ - if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) - goto fail; - - /* Where in input to try to start matching. */ - d2 = regstart[regno]; - - /* Where to stop matching; if both the place to start and - the place to stop matching are in the same string, then - set to the place to stop, otherwise, for now have to use - the end of the first string. */ - - dend2 = ((FIRST_STRING_P (regstart[regno]) - == FIRST_STRING_P (regend[regno])) - ? regend[regno] : end_match_1); - for (;;) - { - /* If necessary, advance to next segment in register - contents. */ - while (d2 == dend2) - { - if (dend2 == end_match_2) break; - if (dend2 == regend[regno]) break; - - /* End of string1 => advance to string2. */ - d2 = string2; - dend2 = regend[regno]; - } - /* At end of register contents => success */ - if (d2 == dend2) break; - - /* If necessary, advance to next segment in data. */ - PREFETCH (); - - /* How many characters left in this segment to match. */ - mcnt = dend - d; - - /* Want how many consecutive characters we can match in - one shot, so, if necessary, adjust the count. */ - if (mcnt > dend2 - d2) - mcnt = dend2 - d2; - - /* Compare that many; failure if mismatch, else move - past them. */ - if (translate - ? bcmp_translate (d, d2, mcnt, translate) - : bcmp (d, d2, mcnt)) - goto fail; - d += mcnt, d2 += mcnt; - - /* Do this because we've match some characters. */ - SET_REGS_MATCHED (); - } - } - break; - - - /* begline matches the empty string at the beginning of the string - (unless `not_bol' is set in `bufp'), and, if - `newline_anchor' is set, after newlines. */ - case begline: - DEBUG_PRINT1 ("EXECUTING begline.\n"); - - if (AT_STRINGS_BEG (d)) - { - if (!bufp->not_bol) break; - } - else if (d[-1] == '\n' && bufp->newline_anchor) - { - break; - } - /* In all other cases, we fail. */ - goto fail; - - - /* endline is the dual of begline. */ - case endline: - DEBUG_PRINT1 ("EXECUTING endline.\n"); - - if (AT_STRINGS_END (d)) - { - if (!bufp->not_eol) break; - } - - /* We have to ``prefetch'' the next character. */ - else if ((d == end1 ? *string2 : *d) == '\n' - && bufp->newline_anchor) - { - break; - } - goto fail; - - - /* Match at the very beginning of the data. */ - case begbuf: - DEBUG_PRINT1 ("EXECUTING begbuf.\n"); - if (AT_STRINGS_BEG (d)) - break; - goto fail; - - - /* Match at the very end of the data. */ - case endbuf: - DEBUG_PRINT1 ("EXECUTING endbuf.\n"); - if (AT_STRINGS_END (d)) - break; - goto fail; - - - /* on_failure_keep_string_jump is used to optimize `.*\n'. It - pushes NULL as the value for the string on the stack. Then - `pop_failure_point' will keep the current value for the - string, instead of restoring it. To see why, consider - matching `foo\nbar' against `.*\n'. The .* matches the foo; - then the . fails against the \n. But the next thing we want - to do is match the \n against the \n; if we restored the - string value, we would be back at the foo. - - Because this is used only in specific cases, we don't need to - check all the things that `on_failure_jump' does, to make - sure the right things get saved on the stack. Hence we don't - share its code. The only reason to push anything on the - stack at all is that otherwise we would have to change - `anychar's code to do something besides goto fail in this - case; that seems worse than this. */ - case on_failure_keep_string_jump: - DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); - - EXTRACT_NUMBER_AND_INCR (mcnt, p); -#ifdef _LIBC - DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt); -#else - DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); -#endif - - PUSH_FAILURE_POINT (p + mcnt, NULL, -2); - break; - - - /* Uses of on_failure_jump: - - Each alternative starts with an on_failure_jump that points - to the beginning of the next alternative. Each alternative - except the last ends with a jump that in effect jumps past - the rest of the alternatives. (They really jump to the - ending jump of the following alternative, because tensioning - these jumps is a hassle.) - - Repeats start with an on_failure_jump that points past both - the repetition text and either the following jump or - pop_failure_jump back to this on_failure_jump. */ - case on_failure_jump: - on_failure: - DEBUG_PRINT1 ("EXECUTING on_failure_jump"); - - EXTRACT_NUMBER_AND_INCR (mcnt, p); -#ifdef _LIBC - DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt); -#else - DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); -#endif - - /* If this on_failure_jump comes right before a group (i.e., - the original * applied to a group), save the information - for that group and all inner ones, so that if we fail back - to this point, the group's information will be correct. - For example, in \(a*\)*\1, we need the preceding group, - and in \(zz\(a*\)b*\)\2, we need the inner group. */ - - /* We can't use `p' to check ahead because we push - a failure point to `p + mcnt' after we do this. */ - p1 = p; - - /* We need to skip no_op's before we look for the - start_memory in case this on_failure_jump is happening as - the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 - against aba. */ - while (p1 < pend && (re_opcode_t) *p1 == no_op) - p1++; - - if (p1 < pend && (re_opcode_t) *p1 == start_memory) - { - /* We have a new highest active register now. This will - get reset at the start_memory we are about to get to, - but we will have saved all the registers relevant to - this repetition op, as described above. */ - highest_active_reg = *(p1 + 1) + *(p1 + 2); - if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) - lowest_active_reg = *(p1 + 1); - } - - DEBUG_PRINT1 (":\n"); - PUSH_FAILURE_POINT (p + mcnt, d, -2); - break; - - - /* A smart repeat ends with `maybe_pop_jump'. - We change it to either `pop_failure_jump' or `jump'. */ - case maybe_pop_jump: - EXTRACT_NUMBER_AND_INCR (mcnt, p); - DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); - { - register unsigned char *p2 = p; - - /* Compare the beginning of the repeat with what in the - pattern follows its end. If we can establish that there - is nothing that they would both match, i.e., that we - would have to backtrack because of (as in, e.g., `a*a') - then we can change to pop_failure_jump, because we'll - never have to backtrack. - - This is not true in the case of alternatives: in - `(a|ab)*' we do need to backtrack to the `ab' alternative - (e.g., if the string was `ab'). But instead of trying to - detect that here, the alternative has put on a dummy - failure point which is what we will end up popping. */ - - /* Skip over open/close-group commands. - If what follows this loop is a ...+ construct, - look at what begins its body, since we will have to - match at least one of that. */ - while (1) - { - if (p2 + 2 < pend - && ((re_opcode_t) *p2 == stop_memory - || (re_opcode_t) *p2 == start_memory)) - p2 += 3; - else if (p2 + 6 < pend - && (re_opcode_t) *p2 == dummy_failure_jump) - p2 += 6; - else - break; - } - - p1 = p + mcnt; - /* p1[0] ... p1[2] are the `on_failure_jump' corresponding - to the `maybe_finalize_jump' of this case. Examine what - follows. */ - - /* If we're at the end of the pattern, we can change. */ - if (p2 == pend) - { - /* Consider what happens when matching ":\(.*\)" - against ":/". I don't really understand this code - yet. */ - p[-3] = (unsigned char) pop_failure_jump; - DEBUG_PRINT1 - (" End of pattern: change to `pop_failure_jump'.\n"); - } - - else if ((re_opcode_t) *p2 == exactn - || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) - { - register unsigned char c - = *p2 == (unsigned char) endline ? '\n' : p2[2]; - - if ((re_opcode_t) p1[3] == exactn && p1[5] != c) - { - p[-3] = (unsigned char) pop_failure_jump; - DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", - c, p1[5]); - } - - else if ((re_opcode_t) p1[3] == charset - || (re_opcode_t) p1[3] == charset_not) - { - int not = (re_opcode_t) p1[3] == charset_not; - - if (c < (unsigned char) (p1[4] * BYTEWIDTH) - && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) - not = !not; - - /* `not' is equal to 1 if c would match, which means - that we can't change to pop_failure_jump. */ - if (!not) - { - p[-3] = (unsigned char) pop_failure_jump; - DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); - } - } - } - else if ((re_opcode_t) *p2 == charset) - { -#ifdef DEBUG - register unsigned char c - = *p2 == (unsigned char) endline ? '\n' : p2[2]; -#endif - -#if 0 - if ((re_opcode_t) p1[3] == exactn - && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5] - && (p2[2 + p1[5] / BYTEWIDTH] - & (1 << (p1[5] % BYTEWIDTH))))) -#else - if ((re_opcode_t) p1[3] == exactn - && ! ((int) p2[1] * BYTEWIDTH > (int) p1[4] - && (p2[2 + p1[4] / BYTEWIDTH] - & (1 << (p1[4] % BYTEWIDTH))))) -#endif - { - p[-3] = (unsigned char) pop_failure_jump; - DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", - c, p1[5]); - } - - else if ((re_opcode_t) p1[3] == charset_not) - { - int idx; - /* We win if the charset_not inside the loop - lists every character listed in the charset after. */ - for (idx = 0; idx < (int) p2[1]; idx++) - if (! (p2[2 + idx] == 0 - || (idx < (int) p1[4] - && ((p2[2 + idx] & ~ p1[5 + idx]) == 0)))) - break; - - if (idx == p2[1]) - { - p[-3] = (unsigned char) pop_failure_jump; - DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); - } - } - else if ((re_opcode_t) p1[3] == charset) - { - int idx; - /* We win if the charset inside the loop - has no overlap with the one after the loop. */ - for (idx = 0; - idx < (int) p2[1] && idx < (int) p1[4]; - idx++) - if ((p2[2 + idx] & p1[5 + idx]) != 0) - break; - - if (idx == p2[1] || idx == p1[4]) - { - p[-3] = (unsigned char) pop_failure_jump; - DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); - } - } - } - } - p -= 2; /* Point at relative address again. */ - if ((re_opcode_t) p[-1] != pop_failure_jump) - { - p[-1] = (unsigned char) jump; - DEBUG_PRINT1 (" Match => jump.\n"); - goto unconditional_jump; - } - /* Note fall through. */ - - - /* The end of a simple repeat has a pop_failure_jump back to - its matching on_failure_jump, where the latter will push a - failure point. The pop_failure_jump takes off failure - points put on by this pop_failure_jump's matching - on_failure_jump; we got through the pattern to here from the - matching on_failure_jump, so didn't fail. */ - case pop_failure_jump: - { - /* We need to pass separate storage for the lowest and - highest registers, even though we don't care about the - actual values. Otherwise, we will restore only one - register from the stack, since lowest will == highest in - `pop_failure_point'. */ - active_reg_t dummy_low_reg, dummy_high_reg; - unsigned char *pdummy; - const char *sdummy; - - DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); - POP_FAILURE_POINT (sdummy, pdummy, - dummy_low_reg, dummy_high_reg, - reg_dummy, reg_dummy, reg_info_dummy); - } - /* Note fall through. */ - - unconditional_jump: -#ifdef _LIBC - DEBUG_PRINT2 ("\n%p: ", p); -#else - DEBUG_PRINT2 ("\n0x%x: ", p); -#endif - /* Note fall through. */ - - /* Unconditionally jump (without popping any failure points). */ - case jump: - EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ - DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); - p += mcnt; /* Do the jump. */ -#ifdef _LIBC - DEBUG_PRINT2 ("(to %p).\n", p); -#else - DEBUG_PRINT2 ("(to 0x%x).\n", p); -#endif - break; - - - /* We need this opcode so we can detect where alternatives end - in `group_match_null_string_p' et al. */ - case jump_past_alt: - DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); - goto unconditional_jump; - - - /* Normally, the on_failure_jump pushes a failure point, which - then gets popped at pop_failure_jump. We will end up at - pop_failure_jump, also, and with a pattern of, say, `a+', we - are skipping over the on_failure_jump, so we have to push - something meaningless for pop_failure_jump to pop. */ - case dummy_failure_jump: - DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); - /* It doesn't matter what we push for the string here. What - the code at `fail' tests is the value for the pattern. */ - PUSH_FAILURE_POINT (0, 0, -2); - goto unconditional_jump; - - - /* At the end of an alternative, we need to push a dummy failure - point in case we are followed by a `pop_failure_jump', because - we don't want the failure point for the alternative to be - popped. For example, matching `(a|ab)*' against `aab' - requires that we match the `ab' alternative. */ - case push_dummy_failure: - DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); - /* See comments just above at `dummy_failure_jump' about the - two zeroes. */ - PUSH_FAILURE_POINT (0, 0, -2); - break; - - /* Have to succeed matching what follows at least n times. - After that, handle like `on_failure_jump'. */ - case succeed_n: - EXTRACT_NUMBER (mcnt, p + 2); - DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); - - assert (mcnt >= 0); - /* Originally, this is how many times we HAVE to succeed. */ - if (mcnt > 0) - { - mcnt--; - p += 2; - STORE_NUMBER_AND_INCR (p, mcnt); -#ifdef _LIBC - DEBUG_PRINT3 (" Setting %p to %d.\n", p - 2, mcnt); -#else - DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - 2, mcnt); -#endif - } - else if (mcnt == 0) - { -#ifdef _LIBC - DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n", p+2); -#else - DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2); -#endif - p[2] = (unsigned char) no_op; - p[3] = (unsigned char) no_op; - goto on_failure; - } - break; - - case jump_n: - EXTRACT_NUMBER (mcnt, p + 2); - DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); - - /* Originally, this is how many times we CAN jump. */ - if (mcnt) - { - mcnt--; - STORE_NUMBER (p + 2, mcnt); -#ifdef _LIBC - DEBUG_PRINT3 (" Setting %p to %d.\n", p + 2, mcnt); -#else - DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + 2, mcnt); -#endif - goto unconditional_jump; - } - /* If don't have to jump any more, skip over the rest of command. */ - else - p += 4; - break; - - case set_number_at: - { - DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); - - EXTRACT_NUMBER_AND_INCR (mcnt, p); - p1 = p + mcnt; - EXTRACT_NUMBER_AND_INCR (mcnt, p); -#ifdef _LIBC - DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt); -#else - DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); -#endif - STORE_NUMBER (p1, mcnt); - break; - } - -#if 0 - /* The DEC Alpha C compiler 3.x generates incorrect code for the - test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of - AT_WORD_BOUNDARY, so this code is disabled. Expanding the - macro and introducing temporary variables works around the bug. */ - - case wordbound: - DEBUG_PRINT1 ("EXECUTING wordbound.\n"); - if (AT_WORD_BOUNDARY (d)) - break; - goto fail; - - case notwordbound: - DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); - if (AT_WORD_BOUNDARY (d)) - goto fail; - break; -#else - case wordbound: - { - boolean prevchar, thischar; - - DEBUG_PRINT1 ("EXECUTING wordbound.\n"); - if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) - break; - - prevchar = WORDCHAR_P (d - 1); - thischar = WORDCHAR_P (d); - if (prevchar != thischar) - break; - goto fail; - } - - case notwordbound: - { - boolean prevchar, thischar; - - DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); - if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) - goto fail; - - prevchar = WORDCHAR_P (d - 1); - thischar = WORDCHAR_P (d); - if (prevchar != thischar) - goto fail; - break; - } -#endif - - case wordbeg: - DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); - if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) - break; - goto fail; - - case wordend: - DEBUG_PRINT1 ("EXECUTING wordend.\n"); - if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) - && (!WORDCHAR_P (d) || AT_STRINGS_END (d))) - break; - goto fail; - -#ifdef emacs - case before_dot: - DEBUG_PRINT1 ("EXECUTING before_dot.\n"); - if (PTR_CHAR_POS ((unsigned char *) d) >= point) - goto fail; - break; - - case at_dot: - DEBUG_PRINT1 ("EXECUTING at_dot.\n"); - if (PTR_CHAR_POS ((unsigned char *) d) != point) - goto fail; - break; - - case after_dot: - DEBUG_PRINT1 ("EXECUTING after_dot.\n"); - if (PTR_CHAR_POS ((unsigned char *) d) <= point) - goto fail; - break; - - case syntaxspec: - DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); - mcnt = *p++; - goto matchsyntax; - - case wordchar: - DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); - mcnt = (int) Sword; - matchsyntax: - PREFETCH (); - /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ - d++; - if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt) - goto fail; - SET_REGS_MATCHED (); - break; - - case notsyntaxspec: - DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); - mcnt = *p++; - goto matchnotsyntax; - - case notwordchar: - DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); - mcnt = (int) Sword; - matchnotsyntax: - PREFETCH (); - /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ - d++; - if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt) - goto fail; - SET_REGS_MATCHED (); - break; - -#else /* not emacs */ - case wordchar: - DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); - PREFETCH (); - if (!WORDCHAR_P (d)) - goto fail; - SET_REGS_MATCHED (); - d++; - break; - - case notwordchar: - DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); - PREFETCH (); - if (WORDCHAR_P (d)) - goto fail; - SET_REGS_MATCHED (); - d++; - break; -#endif /* not emacs */ - - default: - abort (); - } - continue; /* Successfully executed one pattern command; keep going. */ - - - /* We goto here if a matching operation fails. */ - fail: - if (!FAIL_STACK_EMPTY ()) - { /* A restart point is known. Restore to that state. */ - DEBUG_PRINT1 ("\nFAIL:\n"); - POP_FAILURE_POINT (d, p, - lowest_active_reg, highest_active_reg, - regstart, regend, reg_info); - - /* If this failure point is a dummy, try the next one. */ - if (!p) - goto fail; - - /* If we failed to the end of the pattern, don't examine *p. */ - assert (p <= pend); - if (p < pend) - { - boolean is_a_jump_n = false; - - /* If failed to a backwards jump that's part of a repetition - loop, need to pop this failure point and use the next one. */ - switch ((re_opcode_t) *p) - { - case jump_n: - is_a_jump_n = true; - case maybe_pop_jump: - case pop_failure_jump: - case jump: - p1 = p + 1; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - p1 += mcnt; - - if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) - || (!is_a_jump_n - && (re_opcode_t) *p1 == on_failure_jump)) - goto fail; - break; - default: - /* do nothing */ ; - } - } - - if (d >= string1 && d <= end1) - dend = end_match_1; - } - else - break; /* Matching at this starting point really fails. */ - } /* for (;;) */ - - if (best_regs_set) - goto restore_best_regs; - - FREE_VARIABLES (); - - return -1; /* Failure to match. */ -} /* re_match_2 */ - -/* Subroutine definitions for re_match_2. */ - - -/* We are passed P pointing to a register number after a start_memory. - - Return true if the pattern up to the corresponding stop_memory can - match the empty string, and false otherwise. - - If we find the matching stop_memory, sets P to point to one past its number. - Otherwise, sets P to an undefined byte less than or equal to END. - - We don't handle duplicates properly (yet). */ - -static boolean -group_match_null_string_p (p, end, reg_info) - unsigned char **p, *end; - register_info_type *reg_info; -{ - int mcnt; - /* Point to after the args to the start_memory. */ - unsigned char *p1 = *p + 2; - - while (p1 < end) - { - /* Skip over opcodes that can match nothing, and return true or - false, as appropriate, when we get to one that can't, or to the - matching stop_memory. */ - - switch ((re_opcode_t) *p1) - { - /* Could be either a loop or a series of alternatives. */ - case on_failure_jump: - p1++; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - - /* If the next operation is not a jump backwards in the - pattern. */ - - if (mcnt >= 0) - { - /* Go through the on_failure_jumps of the alternatives, - seeing if any of the alternatives cannot match nothing. - The last alternative starts with only a jump, - whereas the rest start with on_failure_jump and end - with a jump, e.g., here is the pattern for `a|b|c': - - /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 - /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 - /exactn/1/c - - So, we have to first go through the first (n-1) - alternatives and then deal with the last one separately. */ - - - /* Deal with the first (n-1) alternatives, which start - with an on_failure_jump (see above) that jumps to right - past a jump_past_alt. */ - - while ((re_opcode_t) p1[mcnt-3] == jump_past_alt) - { - /* `mcnt' holds how many bytes long the alternative - is, including the ending `jump_past_alt' and - its number. */ - - if (!alt_match_null_string_p (p1, p1 + mcnt - 3, - reg_info)) - return false; - - /* Move to right after this alternative, including the - jump_past_alt. */ - p1 += mcnt; - - /* Break if it's the beginning of an n-th alternative - that doesn't begin with an on_failure_jump. */ - if ((re_opcode_t) *p1 != on_failure_jump) - break; - - /* Still have to check that it's not an n-th - alternative that starts with an on_failure_jump. */ - p1++; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - if ((re_opcode_t) p1[mcnt-3] != jump_past_alt) - { - /* Get to the beginning of the n-th alternative. */ - p1 -= 3; - break; - } - } - - /* Deal with the last alternative: go back and get number - of the `jump_past_alt' just before it. `mcnt' contains - the length of the alternative. */ - EXTRACT_NUMBER (mcnt, p1 - 2); - - if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) - return false; - - p1 += mcnt; /* Get past the n-th alternative. */ - } /* if mcnt > 0 */ - break; - - - case stop_memory: - assert (p1[1] == **p); - *p = p1 + 2; - return true; - - - default: - if (!common_op_match_null_string_p (&p1, end, reg_info)) - return false; - } - } /* while p1 < end */ - - return false; -} /* group_match_null_string_p */ - - -/* Similar to group_match_null_string_p, but doesn't deal with alternatives: - It expects P to be the first byte of a single alternative and END one - byte past the last. The alternative can contain groups. */ - -static boolean -alt_match_null_string_p (p, end, reg_info) - unsigned char *p, *end; - register_info_type *reg_info; -{ - int mcnt; - unsigned char *p1 = p; - - while (p1 < end) - { - /* Skip over opcodes that can match nothing, and break when we get - to one that can't. */ - - switch ((re_opcode_t) *p1) - { - /* It's a loop. */ - case on_failure_jump: - p1++; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - p1 += mcnt; - break; - - default: - if (!common_op_match_null_string_p (&p1, end, reg_info)) - return false; - } - } /* while p1 < end */ - - return true; -} /* alt_match_null_string_p */ - - -/* Deals with the ops common to group_match_null_string_p and - alt_match_null_string_p. - - Sets P to one after the op and its arguments, if any. */ - -static boolean -common_op_match_null_string_p (p, end, reg_info) - unsigned char **p, *end; - register_info_type *reg_info; -{ - int mcnt; - boolean ret; - int reg_no; - unsigned char *p1 = *p; - - switch ((re_opcode_t) *p1++) - { - case no_op: - case begline: - case endline: - case begbuf: - case endbuf: - case wordbeg: - case wordend: - case wordbound: - case notwordbound: -#ifdef emacs - case before_dot: - case at_dot: - case after_dot: -#endif - break; - - case start_memory: - reg_no = *p1; - assert (reg_no > 0 && reg_no <= MAX_REGNUM); - ret = group_match_null_string_p (&p1, end, reg_info); - - /* Have to set this here in case we're checking a group which - contains a group and a back reference to it. */ - - if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) - REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; - - if (!ret) - return false; - break; - - /* If this is an optimized succeed_n for zero times, make the jump. */ - case jump: - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - if (mcnt >= 0) - p1 += mcnt; - else - return false; - break; - - case succeed_n: - /* Get to the number of times to succeed. */ - p1 += 2; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - - if (mcnt == 0) - { - p1 -= 4; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - p1 += mcnt; - } - else - return false; - break; - - case duplicate: - if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) - return false; - break; - - case set_number_at: - p1 += 4; - - default: - /* All other opcodes mean we cannot match the empty string. */ - return false; - } - - *p = p1; - return true; -} /* common_op_match_null_string_p */ - - -/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN - bytes; nonzero otherwise. */ - -static int -bcmp_translate (s1, s2, len, translate) - const char *s1, *s2; - register int len; - RE_TRANSLATE_TYPE translate; -{ - register const unsigned char *p1 = (const unsigned char *) s1; - register const unsigned char *p2 = (const unsigned char *) s2; - while (len) - { - if (translate[*p1++] != translate[*p2++]) return 1; - len--; - } - return 0; -} - -/* Entry points for GNU code. */ - -/* re_compile_pattern is the GNU regular expression compiler: it - compiles PATTERN (of length SIZE) and puts the result in BUFP. - Returns 0 if the pattern was valid, otherwise an error string. - - Assumes the `allocated' (and perhaps `buffer') and `translate' fields - are set in BUFP on entry. - - We call regex_compile to do the actual compilation. */ - -const char * -re_compile_pattern (pattern, length, bufp) - const char *pattern; - size_t length; - struct re_pattern_buffer *bufp; -{ - reg_errcode_t ret; - - /* GNU code is written to assume at least RE_NREGS registers will be set - (and at least one extra will be -1). */ - bufp->regs_allocated = REGS_UNALLOCATED; - - /* And GNU code determines whether or not to get register information - by passing null for the REGS argument to re_match, etc., not by - setting no_sub. */ - bufp->no_sub = 0; - - /* Match anchors at newline. */ - bufp->newline_anchor = 1; - - ret = regex_compile (pattern, length, re_syntax_options, bufp); - - if (!ret) - return NULL; - return gettext (re_error_msgid[(int) ret]); -} - -/* Entry points compatible with 4.2 BSD regex library. We don't define - them unless specifically requested. */ - -#if defined (_REGEX_RE_COMP) || defined (_LIBC) - -/* BSD has one and only one pattern buffer. */ -static struct re_pattern_buffer re_comp_buf; - -char * -#ifdef _LIBC -/* Make these definitions weak in libc, so POSIX programs can redefine - these names if they don't use our functions, and still use - regcomp/regexec below without link errors. */ -weak_function -#endif -re_comp (s) - const char *s; -{ - reg_errcode_t ret; - - if (!s) - { - if (!re_comp_buf.buffer) - return gettext ("No previous regular expression"); - return 0; - } - - if (!re_comp_buf.buffer) - { - re_comp_buf.buffer = (unsigned char *) malloc (200); - if (re_comp_buf.buffer == NULL) - return gettext (re_error_msgid[(int) REG_ESPACE]); - re_comp_buf.allocated = 200; - - re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); - if (re_comp_buf.fastmap == NULL) - return gettext (re_error_msgid[(int) REG_ESPACE]); - } - - /* Since `re_exec' always passes NULL for the `regs' argument, we - don't need to initialize the pattern buffer fields which affect it. */ - - /* Match anchors at newlines. */ - re_comp_buf.newline_anchor = 1; - - ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); - - if (!ret) - return NULL; - - /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ - return (char *) gettext (re_error_msgid[(int) ret]); -} - - -int -#ifdef _LIBC -weak_function -#endif -re_exec (s) - const char *s; -{ - const int len = strlen (s); - return - 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); -} - -#endif /* _REGEX_RE_COMP */ - -/* POSIX.2 functions. Don't define these for Emacs. */ - -#ifndef emacs - -/* regcomp takes a regular expression as a string and compiles it. - - PREG is a regex_t *. We do not expect any fields to be initialized, - since POSIX says we shouldn't. Thus, we set - - `buffer' to the compiled pattern; - `used' to the length of the compiled pattern; - `syntax' to RE_SYNTAX_POSIX_EXTENDED if the - REG_EXTENDED bit in CFLAGS is set; otherwise, to - RE_SYNTAX_POSIX_BASIC; - `newline_anchor' to REG_NEWLINE being set in CFLAGS; - `fastmap' and `fastmap_accurate' to zero; - `re_nsub' to the number of subexpressions in PATTERN. - - PATTERN is the address of the pattern string. - - CFLAGS is a series of bits which affect compilation. - - If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we - use POSIX basic syntax. - - If REG_NEWLINE is set, then . and [^...] don't match newline. - Also, regexec will try a match beginning after every newline. - - If REG_ICASE is set, then we considers upper- and lowercase - versions of letters to be equivalent when matching. - - If REG_NOSUB is set, then when PREG is passed to regexec, that - routine will report only success or failure, and nothing about the - registers. - - It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for - the return codes and their meanings.) */ - -int -regcomp (preg, pattern, cflags) - regex_t *preg; - const char *pattern; - int cflags; -{ - reg_errcode_t ret; - reg_syntax_t syntax - = (cflags & REG_EXTENDED) ? - RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; - - /* regex_compile will allocate the space for the compiled pattern. */ - preg->buffer = 0; - preg->allocated = 0; - preg->used = 0; - - /* Don't bother to use a fastmap when searching. This simplifies the - REG_NEWLINE case: if we used a fastmap, we'd have to put all the - characters after newlines into the fastmap. This way, we just try - every character. */ - preg->fastmap = 0; - - if (cflags & REG_ICASE) - { - unsigned i; - - preg->translate - = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE - * sizeof (*(RE_TRANSLATE_TYPE)0)); - if (preg->translate == NULL) - return (int) REG_ESPACE; - - /* Map uppercase characters to corresponding lowercase ones. */ - for (i = 0; i < CHAR_SET_SIZE; i++) - preg->translate[i] = ISUPPER (i) ? tolower (i) : i; - } - else - preg->translate = NULL; - - /* If REG_NEWLINE is set, newlines are treated differently. */ - if (cflags & REG_NEWLINE) - { /* REG_NEWLINE implies neither . nor [^...] match newline. */ - syntax &= ~RE_DOT_NEWLINE; - syntax |= RE_HAT_LISTS_NOT_NEWLINE; - /* It also changes the matching behavior. */ - preg->newline_anchor = 1; - } - else - preg->newline_anchor = 0; - - preg->no_sub = !!(cflags & REG_NOSUB); - - /* POSIX says a null character in the pattern terminates it, so we - can use strlen here in compiling the pattern. */ - ret = regex_compile (pattern, strlen (pattern), syntax, preg); - - /* POSIX doesn't distinguish between an unmatched open-group and an - unmatched close-group: both are REG_EPAREN. */ - if (ret == REG_ERPAREN) ret = REG_EPAREN; - - return (int) ret; -} - - -/* regexec searches for a given pattern, specified by PREG, in the - string STRING. - - If NMATCH is zero or REG_NOSUB was set in the cflags argument to - `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at - least NMATCH elements, and we set them to the offsets of the - corresponding matched substrings. - - EFLAGS specifies `execution flags' which affect matching: if - REG_NOTBOL is set, then ^ does not match at the beginning of the - string; if REG_NOTEOL is set, then $ does not match at the end. - - We return 0 if we find a match and REG_NOMATCH if not. */ - -int -regexec (preg, string, nmatch, pmatch, eflags) - const regex_t *preg; - const char *string; - size_t nmatch; - regmatch_t pmatch[]; - int eflags; -{ - int ret; - struct re_registers regs; - regex_t private_preg; - int len = strlen (string); - boolean want_reg_info = !preg->no_sub && nmatch > 0; - - private_preg = *preg; - - private_preg.not_bol = !!(eflags & REG_NOTBOL); - private_preg.not_eol = !!(eflags & REG_NOTEOL); - - /* The user has told us exactly how many registers to return - information about, via `nmatch'. We have to pass that on to the - matching routines. */ - private_preg.regs_allocated = REGS_FIXED; - - if (want_reg_info) - { - regs.num_regs = nmatch; - regs.start = TALLOC (nmatch, regoff_t); - regs.end = TALLOC (nmatch, regoff_t); - if (regs.start == NULL || regs.end == NULL) - return (int) REG_NOMATCH; - } - - /* Perform the searching operation. */ - ret = re_search (&private_preg, string, len, - /* start: */ 0, /* range: */ len, - want_reg_info ? ®s : (struct re_registers *) 0); - - /* Copy the register information to the POSIX structure. */ - if (want_reg_info) - { - if (ret >= 0) - { - unsigned r; - - for (r = 0; r < nmatch; r++) - { - pmatch[r].rm_so = regs.start[r]; - pmatch[r].rm_eo = regs.end[r]; - } - } - - /* If we needed the temporary register info, free the space now. */ - free (regs.start); - free (regs.end); - } - - /* We want zero return to mean success, unlike `re_search'. */ - return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; -} - - -/* Returns a message corresponding to an error code, ERRCODE, returned - from either regcomp or regexec. We don't use PREG here. */ - -size_t -regerror (int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) -{ - const char *msg; - size_t msg_size; - - if (errcode < 0 - || errcode >= (int) (sizeof (re_error_msgid) - / sizeof (re_error_msgid[0]))) - /* Only error codes returned by the rest of the code should be passed - to this routine. If we are given anything else, or if other regex - code generates an invalid error code, then the program has a bug. - Dump core so we can fix it. */ - abort (); - - msg = gettext (re_error_msgid[errcode]); - - msg_size = strlen (msg) + 1; /* Includes the null. */ - - if (errbuf_size != 0) - { - if (msg_size > errbuf_size) - { - strncpy (errbuf, msg, errbuf_size - 1); - errbuf[errbuf_size - 1] = 0; - } - else - strcpy (errbuf, msg); - } - - return msg_size; -} - - -/* Free dynamically allocated space used by PREG. */ - -void -regfree (preg) - regex_t *preg; -{ - if (preg->buffer != NULL) - free (preg->buffer); - preg->buffer = NULL; - - preg->allocated = 0; - preg->used = 0; - - if (preg->fastmap != NULL) - free (preg->fastmap); - preg->fastmap = NULL; - preg->fastmap_accurate = 0; - - if (preg->translate != NULL) - free (preg->translate); - preg->translate = NULL; -} - -#endif /* not emacs */ diff --git a/src/utilfuns/roman.cpp b/src/utilfuns/roman.cpp index 85f361d..4db9540 100644 --- a/src/utilfuns/roman.cpp +++ b/src/utilfuns/roman.cpp @@ -1,22 +1,20 @@ /* * roman.c - * Copyright 2001 by CrossWire Bible Society - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - * + * + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * */ #include <stdlib.h> @@ -25,9 +23,9 @@ SWORD_NAMESPACE_START -char isroman (const char* str) { - char * ch = (char*)str; - for (; *ch; ch++) +char isroman (const char *str, int maxchars) { + char *ch = (char*)str; + for (; *ch && (!maxchars || (ch-str) <= maxchars); ch++) if (!strchr("IVXLCDMivxlcdm ", *ch)) return 0; return 1; diff --git a/src/utilfuns/sub.c b/src/utilfuns/sub.c deleted file mode 100644 index fcea6e2..0000000 --- a/src/utilfuns/sub.c +++ /dev/null @@ -1,36 +0,0 @@ - -#include <stdio.h> -#include <stdlib.h> - -main(int argc, char **argv) -{ - FILE *fp; - char *buf; - int size; - - if ((argc < 3) || (argc > 4)) { - fprintf(stderr, "usage: %s <string> <substitute string> [filename]\n", *argv); - exit(-1); - } - - if (argc > 3) - fp = fopen(argv[3], "r"); - else fp = stdin; - - size = strlen(argv[1]); - buf = (char *)calloc(size + 1, 1); - - while ((buf[size - 1] = fgetc(fp)) != EOF) { - if (!strcmp(buf, argv[1])) { - printf("\n%s", argv[2]); - memset(buf, 0, size); - continue; - } - if (*buf) { - printf("%c", *buf); - } - memmove(buf, &buf[1], size); - } - buf[size - 1] = 0; - printf("%s", buf); -} diff --git a/src/utilfuns/swbuf.cpp b/src/utilfuns/swbuf.cpp index 430a705..53dd43a 100644 --- a/src/utilfuns/swbuf.cpp +++ b/src/utilfuns/swbuf.cpp @@ -1,7 +1,7 @@ /****************************************************************************** * swbuf.cpp - code for SWBuf used as a transport and utility for data buffers * -* $Id: swbuf.cpp 2169 2008-05-18 02:50:53Z scribe $ +* $Id: swbuf.cpp 2198 2008-09-11 20:59:30Z scribe $ * * Copyright 2003 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -76,7 +76,7 @@ SWBuf::SWBuf(unsigned long initSize) { * WARNING: This function can only write at most * JUNKBUFSIZE to the string per call. */ -void SWBuf::setFormatted(const char *format, ...) { +SWBuf &SWBuf::setFormatted(const char *format, ...) { va_list argptr; va_start(argptr, format); @@ -90,6 +90,7 @@ void SWBuf::setFormatted(const char *format, ...) { va_start(argptr, format); end = vsprintf(buf, format, argptr) + buf; va_end(argptr); + return *this; } /****************************************************************************** diff --git a/src/utilfuns/swversion.cpp b/src/utilfuns/swversion.cpp index 9e61f06..fe112db 100644 --- a/src/utilfuns/swversion.cpp +++ b/src/utilfuns/swversion.cpp @@ -1,3 +1,20 @@ +/* + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + #include <config.h> #include <swversion.h> diff --git a/src/utilfuns/url.cpp b/src/utilfuns/url.cpp index 3a50e2c..549c283 100644 --- a/src/utilfuns/url.cpp +++ b/src/utilfuns/url.cpp @@ -1,7 +1,7 @@ /****************************************************************************** * url.cpp - code for an URL parser utility class * -* $Id: url.cpp 2013 2006-11-25 22:01:04Z dglassey $ +* $Id: url.cpp 2250 2009-02-14 05:48:58Z scribe $ * * Copyright 2003 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -31,6 +31,27 @@ SWORD_NAMESPACE_START +namespace { + typedef std::map< unsigned char, SWBuf > DataMap; + DataMap m; + static class __init { + public: + __init() { + for (unsigned short int c = 32; c <= 255; ++c) { //first set all encoding chars + if ( (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || strchr("-_.!~*'()", c)) { + continue; //we don't need an encoding for this char + } + + SWBuf buf; + buf.setFormatted("%%%-.2X", c); + m[c] = buf; + } + //the special encodings for certain chars + m[' '] = '+'; + } + } ___init; +} + /** * Constructors/Destructors */ @@ -197,24 +218,11 @@ void URL::parse () { } } + const SWBuf URL::encode(const char *urlText) { /*static*/ SWBuf url; url = urlText; - typedef std::map< unsigned char, SWBuf > DataMap; - DataMap m; - for (unsigned short int c = 32; c <= 255; ++c) { //first set all encoding chars - if ( (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || strchr("-_.!~*'()", c)) { - continue; //we don't need an encoding for this char - } - - SWBuf buf; - buf.setFormatted("%%%-.2X", c); - m[c] = buf; - } - //the special encodings for certain chars - m[' '] = '+'; - SWBuf buf; const int length = url.length(); for (int i = 0; i < length; i++) { //fill "buf" diff --git a/src/utilfuns/utilstr.cpp b/src/utilfuns/utilstr.cpp index 52dc286..9a0ddc6 100644 --- a/src/utilfuns/utilstr.cpp +++ b/src/utilfuns/utilstr.cpp @@ -1,20 +1,26 @@ +/* + * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + #include <utilstr.h> #include <ctype.h> #include <string.h> -#include <localemgr.h> - +#include <sysdata.h> -#ifdef _ICU_ -#include <unicode/utypes.h> -#include <unicode/ucnv.h> -#include <unicode/ustring.h> -#include <unicode/uchar.h> - -#include <unicode/unistr.h> -#include <unicode/translit.h> - -#endif SWORD_NAMESPACE_START @@ -67,13 +73,14 @@ const unsigned char SW_toupper_array[256] = */ char *stdstr(char **ipstr, const char *istr, unsigned int memPadFactor) { + if (*ipstr) + delete [] *ipstr; if (istr) { - if (*ipstr) - delete [] *ipstr; int len = strlen(istr) + 1; *ipstr = new char [ len * memPadFactor ]; memcpy(*ipstr, istr, len); } + else *ipstr = 0; return *ipstr; } @@ -174,68 +181,58 @@ int stricmp(const char *s1, const char *s2) { #endif } + /****************************************************************************** - * toupperstr - converts a string to uppercase string + * getUniCharFromUTF8 - retrieves the next Unicode codepoint from a UTF8 string + * and increments buf to start of next codepoint * - * ENT: target - string to convert + * ENT: buf - address of a utf8 buffer * - * RET: target + * RET: buf - incremented past last byte used in computing the current codepoint + * unicode codepoint value (0 with buf incremented is invalid UTF8 byte */ -// char *toupperstr(char *buf) { -// char *ret = buf; -// -// /*if (StringHelper::getSystemStringHelper()) { -// StringHelper::getSystemStringHelper()->upperStringLatin1( ret ); -// } -// else*/ { -// while (*buf) { -// *buf++ = SW_toupper(*buf); -// } -// // } -// return ret; -// } +__u32 getUniCharFromUTF8(const unsigned char **buf) { + __u32 ch = 0; + unsigned char multibuf[7]; + + //case: We're at the end + if (!(**buf)) { + return ch; + } + //case: ANSI + if (!(**buf & 128)) { + ch = **buf; + (*buf)++; + return ch; + } -/****************************************************************************** - * toupperstr - converts a string to uppercase string - * - * ENT: target - string to convert - * - * RET: target - */ + //case: Invalid UTF-8 (illegal continuing byte in initial position) + if ((**buf & 128) && (!(**buf & 64))) { + (*buf)++; + return ch; + } + + //case: 2+ byte codepoint + multibuf[0] = **buf; + multibuf[0] <<= 1; + int subsequent; + for (subsequent = 1; (multibuf[0] & 128) && (subsequent < 7); subsequent++) { + multibuf[0] <<= 1; + multibuf[subsequent] = (*buf)[subsequent]; + multibuf[subsequent] &= 63; + ch <<= 6; + ch |= multibuf[subsequent]; + } + subsequent--; + multibuf[0] <<= 1; + char significantFirstBits = 8 - (2+subsequent); + + ch |= (((__s16)multibuf[0]) << (((6*subsequent)+significantFirstBits)-8)); + *buf += (subsequent+1); + return ch; +} -// char *toupperstr_utf8(char *buf, unsigned int max) { -// char *ret = buf; -// -// /* if (StringHelper::getSystemStringHelper()) { -// StringHelper::getSystemStringHelper()->upperStringUtf8( ret ); -// return ret; -// }*/ -// -// #ifndef _ICU_ -// // try to decide if it's worth trying to toupper. Do we have more -// // characters that are probably lower latin than not? -// long performOp = 0; -// for (const char *ch = buf; *ch; ch++) -// performOp += (*ch > 0) ? 1 : -1; -// -// if (performOp > 0) { -// while (*buf) -// *buf = SW_toupper(*buf++); -// } -// #else -// if (!max) -// max = strlen(ret); -// UErrorCode err = U_ZERO_ERROR; -// UConverter *conv = ucnv_open("UTF-8", &err); -// UnicodeString str(buf, -1, conv, err); -// UnicodeString ustr = str.toUpper(); -// ustr.extract(ret, max, conv, err); -// ucnv_close(conv); -// #endif -// -// return ret; -// } SWORD_NAMESPACE_END diff --git a/src/utilfuns/utilxml.cpp b/src/utilfuns/utilxml.cpp index 9184102..d3af7e5 100644 --- a/src/utilfuns/utilxml.cpp +++ b/src/utilfuns/utilxml.cpp @@ -1,7 +1,7 @@ /****************************************************************************** * utilxml.cpp - implementaion of utility classes to handle XML processing * - * $Id: utilxml.cpp 2096 2007-10-07 00:40:00Z scribe $ + * $Id: utilxml.cpp 2378 2009-05-04 23:18:51Z scribe $ * * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -121,6 +121,22 @@ XMLTag::XMLTag(const char *tagString) { setText(tagString); } +XMLTag::XMLTag(const XMLTag& t) : attributes(t.attributes) { + parsed = t.parsed; + empty = t.empty; + endTag = t.endTag; + if (t.buf) { + int len = strlen(t.buf); + buf = new char[len + 1]; + memcpy(buf, t.buf, len + 1); + } + if (t.name) { + int len = strlen(t.name); + name = new char[len + 1]; + memcpy(name, t.name, len + 1); + } +} + void XMLTag::setText(const char *tagString) { parsed = false; empty = false; @@ -293,4 +309,13 @@ const char *XMLTag::toString() const { } +// if an eID is provided, then we check to be sure we have an attribute <tag eID="xxx"/> value xxx equiv to what is given us +// otherwise, we return if we're a simple XML end </tag>. +bool XMLTag::isEndTag(const char *eID) const { + if (eID) { + return (SWBuf(eID) == getAttribute("eID")); + } + return endTag; +} + SWORD_NAMESPACE_END diff --git a/src/utilfuns/win32/dirent.cpp b/src/utilfuns/win32/dirent.cpp deleted file mode 100644 index 150bf10..0000000 --- a/src/utilfuns/win32/dirent.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - - Implementation of POSIX directory browsing functions and types for Win32. - - Kevlin Henney (mailto:kevlin@acm.org), March 1997. - - Copyright Kevlin Henney, 1997. All rights reserved. - - Permission to use, copy, modify, and distribute this software and its - documentation for any purpose is hereby granted without fee, provided - that this copyright and permissions notice appear in all copies and - derivatives, and that no charge may be made for the software and its - documentation except to cover cost of distribution. - - This software is supplied "as is" without express or implied warranty. - - But that said, if there are any problems please get in touch. - -*/ - -#include <dirent.h> -#include <errno.h> -#include <io.h> -#include <stdlib.h> -#include <string.h> - -struct DIR -{ - long handle; /* -1 for failed rewind */ - struct _finddata_t info; - struct dirent result; /* d_name null iff first time */ - char *name; /* NTBS */ -}; - -DIR *opendir(const char *name) -{ - DIR *dir = 0; - - if(name && name[0]) - { - size_t base_length = strlen(name); - const char *all = /* the root directory is a special case... */ - strchr("/\\", name[base_length - 1]) ? "*" : "/*"; - - if((dir = (DIR *) malloc(sizeof *dir)) != 0 && - (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0) - { - strcat(strcpy(dir->name, name), all); - - if((dir->handle = _findfirst(dir->name, &dir->info)) != -1) - { - dir->result.d_name = 0; - } - else /* rollback */ - { - free(dir->name); - free(dir); - dir = 0; - } - } - else /* rollback */ - { - free(dir); - dir = 0; - errno = ENOMEM; - } - } - else - { - errno = EINVAL; - } - - return dir; -} - -int closedir(DIR *dir) -{ - int result = -1; - - if(dir) - { - if(dir->handle != -1) - { - result = _findclose(dir->handle); - } - - free(dir->name); - free(dir); - } - - if(result == -1) /* map all errors to EBADF */ - { - errno = EBADF; - } - - return result; -} - -struct dirent *readdir(DIR *dir) -{ - struct dirent *result = 0; - - if(dir && dir->handle != -1) - { - if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) - { - result = &dir->result; - result->d_name = dir->info.name; - } - } - else - { - errno = EBADF; - } - - return result; -} - -void rewinddir(DIR *dir) -{ - if(dir && dir->handle != -1) - { - _findclose(dir->handle); - dir->handle = _findfirst(dir->name, &dir->info); - dir->result.d_name = 0; - } - else - { - errno = EBADF; - } -} diff --git a/src/utilfuns/win32/dirent.h b/src/utilfuns/win32/dirent.h deleted file mode 100644 index ba22833..0000000 --- a/src/utilfuns/win32/dirent.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - - Declaration of POSIX directory browsing functions and types for Win32. - - Kevlin Henney (mailto:kevlin@acm.org), March 1997. - - Copyright Kevlin Henney, 1997. All rights reserved. - - Permission to use, copy, modify, and distribute this software and its - documentation for any purpose is hereby granted without fee, provided - that this copyright and permissions notice appear in all copies and - derivatives, and that no charge may be made for the software and its - documentation except to cover cost of distribution. - -*/ - -#ifndef DIRENT_INCLUDED -#define DIRENT_INCLUDED - -typedef struct DIR DIR; - -struct dirent -{ - char *d_name; -}; - -DIR *opendir(const char *); -int closedir(DIR *); -struct dirent *readdir(DIR *); -void rewinddir(DIR *); - -#endif diff --git a/src/utilfuns/zlib/adler32.c b/src/utilfuns/zlib/adler32.c deleted file mode 100644 index c786e9a..0000000 --- a/src/utilfuns/zlib/adler32.c +++ /dev/null @@ -1,48 +0,0 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: adler32.c 1688 2005-01-01 04:42:26Z scribe $ */ - -#include "zlib.h" - -#define BASE 65521L /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} -#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -#define DO16(buf) DO8(buf,0); DO8(buf,8); - -/* ========================================================================= */ -uLong ZEXPORT adler32(adler, buf, len) - uLong adler; - const Bytef *buf; - uInt len; -{ - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int k; - - if (buf == Z_NULL) return 1L; - - while (len > 0) { - k = len < NMAX ? len : NMAX; - len -= k; - while (k >= 16) { - DO16(buf); - buf += 16; - k -= 16; - } - if (k != 0) do { - s1 += *buf++; - s2 += s1; - } while (--k); - s1 %= BASE; - s2 %= BASE; - } - return (s2 << 16) | s1; -} diff --git a/src/utilfuns/zlib/compress.c b/src/utilfuns/zlib/compress.c deleted file mode 100644 index 2b1f048..0000000 --- a/src/utilfuns/zlib/compress.c +++ /dev/null @@ -1,68 +0,0 @@ -/* compress.c -- compress a memory buffer - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: compress.c 1688 2005-01-01 04:42:26Z scribe $ */ - -#include "zlib.h" - -/* =========================================================================== - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ -int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; - int level; -{ - z_stream stream; - int err; - - stream.next_in = (Bytef*)source; - stream.avail_in = (uInt)sourceLen; -#ifdef MAXSEG_64K - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; -#endif - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; - - err = deflateInit(&stream, level); - if (err != Z_OK) return err; - - err = deflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - deflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; - - err = deflateEnd(&stream); - return err; -} - -/* =========================================================================== - */ -int ZEXPORT compress (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ - return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); -} diff --git a/src/utilfuns/zlib/crc32.c b/src/utilfuns/zlib/crc32.c deleted file mode 100644 index e44440c..0000000 --- a/src/utilfuns/zlib/crc32.c +++ /dev/null @@ -1,162 +0,0 @@ -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: crc32.c 1688 2005-01-01 04:42:26Z scribe $ */ - -#include "zlib.h" - -#define local static - -#ifdef DYNAMIC_CRC_TABLE - -local int crc_table_empty = 1; -local uLongf crc_table[256]; -local void make_crc_table OF((void)); - -/* - Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The table is simply the CRC of all possible eight bit values. This is all - the information needed to generate CRC's on data a byte at a time for all - combinations of CRC register values and incoming bytes. -*/ -local void make_crc_table() -{ - uLong c; - int n, k; - uLong poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; - - /* make exclusive-or pattern from polynomial (0xedb88320L) */ - poly = 0L; - for (n = 0; n < sizeof(p)/sizeof(Byte); n++) - poly |= 1L << (31 - p[n]); - - for (n = 0; n < 256; n++) - { - c = (uLong)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[n] = c; - } - crc_table_empty = 0; -} -#else -/* ======================================================================== - * Table of CRC-32's of all single-byte values (made by make_crc_table) - */ -local const uLongf crc_table[256] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL -}; -#endif - -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ -const uLongf * ZEXPORT get_crc_table() -{ -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) make_crc_table(); -#endif - return (const uLongf *)crc_table; -} - -/* ========================================================================= */ -#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); -#define DO2(buf) DO1(buf); DO1(buf); -#define DO4(buf) DO2(buf); DO2(buf); -#define DO8(buf) DO4(buf); DO4(buf); - -/* ========================================================================= */ -uLong ZEXPORT crc32(crc, buf, len) - uLong crc; - const Bytef *buf; - uInt len; -{ - if (buf == Z_NULL) return 0L; -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif - crc = crc ^ 0xffffffffL; - while (len >= 8) - { - DO8(buf); - len -= 8; - } - if (len) do { - DO1(buf); - } while (--len); - return crc ^ 0xffffffffL; -} diff --git a/src/utilfuns/zlib/deflate.c b/src/utilfuns/zlib/deflate.c deleted file mode 100644 index 43ea588..0000000 --- a/src/utilfuns/zlib/deflate.c +++ /dev/null @@ -1,1350 +0,0 @@ -/* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process depends on being able to identify portions - * of the input text which are identical to earlier input (within a - * sliding window trailing behind the input currently being processed). - * - * The most straightforward technique turns out to be the fastest for - * most input files: try all possible matches and select the longest. - * The key feature of this algorithm is that insertions into the string - * dictionary are very simple and thus fast, and deletions are avoided - * completely. Insertions are performed at each input character, whereas - * string matches are performed only when the previous match ends. So it - * is preferable to spend more time in matches to allow very fast string - * insertions and avoid deletions. The matching algorithm for small - * strings is inspired from that of Rabin & Karp. A brute force approach - * is used to find longer strings when a small match has been found. - * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - * (by Leonid Broukhis). - * A previous version of this file used a more sophisticated algorithm - * (by Fiala and Greene) which is guaranteed to run in linear amortized - * time, but has a larger average cost, uses more memory and is patented. - * However the F&G algorithm may be faster for some highly redundant - * files if the parameter max_chain_length (described below) is too large. - * - * ACKNOWLEDGEMENTS - * - * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and - * I found it in 'freeze' written by Leonid Broukhis. - * Thanks to many people for bug reports and testing. - * - * REFERENCES - * - * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in ftp://ds.internic.net/rfc/rfc1951.txt - * - * A description of the Rabin and Karp algorithm is given in the book - * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. - * - * Fiala,E.R., and Greene,D.H. - * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 - * - */ - -/* @(#) $Id: deflate.c 1688 2005-01-01 04:42:26Z scribe $ */ - -#include "deflate.h" - -const char deflate_copyright[] = - " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* =========================================================================== - * Function prototypes. - */ -typedef enum { - need_more, /* block not completed, need more input or more output */ - block_done, /* block flush performed */ - finish_started, /* finish started, need only more output at next deflate */ - finish_done /* finish done, accept no more input or output */ -} block_state; - -typedef block_state (*compress_func) OF((deflate_state *s, int flush)); -/* Compression function. Returns the block state after the call. */ - -local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush)); -local block_state deflate_fast OF((deflate_state *s, int flush)); -local block_state deflate_slow OF((deflate_state *s, int flush)); -local void lm_init OF((deflate_state *s)); -local void putShortMSB OF((deflate_state *s, uInt b)); -local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -#ifdef ASMV - void match_init OF((void)); /* asm code initialization */ - uInt longest_match OF((deflate_state *s, IPos cur_match)); -#else -local uInt longest_match OF((deflate_state *s, IPos cur_match)); -#endif - -#ifdef DEBUG -local void check_match OF((deflate_state *s, IPos start, IPos match, - int length)); -#endif - -/* =========================================================================== - * Local data - */ - -#define NIL 0 -/* Tail of hash chains */ - -#ifndef TOO_FAR -# define TOO_FAR 4096 -#endif -/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -typedef struct config_s { - ush good_length; /* reduce lazy search above this match length */ - ush max_lazy; /* do not perform lazy search above this match length */ - ush nice_length; /* quit search above this match length */ - ush max_chain; - compress_func func; -} config; - -local const config configuration_table[10] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ -/* 2 */ {4, 5, 16, 8, deflate_fast}, -/* 3 */ {4, 6, 32, 32, deflate_fast}, - -/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32, deflate_slow}, -/* 6 */ {8, 16, 128, 128, deflate_slow}, -/* 7 */ {8, 32, 128, 256, deflate_slow}, -/* 8 */ {32, 128, 258, 1024, deflate_slow}, -/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ - -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * For deflate_fast() (levels <= 3) good is ignored and lazy has a different - * meaning. - */ - -#define EQUAL 0 -/* result of memcmp for equal strings */ - -struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ - -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. - */ -#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask) - - -/* =========================================================================== - * Insert string str in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - * If this file is compiled with -DFASTEST, the compression level is forced - * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). - */ -#ifdef FASTEST -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#else -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#endif - -/* =========================================================================== - * Initialize the hash table (avoiding 64K overflow for 16 bit systems). - * prev[] will be initialized on the fly. - */ -#define CLEAR_HASH(s) \ - s->head[s->hash_size-1] = NIL; \ - zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); - -/* ========================================================================= */ -int ZEXPORT deflateInit_(strm, level, version, stream_size) - z_streamp strm; - int level; - const char *version; - int stream_size; -{ - return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY, version, stream_size); - /* To do: ignore strm->next_in if we use it as window */ -} - -/* ========================================================================= */ -int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - version, stream_size) - z_streamp strm; - int level; - int method; - int windowBits; - int memLevel; - int strategy; - const char *version; - int stream_size; -{ - deflate_state *s; - int noheader = 0; - static const char* my_version = ZLIB_VERSION; - - ushf *overlay; - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 24 bits. - */ - - if (version == Z_NULL || version[0] != my_version[0] || - stream_size != sizeof(z_stream)) { - return Z_VERSION_ERROR; - } - if (strm == Z_NULL) return Z_STREAM_ERROR; - - strm->msg = Z_NULL; - if (strm->zalloc == Z_NULL) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == Z_NULL) strm->zfree = zcfree; - - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#ifdef FASTEST - level = 1; -#endif - - if (windowBits < 0) { /* undocumented feature: suppress zlib header */ - noheader = 1; - windowBits = -windowBits; - } - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || - windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_HUFFMAN_ONLY) { - return Z_STREAM_ERROR; - } - s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); - if (s == Z_NULL) return Z_MEM_ERROR; - strm->state = (struct internal_state FAR *)s; - s->strm = strm; - - s->noheader = noheader; - s->w_bits = windowBits; - s->w_size = 1 << s->w_bits; - s->w_mask = s->w_size - 1; - - s->hash_bits = memLevel + 7; - s->hash_size = 1 << s->hash_bits; - s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); - - s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); - s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); - s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); - - s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - s->pending_buf = (uchf *) overlay; - s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); - - if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || - s->pending_buf == Z_NULL) { - strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); - deflateEnd (strm); - return Z_MEM_ERROR; - } - s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - - s->level = level; - s->strategy = strategy; - s->method = (Byte)method; - - return deflateReset(strm); -} - -/* ========================================================================= */ -int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) - z_streamp strm; - const Bytef *dictionary; - uInt dictLength; -{ - deflate_state *s; - uInt length = dictLength; - uInt n; - IPos hash_head = 0; - - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || - strm->state->status != INIT_STATE) return Z_STREAM_ERROR; - - s = strm->state; - strm->adler = adler32(strm->adler, dictionary, dictLength); - - if (length < MIN_MATCH) return Z_OK; - if (length > MAX_DIST(s)) { - length = MAX_DIST(s); -#ifndef USE_DICT_HEAD - dictionary += dictLength - length; /* use the tail of the dictionary */ -#endif - } - zmemcpy(s->window, dictionary, length); - s->strstart = length; - s->block_start = (long)length; - - /* Insert all strings in the hash table (except for the last two bytes). - * s->lookahead stays null, so s->ins_h will be recomputed at the next - * call of fill_window. - */ - s->ins_h = s->window[0]; - UPDATE_HASH(s, s->ins_h, s->window[1]); - for (n = 0; n <= length - MIN_MATCH; n++) { - INSERT_STRING(s, n, hash_head); - } - if (hash_head) hash_head = 0; /* to make compiler happy */ - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateReset (strm) - z_streamp strm; -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; - - strm->total_in = strm->total_out = 0; - strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ - strm->data_type = Z_UNKNOWN; - - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; - - if (s->noheader < 0) { - s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ - } - s->status = s->noheader ? BUSY_STATE : INIT_STATE; - strm->adler = 1; - s->last_flush = Z_NO_FLUSH; - - _tr_init(s); - lm_init(s); - - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateParams(strm, level, strategy) - z_streamp strm; - int level; - int strategy; -{ - deflate_state *s; - compress_func func; - int err = Z_OK; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - - if (level == Z_DEFAULT_COMPRESSION) { - level = 6; - } - if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { - return Z_STREAM_ERROR; - } - func = configuration_table[s->level].func; - - if (func != configuration_table[level].func && strm->total_in != 0) { - /* Flush the last buffer: */ - err = deflate(strm, Z_PARTIAL_FLUSH); - } - if (s->level != level) { - s->level = level; - s->max_lazy_match = configuration_table[level].max_lazy; - s->good_match = configuration_table[level].good_length; - s->nice_match = configuration_table[level].nice_length; - s->max_chain_length = configuration_table[level].max_chain; - } - s->strategy = strategy; - return err; -} - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -local void putShortMSB (s, b) - deflate_state *s; - uInt b; -{ - put_byte(s, (Byte)(b >> 8)); - put_byte(s, (Byte)(b & 0xff)); -} - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). - */ -local void flush_pending(strm) - z_streamp strm; -{ - unsigned len = strm->state->pending; - - if (len > strm->avail_out) len = strm->avail_out; - if (len == 0) return; - - zmemcpy(strm->next_out, strm->state->pending_out, len); - strm->next_out += len; - strm->state->pending_out += len; - strm->total_out += len; - strm->avail_out -= len; - strm->state->pending -= len; - if (strm->state->pending == 0) { - strm->state->pending_out = strm->state->pending_buf; - } -} - -/* ========================================================================= */ -int ZEXPORT deflate (strm, flush) - z_streamp strm; - int flush; -{ - int old_flush; /* value of flush param for previous deflate call */ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_FINISH || flush < 0) { - return Z_STREAM_ERROR; - } - s = strm->state; - - if (strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0) || - (s->status == FINISH_STATE && flush != Z_FINISH)) { - ERR_RETURN(strm, Z_STREAM_ERROR); - } - if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - - s->strm = strm; /* just in case */ - old_flush = s->last_flush; - s->last_flush = flush; - - /* Write the zlib header */ - if (s->status == INIT_STATE) { - - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags = (s->level-1) >> 1; - - if (level_flags > 3) level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - s->status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = 1L; - } - - /* Flush as much pending output as possible */ - if (s->pending != 0) { - flush_pending(strm); - if (strm->avail_out == 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s->last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUFF_ERROR. - */ - } else if (strm->avail_in == 0 && flush <= old_flush && - flush != Z_FINISH) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm->avail_in != 0 || s->lookahead != 0 || - (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { - block_state bstate; - - bstate = (*(configuration_table[s->level].func))(s, flush); - - if (bstate == finish_started || bstate == finish_done) { - s->status = FINISH_STATE; - } - if (bstate == need_more || bstate == finish_started) { - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate == block_done) { - if (flush == Z_PARTIAL_FLUSH) { - _tr_align(s); - } else { /* FULL_FLUSH or SYNC_FLUSH */ - _tr_stored_block(s, (char*)0, 0L, 0); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush == Z_FULL_FLUSH) { - CLEAR_HASH(s); /* forget history */ - } - } - flush_pending(strm); - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - Assert(strm->avail_out > 0, "bug2"); - - if (flush != Z_FINISH) return Z_OK; - if (s->noheader) return Z_STREAM_END; - - /* Write the zlib trailer (adler32) */ - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - s->noheader = -1; /* write the trailer only once! */ - return s->pending != 0 ? Z_OK : Z_STREAM_END; -} - -/* ========================================================================= */ -int ZEXPORT deflateEnd (strm) - z_streamp strm; -{ - int status; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - - status = strm->state->status; - if (status != INIT_STATE && status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } - - /* Deallocate in reverse order of allocations: */ - TRY_FREE(strm, strm->state->pending_buf); - TRY_FREE(strm, strm->state->head); - TRY_FREE(strm, strm->state->prev); - TRY_FREE(strm, strm->state->window); - - ZFREE(strm, strm->state); - strm->state = Z_NULL; - - return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; -} - -/* ========================================================================= - * Copy the source state to the destination state. - * To simplify the source, this is not supported for 16-bit MSDOS (which - * doesn't have enough memory anyway to duplicate compression states). - */ -int ZEXPORT deflateCopy (dest, source) - z_streamp dest; - z_streamp source; -{ -#ifdef MAXSEG_64K - return Z_STREAM_ERROR; -#else - deflate_state *ds; - deflate_state *ss; - ushf *overlay; - - - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { - return Z_STREAM_ERROR; - } - - ss = source->state; - - *dest = *source; - - ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); - if (ds == Z_NULL) return Z_MEM_ERROR; - dest->state = (struct internal_state FAR *) ds; - *ds = *ss; - ds->strm = dest; - - ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); - ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); - ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); - ds->pending_buf = (uchf *) overlay; - - if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || - ds->pending_buf == Z_NULL) { - deflateEnd (dest); - return Z_MEM_ERROR; - } - /* following zmemcpy do not work for 16-bit MSDOS */ - zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); - zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); - - ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); - ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; - - ds->l_desc.dyn_tree = ds->dyn_ltree; - ds->d_desc.dyn_tree = ds->dyn_dtree; - ds->bl_desc.dyn_tree = ds->bl_tree; - - return Z_OK; -#endif -} - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -local int read_buf(strm, buf, size) - z_streamp strm; - Bytef *buf; - unsigned size; -{ - unsigned len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - if (!strm->state->noheader) { - strm->adler = adler32(strm->adler, strm->next_in, len); - } - zmemcpy(buf, strm->next_in, len); - strm->next_in += len; - strm->total_in += len; - - return (int)len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -local void lm_init (s) - deflate_state *s; -{ - s->window_size = (ulg)2L*s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; -#ifdef ASMV - match_init(); /* initialize the asm code */ -#endif -} - -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -#ifndef ASMV -/* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ -#ifndef FASTEST -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - unsigned chain_length = s->max_chain_length;/* max hash chain length */ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ - int nice_match = s->nice_match; /* stop if match long enough */ - IPos limit = s->strstart > (IPos)MAX_DIST(s) ? - s->strstart - (IPos)MAX_DIST(s) : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - Posf *prev = s->prev; - uInt wmask = s->w_mask; - -#ifdef UNALIGNED_OK - /* Compare two bytes at a time. Note: this is not always beneficial. - * Try with and without -DUNALIGNED_OK to check. - */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; - register ush scan_start = *(ushf*)scan; - register ush scan_end = *(ushf*)(scan+best_len-1); -#else - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - register Byte scan_end1 = scan[best_len-1]; - register Byte scan_end = scan[best_len]; -#endif - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s->prev_length >= s->good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - Assert(cur_match < s->strstart, "no future"); - match = s->window + cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2: - */ -#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) - /* This code assumes sizeof(unsigned short) == 2. Do not use - * UNALIGNED_OK if your compiler uses a different size. - */ - if (*(ushf*)(match+best_len-1) != scan_end || - *(ushf*)match != scan_start) continue; - - /* It is not necessary to compare scan[2] and match[2] since they are - * always equal when the other bytes match, given that the hash keys - * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart+3, +5, ... up to strstart+257. We check for insufficient - * lookahead only every 4th comparison; the 128th check will be made - * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is - * necessary to put more guard bytes at the end of the window, or - * to check more often for insufficient lookahead. - */ - Assert(scan[2] == match[2], "scan[2]?"); - scan++, match++; - do { - } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - scan < strend); - /* The funny "do {}" generates better code on most compilers */ - - /* Here, scan <= window+strstart+257 */ - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - if (*scan == *match) scan++; - - len = (MAX_MATCH - 1) - (int)(strend-scan); - scan = strend - (MAX_MATCH-1); - -#else /* UNALIGNED_OK */ - - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match++; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - -#endif /* UNALIGNED_OK */ - - if (len > best_len) { - s->match_start = cur_match; - best_len = len; - if (len >= nice_match) break; -#ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan+best_len-1); -#else - scan_end1 = scan[best_len-1]; - scan_end = scan[best_len]; -#endif - } - } while ((cur_match = prev[cur_match & wmask]) > limit - && --chain_length != 0); - - if ((uInt)best_len <= s->lookahead) return (uInt)best_len; - return s->lookahead; -} - -#else /* FASTEST */ -/* --------------------------------------------------------------------------- - * Optimized version for level == 1 only - */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - Assert(cur_match < s->strstart, "no future"); - - match = s->window + cur_match; - - /* Return failure if the match length is less than 2: - */ - if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match += 2; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - - if (len < MIN_MATCH) return MIN_MATCH - 1; - - s->match_start = cur_match; - return len <= s->lookahead ? len : s->lookahead; -} -#endif /* FASTEST */ -#endif /* ASMV */ - -#ifdef DEBUG -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -local void check_match(s, start, match, length) - deflate_state *s; - IPos start, match; - int length; -{ - /* check that the match is indeed a match */ - if (zmemcmp(s->window + match, - s->window + start, length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); - do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); - do { putc(s->window[start++], stderr); } while (--length != 0); - } -} -#else -# define check_match(s, start, match, length) -#endif - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -local void fill_window(s) - deflate_state *s; -{ - register unsigned n, m; - register Posf *p; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if strstart == 0 - * and lookahead == 1 (input done one byte at time) - */ - more--; - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - } else if (s->strstart >= wsize+MAX_DIST(s)) { - - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; -#ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#endif - more += wsize; - } - if (s->strm->avail_in == 0) return; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead >= MIN_MATCH) { - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); -} - -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ -#define FLUSH_BLOCK_ONLY(s, eof) { \ - _tr_flush_block(s, (s->block_start >= 0L ? \ - (charf *)&s->window[(unsigned)s->block_start] : \ - (charf *)Z_NULL), \ - (ulg)((long)s->strstart - s->block_start), \ - (eof)); \ - s->block_start = s->strstart; \ - flush_pending(s->strm); \ - Tracev((stderr,"[FLUSH]")); \ -} - -/* Same but force premature exit if necessary. */ -#define FLUSH_BLOCK(s, eof) { \ - FLUSH_BLOCK_ONLY(s, eof); \ - if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -local block_state deflate_stored(s, flush) - deflate_state *s; - int flush; -{ - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - ulg max_block_size = 0xffff; - ulg max_start; - - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { - - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (long)s->w_size, "slide too late"); - - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; - - if (s->lookahead == 0) break; /* flush the current block */ - } - Assert(s->block_start >= 0L, "block gone"); - - s->strstart += s->lookahead; - s->lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (ulg)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uInt)(s->strstart - max_start); - s->strstart = (uInt)max_start; - FLUSH_BLOCK(s, 0); - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); - } - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -local block_state deflate_fast(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head = NIL; /* head of the hash chain */ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - if (s->strategy != Z_HUFFMAN_ONLY) { - s->match_length = longest_match (s, hash_head); - } - /* longest_match() sets match_start */ - } - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->match_start, s->match_length); - - _tr_tally_dist(s, s->strstart - s->match_start, - s->match_length - MIN_MATCH, bflush); - - s->lookahead -= s->match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ -#ifndef FASTEST - if (s->match_length <= s->max_insert_length && - s->lookahead >= MIN_MATCH) { - s->match_length--; /* string at strstart already in hash table */ - do { - s->strstart++; - INSERT_STRING(s, s->strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s->match_length != 0); - s->strstart++; - } else -#endif - { - s->strstart += s->match_length; - s->match_length = 0; - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} - -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -local block_state deflate_slow(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head = NIL; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - */ - s->prev_length = s->match_length, s->prev_match = s->match_start; - s->match_length = MIN_MATCH-1; - - if (hash_head != NIL && s->prev_length < s->max_lazy_match && - s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - if (s->strategy != Z_HUFFMAN_ONLY) { - s->match_length = longest_match (s, hash_head); - } - /* longest_match() sets match_start */ - - if (s->match_length <= 5 && (s->strategy == Z_FILTERED || - (s->match_length == MIN_MATCH && - s->strstart - s->match_start > TOO_FAR))) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s->match_length = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { - uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - check_match(s, s->strstart-1, s->prev_match, s->prev_length); - - _tr_tally_dist(s, s->strstart -1 - s->prev_match, - s->prev_length - MIN_MATCH, bflush); - - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s->lookahead -= s->prev_length-1; - s->prev_length -= 2; - do { - if (++s->strstart <= max_insert) { - INSERT_STRING(s, s->strstart, hash_head); - } - } while (--s->prev_length != 0); - s->match_available = 0; - s->match_length = MIN_MATCH-1; - s->strstart++; - - if (bflush) FLUSH_BLOCK(s, 0); - - } else if (s->match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - if (bflush) { - FLUSH_BLOCK_ONLY(s, 0); - } - s->strstart++; - s->lookahead--; - if (s->strm->avail_out == 0) return need_more; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s->match_available = 1; - s->strstart++; - s->lookahead--; - } - } - Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - s->match_available = 0; - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} diff --git a/src/utilfuns/zlib/deflate.h b/src/utilfuns/zlib/deflate.h deleted file mode 100644 index 965e0a3..0000000 --- a/src/utilfuns/zlib/deflate.h +++ /dev/null @@ -1,318 +0,0 @@ -/* deflate.h -- internal compression state - * Copyright (C) 1995-2002 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id: deflate.h 1688 2005-01-01 04:42:26Z scribe $ */ - -#ifndef _DEFLATE_H -#define _DEFLATE_H - -#include "zutil.h" - -/* =========================================================================== - * Internal compression state. - */ - -#define LENGTH_CODES 29 -/* number of length codes, not counting the special END_BLOCK code */ - -#define LITERALS 256 -/* number of literal bytes 0..255 */ - -#define L_CODES (LITERALS+1+LENGTH_CODES) -/* number of Literal or Length codes, including the END_BLOCK code */ - -#define D_CODES 30 -/* number of distance codes */ - -#define BL_CODES 19 -/* number of codes used to transfer the bit lengths */ - -#define HEAP_SIZE (2*L_CODES+1) -/* maximum heap size */ - -#define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ - -#define INIT_STATE 42 -#define BUSY_STATE 113 -#define FINISH_STATE 666 -/* Stream status */ - - -/* Data structure describing a single value and its code string. */ -typedef struct ct_data_s { - union { - ush freq; /* frequency count */ - ush code; /* bit string */ - } fc; - union { - ush dad; /* father node in Huffman tree */ - ush len; /* length of bit string */ - } dl; -} FAR ct_data; - -#define Freq fc.freq -#define Code fc.code -#define Dad dl.dad -#define Len dl.len - -typedef struct static_tree_desc_s static_tree_desc; - -typedef struct tree_desc_s { - ct_data *dyn_tree; /* the dynamic tree */ - int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ -} FAR tree_desc; - -typedef ush Pos; -typedef Pos FAR Posf; -typedef unsigned IPos; - -/* A Pos is an index in the character window. We use short instead of int to - * save space in the various tables. IPos is used only for parameter passing. - */ - -typedef struct internal_state { - z_streamp strm; /* pointer back to this zlib stream */ - int status; /* as the name implies */ - Bytef *pending_buf; /* output still pending */ - ulg pending_buf_size; /* size of pending_buf */ - Bytef *pending_out; /* next pending byte to output to the stream */ - int pending; /* nb of bytes in the pending buffer */ - int noheader; /* suppress zlib header and adler32 */ - Byte data_type; /* UNKNOWN, BINARY or ASCII */ - Byte method; /* STORED (for zip only) or DEFLATED */ - int last_flush; /* value of flush param for previous deflate call */ - - /* used by deflate.c: */ - - uInt w_size; /* LZ77 window size (32K by default) */ - uInt w_bits; /* log2(w_size) (8..16) */ - uInt w_mask; /* w_size - 1 */ - - Bytef *window; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. Also, it limits - * the window size to 64K, which is quite useful on MSDOS. - * To do: use the user input buffer as sliding window. - */ - - ulg window_size; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - Posf *prev; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - Posf *head; /* Heads of the hash chains or NIL. */ - - uInt ins_h; /* hash index of string to be inserted */ - uInt hash_size; /* number of elements in hash table */ - uInt hash_bits; /* log2(hash_size) */ - uInt hash_mask; /* hash_size-1 */ - - uInt hash_shift; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - long block_start; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - uInt match_length; /* length of best match */ - IPos prev_match; /* previous match */ - int match_available; /* set if previous match exists */ - uInt strstart; /* start of string to insert */ - uInt match_start; /* start of matching string */ - uInt lookahead; /* number of valid bytes ahead in window */ - - uInt prev_length; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - uInt max_chain_length; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - uInt max_lazy_match; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ -# define max_insert_length max_lazy_match - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - int level; /* compression level (1..9) */ - int strategy; /* favor or force Huffman coding*/ - - uInt good_match; - /* Use a faster search when the previous match is longer than this */ - - int nice_match; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - /* Didn't use ct_data typedef below to supress compiler warning */ - struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - struct tree_desc_s l_desc; /* desc. for literal tree */ - struct tree_desc_s d_desc; /* desc. for distance tree */ - struct tree_desc_s bl_desc; /* desc. for bit length tree */ - - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - int heap_len; /* number of elements in the heap */ - int heap_max; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - uch depth[2*L_CODES+1]; - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - uchf *l_buf; /* buffer for literals or lengths */ - - uInt lit_bufsize; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - uInt last_lit; /* running index in l_buf */ - - ushf *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - ulg opt_len; /* bit length of current block with optimal trees */ - ulg static_len; /* bit length of current block with static trees */ - uInt matches; /* number of string matches in current block */ - int last_eob_len; /* bit length of EOB code for last block */ - -#ifdef DEBUG - ulg compressed_len; /* total bit length of compressed file mod 2^32 */ - ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ -#endif - - ush bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - int bi_valid; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - -} FAR deflate_state; - -/* Output a byte on the stream. - * IN assertion: there is enough room in pending_buf. - */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} - - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - - /* in trees.c */ -void _tr_init OF((deflate_state *s)); -int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, - int eof)); -void _tr_align OF((deflate_state *s)); -void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, - int eof)); - -#define d_code(dist) \ - ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. _dist_code[256] and _dist_code[257] are never - * used. - */ - -#ifndef DEBUG -/* Inline versions of _tr_tally for speed: */ - -#if defined(GEN_TREES_H) || !defined(STDC) - extern uch _length_code[]; - extern uch _dist_code[]; -#else - extern const uch _length_code[]; - extern const uch _dist_code[]; -#endif - -# define _tr_tally_lit(s, c, flush) \ - { uch cc = (c); \ - s->d_buf[s->last_lit] = 0; \ - s->l_buf[s->last_lit++] = cc; \ - s->dyn_ltree[cc].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -# define _tr_tally_dist(s, distance, length, flush) \ - { uch len = (length); \ - ush dist = (distance); \ - s->d_buf[s->last_lit] = dist; \ - s->l_buf[s->last_lit++] = len; \ - dist--; \ - s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ - s->dyn_dtree[d_code(dist)].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -#else -# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) -# define _tr_tally_dist(s, distance, length, flush) \ - flush = _tr_tally(s, distance, length) -#endif - -#endif diff --git a/src/utilfuns/zlib/gzio.c b/src/utilfuns/zlib/gzio.c deleted file mode 100644 index 612c154..0000000 --- a/src/utilfuns/zlib/gzio.c +++ /dev/null @@ -1,875 +0,0 @@ -/* gzio.c -- IO on .gz files - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Compile this file with -DNO_DEFLATE to avoid the compression code. - */ - -/* @(#) $Id: gzio.c 1688 2005-01-01 04:42:26Z scribe $ */ - -#include <stdio.h> - -#include "zutil.h" - -struct internal_state {int dummy;}; /* for buggy compilers */ - -#ifndef Z_BUFSIZE -# ifdef MAXSEG_64K -# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ -# else -# define Z_BUFSIZE 16384 -# endif -#endif -#ifndef Z_PRINTF_BUFSIZE -# define Z_PRINTF_BUFSIZE 4096 -#endif - -#define ALLOC(size) malloc(size) -#define TRYFREE(p) {if (p) free(p);} - -static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define RESERVED 0xE0 /* bits 5..7: reserved */ - -typedef struct gz_stream { - z_stream stream; - int z_err; /* error code for last stream operation */ - int z_eof; /* set if end of input file */ - FILE *file; /* .gz file */ - Byte *inbuf; /* input buffer */ - Byte *outbuf; /* output buffer */ - uLong crc; /* crc32 of uncompressed data */ - char *msg; /* error message */ - char *path; /* path name for debugging only */ - int transparent; /* 1 if input file is not a .gz file */ - char mode; /* 'w' or 'r' */ - long startpos; /* start of compressed data in file (header skipped) */ -} gz_stream; - - -local gzFile gz_open OF((const char *path, const char *mode, int fd)); -local int do_flush OF((gzFile file, int flush)); -local int get_byte OF((gz_stream *s)); -local void check_header OF((gz_stream *s)); -local int destroy OF((gz_stream *s)); -local void putLong OF((FILE *file, uLong x)); -local uLong getLong OF((gz_stream *s)); - -/* =========================================================================== - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb"). The file is given either by file descriptor - or path name (if fd == -1). - gz_open return NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). -*/ -local gzFile gz_open (path, mode, fd) - const char *path; - const char *mode; - int fd; -{ - int err; - int level = Z_DEFAULT_COMPRESSION; /* compression level */ - int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ - char *p = (char*)mode; - gz_stream *s; - char fmode[80]; /* copy of mode, without the compression level */ - char *m = fmode; - - if (!path || !mode) return Z_NULL; - - s = (gz_stream *)ALLOC(sizeof(gz_stream)); - if (!s) return Z_NULL; - - s->stream.zalloc = (alloc_func)0; - s->stream.zfree = (free_func)0; - s->stream.opaque = (voidpf)0; - s->stream.next_in = s->inbuf = Z_NULL; - s->stream.next_out = s->outbuf = Z_NULL; - s->stream.avail_in = s->stream.avail_out = 0; - s->file = NULL; - s->z_err = Z_OK; - s->z_eof = 0; - s->crc = crc32(0L, Z_NULL, 0); - s->msg = NULL; - s->transparent = 0; - - s->path = (char*)ALLOC(strlen(path)+1); - if (s->path == NULL) { - return destroy(s), (gzFile)Z_NULL; - } - strcpy(s->path, path); /* do this early for debugging */ - - s->mode = '\0'; - do { - if (*p == 'r') s->mode = 'r'; - if (*p == 'w' || *p == 'a') s->mode = 'w'; - if (*p >= '0' && *p <= '9') { - level = *p - '0'; - } else if (*p == 'f') { - strategy = Z_FILTERED; - } else if (*p == 'h') { - strategy = Z_HUFFMAN_ONLY; - } else { - *m++ = *p; /* copy the mode */ - } - } while (*p++ && m != fmode + sizeof(fmode)); - if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; - - if (s->mode == 'w') { -#ifdef NO_DEFLATE - err = Z_STREAM_ERROR; -#else - err = deflateInit2(&(s->stream), level, - Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); - /* windowBits is passed < 0 to suppress zlib header */ - - s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); -#endif - if (err != Z_OK || s->outbuf == Z_NULL) { - return destroy(s), (gzFile)Z_NULL; - } - } else { - s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); - - err = inflateInit2(&(s->stream), -MAX_WBITS); - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are - * present after the compressed stream. - */ - if (err != Z_OK || s->inbuf == Z_NULL) { - return destroy(s), (gzFile)Z_NULL; - } - } - s->stream.avail_out = Z_BUFSIZE; - - errno = 0; - s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); - - if (s->file == NULL) { - return destroy(s), (gzFile)Z_NULL; - } - if (s->mode == 'w') { - /* Write a very simple .gz header: - */ - fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], - Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); - s->startpos = 10L; - /* We use 10L instead of ftell(s->file) to because ftell causes an - * fflush on some systems. This version of the library doesn't use - * startpos anyway in write mode, so this initialization is not - * necessary. - */ - } else { - check_header(s); /* skip the .gz header */ - s->startpos = (ftell(s->file) - s->stream.avail_in); - } - - return (gzFile)s; -} - -/* =========================================================================== - Opens a gzip (.gz) file for reading or writing. -*/ -gzFile ZEXPORT gzopen (path, mode) - const char *path; - const char *mode; -{ - return gz_open (path, mode, -1); -} - -/* =========================================================================== - Associate a gzFile with the file descriptor fd. fd is not dup'ed here - to mimic the behavio(u)r of fdopen. -*/ -gzFile ZEXPORT gzdopen (fd, mode) - int fd; - const char *mode; -{ - char name[20]; - - if (fd < 0) return (gzFile)Z_NULL; - sprintf(name, "<fd:%d>", fd); /* for debugging */ - - return gz_open (name, mode, fd); -} - -/* =========================================================================== - * Update the compression level and strategy - */ -int ZEXPORT gzsetparams (file, level, strategy) - gzFile file; - int level; - int strategy; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - /* Make room to allow flushing */ - if (s->stream.avail_out == 0) { - - s->stream.next_out = s->outbuf; - if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { - s->z_err = Z_ERRNO; - } - s->stream.avail_out = Z_BUFSIZE; - } - - return deflateParams (&(s->stream), level, strategy); -} - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been sucessfully opened for reading. -*/ -local int get_byte(s) - gz_stream *s; -{ - if (s->z_eof) return EOF; - if (s->stream.avail_in == 0) { - errno = 0; - s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); - if (s->stream.avail_in == 0) { - s->z_eof = 1; - if (ferror(s->file)) s->z_err = Z_ERRNO; - return EOF; - } - s->stream.next_in = s->inbuf; - } - s->stream.avail_in--; - return *(s->stream.next_in)++; -} - -/* =========================================================================== - Check the gzip header of a gz_stream opened for reading. Set the stream - mode to transparent if the gzip magic header is not present; set s->err - to Z_DATA_ERROR if the magic header is present but the rest of the header - is incorrect. - IN assertion: the stream s has already been created sucessfully; - s->stream.avail_in is zero for the first time, but may be non-zero - for concatenated .gz files. -*/ -local void check_header(s) - gz_stream *s; -{ - int method; /* method byte */ - int flags; /* flags byte */ - uInt len; - int c; - - /* Check the gzip magic header */ - for (len = 0; len < 2; len++) { - c = get_byte(s); - if (c != gz_magic[len]) { - if (len != 0) s->stream.avail_in++, s->stream.next_in--; - if (c != EOF) { - s->stream.avail_in++, s->stream.next_in--; - s->transparent = 1; - } - s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END; - return; - } - } - method = get_byte(s); - flags = get_byte(s); - if (method != Z_DEFLATED || (flags & RESERVED) != 0) { - s->z_err = Z_DATA_ERROR; - return; - } - - /* Discard time, xflags and OS code: */ - for (len = 0; len < 6; len++) (void)get_byte(s); - - if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ - len = (uInt)get_byte(s); - len += ((uInt)get_byte(s))<<8; - /* len is garbage if EOF but the loop below will quit anyway */ - while (len-- != 0 && get_byte(s) != EOF) ; - } - if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ - while ((c = get_byte(s)) != 0 && c != EOF) ; - } - if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ - while ((c = get_byte(s)) != 0 && c != EOF) ; - } - if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ - for (len = 0; len < 2; len++) (void)get_byte(s); - } - s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; -} - - /* =========================================================================== - * Cleanup then free the given gz_stream. Return a zlib error code. - Try freeing in the reverse order of allocations. - */ -local int destroy (s) - gz_stream *s; -{ - int err = Z_OK; - - if (!s) return Z_STREAM_ERROR; - - TRYFREE(s->msg); - - if (s->stream.state != NULL) { - if (s->mode == 'w') { -#ifdef NO_DEFLATE - err = Z_STREAM_ERROR; -#else - err = deflateEnd(&(s->stream)); -#endif - } else if (s->mode == 'r') { - err = inflateEnd(&(s->stream)); - } - } - if (s->file != NULL && fclose(s->file)) { -#ifdef ESPIPE - if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ -#endif - err = Z_ERRNO; - } - if (s->z_err < 0) err = s->z_err; - - TRYFREE(s->inbuf); - TRYFREE(s->outbuf); - TRYFREE(s->path); - TRYFREE(s); - return err; -} - -/* =========================================================================== - Reads the given number of uncompressed bytes from the compressed file. - gzread returns the number of bytes actually read (0 for end of file). -*/ -int ZEXPORT gzread (file, buf, len) - gzFile file; - voidp buf; - unsigned len; -{ - gz_stream *s = (gz_stream*)file; - Bytef *start = (Bytef*)buf; /* starting point for crc computation */ - Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ - - if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; - - if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; - if (s->z_err == Z_STREAM_END) return 0; /* EOF */ - - next_out = (Byte*)buf; - s->stream.next_out = (Bytef*)buf; - s->stream.avail_out = len; - - while (s->stream.avail_out != 0) { - - if (s->transparent) { - /* Copy first the lookahead bytes: */ - uInt n = s->stream.avail_in; - if (n > s->stream.avail_out) n = s->stream.avail_out; - if (n > 0) { - zmemcpy(s->stream.next_out, s->stream.next_in, n); - next_out += n; - s->stream.next_out = next_out; - s->stream.next_in += n; - s->stream.avail_out -= n; - s->stream.avail_in -= n; - } - if (s->stream.avail_out > 0) { - s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, - s->file); - } - len -= s->stream.avail_out; - s->stream.total_in += (uLong)len; - s->stream.total_out += (uLong)len; - if (len == 0) s->z_eof = 1; - return (int)len; - } - if (s->stream.avail_in == 0 && !s->z_eof) { - - errno = 0; - s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); - if (s->stream.avail_in == 0) { - s->z_eof = 1; - if (ferror(s->file)) { - s->z_err = Z_ERRNO; - break; - } - } - s->stream.next_in = s->inbuf; - } - s->z_err = inflate(&(s->stream), Z_NO_FLUSH); - - if (s->z_err == Z_STREAM_END) { - /* Check CRC and original size */ - s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); - start = s->stream.next_out; - - if (getLong(s) != s->crc) { - s->z_err = Z_DATA_ERROR; - } else { - (void)getLong(s); - /* The uncompressed length returned by above getlong() may - * be different from s->stream.total_out) in case of - * concatenated .gz files. Check for such files: - */ - check_header(s); - if (s->z_err == Z_OK) { - uLong total_in = s->stream.total_in; - uLong total_out = s->stream.total_out; - - inflateReset(&(s->stream)); - s->stream.total_in = total_in; - s->stream.total_out = total_out; - s->crc = crc32(0L, Z_NULL, 0); - } - } - } - if (s->z_err != Z_OK || s->z_eof) break; - } - s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); - - return (int)(len - s->stream.avail_out); -} - - -/* =========================================================================== - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ -int ZEXPORT gzgetc(file) - gzFile file; -{ - unsigned char c; - - return gzread(file, &c, 1) == 1 ? c : -1; -} - - -/* =========================================================================== - Reads bytes from the compressed file until len-1 characters are - read, or a newline character is read and transferred to buf, or an - end-of-file condition is encountered. The string is then terminated - with a null character. - gzgets returns buf, or Z_NULL in case of error. - - The current implementation is not optimized at all. -*/ -char * ZEXPORT gzgets(file, buf, len) - gzFile file; - char *buf; - int len; -{ - char *b = buf; - if (buf == Z_NULL || len <= 0) return Z_NULL; - - while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; - *buf = '\0'; - return b == buf && len > 0 ? Z_NULL : b; -} - - -#ifndef NO_DEFLATE -/* =========================================================================== - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of bytes actually written (0 in case of error). -*/ -int ZEXPORT gzwrite (file, buf, len) - gzFile file; - const voidp buf; - unsigned len; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - s->stream.next_in = (Bytef*)buf; - s->stream.avail_in = len; - - while (s->stream.avail_in != 0) { - - if (s->stream.avail_out == 0) { - - s->stream.next_out = s->outbuf; - if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { - s->z_err = Z_ERRNO; - break; - } - s->stream.avail_out = Z_BUFSIZE; - } - s->z_err = deflate(&(s->stream), Z_NO_FLUSH); - if (s->z_err != Z_OK) break; - } - s->crc = crc32(s->crc, (const Bytef *)buf, len); - - return (int)(len - s->stream.avail_in); -} - -/* =========================================================================== - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). -*/ -#ifdef STDC -#include <stdarg.h> - -int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) -{ - char buf[Z_PRINTF_BUFSIZE]; - va_list va; - int len; - - va_start(va, format); -#ifdef HAS_vsnprintf - (void)vsnprintf(buf, sizeof(buf), format, va); -#else - (void)vsprintf(buf, format, va); -#endif - va_end(va); - len = strlen(buf); /* some *sprintf don't return the nb of bytes written */ - if (len <= 0) return 0; - - return gzwrite(file, buf, (unsigned)len); -} -#else /* not ANSI C */ - -int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) - gzFile file; - const char *format; - int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; -{ - char buf[Z_PRINTF_BUFSIZE]; - int len; - -#ifdef HAS_snprintf - snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); -#else - sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); -#endif - len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */ - if (len <= 0) return 0; - - return gzwrite(file, buf, len); -} -#endif - -/* =========================================================================== - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ -int ZEXPORT gzputc(file, c) - gzFile file; - int c; -{ - unsigned char cc = (unsigned char) c; /* required for big endian systems */ - - return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; -} - - -/* =========================================================================== - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. -*/ -int ZEXPORT gzputs(file, s) - gzFile file; - const char *s; -{ - return gzwrite(file, (char*)s, (unsigned)strlen(s)); -} - - -/* =========================================================================== - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. -*/ -local int do_flush (file, flush) - gzFile file; - int flush; -{ - uInt len; - int done = 0; - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - s->stream.avail_in = 0; /* should be zero already anyway */ - - for (;;) { - len = Z_BUFSIZE - s->stream.avail_out; - - if (len != 0) { - if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { - s->z_err = Z_ERRNO; - return Z_ERRNO; - } - s->stream.next_out = s->outbuf; - s->stream.avail_out = Z_BUFSIZE; - } - if (done) break; - s->z_err = deflate(&(s->stream), flush); - - /* Ignore the second of two consecutive flushes: */ - if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; - - /* deflate has finished flushing only when it hasn't used up - * all the available space in the output buffer: - */ - done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); - - if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; - } - return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; -} - -int ZEXPORT gzflush (file, flush) - gzFile file; - int flush; -{ - gz_stream *s = (gz_stream*)file; - int err = do_flush (file, flush); - - if (err) return err; - fflush(s->file); - return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; -} -#endif /* NO_DEFLATE */ - -/* =========================================================================== - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error. - SEEK_END is not implemented, returns error. - In this version of the library, gzseek can be extremely slow. -*/ -z_off_t ZEXPORT gzseek (file, offset, whence) - gzFile file; - z_off_t offset; - int whence; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || whence == SEEK_END || - s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { - return -1L; - } - - if (s->mode == 'w') { -#ifdef NO_DEFLATE - return -1L; -#else - if (whence == SEEK_SET) { - offset -= s->stream.total_in; - } - if (offset < 0) return -1L; - - /* At this point, offset is the number of zero bytes to write. */ - if (s->inbuf == Z_NULL) { - s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ - zmemzero(s->inbuf, Z_BUFSIZE); - } - while (offset > 0) { - uInt size = Z_BUFSIZE; - if (offset < Z_BUFSIZE) size = (uInt)offset; - - size = gzwrite(file, s->inbuf, size); - if (size == 0) return -1L; - - offset -= size; - } - return (z_off_t)s->stream.total_in; -#endif - } - /* Rest of function is for reading only */ - - /* compute absolute position */ - if (whence == SEEK_CUR) { - offset += s->stream.total_out; - } - if (offset < 0) return -1L; - - if (s->transparent) { - /* map to fseek */ - s->stream.avail_in = 0; - s->stream.next_in = s->inbuf; - if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; - - s->stream.total_in = s->stream.total_out = (uLong)offset; - return offset; - } - - /* For a negative seek, rewind and use positive seek */ - if ((uLong)offset >= s->stream.total_out) { - offset -= s->stream.total_out; - } else if (gzrewind(file) < 0) { - return -1L; - } - /* offset is now the number of bytes to skip. */ - - if (offset != 0 && s->outbuf == Z_NULL) { - s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); - } - while (offset > 0) { - int size = Z_BUFSIZE; - if (offset < Z_BUFSIZE) size = (int)offset; - - size = gzread(file, s->outbuf, (uInt)size); - if (size <= 0) return -1L; - offset -= size; - } - return (z_off_t)s->stream.total_out; -} - -/* =========================================================================== - Rewinds input file. -*/ -int ZEXPORT gzrewind (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'r') return -1; - - s->z_err = Z_OK; - s->z_eof = 0; - s->stream.avail_in = 0; - s->stream.next_in = s->inbuf; - s->crc = crc32(0L, Z_NULL, 0); - - if (s->startpos == 0) { /* not a compressed file */ - rewind(s->file); - return 0; - } - - (void) inflateReset(&s->stream); - return fseek(s->file, s->startpos, SEEK_SET); -} - -/* =========================================================================== - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. -*/ -z_off_t ZEXPORT gztell (file) - gzFile file; -{ - return gzseek(file, 0L, SEEK_CUR); -} - -/* =========================================================================== - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. -*/ -int ZEXPORT gzeof (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - return (s == NULL || s->mode != 'r') ? 0 : s->z_eof; -} - -/* =========================================================================== - Outputs a long in LSB order to the given file -*/ -local void putLong (file, x) - FILE *file; - uLong x; -{ - int n; - for (n = 0; n < 4; n++) { - fputc((int)(x & 0xff), file); - x >>= 8; - } -} - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets z_err in case - of error. -*/ -local uLong getLong (s) - gz_stream *s; -{ - uLong x = (uLong)get_byte(s); - int c; - - x += ((uLong)get_byte(s))<<8; - x += ((uLong)get_byte(s))<<16; - c = get_byte(s); - if (c == EOF) s->z_err = Z_DATA_ERROR; - x += ((uLong)c)<<24; - return x; -} - -/* =========================================================================== - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. -*/ -int ZEXPORT gzclose (file) - gzFile file; -{ - int err; - gz_stream *s = (gz_stream*)file; - - if (s == NULL) return Z_STREAM_ERROR; - - if (s->mode == 'w') { -#ifdef NO_DEFLATE - return Z_STREAM_ERROR; -#else - err = do_flush (file, Z_FINISH); - if (err != Z_OK) return destroy((gz_stream*)file); - - putLong (s->file, s->crc); - putLong (s->file, s->stream.total_in); -#endif - } - return destroy((gz_stream*)file); -} - -/* =========================================================================== - Returns the error message for the last error which occured on the - given compressed file. errnum is set to zlib error number. If an - error occured in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. -*/ -const char* ZEXPORT gzerror (file, errnum) - gzFile file; - int *errnum; -{ - char *m; - gz_stream *s = (gz_stream*)file; - - if (s == NULL) { - *errnum = Z_STREAM_ERROR; - return (const char*)ERR_MSG(Z_STREAM_ERROR); - } - *errnum = s->z_err; - if (*errnum == Z_OK) return (const char*)""; - - m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); - - if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); - - TRYFREE(s->msg); - s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); - strcpy(s->msg, s->path); - strcat(s->msg, ": "); - strcat(s->msg, m); - return (const char*)s->msg; -} diff --git a/src/utilfuns/zlib/infblock.c b/src/utilfuns/zlib/infblock.c deleted file mode 100644 index dd7a6d4..0000000 --- a/src/utilfuns/zlib/infblock.c +++ /dev/null @@ -1,403 +0,0 @@ -/* infblock.c -- interpret and process block types to last block - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infblock.h" -#include "inftrees.h" -#include "infcodes.h" -#include "infutil.h" - -struct inflate_codes_state {int dummy;}; /* for buggy compilers */ - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -/* Table for deflate from PKZIP's appnote.txt. */ -local const uInt border[] = { /* Order of the bit length code lengths */ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -/* - Notes beyond the 1.93a appnote.txt: - - 1. Distance pointers never point before the beginning of the output - stream. - 2. Distance pointers can point back across blocks, up to 32k away. - 3. There is an implied maximum of 7 bits for the bit length table and - 15 bits for the actual data. - 4. If only one code exists, then it is encoded using one bit. (Zero - would be more efficient, but perhaps a little confusing.) If two - codes exist, they are coded using one bit each (0 and 1). - 5. There is no way of sending zero distance codes--a dummy must be - sent if there are none. (History: a pre 2.0 version of PKZIP would - store blocks with no distance codes, but this was discovered to be - too harsh a criterion.) Valid only for 1.93a. 2.04c does allow - zero distance codes, which is sent as one code of zero bits in - length. - 6. There are up to 286 literal/length codes. Code 256 represents the - end-of-block. Note however that the static length tree defines - 288 codes just to fill out the Huffman codes. Codes 286 and 287 - cannot be used though, since there is no length base or extra bits - defined for them. Similarily, there are up to 30 distance codes. - However, static trees define 32 codes (all 5 bits) to fill out the - Huffman codes, but the last two had better not show up in the data. - 7. Unzip can check dynamic Huffman blocks for complete code sets. - The exception is that a single code would not be complete (see #4). - 8. The five bits following the block type is really the number of - literal codes sent minus 257. - 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits - (1+6+6). Therefore, to output three times the length, you output - three codes (1+1+1), whereas to output four times the same length, - you only need two codes (1+3). Hmm. - 10. In the tree reconstruction algorithm, Code = Code + Increment - only if BitLength(i) is not zero. (Pretty obvious.) - 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) - 12. Note: length code 284 can represent 227-258, but length code 285 - really is 258. The last length deserves its own, short code - since it gets used a lot in very redundant files. The length - 258 is special since 258 - 3 (the min match length) is 255. - 13. The literal/length and distance code bit lengths are read as a - single stream of lengths. It is possible (and advantageous) for - a repeat code (16, 17, or 18) to go across the boundary between - the two sets of lengths. - */ - - -void inflate_blocks_reset(s, z, c) -inflate_blocks_statef *s; -z_streamp z; -uLongf *c; -{ - if (c != Z_NULL) - *c = s->check; - if (s->mode == BTREE || s->mode == DTREE) - ZFREE(z, s->sub.trees.blens); - if (s->mode == CODES) - inflate_codes_free(s->sub.decode.codes, z); - s->mode = TYPE; - s->bitk = 0; - s->bitb = 0; - s->read = s->write = s->window; - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); - Tracev((stderr, "inflate: blocks reset\n")); -} - - -inflate_blocks_statef *inflate_blocks_new(z, c, w) -z_streamp z; -check_func c; -uInt w; -{ - inflate_blocks_statef *s; - - if ((s = (inflate_blocks_statef *)ZALLOC - (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) - return s; - if ((s->hufts = - (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) - { - ZFREE(z, s); - return Z_NULL; - } - if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) - { - ZFREE(z, s->hufts); - ZFREE(z, s); - return Z_NULL; - } - s->end = s->window + w; - s->checkfn = c; - s->mode = TYPE; - Tracev((stderr, "inflate: blocks allocated\n")); - inflate_blocks_reset(s, z, Z_NULL); - return s; -} - - -int inflate_blocks(s, z, r) -inflate_blocks_statef *s; -z_streamp z; -int r; -{ - uInt t; /* temporary storage */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input based on current state */ - while (1) switch (s->mode) - { - case TYPE: - NEEDBITS(3) - t = (uInt)b & 7; - s->last = t & 1; - switch (t >> 1) - { - case 0: /* stored */ - Tracev((stderr, "inflate: stored block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - t = k & 7; /* go to byte boundary */ - DUMPBITS(t) - s->mode = LENS; /* get length of stored block */ - break; - case 1: /* fixed */ - Tracev((stderr, "inflate: fixed codes block%s\n", - s->last ? " (last)" : "")); - { - uInt bl, bd; - inflate_huft *tl, *td; - - inflate_trees_fixed(&bl, &bd, &tl, &td, z); - s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); - if (s->sub.decode.codes == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - } - DUMPBITS(3) - s->mode = CODES; - break; - case 2: /* dynamic */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - s->mode = TABLE; - break; - case 3: /* illegal */ - DUMPBITS(3) - s->mode = BAD; - z->msg = (char*)"invalid block type"; - r = Z_DATA_ERROR; - LEAVE - } - break; - case LENS: - NEEDBITS(32) - if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) - { - s->mode = BAD; - z->msg = (char*)"invalid stored block lengths"; - r = Z_DATA_ERROR; - LEAVE - } - s->sub.left = (uInt)b & 0xffff; - b = k = 0; /* dump bits */ - Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); - s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); - break; - case STORED: - if (n == 0) - LEAVE - NEEDOUT - t = s->sub.left; - if (t > n) t = n; - if (t > m) t = m; - zmemcpy(q, p, t); - p += t; n -= t; - q += t; m -= t; - if ((s->sub.left -= t) != 0) - break; - Tracev((stderr, "inflate: stored end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - s->mode = s->last ? DRY : TYPE; - break; - case TABLE: - NEEDBITS(14) - s->sub.trees.table = t = (uInt)b & 0x3fff; -#ifndef PKZIP_BUG_WORKAROUND - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - s->mode = BAD; - z->msg = (char*)"too many length or distance symbols"; - r = Z_DATA_ERROR; - LEAVE - } -#endif - t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); - if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - DUMPBITS(14) - s->sub.trees.index = 0; - Tracev((stderr, "inflate: table sizes ok\n")); - s->mode = BTREE; - case BTREE: - while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) - { - NEEDBITS(3) - s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; - DUMPBITS(3) - } - while (s->sub.trees.index < 19) - s->sub.trees.blens[border[s->sub.trees.index++]] = 0; - s->sub.trees.bb = 7; - t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, - &s->sub.trees.tb, s->hufts, z); - if (t != Z_OK) - { - r = t; - if (r == Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - } - LEAVE - } - s->sub.trees.index = 0; - Tracev((stderr, "inflate: bits tree ok\n")); - s->mode = DTREE; - case DTREE: - while (t = s->sub.trees.table, - s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) - { - inflate_huft *h; - uInt i, j, c; - - t = s->sub.trees.bb; - NEEDBITS(t) - h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); - t = h->bits; - c = h->base; - if (c < 16) - { - DUMPBITS(t) - s->sub.trees.blens[s->sub.trees.index++] = c; - } - else /* c == 16..18 */ - { - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - NEEDBITS(t + i) - DUMPBITS(t) - j += (uInt)b & inflate_mask[i]; - DUMPBITS(i) - i = s->sub.trees.index; - t = s->sub.trees.table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || - (c == 16 && i < 1)) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - z->msg = (char*)"invalid bit length repeat"; - r = Z_DATA_ERROR; - LEAVE - } - c = c == 16 ? s->sub.trees.blens[i - 1] : 0; - do { - s->sub.trees.blens[i++] = c; - } while (--j); - s->sub.trees.index = i; - } - } - s->sub.trees.tb = Z_NULL; - { - uInt bl, bd; - inflate_huft *tl, *td; - inflate_codes_statef *c; - - bl = 9; /* must be <= 9 for lookahead assumptions */ - bd = 6; /* must be <= 9 for lookahead assumptions */ - t = s->sub.trees.table; - t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), - s->sub.trees.blens, &bl, &bd, &tl, &td, - s->hufts, z); - if (t != Z_OK) - { - if (t == (uInt)Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - } - r = t; - LEAVE - } - Tracev((stderr, "inflate: trees ok\n")); - if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.decode.codes = c; - } - ZFREE(z, s->sub.trees.blens); - s->mode = CODES; - case CODES: - UPDATE - if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) - return inflate_flush(s, z, r); - r = Z_OK; - inflate_codes_free(s->sub.decode.codes, z); - LOAD - Tracev((stderr, "inflate: codes end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - if (!s->last) - { - s->mode = TYPE; - break; - } - s->mode = DRY; - case DRY: - FLUSH - if (s->read != s->write) - LEAVE - s->mode = DONE; - case DONE: - r = Z_STREAM_END; - LEAVE - case BAD: - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -} - - -int inflate_blocks_free(s, z) -inflate_blocks_statef *s; -z_streamp z; -{ - inflate_blocks_reset(s, z, Z_NULL); - ZFREE(z, s->window); - ZFREE(z, s->hufts); - ZFREE(z, s); - Tracev((stderr, "inflate: blocks freed\n")); - return Z_OK; -} - - -void inflate_set_dictionary(s, d, n) -inflate_blocks_statef *s; -const Bytef *d; -uInt n; -{ - zmemcpy(s->window, d, n); - s->read = s->write = s->window + n; -} - - -/* Returns true if inflate is currently at the end of a block generated - * by Z_SYNC_FLUSH or Z_FULL_FLUSH. - * IN assertion: s != Z_NULL - */ -int inflate_blocks_sync_point(s) -inflate_blocks_statef *s; -{ - return s->mode == LENS; -} diff --git a/src/utilfuns/zlib/infblock.h b/src/utilfuns/zlib/infblock.h deleted file mode 100644 index 173b226..0000000 --- a/src/utilfuns/zlib/infblock.h +++ /dev/null @@ -1,39 +0,0 @@ -/* infblock.h -- header to use infblock.c - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -struct inflate_blocks_state; -typedef struct inflate_blocks_state FAR inflate_blocks_statef; - -extern inflate_blocks_statef * inflate_blocks_new OF(( - z_streamp z, - check_func c, /* check function */ - uInt w)); /* window size */ - -extern int inflate_blocks OF(( - inflate_blocks_statef *, - z_streamp , - int)); /* initial return code */ - -extern void inflate_blocks_reset OF(( - inflate_blocks_statef *, - z_streamp , - uLongf *)); /* check value on output */ - -extern int inflate_blocks_free OF(( - inflate_blocks_statef *, - z_streamp)); - -extern void inflate_set_dictionary OF(( - inflate_blocks_statef *s, - const Bytef *d, /* dictionary */ - uInt n)); /* dictionary length */ - -extern int inflate_blocks_sync_point OF(( - inflate_blocks_statef *s)); diff --git a/src/utilfuns/zlib/infcodes.c b/src/utilfuns/zlib/infcodes.c deleted file mode 100644 index 0d54ea7..0000000 --- a/src/utilfuns/zlib/infcodes.c +++ /dev/null @@ -1,251 +0,0 @@ -/* infcodes.c -- process literals and length/distance pairs - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" -#include "infblock.h" -#include "infcodes.h" -#include "infutil.h" -#include "inffast.h" - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - START, /* x: set up for LEN */ - LEN, /* i: get length/literal/eob next */ - LENEXT, /* i: getting length extra (have base) */ - DIST, /* i: get distance next */ - DISTEXT, /* i: getting distance extra */ - COPY, /* o: copying bytes in window, waiting for space */ - LIT, /* o: got literal, waiting for output space */ - WASH, /* o: got eob, possibly still output waiting */ - END, /* x: got eob and all data flushed */ - BADCODE} /* x: got error */ -inflate_codes_mode; - -/* inflate codes private state */ -struct inflate_codes_state { - - /* mode */ - inflate_codes_mode mode; /* current inflate_codes mode */ - - /* mode dependent information */ - uInt len; - union { - struct { - inflate_huft *tree; /* pointer into tree */ - uInt need; /* bits needed */ - } code; /* if LEN or DIST, where in tree */ - uInt lit; /* if LIT, literal */ - struct { - uInt get; /* bits to get for extra */ - uInt dist; /* distance back to copy from */ - } copy; /* if EXT or COPY, where and how much */ - } sub; /* submode */ - - /* mode independent information */ - Byte lbits; /* ltree bits decoded per branch */ - Byte dbits; /* dtree bits decoder per branch */ - inflate_huft *ltree; /* literal/length/eob tree */ - inflate_huft *dtree; /* distance tree */ - -}; - - -inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) -uInt bl, bd; -inflate_huft *tl; -inflate_huft *td; /* need separate declaration for Borland C++ */ -z_streamp z; -{ - inflate_codes_statef *c; - - if ((c = (inflate_codes_statef *) - ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) - { - c->mode = START; - c->lbits = (Byte)bl; - c->dbits = (Byte)bd; - c->ltree = tl; - c->dtree = td; - Tracev((stderr, "inflate: codes new\n")); - } - return c; -} - - -int inflate_codes(s, z, r) -inflate_blocks_statef *s; -z_streamp z; -int r; -{ - uInt j; /* temporary storage */ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - unsigned long csf; /* pointer to copy strings from */ - inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input and output based on current state */ - while (1) switch (c->mode) - { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - case START: /* x: set up for LEN */ -#ifndef SLOW - if (m >= 258 && n >= 10) - { - UPDATE - r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); - LOAD - if (r != Z_OK) - { - c->mode = r == Z_STREAM_END ? WASH : BADCODE; - break; - } - } -#endif /* !SLOW */ - c->sub.code.need = c->lbits; - c->sub.code.tree = c->ltree; - c->mode = LEN; - case LEN: /* i: get length/literal/eob next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e == 0) /* literal */ - { - c->sub.lit = t->base; - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", t->base)); - c->mode = LIT; - break; - } - if (e & 16) /* length */ - { - c->sub.copy.get = e & 15; - c->len = t->base; - c->mode = LENEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - if (e & 32) /* end of block */ - { - Tracevv((stderr, "inflate: end of block\n")); - c->mode = WASH; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid literal/length code"; - r = Z_DATA_ERROR; - LEAVE - case LENEXT: /* i: getting length extra (have base) */ - j = c->sub.copy.get; - NEEDBITS(j) - c->len += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - c->sub.code.need = c->dbits; - c->sub.code.tree = c->dtree; - Tracevv((stderr, "inflate: length %u\n", c->len)); - c->mode = DIST; - case DIST: /* i: get distance next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e & 16) /* distance */ - { - c->sub.copy.get = e & 15; - c->sub.copy.dist = t->base; - c->mode = DISTEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid distance code"; - r = Z_DATA_ERROR; - LEAVE - case DISTEXT: /* i: getting distance extra */ - j = c->sub.copy.get; - NEEDBITS(j) - c->sub.copy.dist += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); - c->mode = COPY; - case COPY: /* o: copying bytes in window, waiting for space */ - csf = (unsigned long)q - c->sub.copy.dist; - while (csf < (unsigned long)s->window) /* modulo window size-"while" instead */ - csf += (unsigned long)(s->end - s->window); /* of "if" handles invalid distances */ - while (c->len) - { - NEEDOUT - OUTBYTE(*(Bytef *)csf++) - if (csf == (unsigned long)s->end) - csf = (unsigned long)s->window; - c->len--; - } - c->mode = START; - break; - case LIT: /* o: got literal, waiting for output space */ - NEEDOUT - OUTBYTE(c->sub.lit) - c->mode = START; - break; - case WASH: /* o: got eob, possibly more output */ - if (k > 7) /* return unused byte, if any */ - { - Assert(k < 16, "inflate_codes grabbed too many bytes") - k -= 8; - n++; - p--; /* can always return one */ - } - FLUSH - if (s->read != s->write) - LEAVE - c->mode = END; - case END: - r = Z_STREAM_END; - LEAVE - case BADCODE: /* x: got error */ - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -#ifdef NEED_DUMMY_RETURN - return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ -#endif -} - - -void inflate_codes_free(c, z) -inflate_codes_statef *c; -z_streamp z; -{ - ZFREE(z, c); - Tracev((stderr, "inflate: codes free\n")); -} diff --git a/src/utilfuns/zlib/infcodes.h b/src/utilfuns/zlib/infcodes.h deleted file mode 100644 index 46821a0..0000000 --- a/src/utilfuns/zlib/infcodes.h +++ /dev/null @@ -1,27 +0,0 @@ -/* infcodes.h -- header to use infcodes.c - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -struct inflate_codes_state; -typedef struct inflate_codes_state FAR inflate_codes_statef; - -extern inflate_codes_statef *inflate_codes_new OF(( - uInt, uInt, - inflate_huft *, inflate_huft *, - z_streamp )); - -extern int inflate_codes OF(( - inflate_blocks_statef *, - z_streamp , - int)); - -extern void inflate_codes_free OF(( - inflate_codes_statef *, - z_streamp )); - diff --git a/src/utilfuns/zlib/inffast.c b/src/utilfuns/zlib/inffast.c deleted file mode 100644 index a7ebc64..0000000 --- a/src/utilfuns/zlib/inffast.c +++ /dev/null @@ -1,183 +0,0 @@ -/* inffast.c -- process literals and length/distance pairs fast - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" -#include "infblock.h" -#include "infcodes.h" -#include "infutil.h" -#include "inffast.h" - -struct inflate_codes_state {int dummy;}; /* for buggy compilers */ - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -/* macros for bit input with no checking and for returning unused bytes */ -#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}} -#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;} - -/* Called with number of bytes left to write in window at least 258 - (the maximum string length) and number of input bytes available - at least ten. The ten bytes are six bytes for the longest length/ - distance pair plus four bytes for overloading the bit buffer. */ - -int inflate_fast(bl, bd, tl, td, s, z) -uInt bl, bd; -inflate_huft *tl; -inflate_huft *td; /* need separate declaration for Borland C++ */ -inflate_blocks_statef *s; -z_streamp z; -{ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - uInt ml; /* mask for literal/length tree */ - uInt md; /* mask for distance tree */ - uInt c; /* bytes to copy */ - uInt d; /* distance back to copy from */ - unsigned long csp; /* copy source pointer */ - - /* load input, output, bit values */ - LOAD - - /* initialize masks */ - ml = inflate_mask[bl]; - md = inflate_mask[bd]; - - /* do until not enough input or output space for fast loop */ - do { /* assume called with m >= 258 && n >= 10 */ - /* get literal/length code */ - GRABBITS(20) /* max bits for literal/length code */ - if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - continue; - } - do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits for length */ - e &= 15; - c = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv((stderr, "inflate: * length %u\n", c)); - - /* decode distance base of block to copy */ - GRABBITS(15); /* max bits for distance code */ - e = (t = td + ((uInt)b & md))->exop; - do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits to add to distance base */ - e &= 15; - GRABBITS(e) /* get extra bits (up to 13) */ - d = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv((stderr, "inflate: * distance %u\n", d)); - - /* do the copy */ - m -= c; - csp = (unsigned long)q - d; - if (csp < (unsigned long)s->window) /* wrap if needed */ - { - do { - csp += (unsigned long)(s->end - s->window); /* force pointer in window */ - } while (csp < (unsigned long)s->window); /* covers invalid distances */ - e = (unsigned long)s->end - csp; - if (c > e) - { - c -= e; /* wrapped copy */ - do { - *q++ = *(Bytef *)csp++; - } while (--e); - csp = s->window; - do { - *q++ = *(Bytef *)csp++; - } while (--c); - } - else /* normal copy */ - { - *q++ = *(Bytef *)csp++; c--; - *q++ = *(Bytef *)csp++; c--; - do { - *q++ = *(Bytef *)csp++; - } while (--c); - } - } - else /* normal copy */ - { - *q++ = *(Bytef *)csp++; c--; - *q++ = *(Bytef *)csp++; c--; - do { - *q++ = *(Bytef *)csp++; - } while (--c); - } - break; - } - else if ((e & 64) == 0) - { - t += t->base; - e = (t += ((uInt)b & inflate_mask[e]))->exop; - } - else - { - z->msg = (char*)"invalid distance code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - break; - } - if ((e & 64) == 0) - { - t += t->base; - if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - break; - } - } - else if (e & 32) - { - Tracevv((stderr, "inflate: * end of block\n")); - UNGRAB - UPDATE - return Z_STREAM_END; - } - else - { - z->msg = (char*)"invalid literal/length code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - } while (m >= 258 && n >= 10); - - /* not enough input or output--restore pointers and return */ - UNGRAB - UPDATE - return Z_OK; -} diff --git a/src/utilfuns/zlib/inffast.h b/src/utilfuns/zlib/inffast.h deleted file mode 100644 index a31a4bb..0000000 --- a/src/utilfuns/zlib/inffast.h +++ /dev/null @@ -1,17 +0,0 @@ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -extern int inflate_fast OF(( - uInt, - uInt, - inflate_huft *, - inflate_huft *, - inflate_blocks_statef *, - z_streamp )); diff --git a/src/utilfuns/zlib/inffixed.h b/src/utilfuns/zlib/inffixed.h deleted file mode 100644 index 77f7e76..0000000 --- a/src/utilfuns/zlib/inffixed.h +++ /dev/null @@ -1,151 +0,0 @@ -/* inffixed.h -- table for decoding fixed codes - * Generated automatically by the maketree.c program - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -local uInt fixed_bl = 9; -local uInt fixed_bd = 5; -local inflate_huft fixed_tl[] = { - {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, - {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, - {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, - {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, - {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, - {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, - {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, - {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, - {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, - {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, - {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, - {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, - {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, - {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, - {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, - {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, - {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, - {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, - {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, - {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, - {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, - {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, - {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, - {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, - {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, - {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, - {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, - {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, - {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, - {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, - {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, - {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, - {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, - {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, - {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, - {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, - {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, - {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, - {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, - {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, - {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, - {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, - {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, - {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, - {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, - {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, - {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, - {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, - {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, - {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, - {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, - {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, - {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, - {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, - {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, - {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, - {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, - {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, - {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, - {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, - {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, - {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, - {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, - {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, - {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, - {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, - {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, - {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, - {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, - {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, - {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, - {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, - {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, - {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, - {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, - {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, - {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, - {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, - {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, - {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, - {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, - {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, - {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, - {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, - {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, - {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, - {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, - {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, - {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, - {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, - {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, - {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, - {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, - {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, - {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, - {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, - {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, - {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, - {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, - {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, - {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, - {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, - {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, - {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, - {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, - {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, - {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, - {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, - {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, - {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, - {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, - {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, - {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, - {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, - {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, - {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, - {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, - {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, - {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, - {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, - {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, - {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, - {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, - {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} - }; -local inflate_huft fixed_td[] = { - {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, - {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, - {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, - {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, - {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, - {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, - {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, - {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} - }; diff --git a/src/utilfuns/zlib/inflate.c b/src/utilfuns/zlib/inflate.c deleted file mode 100644 index dfb2e86..0000000 --- a/src/utilfuns/zlib/inflate.c +++ /dev/null @@ -1,366 +0,0 @@ -/* inflate.c -- zlib interface to inflate modules - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infblock.h" - -struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ - -typedef enum { - METHOD, /* waiting for method byte */ - FLAG, /* waiting for flag byte */ - DICT4, /* four dictionary check bytes to go */ - DICT3, /* three dictionary check bytes to go */ - DICT2, /* two dictionary check bytes to go */ - DICT1, /* one dictionary check byte to go */ - DICT0, /* waiting for inflateSetDictionary */ - BLOCKS, /* decompressing blocks */ - CHECK4, /* four check bytes to go */ - CHECK3, /* three check bytes to go */ - CHECK2, /* two check bytes to go */ - CHECK1, /* one check byte to go */ - DONE, /* finished check, done */ - BAD} /* got an error--stay here */ -inflate_mode; - -/* inflate private state */ -struct internal_state { - - /* mode */ - inflate_mode mode; /* current inflate mode */ - - /* mode dependent information */ - union { - uInt method; /* if FLAGS, method byte */ - struct { - uLong was; /* computed check value */ - uLong need; /* stream check value */ - } check; /* if CHECK, check values to compare */ - uInt marker; /* if BAD, inflateSync's marker bytes count */ - } sub; /* submode */ - - /* mode independent information */ - int nowrap; /* flag for no wrapper */ - uInt wbits; /* log2(window size) (8..15, defaults to 15) */ - inflate_blocks_statef - *blocks; /* current inflate_blocks state */ - -}; - - -int ZEXPORT inflateReset(z) -z_streamp z; -{ - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - z->total_in = z->total_out = 0; - z->msg = Z_NULL; - z->state->mode = z->state->nowrap ? BLOCKS : METHOD; - inflate_blocks_reset(z->state->blocks, z, Z_NULL); - Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - - -int ZEXPORT inflateEnd(z) -z_streamp z; -{ - if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->blocks != Z_NULL) - inflate_blocks_free(z->state->blocks, z); - ZFREE(z, z->state); - z->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} - - -int ZEXPORT inflateInit2_(z, w, version, stream_size) -z_streamp z; -int w; -const char *version; -int stream_size; -{ - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != sizeof(z_stream)) - return Z_VERSION_ERROR; - - /* initialize state */ - if (z == Z_NULL) - return Z_STREAM_ERROR; - z->msg = Z_NULL; - if (z->zalloc == Z_NULL) - { - z->zalloc = zcalloc; - z->opaque = (voidpf)0; - } - if (z->zfree == Z_NULL) z->zfree = zcfree; - if ((z->state = (struct internal_state FAR *) - ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) - return Z_MEM_ERROR; - z->state->blocks = Z_NULL; - - /* handle undocumented nowrap option (no zlib header or check) */ - z->state->nowrap = 0; - if (w < 0) - { - w = - w; - z->state->nowrap = 1; - } - - /* set window size */ - if (w < 8 || w > 15) - { - inflateEnd(z); - return Z_STREAM_ERROR; - } - z->state->wbits = (uInt)w; - - /* create inflate_blocks state */ - if ((z->state->blocks = - inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) - == Z_NULL) - { - inflateEnd(z); - return Z_MEM_ERROR; - } - Tracev((stderr, "inflate: allocated\n")); - - /* reset state */ - inflateReset(z); - return Z_OK; -} - - -int ZEXPORT inflateInit_(z, version, stream_size) -z_streamp z; -const char *version; -int stream_size; -{ - return inflateInit2_(z, DEF_WBITS, version, stream_size); -} - - -#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} -#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) - -int ZEXPORT inflate(z, f) -z_streamp z; -int f; -{ - int r; - uInt b; - - if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) - return Z_STREAM_ERROR; - f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; - r = Z_BUF_ERROR; - while (1) switch (z->state->mode) - { - case METHOD: - NEEDBYTE - if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) - { - z->state->mode = BAD; - z->msg = (char*)"unknown compression method"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - if ((z->state->sub.method >> 4) + 8 > z->state->wbits) - { - z->state->mode = BAD; - z->msg = (char*)"invalid window size"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - z->state->mode = FLAG; - case FLAG: - NEEDBYTE - b = NEXTBYTE; - if (((z->state->sub.method << 8) + b) % 31) - { - z->state->mode = BAD; - z->msg = (char*)"incorrect header check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Tracev((stderr, "inflate: zlib header ok\n")); - if (!(b & PRESET_DICT)) - { - z->state->mode = BLOCKS; - break; - } - z->state->mode = DICT4; - case DICT4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = DICT3; - case DICT3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = DICT2; - case DICT2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = DICT1; - case DICT1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; - z->adler = z->state->sub.check.need; - z->state->mode = DICT0; - return Z_NEED_DICT; - case DICT0: - z->state->mode = BAD; - z->msg = (char*)"need dictionary"; - z->state->sub.marker = 0; /* can try inflateSync */ - return Z_STREAM_ERROR; - case BLOCKS: - r = inflate_blocks(z->state->blocks, z, r); - if (r == Z_DATA_ERROR) - { - z->state->mode = BAD; - z->state->sub.marker = 0; /* can try inflateSync */ - break; - } - if (r == Z_OK) - r = f; - if (r != Z_STREAM_END) - return r; - r = f; - inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); - if (z->state->nowrap) - { - z->state->mode = DONE; - break; - } - z->state->mode = CHECK4; - case CHECK4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = CHECK3; - case CHECK3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = CHECK2; - case CHECK2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = CHECK1; - case CHECK1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; - - if (z->state->sub.check.was != z->state->sub.check.need) - { - z->state->mode = BAD; - z->msg = (char*)"incorrect data check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Tracev((stderr, "inflate: zlib check ok\n")); - z->state->mode = DONE; - case DONE: - return Z_STREAM_END; - case BAD: - return Z_DATA_ERROR; - default: - return Z_STREAM_ERROR; - } -#ifdef NEED_DUMMY_RETURN - return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ -#endif -} - - -int ZEXPORT inflateSetDictionary(z, dictionary, dictLength) -z_streamp z; -const Bytef *dictionary; -uInt dictLength; -{ - uInt length = dictLength; - - if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) - return Z_STREAM_ERROR; - - if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; - z->adler = 1L; - - if (length >= ((uInt)1<<z->state->wbits)) - { - length = (1<<z->state->wbits)-1; - dictionary += dictLength - length; - } - inflate_set_dictionary(z->state->blocks, dictionary, length); - z->state->mode = BLOCKS; - return Z_OK; -} - - -int ZEXPORT inflateSync(z) -z_streamp z; -{ - uInt n; /* number of bytes to look at */ - Bytef *p; /* pointer to bytes */ - uInt m; /* number of marker bytes found in a row */ - uLong r, w; /* temporaries to save total_in and total_out */ - - /* set up */ - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->mode != BAD) - { - z->state->mode = BAD; - z->state->sub.marker = 0; - } - if ((n = z->avail_in) == 0) - return Z_BUF_ERROR; - p = z->next_in; - m = z->state->sub.marker; - - /* search */ - while (n && m < 4) - { - static const Byte mark[4] = {0, 0, 0xff, 0xff}; - if (*p == mark[m]) - m++; - else if (*p) - m = 0; - else - m = 4 - m; - p++, n--; - } - - /* restore */ - z->total_in += p - z->next_in; - z->next_in = p; - z->avail_in = n; - z->state->sub.marker = m; - - /* return no joy or set up to restart on a new block */ - if (m != 4) - return Z_DATA_ERROR; - r = z->total_in; w = z->total_out; - inflateReset(z); - z->total_in = r; z->total_out = w; - z->state->mode = BLOCKS; - return Z_OK; -} - - -/* Returns true if inflate is currently at the end of a block generated - * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH - * but removes the length bytes of the resulting empty stored block. When - * decompressing, PPP checks that at the end of input packet, inflate is - * waiting for these length bytes. - */ -int ZEXPORT inflateSyncPoint(z) -z_streamp z; -{ - if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) - return Z_STREAM_ERROR; - return inflate_blocks_sync_point(z->state->blocks); -} diff --git a/src/utilfuns/zlib/inftrees.c b/src/utilfuns/zlib/inftrees.c deleted file mode 100644 index 4c32ca3..0000000 --- a/src/utilfuns/zlib/inftrees.c +++ /dev/null @@ -1,454 +0,0 @@ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" - -#if !defined(BUILDFIXED) && !defined(STDC) -# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ -#endif - -const char inflate_copyright[] = - " inflate 1.1.4 Copyright 1995-2002 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ -struct internal_state {int dummy;}; /* for buggy compilers */ - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - - -local int huft_build OF(( - uIntf *, /* code lengths in bits */ - uInt, /* number of codes */ - uInt, /* number of "simple" codes */ - const uIntf *, /* list of base values for non-simple codes */ - const uIntf *, /* list of extra bits for non-simple codes */ - inflate_huft * FAR*,/* result: starting table */ - uIntf *, /* maximum lookup bits (returns actual) */ - inflate_huft *, /* space for trees */ - uInt *, /* hufts used in space */ - uIntf * )); /* space for values */ - -/* Tables for deflate from PKZIP's appnote.txt. */ -local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - /* see note #13 above about 258 */ -local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ -local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; -local const uInt cpdext[30] = { /* Extra bits for distance codes */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; - -/* - Huffman code decoding is performed using a multi-level table lookup. - The fastest way to decode is to simply build a lookup table whose - size is determined by the longest code. However, the time it takes - to build this table can also be a factor if the data being decoded - is not very long. The most common codes are necessarily the - shortest codes, so those codes dominate the decoding time, and hence - the speed. The idea is you can have a shorter table that decodes the - shorter, more probable codes, and then point to subsidiary tables for - the longer codes. The time it costs to decode the longer codes is - then traded against the time it takes to make longer tables. - - This results of this trade are in the variables lbits and dbits - below. lbits is the number of bits the first level table for literal/ - length codes can decode in one step, and dbits is the same thing for - the distance codes. Subsequent tables are also less than or equal to - those sizes. These values may be adjusted either when all of the - codes are shorter than that, in which case the longest code length in - bits is used, or when the shortest code is *longer* than the requested - table size, in which case the length of the shortest code in bits is - used. - - There are two different values for the two tables, since they code a - different number of possibilities each. The literal/length table - codes 286 possible values, or in a flat code, a little over eight - bits. The distance table codes 30 possible values, or a little less - than five bits, flat. The optimum values for speed end up being - about one bit more than those, so lbits is 8+1 and dbits is 5+1. - The optimum values may differ though from machine to machine, and - possibly even between compilers. Your mileage may vary. - */ - - -/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ -#define BMAX 15 /* maximum bit length of any code */ - -local int huft_build(b, n, s, d, e, t, m, hp, hn, v) -uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ -uInt n; /* number of codes (assumed <= 288) */ -uInt s; /* number of simple-valued codes (0..s-1) */ -const uIntf *d; /* list of base values for non-simple codes */ -const uIntf *e; /* list of extra bits for non-simple codes */ -inflate_huft * FAR *t; /* result: starting table */ -uIntf *m; /* maximum lookup bits, returns actual */ -inflate_huft *hp; /* space for trees */ -uInt *hn; /* hufts used in space */ -uIntf *v; /* working area: values in order of bit length */ -/* Given a list of code lengths and a maximum table size, make a set of - tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR - if the given code set is incomplete (the tables are still built in this - case), or Z_DATA_ERROR if the input is invalid. */ -{ - - uInt a; /* counter for codes of length k */ - uInt c[BMAX+1]; /* bit length count table */ - uInt f; /* i repeats in table every f entries */ - int g; /* maximum code length */ - int h; /* table level */ - register uInt i; /* counter, current code */ - register uInt j; /* counter */ - register int k; /* number of bits in current code */ - int l; /* bits per table (returned in m) */ - uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ - register uIntf *p; /* pointer into c[], b[], or v[] */ - inflate_huft *q; /* points to current table */ - struct inflate_huft_s r; /* table entry for structure assignment */ - inflate_huft *u[BMAX]; /* table stack */ - register int w; /* bits before this table == (l * h) */ - uInt x[BMAX+1]; /* bit offsets, then code stack */ - uIntf *xp; /* pointer into x */ - int y; /* number of dummy codes added */ - uInt z; /* number of entries in current table */ - - - /* Generate counts for each bit length */ - p = c; -#define C0 *p++ = 0; -#define C2 C0 C0 C0 C0 -#define C4 C2 C2 C2 C2 - C4 /* clear c[]--assume BMAX+1 is 16 */ - p = b; i = n; - do { - c[*p++]++; /* assume all entries <= BMAX */ - } while (--i); - if (c[0] == n) /* null input--all zero length codes */ - { - *t = (inflate_huft *)Z_NULL; - *m = 0; - return Z_OK; - } - - - /* Find minimum and maximum length, bound *m by those */ - l = *m; - for (j = 1; j <= BMAX; j++) - if (c[j]) - break; - k = j; /* minimum code length */ - if ((uInt)l < j) - l = j; - for (i = BMAX; i; i--) - if (c[i]) - break; - g = i; /* maximum code length */ - if ((uInt)l > i) - l = i; - *m = l; - - - /* Adjust last length count to fill out codes, if needed */ - for (y = 1 << j; j < i; j++, y <<= 1) - if ((y -= c[j]) < 0) - return Z_DATA_ERROR; - if ((y -= c[i]) < 0) - return Z_DATA_ERROR; - c[i] += y; - - - /* Generate starting offsets into the value table for each length */ - x[1] = j = 0; - p = c + 1; xp = x + 2; - while (--i) { /* note that i == g from above */ - *xp++ = (j += *p++); - } - - - /* Make a table of values in order of bit lengths */ - p = b; i = 0; - do { - if ((j = *p++) != 0) - v[x[j]++] = i; - } while (++i < n); - n = x[g]; /* set n to length of v */ - - - /* Generate the Huffman codes and for each, make the table entries */ - x[0] = i = 0; /* first Huffman code is zero */ - p = v; /* grab values in bit order */ - h = -1; /* no tables yet--level -1 */ - w = -l; /* bits decoded == (l * h) */ - u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ - q = (inflate_huft *)Z_NULL; /* ditto */ - z = 0; /* ditto */ - - /* go through the bit lengths (k already is bits in shortest code) */ - for (; k <= g; k++) - { - a = c[k]; - while (a--) - { - /* here i is the Huffman code of length k bits for value *p */ - /* make tables up to required level */ - while (k > w + l) - { - h++; - w += l; /* previous table always l bits */ - - /* compute minimum size table less than or equal to l bits */ - z = g - w; - z = z > (uInt)l ? l : z; /* table size upper limit */ - if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ - { /* too few codes for k-w bit table */ - f -= a + 1; /* deduct codes from patterns left */ - xp = c + k; - if (j < z) - while (++j < z) /* try smaller tables up to z bits */ - { - if ((f <<= 1) <= *++xp) - break; /* enough codes to use up j bits */ - f -= *xp; /* else deduct codes from patterns */ - } - } - z = 1 << j; /* table entries for j-bit table */ - - /* allocate new table */ - if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ - return Z_DATA_ERROR; /* overflow of MANY */ - u[h] = q = hp + *hn; - *hn += z; - - /* connect to last table, if there is one */ - if (h) - { - x[h] = i; /* save pattern for backing up */ - r.bits = (Byte)l; /* bits to dump before this table */ - r.exop = (Byte)j; /* bits in this table */ - j = i >> (w - l); - r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ - u[h-1][j] = r; /* connect to last table */ - } - else - *t = q; /* first table is returned result */ - } - - /* set up table entry in r */ - r.bits = (Byte)(k - w); - if (p >= v + n) - r.exop = 128 + 64; /* out of values--invalid code */ - else if (*p < s) - { - r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ - r.base = *p++; /* simple code is just the value */ - } - else - { - r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ - r.base = d[*p++ - s]; - } - - /* fill code-like entries with r */ - f = 1 << (k - w); - for (j = i >> w; j < z; j += f) - q[j] = r; - - /* backwards increment the k-bit code i */ - for (j = 1 << (k - 1); i & j; j >>= 1) - i ^= j; - i ^= j; - - /* backup over finished tables */ - mask = (1 << w) - 1; /* needed on HP, cc -O bug */ - while ((i & mask) != x[h]) - { - h--; /* don't need to update q */ - w -= l; - mask = (1 << w) - 1; - } - } - } - - - /* Return Z_BUF_ERROR if we were given an incomplete table */ - return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -} - - -int inflate_trees_bits(c, bb, tb, hp, z) -uIntf *c; /* 19 code lengths */ -uIntf *bb; /* bits tree desired/actual depth */ -inflate_huft * FAR *tb; /* bits tree result */ -inflate_huft *hp; /* space for trees */ -z_streamp z; /* for messages */ -{ - int r; - uInt hn = 0; /* hufts used in space */ - uIntf *v; /* work area for huft_build */ - - if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, - tb, bb, hp, &hn, v); - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed dynamic bit lengths tree"; - else if (r == Z_BUF_ERROR || *bb == 0) - { - z->msg = (char*)"incomplete dynamic bit lengths tree"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; -} - - -int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) -uInt nl; /* number of literal/length codes */ -uInt nd; /* number of distance codes */ -uIntf *c; /* that many (total) code lengths */ -uIntf *bl; /* literal desired/actual bit depth */ -uIntf *bd; /* distance desired/actual bit depth */ -inflate_huft * FAR *tl; /* literal/length tree result */ -inflate_huft * FAR *td; /* distance tree result */ -inflate_huft *hp; /* space for trees */ -z_streamp z; /* for messages */ -{ - int r; - uInt hn = 0; /* hufts used in space */ - uIntf *v; /* work area for huft_build */ - - /* allocate work area */ - if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - - /* build literal/length tree */ - r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); - if (r != Z_OK || *bl == 0) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed literal/length tree"; - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"incomplete literal/length tree"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; - } - - /* build distance tree */ - r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); - if (r != Z_OK || (*bd == 0 && nl > 257)) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed distance tree"; - else if (r == Z_BUF_ERROR) { -#ifdef PKZIP_BUG_WORKAROUND - r = Z_OK; - } -#else - z->msg = (char*)"incomplete distance tree"; - r = Z_DATA_ERROR; - } - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"empty distance tree with lengths"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; -#endif - } - - /* done */ - ZFREE(z, v); - return Z_OK; -} - - -/* build fixed tables only once--keep them here */ -#ifdef BUILDFIXED -local int fixed_built = 0; -#define FIXEDH 544 /* number of hufts used by fixed tables */ -local inflate_huft fixed_mem[FIXEDH]; -local uInt fixed_bl; -local uInt fixed_bd; -local inflate_huft *fixed_tl; -local inflate_huft *fixed_td; -#else -#include "inffixed.h" -#endif - - -int inflate_trees_fixed(bl, bd, tl, td, z) -uIntf *bl; /* literal desired/actual bit depth */ -uIntf *bd; /* distance desired/actual bit depth */ -inflate_huft * FAR *tl; /* literal/length tree result */ -inflate_huft * FAR *td; /* distance tree result */ -z_streamp z; /* for memory allocation */ -{ -#ifdef BUILDFIXED - /* build fixed tables if not already */ - if (!fixed_built) - { - int k; /* temporary variable */ - uInt f = 0; /* number of hufts used in fixed_mem */ - uIntf *c; /* length list for huft_build */ - uIntf *v; /* work area for huft_build */ - - /* allocate memory */ - if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - { - ZFREE(z, c); - return Z_MEM_ERROR; - } - - /* literal table */ - for (k = 0; k < 144; k++) - c[k] = 8; - for (; k < 256; k++) - c[k] = 9; - for (; k < 280; k++) - c[k] = 7; - for (; k < 288; k++) - c[k] = 8; - fixed_bl = 9; - huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, - fixed_mem, &f, v); - - /* distance table */ - for (k = 0; k < 30; k++) - c[k] = 5; - fixed_bd = 5; - huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, - fixed_mem, &f, v); - - /* done */ - ZFREE(z, v); - ZFREE(z, c); - fixed_built = 1; - } -#endif - *bl = fixed_bl; - *bd = fixed_bd; - *tl = fixed_tl; - *td = fixed_td; - return Z_OK; -} diff --git a/src/utilfuns/zlib/inftrees.h b/src/utilfuns/zlib/inftrees.h deleted file mode 100644 index 04b73b7..0000000 --- a/src/utilfuns/zlib/inftrees.h +++ /dev/null @@ -1,58 +0,0 @@ -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Huffman code lookup table entry--this entry is four bytes for machines - that have 16-bit pointers (e.g. PC's in the small or medium model). */ - -typedef struct inflate_huft_s FAR inflate_huft; - -struct inflate_huft_s { - union { - struct { - Byte Exop; /* number of extra bits or operation */ - Byte Bits; /* number of bits in this code or subcode */ - } what; - uInt pad; /* pad structure to a power of 2 (4 bytes for */ - } word; /* 16-bit, 8 bytes for 32-bit int's) */ - uInt base; /* literal, length base, distance base, - or table offset */ -}; - -/* Maximum size of dynamic tree. The maximum found in a long but non- - exhaustive search was 1004 huft structures (850 for length/literals - and 154 for distances, the latter actually the result of an - exhaustive search). The actual maximum is not known, but the - value below is more than safe. */ -#define MANY 1440 - -extern int inflate_trees_bits OF(( - uIntf *, /* 19 code lengths */ - uIntf *, /* bits tree desired/actual depth */ - inflate_huft * FAR *, /* bits tree result */ - inflate_huft *, /* space for trees */ - z_streamp)); /* for messages */ - -extern int inflate_trees_dynamic OF(( - uInt, /* number of literal/length codes */ - uInt, /* number of distance codes */ - uIntf *, /* that many (total) code lengths */ - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - inflate_huft * FAR *, /* literal/length tree result */ - inflate_huft * FAR *, /* distance tree result */ - inflate_huft *, /* space for trees */ - z_streamp)); /* for messages */ - -extern int inflate_trees_fixed OF(( - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - inflate_huft * FAR *, /* literal/length tree result */ - inflate_huft * FAR *, /* distance tree result */ - z_streamp)); /* for memory allocation */ diff --git a/src/utilfuns/zlib/infutil.c b/src/utilfuns/zlib/infutil.c deleted file mode 100644 index 9a07622..0000000 --- a/src/utilfuns/zlib/infutil.c +++ /dev/null @@ -1,87 +0,0 @@ -/* inflate_util.c -- data and routines common to blocks and codes - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infblock.h" -#include "inftrees.h" -#include "infcodes.h" -#include "infutil.h" - -struct inflate_codes_state {int dummy;}; /* for buggy compilers */ - -/* And'ing with mask[n] masks the lower n bits */ -uInt inflate_mask[17] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; - - -/* copy as much as possible from the sliding window to the output area */ -int inflate_flush(s, z, r) -inflate_blocks_statef *s; -z_streamp z; -int r; -{ - uInt n; - Bytef *p; - Bytef *q; - - /* local copies of source and destination pointers */ - p = z->next_out; - q = s->read; - - /* compute number of bytes to copy as far as end of window */ - n = (uInt)((q <= s->write ? s->write : s->end) - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy as far as end of window */ - zmemcpy(p, q, n); - p += n; - q += n; - - /* see if more to copy at beginning of window */ - if (q == s->end) - { - /* wrap pointers */ - q = s->window; - if (s->write == s->end) - s->write = s->window; - - /* compute bytes to copy */ - n = (uInt)(s->write - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy */ - zmemcpy(p, q, n); - p += n; - q += n; - } - - /* update pointers */ - z->next_out = p; - s->read = q; - - /* done */ - return r; -} diff --git a/src/utilfuns/zlib/infutil.h b/src/utilfuns/zlib/infutil.h deleted file mode 100644 index 4401df8..0000000 --- a/src/utilfuns/zlib/infutil.h +++ /dev/null @@ -1,98 +0,0 @@ -/* infutil.h -- types and macros common to blocks and codes - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef _INFUTIL_H -#define _INFUTIL_H - -typedef enum { - TYPE, /* get type bits (3, including end bit) */ - LENS, /* get lengths for stored */ - STORED, /* processing stored block */ - TABLE, /* get table lengths */ - BTREE, /* get bit lengths tree for a dynamic block */ - DTREE, /* get length, distance trees for a dynamic block */ - CODES, /* processing fixed or dynamic block */ - DRY, /* output remaining window bytes */ - DONE, /* finished last block, done */ - BAD} /* got a data error--stuck here */ -inflate_block_mode; - -/* inflate blocks semi-private state */ -struct inflate_blocks_state { - - /* mode */ - inflate_block_mode mode; /* current inflate_block mode */ - - /* mode dependent information */ - union { - uInt left; /* if STORED, bytes left to copy */ - struct { - uInt table; /* table lengths (14 bits) */ - uInt index; /* index into blens (or border) */ - uIntf *blens; /* bit lengths of codes */ - uInt bb; /* bit length tree depth */ - inflate_huft *tb; /* bit length decoding tree */ - } trees; /* if DTREE, decoding info for trees */ - struct { - inflate_codes_statef - *codes; - } decode; /* if CODES, current state */ - } sub; /* submode */ - uInt last; /* true if this block is the last block */ - - /* mode independent information */ - uInt bitk; /* bits in bit buffer */ - uLong bitb; /* bit buffer */ - inflate_huft *hufts; /* single malloc for tree space */ - Bytef *window; /* sliding window */ - Bytef *end; /* one byte after sliding window */ - Bytef *read; /* window read pointer */ - Bytef *write; /* window write pointer */ - check_func checkfn; /* check function */ - uLong check; /* check on output */ - -}; - - -/* defines for inflate input/output */ -/* update pointers and return */ -#define UPDBITS {s->bitb=b;s->bitk=k;} -#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -#define UPDOUT {s->write=q;} -#define UPDATE {UPDBITS UPDIN UPDOUT} -#define LEAVE {UPDATE return inflate_flush(s,z,r);} -/* get bytes and bits */ -#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -#define NEXTBYTE (n--,*p++) -#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}} -#define DUMPBITS(j) {b>>=(j);k-=(j);} -/* output bytes */ -#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q) -#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} -#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} -#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -/* load local pointers */ -#define LOAD {LOADIN LOADOUT} - -/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ -extern uInt inflate_mask[17]; - -/* copy as much as possible from the sliding window to the output area */ -extern int inflate_flush OF(( - inflate_blocks_statef *, - z_streamp , - int)); - -struct internal_state {int dummy;}; /* for buggy compilers */ - -#endif diff --git a/src/utilfuns/zlib/maketree.c b/src/utilfuns/zlib/maketree.c deleted file mode 100644 index a16d4b1..0000000 --- a/src/utilfuns/zlib/maketree.c +++ /dev/null @@ -1,85 +0,0 @@ -/* maketree.c -- make inffixed.h table for decoding fixed codes - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* This program is included in the distribution for completeness. - You do not need to compile or run this program since inffixed.h - is already included in the distribution. To use this program - you need to compile zlib with BUILDFIXED defined and then compile - and link this program with the zlib library. Then the output of - this program can be piped to inffixed.h. */ - -#include <stdio.h> -#include <stdlib.h> -#include "zutil.h" -#include "inftrees.h" - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -/* generate initialization table for an inflate_huft structure array */ -void maketree(uInt b, inflate_huft *t) -{ - int i, e; - - i = 0; - while (1) - { - e = t[i].exop; - if (e && (e & (16+64)) == 0) /* table pointer */ - { - fprintf(stderr, "maketree: cannot initialize sub-tables!\n"); - exit(1); - } - if (i % 4 == 0) - printf("\n "); - printf(" {{{%u,%u}},%u}", t[i].exop, t[i].bits, t[i].base); - if (++i == (1<<b)) - break; - putchar(','); - } - puts(""); -} - -/* create the fixed tables in C initialization syntax */ -void main(void) -{ - int r; - uInt bl, bd; - inflate_huft *tl, *td; - z_stream z; - - z.zalloc = zcalloc; - z.opaque = (voidpf)0; - z.zfree = zcfree; - r = inflate_trees_fixed(&bl, &bd, &tl, &td, &z); - if (r) - { - fprintf(stderr, "inflate_trees_fixed error %d\n", r); - return; - } - puts("/* inffixed.h -- table for decoding fixed codes"); - puts(" * Generated automatically by the maketree.c program"); - puts(" */"); - puts(""); - puts("/* WARNING: this file should *not* be used by applications. It is"); - puts(" part of the implementation of the compression library and is"); - puts(" subject to change. Applications should only use zlib.h."); - puts(" */"); - puts(""); - printf("local uInt fixed_bl = %d;\n", bl); - printf("local uInt fixed_bd = %d;\n", bd); - printf("local inflate_huft fixed_tl[] = {"); - maketree(bl, tl); - puts(" };"); - printf("local inflate_huft fixed_td[] = {"); - maketree(bd, td); - puts(" };"); -} diff --git a/src/utilfuns/zlib/trees.c b/src/utilfuns/zlib/trees.c deleted file mode 100644 index b3117b3..0000000 --- a/src/utilfuns/zlib/trees.c +++ /dev/null @@ -1,1214 +0,0 @@ -/* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2002 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process uses several Huffman trees. The more - * common source values are represented by shorter bit sequences. - * - * Each code tree is stored in a compressed form which is itself - * a Huffman encoding of the lengths of all the code strings (in - * ascending order by source values). The actual code strings are - * reconstructed from the lengths in the inflate process, as described - * in the deflate specification. - * - * REFERENCES - * - * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". - * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc - * - * Storer, James A. - * Data Compression: Methods and Theory, pp. 49-50. - * Computer Science Press, 1988. ISBN 0-7167-8156-5. - * - * Sedgewick, R. - * Algorithms, p290. - * Addison-Wesley, 1983. ISBN 0-201-06672-6. - */ - -/* @(#) $Id: trees.c 1688 2005-01-01 04:42:26Z scribe $ */ - -/* #define GEN_TREES_H */ - -#include "deflate.h" - -#ifdef DEBUG -# include <ctype.h> -#endif - -/* =========================================================================== - * Constants - */ - -#define MAX_BL_BITS 7 -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -#define END_BLOCK 256 -/* end of block literal code */ - -#define REP_3_6 16 -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -#define REPZ_3_10 17 -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -#define REPZ_11_138 18 -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ - = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; - -local const int extra_dbits[D_CODES] /* extra bits for each distance code */ - = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ - = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -local const uch bl_order[BL_CODES] - = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -#define Buf_size (8 * 2*sizeof(char)) -/* Number of bits used within bi_buf. (bi_buf might be implemented on - * more than 16 bits on some systems.) - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ - -#if defined(GEN_TREES_H) || !defined(STDC) -/* non ANSI compilers may not accept trees.h */ - -local ct_data static_ltree[L_CODES+2]; -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -local ct_data static_dtree[D_CODES]; -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -uch _dist_code[DIST_CODE_LEN]; -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -uch _length_code[MAX_MATCH-MIN_MATCH+1]; -/* length code for each normalized match length (0 == MIN_MATCH) */ - -local int base_length[LENGTH_CODES]; -/* First normalized length for each code (0 = MIN_MATCH) */ - -local int base_dist[D_CODES]; -/* First normalized distance for each code (0 = distance of 1) */ - -#else -# include "trees.h" -#endif /* GEN_TREES_H */ - -struct static_tree_desc_s { - const ct_data *static_tree; /* static tree or NULL */ - const intf *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - int max_length; /* max bit length for the codes */ -}; - -local static_tree_desc static_l_desc = -{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; - -local static_tree_desc static_d_desc = -{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; - -local static_tree_desc static_bl_desc = -{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; - -/* =========================================================================== - * Local (static) routines in this file. - */ - -local void tr_static_init OF((void)); -local void init_block OF((deflate_state *s)); -local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -local void build_tree OF((deflate_state *s, tree_desc *desc)); -local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local int build_bl_tree OF((deflate_state *s)); -local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, - int blcodes)); -local void compress_block OF((deflate_state *s, ct_data *ltree, - ct_data *dtree)); -local void set_data_type OF((deflate_state *s)); -local unsigned bi_reverse OF((unsigned value, int length)); -local void bi_windup OF((deflate_state *s)); -local void bi_flush OF((deflate_state *s)); -local void copy_block OF((deflate_state *s, charf *buf, unsigned len, - int header)); - -#ifdef GEN_TREES_H -local void gen_trees_header OF((void)); -#endif - -#ifndef DEBUG -# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) - /* Send a code of the given tree. c and tree must not have side effects */ - -#else /* DEBUG */ -# define send_code(s, c, tree) \ - { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ - send_bits(s, tree[c].Code, tree[c].Len); } -#endif - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -#define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ -} - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -#ifdef DEBUG -local void send_bits OF((deflate_state *s, int value, int length)); - -local void send_bits(s, value, length) - deflate_state *s; - int value; /* value to send */ - int length; /* number of bits */ -{ - Tracevv((stderr," l %2d v %4x ", length, value)); - Assert(length > 0 && length <= 15, "invalid length"); - s->bits_sent += (ulg)length; - - /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) - * unused bits in value. - */ - if (s->bi_valid > (int)Buf_size - length) { - s->bi_buf |= (value << s->bi_valid); - put_short(s, s->bi_buf); - s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); - s->bi_valid += length - Buf_size; - } else { - s->bi_buf |= value << s->bi_valid; - s->bi_valid += length; - } -} -#else /* !DEBUG */ - -#define send_bits(s, value, length) \ -{ int len = length;\ - if (s->bi_valid > (int)Buf_size - len) {\ - int val = value;\ - s->bi_buf |= (val << s->bi_valid);\ - put_short(s, s->bi_buf);\ - s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ - s->bi_valid += len - Buf_size;\ - } else {\ - s->bi_buf |= (value) << s->bi_valid;\ - s->bi_valid += len;\ - }\ -} -#endif /* DEBUG */ - - -#define MAX(a,b) (a >= b ? a : b) -/* the arguments must not have side effects */ - -/* =========================================================================== - * Initialize the various 'constant' tables. - */ -local void tr_static_init() -{ -#if defined(GEN_TREES_H) || !defined(STDC) - static int static_init_done = 0; - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - if (static_init_done) return; - - /* For some embedded targets, global variables are not initialized: */ - static_l_desc.static_tree = static_ltree; - static_l_desc.extra_bits = extra_lbits; - static_d_desc.static_tree = static_dtree; - static_d_desc.extra_bits = extra_dbits; - static_bl_desc.extra_bits = extra_blbits; - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1<<extra_lbits[code]); n++) { - _length_code[length++] = (uch)code; - } - } - Assert (length == 256, "tr_static_init: length != 256"); - /* Note that the length 255 (match length 258) can be represented - * in two different ways: code 284 + 5 bits or code 285, so we - * overwrite length_code[255] to use the best encoding: - */ - _length_code[length-1] = (uch)code; - - /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1<<extra_dbits[code]); n++) { - _dist_code[dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: dist != 256"); - dist >>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - _dist_code[256 + dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; - n = 0; - while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse((unsigned)n, 5); - } - static_init_done = 1; - -# ifdef GEN_TREES_H - gen_trees_header(); -# endif -#endif /* defined(GEN_TREES_H) || !defined(STDC) */ -} - -/* =========================================================================== - * Genererate the file trees.h describing the static trees. - */ -#ifdef GEN_TREES_H -# ifndef DEBUG -# include <stdio.h> -# endif - -# define SEPARATOR(i, last, width) \ - ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) - -void gen_trees_header() -{ - FILE *header = fopen("trees.h", "w"); - int i; - - Assert (header != NULL, "Can't open trees.h"); - fprintf(header, - "/* header created automatically with -DGEN_TREES_H */\n\n"); - - fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); - for (i = 0; i < L_CODES+2; i++) { - fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, - static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); - } - - fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, - static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); - } - - fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); - for (i = 0; i < DIST_CODE_LEN; i++) { - fprintf(header, "%2u%s", _dist_code[i], - SEPARATOR(i, DIST_CODE_LEN-1, 20)); - } - - fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); - for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { - fprintf(header, "%2u%s", _length_code[i], - SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); - } - - fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); - for (i = 0; i < LENGTH_CODES; i++) { - fprintf(header, "%1u%s", base_length[i], - SEPARATOR(i, LENGTH_CODES-1, 20)); - } - - fprintf(header, "local const int base_dist[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "%5u%s", base_dist[i], - SEPARATOR(i, D_CODES-1, 10)); - } - - fclose(header); -} -#endif /* GEN_TREES_H */ - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -void _tr_init(s) - deflate_state *s; -{ - tr_static_init(); - - s->l_desc.dyn_tree = s->dyn_ltree; - s->l_desc.stat_desc = &static_l_desc; - - s->d_desc.dyn_tree = s->dyn_dtree; - s->d_desc.stat_desc = &static_d_desc; - - s->bl_desc.dyn_tree = s->bl_tree; - s->bl_desc.stat_desc = &static_bl_desc; - - s->bi_buf = 0; - s->bi_valid = 0; - s->last_eob_len = 8; /* enough lookahead for inflate */ -#ifdef DEBUG - s->compressed_len = 0L; - s->bits_sent = 0L; -#endif - - /* Initialize the first block of the first file: */ - init_block(s); -} - -/* =========================================================================== - * Initialize a new block. - */ -local void init_block(s) - deflate_state *s; -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; -} - -#define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ - - -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ -#define pqremove(s, tree, top) \ -{\ - top = s->heap[SMALLEST]; \ - s->heap[SMALLEST] = s->heap[s->heap_len--]; \ - pqdownheap(s, tree, SMALLEST); \ -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -#define smaller(tree, n, m, depth) \ - (tree[n].Freq < tree[m].Freq || \ - (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -local void pqdownheap(s, tree, k) - deflate_state *s; - ct_data *tree; /* the tree to restore */ - int k; /* node to move down */ -{ - int v = s->heap[k]; - int j = k << 1; /* left son of k */ - while (j <= s->heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s->heap[j], s->depth)) break; - - /* Exchange v with the smallest son */ - s->heap[k] = s->heap[j]; k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s->heap[k] = v; -} - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -local void gen_bitlen(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - const ct_data *stree = desc->stat_desc->static_tree; - const intf *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - int max_length = desc->stat_desc->max_length; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - ush f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { - n = s->heap[h]; - bits = tree[tree[n].Dad].Len + 1; - if (bits > max_length) bits = max_length, overflow++; - tree[n].Len = (ush)bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) continue; /* not a leaf node */ - - s->bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n-base]; - f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); - } - if (overflow == 0) return; - - Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length-1; - while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ - s->bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = s->bl_count[bits]; - while (n != 0) { - m = s->heap[--h]; - if (m > max_code) continue; - if (tree[m].Len != (unsigned) bits) { - Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; - tree[m].Len = (ush)bits; - } - n--; - } - } -} - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -local void gen_codes (tree, max_code, bl_count) - ct_data *tree; /* the tree to decorate */ - int max_code; /* largest code with non zero frequency */ - ushf *bl_count; /* number of codes at each bit length */ -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, - "inconsistent bit counts"); - Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); - - for (n = 0; n <= max_code; n++) { - int len = tree[n].Len; - if (len == 0) continue; - /* Now reverse the bits */ - tree[n].Code = bi_reverse(next_code[len]++, len); - - Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", - n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); - } -} - -/* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ -local void build_tree(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - const ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s->heap_len = 0, s->heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - s->heap[++(s->heap_len)] = max_code = n; - s->depth[n] = 0; - } else { - tree[n].Len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s->heap_len < 2) { - node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); - tree[node].Freq = 1; - s->depth[node] = 0; - s->opt_len--; if (stree) s->static_len -= stree[node].Len; - /* node is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - pqremove(s, tree, n); /* n = node of least frequency */ - m = s->heap[SMALLEST]; /* m = node of next least frequency */ - - s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ - s->heap[--(s->heap_max)] = m; - - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (ush)node; -#ifdef DUMP_BL_TREE - if (tree == s->bl_tree) { - fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); - } -#endif - /* and insert the new node in the heap */ - s->heap[SMALLEST] = node++; - pqdownheap(s, tree, SMALLEST); - - } while (s->heap_len >= 2); - - s->heap[--(s->heap_max)] = s->heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, (tree_desc *)desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes ((ct_data *)tree, max_code, s->bl_count); -} - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -local void scan_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) s->bl_tree[curlen].Freq++; - s->bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - s->bl_tree[REPZ_3_10].Freq++; - } else { - s->bl_tree[REPZ_11_138].Freq++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -local void send_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen == 0) max_count = 138, min_count = 3; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { send_code(s, curlen, s->bl_tree); } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(s, curlen, s->bl_tree); count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); - - } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -local int build_bl_tree(s) - deflate_state *s; -{ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); - scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; - } - /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; - Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - s->opt_len, s->static_len)); - - return max_blindex; -} - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -local void send_all_trees(s, lcodes, dcodes, blcodes) - deflate_state *s; - int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - int rank; /* index in bl_order */ - - Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - "too many codes"); - Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); - } - Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ - Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ - Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -} - -/* =========================================================================== - * Send a stored block - */ -void _tr_stored_block(s, buf, stored_len, eof) - deflate_state *s; - charf *buf; /* input block */ - ulg stored_len; /* length of input block */ - int eof; /* true if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ -#ifdef DEBUG - s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; - s->compressed_len += (stored_len + 4) << 3; -#endif - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ -} - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - * The current inflate code requires 9 bits of lookahead. If the - * last two codes for the previous block (real code plus EOB) were coded - * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode - * the last real code. In this case we send two empty static blocks instead - * of one. (There are no problems if the previous block is stored or fixed.) - * To simplify the code, we assume the worst case of last real code encoded - * on one bit only. - */ -void _tr_align(s) - deflate_state *s; -{ - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ -#endif - bi_flush(s); - /* Of the 10 bits for the empty block, we have already sent - * (10 - bi_valid) bits. The lookahead for the last real code (before - * the EOB of the previous block) was thus at least one plus the length - * of the EOB plus what we have just sent of the empty static block. - */ - if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; -#endif - bi_flush(s); - } - s->last_eob_len = 7; -} - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ -void _tr_flush_block(s, buf, stored_len, eof) - deflate_state *s; - charf *buf; /* input block, or NULL if too old */ - ulg stored_len; /* length of input block */ - int eof; /* true if this is the last block for a file */ -{ - ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s->level > 0) { - - /* Check if the file is ascii or binary */ - if (s->data_type == Z_UNKNOWN) set_data_type(s); - - /* Construct the literal and distance trees */ - build_tree(s, (tree_desc *)(&(s->l_desc))); - Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - - build_tree(s, (tree_desc *)(&(s->d_desc))); - Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute first the block length in bytes*/ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; - - Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); - - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; - - } else { - Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - -#ifdef FORCE_STORED - if (buf != (char*)0) { /* force stored block */ -#else - if (stored_len+4 <= opt_lenb && buf != (char*)0) { - /* 4: two words for the lengths */ -#endif - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, eof); - -#ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ -#else - } else if (static_lenb == opt_lenb) { -#endif - send_bits(s, (STATIC_TREES<<1)+eof, 3); - compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->static_len; -#endif - } else { - send_bits(s, (DYN_TREES<<1)+eof, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); - compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->opt_len; -#endif - } - Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (eof) { - bi_windup(s); -#ifdef DEBUG - s->compressed_len += 7; /* align on byte boundary */ -#endif - } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*eof)); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -int _tr_tally (s, dist, lc) - deflate_state *s; - unsigned dist; /* distance of matched string */ - unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - s->d_buf[s->last_lit] = (ush)dist; - s->l_buf[s->last_lit++] = (uch)lc; - if (dist == 0) { - /* lc is the unmatched char */ - s->dyn_ltree[lc].Freq++; - } else { - s->matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert((ush)dist < (ush)MAX_DIST(s) && - (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - } - -#ifdef TRUNCATE_BLOCK - /* Try to guess if it is profitable to stop the current block here */ - if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)s->last_lit*8L; - ulg in_length = (ulg)((long)s->strstart - s->block_start); - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - s->last_lit, in_length, out_length, - 100L - out_length*100L/in_length)); - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } -#endif - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -local void compress_block(s, ltree, dtree) - deflate_state *s; - ct_data *ltree; /* literal tree */ - ct_data *dtree; /* distance tree */ -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); - - } while (lx < s->last_lit); - - send_code(s, END_BLOCK, ltree); - s->last_eob_len = ltree[END_BLOCK].Len; -} - -/* =========================================================================== - * Set the data type to ASCII or BINARY, using a crude approximation: - * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. - * IN assertion: the fields freq of dyn_ltree are set and the total of all - * frequencies does not exceed 64K (to fit in an int on 16 bit machines). - */ -local void set_data_type(s) - deflate_state *s; -{ - int n = 0; - unsigned ascii_freq = 0; - unsigned bin_freq = 0; - while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; - while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; - while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; - s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -local unsigned bi_reverse(code, len) - unsigned code; /* the value to invert */ - int len; /* its bit length */ -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -local void bi_flush(s) - deflate_state *s; -{ - if (s->bi_valid == 16) { - put_short(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } -} - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -local void bi_windup(s) - deflate_state *s; -{ - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; -#endif -} - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -local void copy_block(s, buf, len, header) - deflate_state *s; - charf *buf; /* the input data */ - unsigned len; /* its length */ - int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - s->last_eob_len = 8; /* enough lookahead for inflate */ - - if (header) { - put_short(s, (ush)len); - put_short(s, (ush)~len); -#ifdef DEBUG - s->bits_sent += 2*16; -#endif - } -#ifdef DEBUG - s->bits_sent += (ulg)len<<3; -#endif - while (len--) { - put_byte(s, *buf++); - } -} diff --git a/src/utilfuns/zlib/trees.h b/src/utilfuns/zlib/trees.h deleted file mode 100644 index 72facf9..0000000 --- a/src/utilfuns/zlib/trees.h +++ /dev/null @@ -1,128 +0,0 @@ -/* header created automatically with -DGEN_TREES_H */ - -local const ct_data static_ltree[L_CODES+2] = { -{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, -{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, -{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, -{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, -{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, -{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, -{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, -{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, -{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, -{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, -{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, -{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, -{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, -{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, -{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, -{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, -{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, -{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, -{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, -{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, -{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, -{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, -{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, -{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, -{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, -{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, -{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, -{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, -{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, -{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, -{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, -{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, -{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, -{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, -{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, -{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, -{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, -{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, -{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, -{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, -{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, -{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, -{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, -{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, -{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, -{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, -{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, -{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, -{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, -{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, -{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, -{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, -{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, -{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, -{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, -{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, -{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, -{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} -}; - -local const ct_data static_dtree[D_CODES] = { -{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, -{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, -{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, -{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, -{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, -{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} -}; - -const uch _dist_code[DIST_CODE_LEN] = { - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, -10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, -11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, -12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, -18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 -}; - -const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, -13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, -17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, -19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, -21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, -22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 -}; - -local const int base_length[LENGTH_CODES] = { -0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, -64, 80, 96, 112, 128, 160, 192, 224, 0 -}; - -local const int base_dist[D_CODES] = { - 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, - 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, - 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 -}; - diff --git a/src/utilfuns/zlib/uncompr.c b/src/utilfuns/zlib/uncompr.c deleted file mode 100644 index 45a4687..0000000 --- a/src/utilfuns/zlib/uncompr.c +++ /dev/null @@ -1,58 +0,0 @@ -/* uncompr.c -- decompress a memory buffer - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: uncompr.c 1688 2005-01-01 04:42:26Z scribe $ */ - -#include "zlib.h" - -/* =========================================================================== - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. -*/ -int ZEXPORT uncompress (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ - z_stream stream; - int err; - - stream.next_in = (Bytef*)source; - stream.avail_in = (uInt)sourceLen; - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; - - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - - err = inflateInit(&stream); - if (err != Z_OK) return err; - - err = inflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; - - err = inflateEnd(&stream); - return err; -} diff --git a/src/utilfuns/zlib/zutil.c b/src/utilfuns/zlib/zutil.c deleted file mode 100644 index 55e047c..0000000 --- a/src/utilfuns/zlib/zutil.c +++ /dev/null @@ -1,225 +0,0 @@ -/* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: zutil.c 1688 2005-01-01 04:42:26Z scribe $ */ - -#include "zutil.h" - -struct internal_state {int dummy;}; /* for buggy compilers */ - -#ifndef STDC -extern void exit OF((int)); -#endif - -const char *z_errmsg[10] = { -"need dictionary", /* Z_NEED_DICT 2 */ -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -"incompatible version",/* Z_VERSION_ERROR (-6) */ -""}; - - -const char * ZEXPORT zlibVersion() -{ - return ZLIB_VERSION; -} - -#ifdef DEBUG - -# ifndef verbose -# define verbose 0 -# endif -int z_verbose = verbose; - -void z_error (m) - char *m; -{ - fprintf(stderr, "%s\n", m); - exit(1); -} -#endif - -/* exported to allow conversion of error code to string for compress() and - * uncompress() - */ -const char * ZEXPORT zError(err) - int err; -{ - return ERR_MSG(err); -} - - -#ifndef HAVE_MEMCPY - -void zmemcpy(dest, source, len) - Bytef* dest; - const Bytef* source; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = *source++; /* ??? to be unrolled */ - } while (--len != 0); -} - -int zmemcmp(s1, s2, len) - const Bytef* s1; - const Bytef* s2; - uInt len; -{ - uInt j; - - for (j = 0; j < len; j++) { - if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; - } - return 0; -} - -void zmemzero(dest, len) - Bytef* dest; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = 0; /* ??? to be unrolled */ - } while (--len != 0); -} -#endif - -#ifdef __TURBOC__ -#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) -/* Small and medium model in Turbo C are for now limited to near allocation - * with reduced MAX_WBITS and MAX_MEM_LEVEL - */ -# define MY_ZCALLOC - -/* Turbo C malloc() does not allow dynamic allocation of 64K bytes - * and farmalloc(64K) returns a pointer with an offset of 8, so we - * must fix the pointer. Warning: the pointer must be put back to its - * original form in order to free it, use zcfree(). - */ - -#define MAX_PTR 10 -/* 10*64K = 640K */ - -local int next_ptr = 0; - -typedef struct ptr_table_s { - voidpf org_ptr; - voidpf new_ptr; -} ptr_table; - -local ptr_table table[MAX_PTR]; -/* This table is used to remember the original form of pointers - * to large buffers (64K). Such pointers are normalized with a zero offset. - * Since MSDOS is not a preemptive multitasking OS, this table is not - * protected from concurrent access. This hack doesn't work anyway on - * a protected system like OS/2. Use Microsoft C instead. - */ - -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - voidpf buf = opaque; /* just to make some compilers happy */ - ulg bsize = (ulg)items*size; - - /* If we allocate less than 65520 bytes, we assume that farmalloc - * will return a usable pointer which doesn't have to be normalized. - */ - if (bsize < 65520L) { - buf = farmalloc(bsize); - if (*(ush*)&buf != 0) return buf; - } else { - buf = farmalloc(bsize + 16L); - } - if (buf == NULL || next_ptr >= MAX_PTR) return NULL; - table[next_ptr].org_ptr = buf; - - /* Normalize the pointer to seg:0 */ - *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; - *(ush*)&buf = 0; - table[next_ptr++].new_ptr = buf; - return buf; -} - -void zcfree (voidpf opaque, voidpf ptr) -{ - int n; - if (*(ush*)&ptr != 0) { /* object < 64K */ - farfree(ptr); - return; - } - /* Find the original pointer */ - for (n = 0; n < next_ptr; n++) { - if (ptr != table[n].new_ptr) continue; - - farfree(table[n].org_ptr); - while (++n < next_ptr) { - table[n-1] = table[n]; - } - next_ptr--; - return; - } - ptr = opaque; /* just to make some compilers happy */ - Assert(0, "zcfree: ptr not found"); -} -#endif -#endif /* __TURBOC__ */ - - -#if defined(M_I86) && !defined(__32BIT__) -/* Microsoft C in 16-bit mode */ - -# define MY_ZCALLOC - -#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) -# define _halloc halloc -# define _hfree hfree -#endif - -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - return _halloc((long)items, size); -} - -void zcfree (voidpf opaque, voidpf ptr) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - _hfree(ptr); -} - -#endif /* MSC */ - - -#ifndef MY_ZCALLOC /* Any system without a special alloc function */ - -#ifndef STDC -extern voidp calloc OF((uInt items, uInt size)); -extern void free OF((voidpf ptr)); -#endif - -voidpf zcalloc (opaque, items, size) - voidpf opaque; - unsigned items; - unsigned size; -{ - if (opaque) items += size - size; /* make compiler happy */ - return (voidpf)calloc(items, size); -} - -void zcfree (opaque, ptr) - voidpf opaque; - voidpf ptr; -{ - free(ptr); - if (opaque) return; /* make compiler happy */ -} - -#endif /* MY_ZCALLOC */ diff --git a/src/utilfuns/zlib/zutil.h b/src/utilfuns/zlib/zutil.h deleted file mode 100644 index 538fc57..0000000 --- a/src/utilfuns/zlib/zutil.h +++ /dev/null @@ -1,220 +0,0 @@ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id: zutil.h 1688 2005-01-01 04:42:26Z scribe $ */ - -#ifndef _Z_UTIL_H -#define _Z_UTIL_H - -#include "zlib.h" - -#ifdef STDC -# include <stddef.h> -# include <string.h> -# include <stdlib.h> -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include <errno.h> -#endif - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -typedef unsigned char uch; -typedef uch FAR uchf; -typedef unsigned short ush; -typedef ush FAR ushf; -typedef unsigned long ulg; - -extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ -/* (size given to avoid silly warnings with Visual C++) */ - -#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] - -#define ERR_RETURN(strm,err) \ - return (strm->msg = (char*)ERR_MSG(err), (err)) -/* To be used only when the state is known to be valid */ - - /* common constants */ - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - - /* target dependencies */ - -#ifdef MSDOS -# define OS_CODE 0x00 -# if defined(__TURBOC__) || defined(__BORLANDC__) -# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -# include <alloc.h> -# endif -# else /* MSC or DJGPP */ -# include <malloc.h> -# endif -#endif - -#ifdef OS2 -# define OS_CODE 0x06 -#endif - -#ifdef WIN32 /* Window 95 & Windows NT */ -# define OS_CODE 0x0b -#endif - -#if defined(VAXC) || defined(VMS) -# define OS_CODE 0x02 -# define F_OPEN(name, mode) \ - fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -#endif - -#ifdef AMIGA -# define OS_CODE 0x01 -#endif - -#if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 -#endif - -#if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 0x07 -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include <unix.h> /* for fdopen */ -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ -# endif -# endif -#endif - -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0F -#endif - -#ifdef TOPS20 -# define OS_CODE 0x0a -#endif - -#if defined(_BEOS_) || defined(RISCOS) -# define fdopen(fd,mode) NULL /* No fdopen() */ -#endif - -#if (defined(_MSC_VER) && (_MSC_VER > 600)) -# define fdopen(fd,type) _fdopen(fd,type) -#endif - - - /* Common defaults */ - -#ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ -#endif - -#ifndef F_OPEN -# define F_OPEN(name, mode) fopen((name), (mode)) -#endif - - /* functions */ - -#ifdef HAVE_STRERROR - extern char *strerror OF((int)); -# define zstrerror(errnum) strerror(errnum) -#else -# define zstrerror(errnum) "" -#endif - -#if defined(pyr) -# define NO_MEMCPY -#endif -#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) - /* Use our own functions for small and medium model with MSC <= 5.0. - * You may have to use the same strategy for Borland C (untested). - * The __SC__ check is for Symantec. - */ -# define NO_MEMCPY -#endif -#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) -# define HAVE_MEMCPY -#endif -#ifdef HAVE_MEMCPY -# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -# define zmemcpy _fmemcpy -# define zmemcmp _fmemcmp -# define zmemzero(dest, len) _fmemset(dest, 0, len) -# else -# define zmemcpy memcpy -# define zmemcmp memcmp -# define zmemzero(dest, len) memset(dest, 0, len) -# endif -#else - extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - extern void zmemzero OF((Bytef* dest, uInt len)); -#endif - -/* Diagnostic functions */ -#ifdef DEBUG -# include <stdio.h> - extern int z_verbose; - extern void z_error OF((char *m)); -# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -# define Trace(x) {if (z_verbose>=0) fprintf x ;} -# define Tracev(x) {if (z_verbose>0) fprintf x ;} -# define Tracevv(x) {if (z_verbose>1) fprintf x ;} -# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} -# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - - -typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, - uInt len)); -voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); -void zcfree OF((voidpf opaque, voidpf ptr)); - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) -#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} - -#endif /* _Z_UTIL_H */ |