/* -*- 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