summaryrefslogtreecommitdiff
path: root/db/mork/src/morkBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'db/mork/src/morkBuilder.cpp')
-rw-r--r--db/mork/src/morkBuilder.cpp1031
1 files changed, 1031 insertions, 0 deletions
diff --git a/db/mork/src/morkBuilder.cpp b/db/mork/src/morkBuilder.cpp
new file mode 100644
index 0000000000..27e5bd1988
--- /dev/null
+++ b/db/mork/src/morkBuilder.cpp
@@ -0,0 +1,1031 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _MDB_
+#include "mdb.h"
+#endif
+
+#ifndef _MORK_
+#include "mork.h"
+#endif
+
+#ifndef _MORKNODE_
+#include "morkNode.h"
+#endif
+
+#ifndef _MORKMAP_
+#include "morkMap.h"
+#endif
+
+#ifndef _MORKENV_
+#include "morkEnv.h"
+#endif
+
+#ifndef _MORKPARSER_
+#include "morkParser.h"
+#endif
+
+#ifndef _MORKBUILDER_
+#include "morkBuilder.h"
+#endif
+
+#ifndef _MORKCELL_
+#include "morkCell.h"
+#endif
+
+#ifndef _MORKSTORE_
+#include "morkStore.h"
+#endif
+
+#ifndef _MORKTABLE_
+#include "morkTable.h"
+#endif
+
+#ifndef _MORKROW_
+#include "morkRow.h"
+#endif
+
+#ifndef _MORKCELL_
+#include "morkCell.h"
+#endif
+
+#ifndef _MORKATOM_
+#include "morkAtom.h"
+#endif
+
+#ifndef _MORKATOMSPACE_
+#include "morkAtomSpace.h"
+#endif
+
+#ifndef _MORKROWSPACE_
+#include "morkRowSpace.h"
+#endif
+
+//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
+
+// ````` ````` ````` ````` `````
+// { ===== begin morkNode interface =====
+
+/*public virtual*/ void
+morkBuilder::CloseMorkNode(morkEnv* ev) // CloseBuilder() only if open
+{
+ if ( this->IsOpenNode() )
+ {
+ this->MarkClosing();
+ this->CloseBuilder(ev);
+ this->MarkShut();
+ }
+}
+
+/*public virtual*/
+morkBuilder::~morkBuilder() // assert CloseBuilder() executed earlier
+{
+ MORK_ASSERT(mBuilder_Store==0);
+ MORK_ASSERT(mBuilder_Row==0);
+ MORK_ASSERT(mBuilder_Table==0);
+ MORK_ASSERT(mBuilder_Cell==0);
+ MORK_ASSERT(mBuilder_RowSpace==0);
+ MORK_ASSERT(mBuilder_AtomSpace==0);
+}
+
+/*public non-poly*/
+morkBuilder::morkBuilder(morkEnv* ev,
+ const morkUsage& inUsage, nsIMdbHeap* ioHeap,
+ morkStream* ioStream, mdb_count inBytesPerParseSegment,
+ nsIMdbHeap* ioSlotHeap, morkStore* ioStore)
+
+: morkParser(ev, inUsage, ioHeap, ioStream,
+ inBytesPerParseSegment, ioSlotHeap)
+
+, mBuilder_Store( 0 )
+
+, mBuilder_Table( 0 )
+, mBuilder_Row( 0 )
+, mBuilder_Cell( 0 )
+
+, mBuilder_RowSpace( 0 )
+, mBuilder_AtomSpace( 0 )
+
+, mBuilder_OidAtomSpace( 0 )
+, mBuilder_ScopeAtomSpace( 0 )
+
+, mBuilder_PortForm( 0 )
+, mBuilder_PortRowScope( (mork_scope) 'r' )
+, mBuilder_PortAtomScope( (mork_scope) 'v' )
+
+, mBuilder_TableForm( 0 )
+, mBuilder_TableRowScope( (mork_scope) 'r' )
+, mBuilder_TableAtomScope( (mork_scope) 'v' )
+, mBuilder_TableKind( 0 )
+
+, mBuilder_TablePriority( morkPriority_kLo )
+, mBuilder_TableIsUnique( morkBool_kFalse )
+, mBuilder_TableIsVerbose( morkBool_kFalse )
+, mBuilder_TablePadByte( 0 )
+
+, mBuilder_RowForm( 0 )
+, mBuilder_RowRowScope( (mork_scope) 'r' )
+, mBuilder_RowAtomScope( (mork_scope) 'v' )
+
+, mBuilder_CellForm( 0 )
+, mBuilder_CellAtomScope( (mork_scope) 'v' )
+
+, mBuilder_DictForm( 0 )
+, mBuilder_DictAtomScope( (mork_scope) 'v' )
+
+, mBuilder_MetaTokenSlot( 0 )
+
+, mBuilder_DoCutRow( morkBool_kFalse )
+, mBuilder_DoCutCell( morkBool_kFalse )
+, mBuilder_CellsVecFill( 0 )
+{
+ if ( ev->Good() )
+ {
+ if ( ioStore )
+ {
+ morkStore::SlotWeakStore(ioStore, ev, &mBuilder_Store);
+ if ( ev->Good() )
+ mNode_Derived = morkDerived_kBuilder;
+ }
+ else
+ ev->NilPointerError();
+ }
+
+}
+
+/*public non-poly*/ void
+morkBuilder::CloseBuilder(morkEnv* ev) // called by CloseMorkNode();
+{
+ if ( this->IsNode() )
+ {
+ mBuilder_Row = 0;
+ mBuilder_Cell = 0;
+ mBuilder_MetaTokenSlot = 0;
+
+ morkTable::SlotStrongTable((morkTable*) 0, ev, &mBuilder_Table);
+ morkStore::SlotWeakStore((morkStore*) 0, ev, &mBuilder_Store);
+
+ morkRowSpace::SlotStrongRowSpace((morkRowSpace*) 0, ev,
+ &mBuilder_RowSpace);
+
+ morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*) 0, ev,
+ &mBuilder_AtomSpace);
+
+ morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*) 0, ev,
+ &mBuilder_OidAtomSpace);
+
+ morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*) 0, ev,
+ &mBuilder_ScopeAtomSpace);
+ this->CloseParser(ev);
+ this->MarkShut();
+ }
+ else
+ this->NonNodeError(ev);
+}
+
+// } ===== end morkNode methods =====
+// ````` ````` ````` ````` `````
+
+/*static*/ void
+morkBuilder::NonBuilderTypeError(morkEnv* ev)
+{
+ ev->NewError("non morkBuilder");
+}
+
+/*static*/ void
+morkBuilder::NilBuilderCellError(morkEnv* ev)
+{
+ ev->NewError("nil mBuilder_Cell");
+}
+
+/*static*/ void
+morkBuilder::NilBuilderRowError(morkEnv* ev)
+{
+ ev->NewError("nil mBuilder_Row");
+}
+
+/*static*/ void
+morkBuilder::NilBuilderTableError(morkEnv* ev)
+{
+ ev->NewError("nil mBuilder_Table");
+}
+
+/*static*/ void
+morkBuilder::NonColumnSpaceScopeError(morkEnv* ev)
+{
+ ev->NewError("column space != 'c'");
+}
+
+void
+morkBuilder::LogGlitch(morkEnv* ev, const morkGlitch& inGlitch,
+ const char* inKind)
+{
+ MORK_USED_2(inGlitch,inKind);
+ ev->NewWarning("parsing glitch");
+}
+
+/*virtual*/ void
+morkBuilder::MidToYarn(morkEnv* ev,
+ const morkMid& inMid, // typically an alias to concat with strings
+ mdbYarn* outYarn)
+// The parser might ask that some aliases be turned into yarns, so they
+// can be concatenated into longer blobs under some circumstances. This
+// is an alternative to using a long and complex callback for many parts
+// for a single cell value.
+{
+ mBuilder_Store->MidToYarn(ev, inMid, outYarn);
+}
+
+/*virtual*/ void
+morkBuilder::OnNewPort(morkEnv* ev, const morkPlace& inPlace)
+// mp:Start ::= OnNewPort mp:PortItem* OnPortEnd
+// mp:PortItem ::= mp:Content | mp:Group | OnPortGlitch
+// mp:Content ::= mp:PortRow | mp:Dict | mp:Table | mp:Row
+{
+ MORK_USED_2(ev,inPlace);
+ // mParser_InPort = morkBool_kTrue;
+ mBuilder_PortForm = 0;
+ mBuilder_PortRowScope = (mork_scope) 'r';
+ mBuilder_PortAtomScope = (mork_scope) 'v';
+}
+
+/*virtual*/ void
+morkBuilder::OnPortGlitch(morkEnv* ev, const morkGlitch& inGlitch)
+{
+ this->LogGlitch(ev, inGlitch, "port");
+}
+
+/*virtual*/ void
+morkBuilder::OnPortEnd(morkEnv* ev, const morkSpan& inSpan)
+// mp:Start ::= OnNewPort mp:PortItem* OnPortEnd
+{
+ MORK_USED_2(ev,inSpan);
+ // ev->StubMethodOnlyError();
+ // nothing to do?
+ // mParser_InPort = morkBool_kFalse;
+}
+
+/*virtual*/ void
+morkBuilder::OnNewGroup(morkEnv* ev, const morkPlace& inPlace, mork_gid inGid)
+{
+ MORK_USED_1(inPlace);
+ mParser_InGroup = morkBool_kTrue;
+ mork_pos startPos = inPlace.mPlace_Pos;
+
+ morkStore* store = mBuilder_Store;
+ if ( store )
+ {
+ if ( inGid >= store->mStore_CommitGroupIdentity )
+ store->mStore_CommitGroupIdentity = inGid + 1;
+
+ if ( !store->mStore_FirstCommitGroupPos )
+ store->mStore_FirstCommitGroupPos = startPos;
+ else if ( !store->mStore_SecondCommitGroupPos )
+ store->mStore_SecondCommitGroupPos = startPos;
+ }
+}
+
+/*virtual*/ void
+morkBuilder::OnGroupGlitch(morkEnv* ev, const morkGlitch& inGlitch)
+{
+ this->LogGlitch(ev, inGlitch, "group");
+}
+
+/*virtual*/ void
+morkBuilder::OnGroupCommitEnd(morkEnv* ev, const morkSpan& inSpan)
+{
+ MORK_USED_2(ev,inSpan);
+ // mParser_InGroup = morkBool_kFalse;
+ // ev->StubMethodOnlyError();
+}
+
+/*virtual*/ void
+morkBuilder::OnGroupAbortEnd(morkEnv* ev, const morkSpan& inSpan)
+{
+ MORK_USED_1(inSpan);
+ // mParser_InGroup = morkBool_kFalse;
+ ev->StubMethodOnlyError();
+}
+
+/*virtual*/ void
+morkBuilder::OnNewPortRow(morkEnv* ev, const morkPlace& inPlace,
+ const morkMid& inMid, mork_change inChange)
+{
+ MORK_USED_3(inMid,inPlace,inChange);
+ // mParser_InPortRow = morkBool_kTrue;
+ ev->StubMethodOnlyError();
+}
+
+/*virtual*/ void
+morkBuilder::OnPortRowGlitch(morkEnv* ev, const morkGlitch& inGlitch)
+{
+ this->LogGlitch(ev, inGlitch, "port row");
+}
+
+/*virtual*/ void
+morkBuilder::OnPortRowEnd(morkEnv* ev, const morkSpan& inSpan)
+{
+ MORK_USED_1(inSpan);
+ // mParser_InPortRow = morkBool_kFalse;
+ ev->StubMethodOnlyError();
+}
+
+/*virtual*/ void
+morkBuilder::OnNewTable(morkEnv* ev, const morkPlace& inPlace,
+ const morkMid& inMid, mork_bool inCutAllRows)
+// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
+// mp:TableItem ::= mp:Row | mp:MetaTable | OnTableGlitch
+// mp:MetaTable ::= OnNewMeta mp:MetaItem* mp:Row OnMetaEnd
+// mp:Meta ::= OnNewMeta mp:MetaItem* OnMetaEnd
+// mp:MetaItem ::= mp:Cell | OnMetaGlitch
+{
+ MORK_USED_1(inPlace);
+ // mParser_InTable = morkBool_kTrue;
+ mBuilder_TableForm = mBuilder_PortForm;
+ mBuilder_TableRowScope = mBuilder_PortRowScope;
+ mBuilder_TableAtomScope = mBuilder_PortAtomScope;
+ mBuilder_TableKind = morkStore_kNoneToken;
+
+ mBuilder_TablePriority = morkPriority_kLo;
+ mBuilder_TableIsUnique = morkBool_kFalse;
+ mBuilder_TableIsVerbose = morkBool_kFalse;
+
+ morkTable* table = mBuilder_Store->MidToTable(ev, inMid);
+ morkTable::SlotStrongTable(table, ev, &mBuilder_Table);
+ if ( table )
+ {
+ if ( table->mTable_RowSpace )
+ mBuilder_TableRowScope = table->mTable_RowSpace->SpaceScope();
+
+ if ( inCutAllRows )
+ table->CutAllRows(ev);
+ }
+}
+
+/*virtual*/ void
+morkBuilder::OnTableGlitch(morkEnv* ev, const morkGlitch& inGlitch)
+{
+ this->LogGlitch(ev, inGlitch, "table");
+}
+
+/*virtual*/ void
+morkBuilder::OnTableEnd(morkEnv* ev, const morkSpan& inSpan)
+// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
+{
+ MORK_USED_1(inSpan);
+ // mParser_InTable = morkBool_kFalse;
+ if ( mBuilder_Table )
+ {
+ mBuilder_Table->mTable_Priority = mBuilder_TablePriority;
+
+ if ( mBuilder_TableIsUnique )
+ mBuilder_Table->SetTableUnique();
+
+ if ( mBuilder_TableIsVerbose )
+ mBuilder_Table->SetTableVerbose();
+
+ morkTable::SlotStrongTable((morkTable*) 0, ev, &mBuilder_Table);
+ }
+ else
+ this->NilBuilderTableError(ev);
+
+ mBuilder_Row = 0;
+ mBuilder_Cell = 0;
+
+
+ mBuilder_TablePriority = morkPriority_kLo;
+ mBuilder_TableIsUnique = morkBool_kFalse;
+ mBuilder_TableIsVerbose = morkBool_kFalse;
+
+ if ( mBuilder_TableKind == morkStore_kNoneToken )
+ ev->NewError("missing table kind");
+
+ mBuilder_CellAtomScope = mBuilder_RowAtomScope =
+ mBuilder_TableAtomScope = mBuilder_PortAtomScope;
+
+ mBuilder_DoCutCell = morkBool_kFalse;
+ mBuilder_DoCutRow = morkBool_kFalse;
+}
+
+/*virtual*/ void
+morkBuilder::OnNewMeta(morkEnv* ev, const morkPlace& inPlace)
+// mp:Meta ::= OnNewMeta mp:MetaItem* OnMetaEnd
+// mp:MetaItem ::= mp:Cell | OnMetaGlitch
+// mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
+// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_2(ev,inPlace);
+ // mParser_InMeta = morkBool_kTrue;
+
+}
+
+/*virtual*/ void
+morkBuilder::OnMetaGlitch(morkEnv* ev, const morkGlitch& inGlitch)
+{
+ this->LogGlitch(ev, inGlitch, "meta");
+}
+
+/*virtual*/ void
+morkBuilder::OnMetaEnd(morkEnv* ev, const morkSpan& inSpan)
+// mp:Meta ::= OnNewMeta mp:MetaItem* OnMetaEnd
+{
+ MORK_USED_2(ev,inSpan);
+ // mParser_InMeta = morkBool_kFalse;
+}
+
+/*virtual*/ void
+morkBuilder::OnMinusRow(morkEnv* ev)
+{
+ MORK_USED_1(ev);
+ mBuilder_DoCutRow = morkBool_kTrue;
+}
+
+/*virtual*/ void
+morkBuilder::OnNewRow(morkEnv* ev, const morkPlace& inPlace,
+ const morkMid& inMid, mork_bool inCutAllCols)
+// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
+// mp:TableItem ::= mp:Row | mp:MetaTable | OnTableGlitch
+// mp:MetaTable ::= OnNewMeta mp:MetaItem* mp:Row OnMetaEnd
+// mp:Row ::= OnMinusRow? OnNewRow mp:RowItem* OnRowEnd
+// mp:RowItem ::= mp:Cell | mp:Meta | OnRowGlitch
+// mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
+// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_1(inPlace);
+ // mParser_InRow = morkBool_kTrue;
+
+ mBuilder_CellForm = mBuilder_RowForm = mBuilder_TableForm;
+ mBuilder_CellAtomScope = mBuilder_RowAtomScope = mBuilder_TableAtomScope;
+ mBuilder_RowRowScope = mBuilder_TableRowScope;
+ morkStore* store = mBuilder_Store;
+
+ if ( !inMid.mMid_Buf && !inMid.mMid_Oid.mOid_Scope )
+ {
+ morkMid mid(inMid);
+ mid.mMid_Oid.mOid_Scope = mBuilder_RowRowScope;
+ mBuilder_Row = store->MidToRow(ev, mid);
+ }
+ else
+ {
+ mBuilder_Row = store->MidToRow(ev, inMid);
+ }
+ morkRow* row = mBuilder_Row;
+ if ( row && inCutAllCols )
+ {
+ row->CutAllColumns(ev);
+ }
+
+ morkTable* table = mBuilder_Table;
+ if ( table )
+ {
+ if ( row )
+ {
+ if ( mParser_InMeta )
+ {
+ morkRow* metaRow = table->mTable_MetaRow;
+ if ( !metaRow )
+ {
+ table->mTable_MetaRow = row;
+ table->mTable_MetaRowOid = row->mRow_Oid;
+ row->AddRowGcUse(ev);
+ }
+ else if ( metaRow != row ) // not identical?
+ ev->NewError("duplicate table meta row");
+ }
+ else
+ {
+ if ( mBuilder_DoCutRow )
+ table->CutRow(ev, row);
+ else
+ table->AddRow(ev, row);
+ }
+ }
+ }
+ // else // it is now okay to have rows outside a table:
+ // this->NilBuilderTableError(ev);
+
+ mBuilder_DoCutRow = morkBool_kFalse;
+}
+
+/*virtual*/ void
+morkBuilder::OnRowPos(morkEnv* ev, mork_pos inRowPos)
+{
+ if ( mBuilder_Row && mBuilder_Table && !mParser_InMeta )
+ {
+ mork_pos hintFromPos = 0; // best hint when we don't know position
+ mBuilder_Table->MoveRow(ev, mBuilder_Row, hintFromPos, inRowPos);
+ }
+}
+
+/*virtual*/ void
+morkBuilder::OnRowGlitch(morkEnv* ev, const morkGlitch& inGlitch)
+{
+ this->LogGlitch(ev, inGlitch, "row");
+}
+
+void
+morkBuilder::FlushBuilderCells(morkEnv* ev)
+{
+ if ( mBuilder_Row )
+ {
+ morkPool* pool = mBuilder_Store->StorePool();
+ morkCell* cells = mBuilder_CellsVec;
+ mork_fill fill = mBuilder_CellsVecFill;
+ mBuilder_Row->TakeCells(ev, cells, fill, mBuilder_Store);
+
+ morkCell* end = cells + fill;
+ --cells; // prepare for preincrement
+ while ( ++cells < end )
+ {
+ if ( cells->mCell_Atom )
+ cells->SetAtom(ev, (morkAtom*) 0, pool);
+ }
+ mBuilder_CellsVecFill = 0;
+ }
+ else
+ this->NilBuilderRowError(ev);
+}
+
+/*virtual*/ void
+morkBuilder::OnRowEnd(morkEnv* ev, const morkSpan& inSpan)
+// mp:Row ::= OnMinusRow? OnNewRow mp:RowItem* OnRowEnd
+{
+ MORK_USED_1(inSpan);
+ // mParser_InRow = morkBool_kFalse;
+ if ( mBuilder_Row )
+ {
+ this->FlushBuilderCells(ev);
+ }
+ else
+ this->NilBuilderRowError(ev);
+
+ mBuilder_Row = 0;
+ mBuilder_Cell = 0;
+
+ mBuilder_DoCutCell = morkBool_kFalse;
+ mBuilder_DoCutRow = morkBool_kFalse;
+}
+
+/*virtual*/ void
+morkBuilder::OnNewDict(morkEnv* ev, const morkPlace& inPlace)
+// mp:Dict ::= OnNewDict mp:DictItem* OnDictEnd
+// mp:DictItem ::= OnAlias | OnAliasGlitch | mp:Meta | OnDictGlitch
+{
+ MORK_USED_2(ev,inPlace);
+ // mParser_InDict = morkBool_kTrue;
+
+ mBuilder_CellForm = mBuilder_DictForm = mBuilder_PortForm;
+ mBuilder_CellAtomScope = mBuilder_DictAtomScope = mBuilder_PortAtomScope;
+}
+
+/*virtual*/ void
+morkBuilder::OnDictGlitch(morkEnv* ev, const morkGlitch& inGlitch)
+{
+ this->LogGlitch(ev, inGlitch, "dict");
+}
+
+/*virtual*/ void
+morkBuilder::OnDictEnd(morkEnv* ev, const morkSpan& inSpan)
+// mp:Dict ::= OnNewDict mp:DictItem* OnDictEnd
+{
+ MORK_USED_2(ev,inSpan);
+ // mParser_InDict = morkBool_kFalse;
+
+ mBuilder_DictForm = 0;
+ mBuilder_DictAtomScope = 0;
+}
+
+/*virtual*/ void
+morkBuilder::OnAlias(morkEnv* ev, const morkSpan& inSpan,
+ const morkMid& inMid)
+{
+ MORK_USED_1(inSpan);
+ if ( mParser_InDict )
+ {
+ morkMid mid = inMid; // local copy for modification
+ mid.mMid_Oid.mOid_Scope = mBuilder_DictAtomScope;
+ mBuilder_Store->AddAlias(ev, mid, mBuilder_DictForm);
+ }
+ else
+ ev->NewError("alias not in dict");
+}
+
+/*virtual*/ void
+morkBuilder::OnAliasGlitch(morkEnv* ev, const morkGlitch& inGlitch)
+{
+ this->LogGlitch(ev, inGlitch, "alias");
+}
+
+
+morkCell*
+morkBuilder::AddBuilderCell(morkEnv* ev,
+ const morkMid& inMid, mork_change inChange)
+{
+ morkCell* outCell = 0;
+ mork_column column = inMid.mMid_Oid.mOid_Id;
+
+ if ( ev->Good() )
+ {
+ if ( mBuilder_CellsVecFill >= morkBuilder_kCellsVecSize )
+ this->FlushBuilderCells(ev);
+ if ( ev->Good() )
+ {
+ if ( mBuilder_CellsVecFill < morkBuilder_kCellsVecSize )
+ {
+ mork_fill indx = mBuilder_CellsVecFill++;
+ outCell = mBuilder_CellsVec + indx;
+ outCell->SetColumnAndChange(column, inChange);
+ outCell->mCell_Atom = 0;
+ }
+ else
+ ev->NewError("out of builder cells");
+ }
+ }
+ return outCell;
+}
+
+/*virtual*/ void
+morkBuilder::OnMinusCell(morkEnv* ev)
+{
+ MORK_USED_1(ev);
+ mBuilder_DoCutCell = morkBool_kTrue;
+}
+
+/*virtual*/ void
+morkBuilder::OnNewCell(morkEnv* ev, const morkPlace& inPlace,
+ const morkMid* inMid, const morkBuf* inBuf)
+// Exactly one of inMid and inBuf is nil, and the other is non-nil.
+// When hex ID syntax is used for a column, then inMid is not nil, and
+// when a naked string names a column, then inBuf is not nil.
+
+ // mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
+ // mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+ // mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_1(inPlace);
+ // mParser_InCell = morkBool_kTrue;
+
+ mork_change cellChange = ( mBuilder_DoCutCell )?
+ morkChange_kCut : morkChange_kAdd;
+
+ mBuilder_DoCutCell = morkBool_kFalse;
+
+ mBuilder_CellAtomScope = mBuilder_RowAtomScope;
+
+ mBuilder_Cell = 0; // nil until determined for a row
+ morkStore* store = mBuilder_Store;
+ mork_scope scope = morkStore_kColumnSpaceScope;
+ morkMid tempMid; // space for local and modifiable cell mid
+ morkMid* cellMid = &tempMid; // default to local if inMid==0
+
+ if ( inMid ) // mid parameter is actually provided?
+ {
+ *cellMid = *inMid; // bitwise copy for modifiable local mid
+
+ if ( !cellMid->mMid_Oid.mOid_Scope )
+ {
+ if ( cellMid->mMid_Buf )
+ {
+ scope = store->BufToToken(ev, cellMid->mMid_Buf);
+ cellMid->mMid_Buf = 0; // don't do scope lookup again
+ ev->NewWarning("column mids need column scope");
+ }
+ cellMid->mMid_Oid.mOid_Scope = scope;
+ }
+ }
+ else if ( inBuf ) // buf points to naked column string name?
+ {
+ cellMid->ClearMid();
+ cellMid->mMid_Oid.mOid_Id = store->BufToToken(ev, inBuf);
+ cellMid->mMid_Oid.mOid_Scope = scope; // kColumnSpaceScope
+ }
+ else
+ ev->NilPointerError(); // either inMid or inBuf must be non-nil
+
+ mork_column column = cellMid->mMid_Oid.mOid_Id;
+
+ if ( mBuilder_Row && ev->Good() ) // this cell must be inside a row
+ {
+ // mBuilder_Cell = this->AddBuilderCell(ev, *cellMid, cellChange);
+
+ if ( mBuilder_CellsVecFill >= morkBuilder_kCellsVecSize )
+ this->FlushBuilderCells(ev);
+ if ( ev->Good() )
+ {
+ if ( mBuilder_CellsVecFill < morkBuilder_kCellsVecSize )
+ {
+ mork_fill ix = mBuilder_CellsVecFill++;
+ morkCell* cell = mBuilder_CellsVec + ix;
+ cell->SetColumnAndChange(column, cellChange);
+
+ cell->mCell_Atom = 0;
+ mBuilder_Cell = cell;
+ }
+ else
+ ev->NewError("out of builder cells");
+ }
+ }
+
+ else if ( mParser_InMeta && ev->Good() ) // cell is in metainfo structure?
+ {
+ if ( scope == morkStore_kColumnSpaceScope )
+ {
+ if ( mParser_InTable ) // metainfo for table?
+ {
+ if ( column == morkStore_kKindColumn )
+ mBuilder_MetaTokenSlot = &mBuilder_TableKind;
+ else if ( column == morkStore_kStatusColumn )
+ mBuilder_MetaTokenSlot = &mBuilder_TableStatus;
+ else if ( column == morkStore_kRowScopeColumn )
+ mBuilder_MetaTokenSlot = &mBuilder_TableRowScope;
+ else if ( column == morkStore_kAtomScopeColumn )
+ mBuilder_MetaTokenSlot = &mBuilder_TableAtomScope;
+ else if ( column == morkStore_kFormColumn )
+ mBuilder_MetaTokenSlot = &mBuilder_TableForm;
+ }
+ else if ( mParser_InDict ) // metainfo for dict?
+ {
+ if ( column == morkStore_kAtomScopeColumn )
+ mBuilder_MetaTokenSlot = &mBuilder_DictAtomScope;
+ else if ( column == morkStore_kFormColumn )
+ mBuilder_MetaTokenSlot = &mBuilder_DictForm;
+ }
+ else if ( mParser_InRow ) // metainfo for row?
+ {
+ if ( column == morkStore_kAtomScopeColumn )
+ mBuilder_MetaTokenSlot = &mBuilder_RowAtomScope;
+ else if ( column == morkStore_kRowScopeColumn )
+ mBuilder_MetaTokenSlot = &mBuilder_RowRowScope;
+ else if ( column == morkStore_kFormColumn )
+ mBuilder_MetaTokenSlot = &mBuilder_RowForm;
+ }
+ }
+ else
+ ev->NewWarning("expected column scope");
+ }
+}
+
+/*virtual*/ void
+morkBuilder::OnCellGlitch(morkEnv* ev, const morkGlitch& inGlitch)
+{
+ this->LogGlitch(ev, inGlitch, "cell");
+}
+
+/*virtual*/ void
+morkBuilder::OnCellForm(morkEnv* ev, mork_cscode inCharsetFormat)
+{
+ morkCell* cell = mBuilder_Cell;
+ if ( cell )
+ {
+ mBuilder_CellForm = inCharsetFormat;
+ }
+ else
+ this->NilBuilderCellError(ev);
+}
+
+/*virtual*/ void
+morkBuilder::OnCellEnd(morkEnv* ev, const morkSpan& inSpan)
+// mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
+{
+ MORK_USED_2(ev,inSpan);
+ // mParser_InCell = morkBool_kFalse;
+
+ mBuilder_MetaTokenSlot = 0;
+ mBuilder_CellAtomScope = mBuilder_RowAtomScope;
+}
+
+/*virtual*/ void
+morkBuilder::OnValue(morkEnv* ev, const morkSpan& inSpan,
+ const morkBuf& inBuf)
+// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_1(inSpan);
+ morkStore* store = mBuilder_Store;
+ morkCell* cell = mBuilder_Cell;
+ if ( cell )
+ {
+ mdbYarn yarn;
+ yarn.mYarn_Buf = inBuf.mBuf_Body;
+ yarn.mYarn_Fill = yarn.mYarn_Size = inBuf.mBuf_Fill;
+ yarn.mYarn_More = 0;
+ yarn.mYarn_Form = mBuilder_CellForm;
+ yarn.mYarn_Grow = 0;
+ morkAtom* atom = store->YarnToAtom(ev, &yarn, true /* create */);
+ cell->SetAtom(ev, atom, store->StorePool());
+ }
+ else if ( mParser_InMeta )
+ {
+ mork_token* metaSlot = mBuilder_MetaTokenSlot;
+ if ( metaSlot )
+ {
+ if ( metaSlot == &mBuilder_TableStatus ) // table status?
+ {
+ if ( mParser_InTable && mBuilder_Table )
+ {
+ const char* body = (const char*) inBuf.mBuf_Body;
+ mork_fill bufFill = inBuf.mBuf_Fill;
+ if ( body && bufFill )
+ {
+ const char* bodyEnd = body + bufFill;
+ while ( body < bodyEnd )
+ {
+ int c = *body++;
+ switch ( c )
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ mBuilder_TablePriority = (mork_priority) ( c - '0' );
+ break;
+
+ case 'u':
+ case 'U':
+ mBuilder_TableIsUnique = morkBool_kTrue;
+ break;
+
+ case 'v':
+ case 'V':
+ mBuilder_TableIsVerbose = morkBool_kTrue;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ mork_token token = store->BufToToken(ev, &inBuf);
+ if ( token )
+ {
+ *metaSlot = token;
+ if ( metaSlot == &mBuilder_TableKind ) // table kind?
+ {
+ if ( mParser_InTable && mBuilder_Table )
+ mBuilder_Table->mTable_Kind = token;
+ }
+ }
+ }
+ }
+ }
+ else
+ this->NilBuilderCellError(ev);
+}
+
+/*virtual*/ void
+morkBuilder::OnValueMid(morkEnv* ev, const morkSpan& inSpan,
+ const morkMid& inMid)
+// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_1(inSpan);
+ morkStore* store = mBuilder_Store;
+ morkCell* cell = mBuilder_Cell;
+
+ morkMid valMid; // local mid for modifications
+ mdbOid* valOid = &valMid.mMid_Oid; // ref to oid inside mid
+ *valOid = inMid.mMid_Oid; // bitwise copy inMid's oid
+
+ if ( inMid.mMid_Buf )
+ {
+ if ( !valOid->mOid_Scope )
+ store->MidToOid(ev, inMid, valOid);
+ }
+ else if ( !valOid->mOid_Scope )
+ valOid->mOid_Scope = mBuilder_CellAtomScope;
+
+ if ( cell )
+ {
+ morkBookAtom* atom = store->MidToAtom(ev, valMid);
+ if ( atom )
+ cell->SetAtom(ev, atom, store->StorePool());
+ else
+ ev->NewError("undefined cell value alias");
+ }
+ else if ( mParser_InMeta )
+ {
+ mork_token* metaSlot = mBuilder_MetaTokenSlot;
+ if ( metaSlot )
+ {
+ mork_scope valScope = valOid->mOid_Scope;
+ if ( !valScope || valScope == morkStore_kColumnSpaceScope )
+ {
+ if ( ev->Good() && valMid.HasSomeId() )
+ {
+ *metaSlot = valOid->mOid_Id;
+ if ( metaSlot == &mBuilder_TableKind ) // table kind?
+ {
+ if ( mParser_InTable && mBuilder_Table )
+ {
+ mBuilder_Table->mTable_Kind = valOid->mOid_Id;
+ }
+ else
+ ev->NewWarning("mBuilder_TableKind not in table");
+ }
+ else if ( metaSlot == &mBuilder_TableStatus ) // table status?
+ {
+ if ( mParser_InTable && mBuilder_Table )
+ {
+ // $$ what here??
+ }
+ else
+ ev->NewWarning("mBuilder_TableStatus not in table");
+ }
+ }
+ }
+ else
+ this->NonColumnSpaceScopeError(ev);
+ }
+ }
+ else
+ this->NilBuilderCellError(ev);
+}
+
+/*virtual*/ void
+morkBuilder::OnRowMid(morkEnv* ev, const morkSpan& inSpan,
+ const morkMid& inMid)
+// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_1(inSpan);
+ morkStore* store = mBuilder_Store;
+ morkCell* cell = mBuilder_Cell;
+ if ( cell )
+ {
+ mdbOid rowOid = inMid.mMid_Oid;
+ if ( inMid.mMid_Buf )
+ {
+ if ( !rowOid.mOid_Scope )
+ store->MidToOid(ev, inMid, &rowOid);
+ }
+ else if ( !rowOid.mOid_Scope )
+ rowOid.mOid_Scope = mBuilder_RowRowScope;
+
+ if ( ev->Good() )
+ {
+ morkPool* pool = store->StorePool();
+ morkAtom* atom = pool->NewRowOidAtom(ev, rowOid, &store->mStore_Zone);
+ if ( atom )
+ {
+ cell->SetAtom(ev, atom, pool);
+ morkRow* row = store->OidToRow(ev, &rowOid);
+ if ( row ) // found or created such a row?
+ row->AddRowGcUse(ev);
+ }
+ }
+ }
+ else
+ this->NilBuilderCellError(ev);
+}
+
+/*virtual*/ void
+morkBuilder::OnTableMid(morkEnv* ev, const morkSpan& inSpan,
+ const morkMid& inMid)
+// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_1(inSpan);
+ morkStore* store = mBuilder_Store;
+ morkCell* cell = mBuilder_Cell;
+ if ( cell )
+ {
+ mdbOid tableOid = inMid.mMid_Oid;
+ if ( inMid.mMid_Buf )
+ {
+ if ( !tableOid.mOid_Scope )
+ store->MidToOid(ev, inMid, &tableOid);
+ }
+ else if ( !tableOid.mOid_Scope )
+ tableOid.mOid_Scope = mBuilder_RowRowScope;
+
+ if ( ev->Good() )
+ {
+ morkPool* pool = store->StorePool();
+ morkAtom* atom = pool->NewTableOidAtom(ev, tableOid, &store->mStore_Zone);
+ if ( atom )
+ {
+ cell->SetAtom(ev, atom, pool);
+ morkTable* table = store->OidToTable(ev, &tableOid,
+ /*optionalMetaRowOid*/ (mdbOid*) 0);
+ if ( table ) // found or created such a table?
+ table->AddTableGcUse(ev);
+ }
+ }
+ }
+ else
+ this->NilBuilderCellError(ev);
+}
+
+
+//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789