Back to index

lightning-sunbird  0.9+nobinonly
morkBuilder.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef _MDB_
00039 #include "mdb.h"
00040 #endif
00041 
00042 #ifndef _MORK_
00043 #include "mork.h"
00044 #endif
00045 
00046 #ifndef _MORKNODE_
00047 #include "morkNode.h"
00048 #endif
00049 
00050 #ifndef _MORKMAP_
00051 #include "morkMap.h"
00052 #endif
00053 
00054 #ifndef _MORKENV_
00055 #include "morkEnv.h"
00056 #endif
00057 
00058 #ifndef _MORKPARSER_
00059 #include "morkParser.h"
00060 #endif
00061 
00062 #ifndef _MORKBUILDER_
00063 #include "morkBuilder.h"
00064 #endif
00065 
00066 #ifndef _MORKCELL_
00067 #include "morkCell.h"
00068 #endif
00069 
00070 #ifndef _MORKSTORE_
00071 #include "morkStore.h"
00072 #endif
00073 
00074 #ifndef _MORKTABLE_
00075 #include "morkTable.h"
00076 #endif
00077 
00078 #ifndef _MORKROW_
00079 #include "morkRow.h"
00080 #endif
00081 
00082 #ifndef _MORKCELL_
00083 #include "morkCell.h"
00084 #endif
00085 
00086 #ifndef _MORKATOM_
00087 #include "morkAtom.h"
00088 #endif
00089 
00090 #ifndef _MORKATOMSPACE_
00091 #include "morkAtomSpace.h"
00092 #endif
00093 
00094 #ifndef _MORKROWSPACE_
00095 #include "morkRowSpace.h"
00096 #endif
00097 
00098 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00099 
00100 // ````` ````` ````` ````` ````` 
00101 // { ===== begin morkNode interface =====
00102 
00103 /*public virtual*/ void
00104 morkBuilder::CloseMorkNode(morkEnv* ev) // CloseBuilder() only if open
00105 {
00106   if ( this->IsOpenNode() )
00107   {
00108     this->MarkClosing();
00109     this->CloseBuilder(ev);
00110     this->MarkShut();
00111   }
00112 }
00113 
00114 /*public virtual*/
00115 morkBuilder::~morkBuilder() // assert CloseBuilder() executed earlier
00116 {
00117   MORK_ASSERT(mBuilder_Store==0);
00118   MORK_ASSERT(mBuilder_Row==0);
00119   MORK_ASSERT(mBuilder_Table==0);
00120   MORK_ASSERT(mBuilder_Cell==0);
00121   MORK_ASSERT(mBuilder_RowSpace==0);
00122   MORK_ASSERT(mBuilder_AtomSpace==0);
00123 }
00124 
00125 /*public non-poly*/
00126 morkBuilder::morkBuilder(morkEnv* ev,
00127   const morkUsage& inUsage, nsIMdbHeap* ioHeap, 
00128   morkStream* ioStream, mdb_count inBytesPerParseSegment,
00129   nsIMdbHeap* ioSlotHeap, morkStore* ioStore)
00130 
00131 : morkParser(ev, inUsage, ioHeap, ioStream,
00132   inBytesPerParseSegment, ioSlotHeap)
00133   
00134 , mBuilder_Store( 0 )
00135   
00136 , mBuilder_Table( 0 )
00137 , mBuilder_Row( 0 )
00138 , mBuilder_Cell( 0 )
00139   
00140 , mBuilder_RowSpace( 0 )
00141 , mBuilder_AtomSpace( 0 )
00142   
00143 , mBuilder_OidAtomSpace( 0 )
00144 , mBuilder_ScopeAtomSpace( 0 )
00145   
00146 , mBuilder_PortForm( 0 )
00147 , mBuilder_PortRowScope( (mork_scope) 'r' )
00148 , mBuilder_PortAtomScope( (mork_scope) 'v' )
00149 
00150 , mBuilder_TableForm( 0 )
00151 , mBuilder_TableRowScope( (mork_scope) 'r' )
00152 , mBuilder_TableAtomScope( (mork_scope) 'v' )
00153 , mBuilder_TableKind( 0 )
00154 
00155 , mBuilder_TablePriority( morkPriority_kLo )
00156 , mBuilder_TableIsUnique( morkBool_kFalse )
00157 , mBuilder_TableIsVerbose( morkBool_kFalse )
00158 , mBuilder_TablePadByte( 0 )
00159   
00160 , mBuilder_RowForm( 0 )
00161 , mBuilder_RowRowScope( (mork_scope) 'r' )
00162 , mBuilder_RowAtomScope( (mork_scope) 'v' )
00163 
00164 , mBuilder_CellForm( 0 )
00165 , mBuilder_CellAtomScope( (mork_scope) 'v' )
00166 
00167 , mBuilder_DictForm( 0 )
00168 , mBuilder_DictAtomScope( (mork_scope) 'v' )
00169 
00170 , mBuilder_MetaTokenSlot( 0 )
00171   
00172 , mBuilder_DoCutRow( morkBool_kFalse )
00173 , mBuilder_DoCutCell( morkBool_kFalse )
00174 , mBuilder_CellsVecFill( 0 )
00175 {
00176   if ( ev->Good() )
00177   {
00178     if ( ioStore )
00179     {
00180       morkStore::SlotWeakStore(ioStore, ev, &mBuilder_Store);
00181       if ( ev->Good() )
00182         mNode_Derived = morkDerived_kBuilder;
00183     }
00184     else
00185       ev->NilPointerError();
00186   }
00187    
00188 }
00189 
00190 /*public non-poly*/ void
00191 morkBuilder::CloseBuilder(morkEnv* ev) // called by CloseMorkNode();
00192 {
00193   if ( this )
00194   {
00195     if ( this->IsNode() )
00196     {
00197       mBuilder_Row = 0;
00198       mBuilder_Cell = 0;
00199       mBuilder_MetaTokenSlot = 0;
00200       
00201       morkTable::SlotStrongTable((morkTable*) 0, ev, &mBuilder_Table);
00202       morkStore::SlotWeakStore((morkStore*) 0, ev, &mBuilder_Store);
00203 
00204       morkRowSpace::SlotStrongRowSpace((morkRowSpace*) 0, ev,
00205         &mBuilder_RowSpace);
00206 
00207       morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*) 0, ev,
00208         &mBuilder_AtomSpace);
00209 
00210       morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*) 0, ev,
00211         &mBuilder_OidAtomSpace);
00212 
00213       morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*) 0, ev,
00214         &mBuilder_ScopeAtomSpace);
00215       this->CloseParser(ev);
00216       this->MarkShut();
00217     }
00218     else
00219       this->NonNodeError(ev);
00220   }
00221   else
00222     ev->NilPointerError();
00223 }
00224 
00225 // } ===== end morkNode methods =====
00226 // ````` ````` ````` ````` ````` 
00227 
00228 /*static*/ void
00229 morkBuilder::NonBuilderTypeError(morkEnv* ev)
00230 {
00231   ev->NewError("non morkBuilder");
00232 }
00233 
00234 /*static*/ void
00235 morkBuilder::NilBuilderCellError(morkEnv* ev)
00236 {
00237   ev->NewError("nil mBuilder_Cell");
00238 }
00239 
00240 /*static*/ void
00241 morkBuilder::NilBuilderRowError(morkEnv* ev)
00242 {
00243   ev->NewError("nil mBuilder_Row");
00244 }
00245 
00246 /*static*/ void
00247 morkBuilder::NilBuilderTableError(morkEnv* ev)
00248 {
00249   ev->NewError("nil mBuilder_Table");
00250 }
00251 
00252 /*static*/ void
00253 morkBuilder::NonColumnSpaceScopeError(morkEnv* ev)
00254 {
00255   ev->NewError("column space != 'c'");
00256 }
00257 
00258 void
00259 morkBuilder::LogGlitch(morkEnv* ev, const morkGlitch& inGlitch, 
00260   const char* inKind)
00261 {
00262   MORK_USED_2(inGlitch,inKind);
00263   ev->NewWarning("parsing glitch");
00264 }
00265 
00266 /*virtual*/ void
00267 morkBuilder::MidToYarn(morkEnv* ev,
00268   const morkMid& inMid,  // typically an alias to concat with strings
00269   mdbYarn* outYarn)
00270 // The parser might ask that some aliases be turned into yarns, so they
00271 // can be concatenated into longer blobs under some circumstances.  This
00272 // is an alternative to using a long and complex callback for many parts
00273 // for a single cell value.
00274 {
00275   mBuilder_Store->MidToYarn(ev, inMid, outYarn);
00276 }
00277 
00278 /*virtual*/ void
00279 morkBuilder::OnNewPort(morkEnv* ev, const morkPlace& inPlace)
00280 // mp:Start     ::= OnNewPort mp:PortItem* OnPortEnd
00281 // mp:PortItem  ::= mp:Content | mp:Group | OnPortGlitch
00282 // mp:Content   ::= mp:PortRow | mp:Dict | mp:Table | mp:Row
00283 {
00284   MORK_USED_2(ev,inPlace);
00285   // mParser_InPort = morkBool_kTrue;
00286   mBuilder_PortForm = 0;
00287   mBuilder_PortRowScope = (mork_scope) 'r';
00288   mBuilder_PortAtomScope = (mork_scope) 'v';
00289 }
00290 
00291 /*virtual*/ void
00292 morkBuilder::OnPortGlitch(morkEnv* ev, const morkGlitch& inGlitch)  
00293 {
00294   this->LogGlitch(ev, inGlitch, "port");
00295 }
00296 
00297 /*virtual*/ void
00298 morkBuilder::OnPortEnd(morkEnv* ev, const morkSpan& inSpan)
00299 // mp:Start     ::= OnNewPort mp:PortItem* OnPortEnd
00300 {
00301   MORK_USED_2(ev,inSpan);
00302   // ev->StubMethodOnlyError();
00303   // nothing to do?
00304   // mParser_InPort = morkBool_kFalse;
00305 }
00306 
00307 /*virtual*/ void
00308 morkBuilder::OnNewGroup(morkEnv* ev, const morkPlace& inPlace, mork_gid inGid)
00309 {
00310   MORK_USED_1(inPlace);
00311   // mParser_InGroup = morkBool_kTrue;
00312   mork_pos startPos = inPlace.mPlace_Pos;
00313 
00314   morkStore* store = mBuilder_Store;
00315   if ( store )
00316   {
00317     if ( inGid >= store->mStore_CommitGroupIdentity )
00318       store->mStore_CommitGroupIdentity = inGid + 1;
00319   
00320     if ( !store->mStore_FirstCommitGroupPos )
00321       store->mStore_FirstCommitGroupPos = startPos;
00322     else if ( !store->mStore_SecondCommitGroupPos )
00323       store->mStore_SecondCommitGroupPos = startPos;
00324   }
00325 }
00326 
00327 /*virtual*/ void
00328 morkBuilder::OnGroupGlitch(morkEnv* ev, const morkGlitch& inGlitch) 
00329 {
00330   this->LogGlitch(ev, inGlitch, "group");
00331 }
00332 
00333 /*virtual*/ void
00334 morkBuilder::OnGroupCommitEnd(morkEnv* ev, const morkSpan& inSpan)  
00335 {
00336   MORK_USED_2(ev,inSpan);
00337   // mParser_InGroup = morkBool_kFalse;
00338   // ev->StubMethodOnlyError();
00339 }
00340 
00341 /*virtual*/ void
00342 morkBuilder::OnGroupAbortEnd(morkEnv* ev, const morkSpan& inSpan) 
00343 {
00344   MORK_USED_1(inSpan);
00345   // mParser_InGroup = morkBool_kFalse;
00346   ev->StubMethodOnlyError();
00347 }
00348 
00349 /*virtual*/ void
00350 morkBuilder::OnNewPortRow(morkEnv* ev, const morkPlace& inPlace, 
00351   const morkMid& inMid, mork_change inChange)
00352 {
00353   MORK_USED_3(inMid,inPlace,inChange);
00354   // mParser_InPortRow = morkBool_kTrue;
00355   ev->StubMethodOnlyError();
00356 }
00357 
00358 /*virtual*/ void
00359 morkBuilder::OnPortRowGlitch(morkEnv* ev, const morkGlitch& inGlitch)
00360 {
00361   this->LogGlitch(ev, inGlitch, "port row");
00362 }
00363 
00364 /*virtual*/ void
00365 morkBuilder::OnPortRowEnd(morkEnv* ev, const morkSpan& inSpan)
00366 {
00367   MORK_USED_1(inSpan);
00368   // mParser_InPortRow = morkBool_kFalse;
00369   ev->StubMethodOnlyError();
00370 }
00371 
00372 /*virtual*/ void
00373 morkBuilder::OnNewTable(morkEnv* ev, const morkPlace& inPlace,
00374   const morkMid& inMid, mork_bool inCutAllRows)
00375 // mp:Table     ::= OnNewTable mp:TableItem* OnTableEnd
00376 // mp:TableItem ::= mp:Row | mp:MetaTable | OnTableGlitch
00377 // mp:MetaTable ::= OnNewMeta mp:MetaItem* mp:Row OnMetaEnd
00378 // mp:Meta      ::= OnNewMeta mp:MetaItem* OnMetaEnd
00379 // mp:MetaItem  ::= mp:Cell | OnMetaGlitch
00380 {
00381   MORK_USED_1(inPlace);
00382   // mParser_InTable = morkBool_kTrue;
00383   mBuilder_TableForm = mBuilder_PortForm;
00384   mBuilder_TableRowScope = mBuilder_PortRowScope;
00385   mBuilder_TableAtomScope = mBuilder_PortAtomScope;
00386   mBuilder_TableKind = morkStore_kNoneToken;
00387   
00388   mBuilder_TablePriority = morkPriority_kLo;
00389   mBuilder_TableIsUnique = morkBool_kFalse;
00390   mBuilder_TableIsVerbose = morkBool_kFalse;
00391 
00392   morkTable* table = mBuilder_Store->MidToTable(ev, inMid);
00393   morkTable::SlotStrongTable(table, ev, &mBuilder_Table);
00394   if ( table )
00395   {
00396     if ( table->mTable_RowSpace )
00397       mBuilder_TableRowScope = table->mTable_RowSpace->SpaceScope();
00398       
00399     if ( inCutAllRows )
00400       table->CutAllRows(ev);
00401   }
00402 }
00403 
00404 /*virtual*/ void
00405 morkBuilder::OnTableGlitch(morkEnv* ev, const morkGlitch& inGlitch)
00406 {
00407   this->LogGlitch(ev, inGlitch, "table");
00408 }
00409 
00410 /*virtual*/ void
00411 morkBuilder::OnTableEnd(morkEnv* ev, const morkSpan& inSpan)
00412 // mp:Table     ::= OnNewTable mp:TableItem* OnTableEnd
00413 {
00414   MORK_USED_1(inSpan);
00415   // mParser_InTable = morkBool_kFalse;
00416   if ( mBuilder_Table )
00417   {
00418     mBuilder_Table->mTable_Priority = mBuilder_TablePriority;
00419     
00420     if ( mBuilder_TableIsUnique )
00421       mBuilder_Table->SetTableUnique();
00422 
00423     if ( mBuilder_TableIsVerbose )
00424       mBuilder_Table->SetTableVerbose();
00425   
00426     morkTable::SlotStrongTable((morkTable*) 0, ev, &mBuilder_Table);
00427   }
00428   else
00429     this->NilBuilderTableError(ev);
00430     
00431   mBuilder_Row = 0;
00432   mBuilder_Cell = 0;
00433   
00434   
00435   mBuilder_TablePriority = morkPriority_kLo;
00436   mBuilder_TableIsUnique = morkBool_kFalse;
00437   mBuilder_TableIsVerbose = morkBool_kFalse;
00438 
00439   if ( mBuilder_TableKind == morkStore_kNoneToken )
00440     ev->NewError("missing table kind");
00441 
00442   mBuilder_CellAtomScope = mBuilder_RowAtomScope =
00443     mBuilder_TableAtomScope = mBuilder_PortAtomScope;
00444 
00445   mBuilder_DoCutCell = morkBool_kFalse;
00446   mBuilder_DoCutRow = morkBool_kFalse;
00447 }
00448 
00449 /*virtual*/ void
00450 morkBuilder::OnNewMeta(morkEnv* ev, const morkPlace& inPlace)
00451 // mp:Meta      ::= OnNewMeta mp:MetaItem* OnMetaEnd
00452 // mp:MetaItem  ::= mp:Cell | OnMetaGlitch
00453 // mp:Cell      ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
00454 // mp:CellItem  ::= mp:Slot | OnCellForm | OnCellGlitch
00455 // mp:Slot      ::= OnValue | OnValueMid | OnRowMid | OnTableMid
00456 {
00457   MORK_USED_2(ev,inPlace);
00458   // mParser_InMeta = morkBool_kTrue;
00459   
00460 }
00461 
00462 /*virtual*/ void
00463 morkBuilder::OnMetaGlitch(morkEnv* ev, const morkGlitch& inGlitch)
00464 {
00465   this->LogGlitch(ev, inGlitch, "meta");
00466 }
00467 
00468 /*virtual*/ void
00469 morkBuilder::OnMetaEnd(morkEnv* ev, const morkSpan& inSpan)
00470 // mp:Meta      ::= OnNewMeta mp:MetaItem* OnMetaEnd
00471 {
00472   MORK_USED_2(ev,inSpan);
00473   // mParser_InMeta = morkBool_kFalse;
00474 }
00475 
00476 /*virtual*/ void
00477 morkBuilder::OnMinusRow(morkEnv* ev)
00478 {
00479   MORK_USED_1(ev);
00480   mBuilder_DoCutRow = morkBool_kTrue;
00481 }
00482 
00483 /*virtual*/ void
00484 morkBuilder::OnNewRow(morkEnv* ev, const morkPlace& inPlace, 
00485   const morkMid& inMid, mork_bool inCutAllCols)
00486 // mp:Table     ::= OnNewTable mp:TableItem* OnTableEnd
00487 // mp:TableItem ::= mp:Row | mp:MetaTable | OnTableGlitch
00488 // mp:MetaTable ::= OnNewMeta mp:MetaItem* mp:Row OnMetaEnd
00489 // mp:Row       ::= OnMinusRow? OnNewRow mp:RowItem* OnRowEnd
00490 // mp:RowItem   ::= mp:Cell | mp:Meta | OnRowGlitch
00491 // mp:Cell      ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
00492 // mp:CellItem  ::= mp:Slot | OnCellForm | OnCellGlitch
00493 // mp:Slot      ::= OnValue | OnValueMid | OnRowMid | OnTableMid
00494 {
00495   MORK_USED_1(inPlace);
00496   // mParser_InRow = morkBool_kTrue;
00497   
00498   mBuilder_CellForm = mBuilder_RowForm = mBuilder_TableForm;
00499   mBuilder_CellAtomScope = mBuilder_RowAtomScope = mBuilder_TableAtomScope;
00500   mBuilder_RowRowScope = mBuilder_TableRowScope;
00501   morkStore* store = mBuilder_Store;
00502   
00503   if ( !inMid.mMid_Buf && !inMid.mMid_Oid.mOid_Scope )
00504   {
00505     morkMid mid(inMid);
00506     mid.mMid_Oid.mOid_Scope = mBuilder_RowRowScope;
00507     mBuilder_Row = store->MidToRow(ev, mid);
00508   }
00509   else
00510   {
00511     mBuilder_Row = store->MidToRow(ev, inMid);
00512   }
00513   morkRow* row = mBuilder_Row;
00514   if ( row && inCutAllCols )
00515   {
00516     row->CutAllColumns(ev);
00517   }
00518 
00519   morkTable* table = mBuilder_Table;
00520   if ( table )
00521   {
00522     if ( row )
00523     {
00524       if ( mParser_InMeta )
00525       {
00526         morkRow* metaRow = table->mTable_MetaRow;
00527         if ( !metaRow )
00528         {
00529           table->mTable_MetaRow = row;
00530           table->mTable_MetaRowOid = row->mRow_Oid;
00531           row->AddRowGcUse(ev);
00532         }
00533         else if ( metaRow != row ) // not identical?
00534           ev->NewError("duplicate table meta row");
00535       }
00536       else
00537       {
00538         if ( mBuilder_DoCutRow )
00539           table->CutRow(ev, row);
00540         else
00541           table->AddRow(ev, row);
00542       }
00543     }
00544   }
00545   // else // it is now okay to have rows outside a table:
00546   //  this->NilBuilderTableError(ev);
00547     
00548   mBuilder_DoCutRow = morkBool_kFalse;
00549 }
00550 
00551 /*virtual*/ void
00552 morkBuilder::OnRowPos(morkEnv* ev, mork_pos inRowPos) 
00553 {
00554   if ( mBuilder_Row && mBuilder_Table && !mParser_InMeta )
00555   {
00556     mork_pos hintFromPos = 0; // best hint when we don't know position
00557     mBuilder_Table->MoveRow(ev, mBuilder_Row, hintFromPos, inRowPos);
00558   }
00559 }
00560 
00561 /*virtual*/ void
00562 morkBuilder::OnRowGlitch(morkEnv* ev, const morkGlitch& inGlitch) 
00563 {
00564   this->LogGlitch(ev, inGlitch, "row");
00565 }
00566 
00567 void
00568 morkBuilder::FlushBuilderCells(morkEnv* ev)
00569 {
00570   if ( mBuilder_Row )
00571   {
00572     morkPool* pool = mBuilder_Store->StorePool();
00573     morkCell* cells = mBuilder_CellsVec;
00574     mork_fill fill = mBuilder_CellsVecFill;
00575     mBuilder_Row->TakeCells(ev, cells, fill, mBuilder_Store);
00576 
00577     morkCell* end = cells + fill;
00578     --cells; // prepare for preincrement
00579     while ( ++cells < end )
00580     {
00581       if ( cells->mCell_Atom )
00582         cells->SetAtom(ev, (morkAtom*) 0, pool);
00583     }
00584     mBuilder_CellsVecFill = 0;
00585   }
00586   else
00587     this->NilBuilderRowError(ev);
00588 }
00589 
00590 /*virtual*/ void
00591 morkBuilder::OnRowEnd(morkEnv* ev, const morkSpan& inSpan) 
00592 // mp:Row       ::= OnMinusRow? OnNewRow mp:RowItem* OnRowEnd
00593 {
00594   MORK_USED_1(inSpan);
00595   // mParser_InRow = morkBool_kFalse;
00596   if ( mBuilder_Row )
00597   {
00598     this->FlushBuilderCells(ev);
00599   }
00600   else
00601     this->NilBuilderRowError(ev);
00602     
00603   mBuilder_Row = 0;
00604   mBuilder_Cell = 0;
00605 
00606   mBuilder_DoCutCell = morkBool_kFalse;
00607   mBuilder_DoCutRow = morkBool_kFalse;
00608 }
00609 
00610 /*virtual*/ void
00611 morkBuilder::OnNewDict(morkEnv* ev, const morkPlace& inPlace)
00612 // mp:Dict      ::= OnNewDict mp:DictItem* OnDictEnd
00613 // mp:DictItem  ::= OnAlias | OnAliasGlitch | mp:Meta | OnDictGlitch
00614 {
00615   MORK_USED_2(ev,inPlace);
00616   // mParser_InDict = morkBool_kTrue;
00617   
00618   mBuilder_CellForm = mBuilder_DictForm = mBuilder_PortForm;
00619   mBuilder_CellAtomScope = mBuilder_DictAtomScope = mBuilder_PortAtomScope;
00620 }
00621 
00622 /*virtual*/ void
00623 morkBuilder::OnDictGlitch(morkEnv* ev, const morkGlitch& inGlitch) 
00624 {
00625   this->LogGlitch(ev, inGlitch, "dict");
00626 }
00627 
00628 /*virtual*/ void
00629 morkBuilder::OnDictEnd(morkEnv* ev, const morkSpan& inSpan)  
00630 // mp:Dict      ::= OnNewDict mp:DictItem* OnDictEnd
00631 {
00632   MORK_USED_2(ev,inSpan);
00633   // mParser_InDict = morkBool_kFalse;
00634 
00635   mBuilder_DictForm = 0;
00636   mBuilder_DictAtomScope = 0;
00637 }
00638 
00639 /*virtual*/ void
00640 morkBuilder::OnAlias(morkEnv* ev, const morkSpan& inSpan,
00641   const morkMid& inMid)
00642 {
00643   MORK_USED_1(inSpan);
00644   if ( mParser_InDict )
00645   {
00646     morkMid mid = inMid; // local copy for modification
00647     mid.mMid_Oid.mOid_Scope = mBuilder_DictAtomScope;
00648     mBuilder_Store->AddAlias(ev, mid, mBuilder_DictForm);
00649   }
00650   else
00651     ev->NewError("alias not in dict");
00652 }
00653 
00654 /*virtual*/ void
00655 morkBuilder::OnAliasGlitch(morkEnv* ev, const morkGlitch& inGlitch)
00656 {
00657   this->LogGlitch(ev, inGlitch, "alias");
00658 }
00659 
00660 
00661 morkCell* 
00662 morkBuilder::AddBuilderCell(morkEnv* ev,
00663   const morkMid& inMid, mork_change inChange)
00664 {
00665   morkCell* outCell = 0;
00666   mork_column column = inMid.mMid_Oid.mOid_Id;
00667   
00668   if ( ev->Good() )
00669   {
00670     if ( mBuilder_CellsVecFill >= morkBuilder_kCellsVecSize )
00671       this->FlushBuilderCells(ev);
00672     if ( ev->Good() )
00673     {
00674       if ( mBuilder_CellsVecFill < morkBuilder_kCellsVecSize )
00675       {
00676         mork_fill indx = mBuilder_CellsVecFill++;
00677         outCell = mBuilder_CellsVec + indx;
00678         outCell->SetColumnAndChange(column, inChange);
00679         outCell->mCell_Atom = 0;
00680       }
00681       else
00682         ev->NewError("out of builder cells");
00683     }
00684   }
00685   return outCell;
00686 }
00687 
00688 /*virtual*/ void
00689 morkBuilder::OnMinusCell(morkEnv* ev)
00690 {
00691   MORK_USED_1(ev);
00692   mBuilder_DoCutCell = morkBool_kTrue;
00693 }
00694 
00695 /*virtual*/ void
00696 morkBuilder::OnNewCell(morkEnv* ev, const morkPlace& inPlace,
00697     const morkMid* inMid, const morkBuf* inBuf)
00698 // Exactly one of inMid and inBuf is nil, and the other is non-nil.
00699 // When hex ID syntax is used for a column, then inMid is not nil, and
00700 // when a naked string names a column, then inBuf is not nil.
00701   
00702   // mp:Cell      ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
00703   // mp:CellItem  ::= mp:Slot | OnCellForm | OnCellGlitch
00704   // mp:Slot      ::= OnValue | OnValueMid | OnRowMid | OnTableMid
00705 {
00706   MORK_USED_1(inPlace);
00707   // mParser_InCell = morkBool_kTrue;
00708   
00709   mork_change cellChange = ( mBuilder_DoCutCell )?
00710     morkChange_kCut : morkChange_kAdd;
00711     
00712   mBuilder_DoCutCell = morkBool_kFalse;
00713   
00714   mBuilder_CellAtomScope = mBuilder_RowAtomScope;
00715   
00716   mBuilder_Cell = 0; // nil until determined for a row
00717   morkStore* store = mBuilder_Store;
00718   mork_scope scope = morkStore_kColumnSpaceScope;
00719   morkMid tempMid; // space for local and modifiable cell mid
00720   morkMid* cellMid = &tempMid; // default to local if inMid==0
00721   
00722   if ( inMid ) // mid parameter is actually provided?
00723   {
00724     *cellMid = *inMid; // bitwise copy for modifiable local mid
00725 
00726     if ( !cellMid->mMid_Oid.mOid_Scope ) 
00727     {
00728       if ( cellMid->mMid_Buf )
00729       {
00730         scope = store->BufToToken(ev, cellMid->mMid_Buf);
00731         cellMid->mMid_Buf = 0; // don't do scope lookup again
00732         ev->NewWarning("column mids need column scope");
00733       }
00734       cellMid->mMid_Oid.mOid_Scope = scope;
00735     }
00736   }
00737   else if ( inBuf ) // buf points to naked column string name?
00738   {
00739     cellMid->ClearMid();
00740     cellMid->mMid_Oid.mOid_Id = store->BufToToken(ev, inBuf);
00741     cellMid->mMid_Oid.mOid_Scope = scope; // kColumnSpaceScope
00742   }
00743   else
00744     ev->NilPointerError(); // either inMid or inBuf must be non-nil
00745 
00746   mork_column column = cellMid->mMid_Oid.mOid_Id;
00747   
00748   if ( mBuilder_Row && ev->Good() ) // this cell must be inside a row
00749   {
00750       // mBuilder_Cell = this->AddBuilderCell(ev, *cellMid, cellChange);
00751 
00752       if ( mBuilder_CellsVecFill >= morkBuilder_kCellsVecSize )
00753         this->FlushBuilderCells(ev);
00754       if ( ev->Good() )
00755       {
00756         if ( mBuilder_CellsVecFill < morkBuilder_kCellsVecSize )
00757         {
00758           mork_fill ix = mBuilder_CellsVecFill++;
00759           morkCell* cell =  mBuilder_CellsVec + ix;
00760           cell->SetColumnAndChange(column, cellChange);
00761           
00762           cell->mCell_Atom = 0;
00763           mBuilder_Cell = cell;
00764         }
00765         else
00766           ev->NewError("out of builder cells");
00767       }
00768   }
00769 
00770   else if ( mParser_InMeta &&  ev->Good() ) // cell is in metainfo structure?
00771   {
00772     if ( scope == morkStore_kColumnSpaceScope )
00773     {
00774       if ( mParser_InTable ) // metainfo for table?
00775       {
00776         if ( column == morkStore_kKindColumn )
00777           mBuilder_MetaTokenSlot = &mBuilder_TableKind;
00778         else if ( column == morkStore_kStatusColumn )
00779           mBuilder_MetaTokenSlot = &mBuilder_TableStatus;
00780         else if ( column == morkStore_kRowScopeColumn )
00781           mBuilder_MetaTokenSlot = &mBuilder_TableRowScope;
00782         else if ( column == morkStore_kAtomScopeColumn )
00783           mBuilder_MetaTokenSlot = &mBuilder_TableAtomScope;
00784         else if ( column == morkStore_kFormColumn )
00785           mBuilder_MetaTokenSlot = &mBuilder_TableForm;
00786       }
00787       else if ( mParser_InDict ) // metainfo for dict?
00788       {
00789         if ( column == morkStore_kAtomScopeColumn )
00790           mBuilder_MetaTokenSlot = &mBuilder_DictAtomScope;
00791         else if ( column == morkStore_kFormColumn )
00792           mBuilder_MetaTokenSlot = &mBuilder_DictForm;
00793       }
00794       else if ( mParser_InRow ) // metainfo for row?
00795       {
00796         if ( column == morkStore_kAtomScopeColumn )
00797           mBuilder_MetaTokenSlot = &mBuilder_RowAtomScope;
00798         else if ( column == morkStore_kRowScopeColumn )
00799           mBuilder_MetaTokenSlot = &mBuilder_RowRowScope;
00800         else if ( column == morkStore_kFormColumn )
00801           mBuilder_MetaTokenSlot = &mBuilder_RowForm;
00802       }
00803     }
00804     else
00805       ev->NewWarning("expected column scope");
00806   }
00807 }
00808 
00809 /*virtual*/ void
00810 morkBuilder::OnCellGlitch(morkEnv* ev, const morkGlitch& inGlitch)
00811 {
00812   this->LogGlitch(ev, inGlitch, "cell");
00813 }
00814 
00815 /*virtual*/ void
00816 morkBuilder::OnCellForm(morkEnv* ev, mork_cscode inCharsetFormat)
00817 {
00818   morkCell* cell = mBuilder_Cell;
00819   if ( cell )
00820   {
00821     mBuilder_CellForm = inCharsetFormat;
00822   }
00823   else
00824     this->NilBuilderCellError(ev);
00825 }
00826 
00827 /*virtual*/ void
00828 morkBuilder::OnCellEnd(morkEnv* ev, const morkSpan& inSpan)
00829 // mp:Cell      ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
00830 {
00831   MORK_USED_2(ev,inSpan);
00832   // mParser_InCell = morkBool_kFalse;
00833   
00834   mBuilder_MetaTokenSlot = 0;
00835   mBuilder_CellAtomScope = mBuilder_RowAtomScope;
00836 }
00837 
00838 /*virtual*/ void
00839 morkBuilder::OnValue(morkEnv* ev, const morkSpan& inSpan,
00840   const morkBuf& inBuf)
00841 // mp:CellItem  ::= mp:Slot | OnCellForm | OnCellGlitch
00842 // mp:Slot      ::= OnValue | OnValueMid | OnRowMid | OnTableMid
00843 {
00844   MORK_USED_1(inSpan);
00845   morkStore* store = mBuilder_Store;
00846   morkCell* cell = mBuilder_Cell;
00847   if ( cell )
00848   {
00849     mdbYarn yarn;
00850     yarn.mYarn_Buf = inBuf.mBuf_Body;
00851     yarn.mYarn_Fill = yarn.mYarn_Size = inBuf.mBuf_Fill;
00852     yarn.mYarn_More = 0;
00853     yarn.mYarn_Form = mBuilder_CellForm;
00854     yarn.mYarn_Grow = 0;
00855     morkAtom* atom = store->YarnToAtom(ev, &yarn, PR_TRUE /* create */);
00856     cell->SetAtom(ev, atom, store->StorePool());
00857   }
00858   else if ( mParser_InMeta )
00859   {
00860     mork_token* metaSlot = mBuilder_MetaTokenSlot;
00861     if ( metaSlot )
00862     {
00863       if ( metaSlot == &mBuilder_TableStatus ) // table status?
00864       {
00865         if ( mParser_InTable && mBuilder_Table )
00866         {
00867           const char* body = (const char*) inBuf.mBuf_Body;
00868           mork_fill bufFill = inBuf.mBuf_Fill;
00869           if ( body && bufFill )
00870           {
00871             const char* bodyEnd = body + bufFill;
00872             while ( body < bodyEnd )
00873             {
00874               int c = *body++;
00875               switch ( c )
00876               {
00877                 case '0':
00878                 case '1':
00879                 case '2':
00880                 case '3':
00881                 case '4':
00882                 case '5':
00883                 case '6':
00884                 case '7':
00885                 case '8':
00886                 case '9':
00887                   mBuilder_TablePriority = (mork_priority) ( c - '0' );
00888                   break;
00889                 
00890                 case 'u':
00891                 case 'U':
00892                   mBuilder_TableIsUnique = morkBool_kTrue;
00893                   break;
00894                   
00895                 case 'v':
00896                 case 'V':
00897                   mBuilder_TableIsVerbose = morkBool_kTrue;
00898                   break;
00899               }
00900             }
00901           }
00902         }
00903       }
00904       else
00905       {
00906         mork_token token = store->BufToToken(ev, &inBuf);
00907         if ( token )
00908         {
00909           *metaSlot = token;
00910           if ( metaSlot == &mBuilder_TableKind ) // table kind?
00911           {
00912             if ( mParser_InTable && mBuilder_Table )
00913               mBuilder_Table->mTable_Kind = token;
00914           }
00915         }
00916       }
00917     }
00918   }
00919   else
00920     this->NilBuilderCellError(ev);
00921 }
00922 
00923 /*virtual*/ void
00924 morkBuilder::OnValueMid(morkEnv* ev, const morkSpan& inSpan,
00925   const morkMid& inMid)
00926 // mp:CellItem  ::= mp:Slot | OnCellForm | OnCellGlitch
00927 // mp:Slot      ::= OnValue | OnValueMid | OnRowMid | OnTableMid
00928 {
00929   MORK_USED_1(inSpan);
00930   morkStore* store = mBuilder_Store;
00931   morkCell* cell = mBuilder_Cell;
00932 
00933   morkMid valMid; // local mid for modifications
00934   mdbOid* valOid = &valMid.mMid_Oid; // ref to oid inside mid
00935   *valOid = inMid.mMid_Oid; // bitwise copy inMid's oid
00936   
00937   if ( inMid.mMid_Buf )
00938   {
00939     if ( !valOid->mOid_Scope )
00940       store->MidToOid(ev, inMid, valOid);
00941   }
00942   else if ( !valOid->mOid_Scope )
00943     valOid->mOid_Scope = mBuilder_CellAtomScope;
00944   
00945   if ( cell )
00946   {
00947     morkBookAtom* atom = store->MidToAtom(ev, valMid);
00948     if ( atom )
00949       cell->SetAtom(ev, atom, store->StorePool());
00950     else
00951       ev->NewError("undefined cell value alias");
00952   }
00953   else if ( mParser_InMeta )
00954   {
00955     mork_token* metaSlot = mBuilder_MetaTokenSlot;
00956     if ( metaSlot )
00957     {
00958       mork_scope valScope = valOid->mOid_Scope;
00959       if ( !valScope || valScope == morkStore_kColumnSpaceScope )
00960       {
00961         if ( ev->Good() && valMid.HasSomeId() )
00962         {
00963           *metaSlot = valOid->mOid_Id;
00964           if ( metaSlot == &mBuilder_TableKind ) // table kind?
00965           {
00966             if ( mParser_InTable && mBuilder_Table )
00967             {
00968               mBuilder_Table->mTable_Kind = valOid->mOid_Id;
00969             }
00970             else
00971               ev->NewWarning("mBuilder_TableKind not in table");
00972           }
00973           else if ( metaSlot == &mBuilder_TableStatus ) // table status?
00974           {
00975             if ( mParser_InTable && mBuilder_Table )
00976             {
00977               // $$ what here??
00978             }
00979             else
00980               ev->NewWarning("mBuilder_TableStatus not in table");
00981           }
00982         }
00983       }
00984       else
00985         this->NonColumnSpaceScopeError(ev);
00986     }
00987   }
00988   else
00989     this->NilBuilderCellError(ev);
00990 }
00991 
00992 /*virtual*/ void
00993 morkBuilder::OnRowMid(morkEnv* ev, const morkSpan& inSpan,
00994   const morkMid& inMid)
00995 // mp:CellItem  ::= mp:Slot | OnCellForm | OnCellGlitch
00996 // mp:Slot      ::= OnValue | OnValueMid | OnRowMid | OnTableMid
00997 {
00998   MORK_USED_1(inSpan);
00999   morkStore* store = mBuilder_Store;
01000   morkCell* cell = mBuilder_Cell;
01001   if ( cell )
01002   {
01003     mdbOid rowOid = inMid.mMid_Oid;
01004     if ( inMid.mMid_Buf )
01005     {
01006       if ( !rowOid.mOid_Scope )
01007         store->MidToOid(ev, inMid, &rowOid);
01008     }
01009     else if ( !rowOid.mOid_Scope )
01010       rowOid.mOid_Scope = mBuilder_RowRowScope;
01011     
01012     if ( ev->Good() )
01013      {
01014        morkPool* pool = store->StorePool();
01015        morkAtom* atom = pool->NewRowOidAtom(ev, rowOid, &store->mStore_Zone);
01016        if ( atom )
01017        {
01018          cell->SetAtom(ev, atom, pool);
01019          morkRow* row = store->OidToRow(ev, &rowOid);
01020          if ( row ) // found or created such a row?
01021            row->AddRowGcUse(ev);
01022        }
01023      }
01024   }
01025   else
01026     this->NilBuilderCellError(ev);
01027 }
01028 
01029 /*virtual*/ void
01030 morkBuilder::OnTableMid(morkEnv* ev, const morkSpan& inSpan,
01031   const morkMid& inMid)
01032 // mp:CellItem  ::= mp:Slot | OnCellForm | OnCellGlitch
01033 // mp:Slot      ::= OnValue | OnValueMid | OnRowMid | OnTableMid
01034 {
01035   MORK_USED_1(inSpan);
01036   morkStore* store = mBuilder_Store;
01037   morkCell* cell = mBuilder_Cell;
01038   if ( cell )
01039   {
01040     mdbOid tableOid = inMid.mMid_Oid;
01041     if ( inMid.mMid_Buf )
01042     {
01043       if ( !tableOid.mOid_Scope )
01044         store->MidToOid(ev, inMid, &tableOid);
01045     }
01046     else if ( !tableOid.mOid_Scope )
01047       tableOid.mOid_Scope = mBuilder_RowRowScope;
01048     
01049     if ( ev->Good() )
01050      {
01051        morkPool* pool = store->StorePool();
01052        morkAtom* atom = pool->NewTableOidAtom(ev, tableOid, &store->mStore_Zone);
01053        if ( atom )
01054        {
01055          cell->SetAtom(ev, atom, pool);
01056          morkTable* table = store->OidToTable(ev, &tableOid,
01057            /*optionalMetaRowOid*/ (mdbOid*) 0);
01058          if ( table ) // found or created such a table?
01059            table->AddTableGcUse(ev);
01060        }
01061      }
01062   }
01063   else
01064     this->NilBuilderCellError(ev);
01065 }
01066 
01067 
01068 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789