Reenable test.
[wine-gecko.git] / db / mork / src / morkBuilder.cpp
blob47c23ecfc1f1802c1f6a2a2c71beb55275335c38
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1999
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #ifndef _MDB_
39 #include "mdb.h"
40 #endif
42 #ifndef _MORK_
43 #include "mork.h"
44 #endif
46 #ifndef _MORKNODE_
47 #include "morkNode.h"
48 #endif
50 #ifndef _MORKMAP_
51 #include "morkMap.h"
52 #endif
54 #ifndef _MORKENV_
55 #include "morkEnv.h"
56 #endif
58 #ifndef _MORKPARSER_
59 #include "morkParser.h"
60 #endif
62 #ifndef _MORKBUILDER_
63 #include "morkBuilder.h"
64 #endif
66 #ifndef _MORKCELL_
67 #include "morkCell.h"
68 #endif
70 #ifndef _MORKSTORE_
71 #include "morkStore.h"
72 #endif
74 #ifndef _MORKTABLE_
75 #include "morkTable.h"
76 #endif
78 #ifndef _MORKROW_
79 #include "morkRow.h"
80 #endif
82 #ifndef _MORKCELL_
83 #include "morkCell.h"
84 #endif
86 #ifndef _MORKATOM_
87 #include "morkAtom.h"
88 #endif
90 #ifndef _MORKATOMSPACE_
91 #include "morkAtomSpace.h"
92 #endif
94 #ifndef _MORKROWSPACE_
95 #include "morkRowSpace.h"
96 #endif
98 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
100 // ````` ````` ````` ````` `````
101 // { ===== begin morkNode interface =====
103 /*public virtual*/ void
104 morkBuilder::CloseMorkNode(morkEnv* ev) // CloseBuilder() only if open
106 if ( this->IsOpenNode() )
108 this->MarkClosing();
109 this->CloseBuilder(ev);
110 this->MarkShut();
114 /*public virtual*/
115 morkBuilder::~morkBuilder() // assert CloseBuilder() executed earlier
117 MORK_ASSERT(mBuilder_Store==0);
118 MORK_ASSERT(mBuilder_Row==0);
119 MORK_ASSERT(mBuilder_Table==0);
120 MORK_ASSERT(mBuilder_Cell==0);
121 MORK_ASSERT(mBuilder_RowSpace==0);
122 MORK_ASSERT(mBuilder_AtomSpace==0);
125 /*public non-poly*/
126 morkBuilder::morkBuilder(morkEnv* ev,
127 const morkUsage& inUsage, nsIMdbHeap* ioHeap,
128 morkStream* ioStream, mdb_count inBytesPerParseSegment,
129 nsIMdbHeap* ioSlotHeap, morkStore* ioStore)
131 : morkParser(ev, inUsage, ioHeap, ioStream,
132 inBytesPerParseSegment, ioSlotHeap)
134 , mBuilder_Store( 0 )
136 , mBuilder_Table( 0 )
137 , mBuilder_Row( 0 )
138 , mBuilder_Cell( 0 )
140 , mBuilder_RowSpace( 0 )
141 , mBuilder_AtomSpace( 0 )
143 , mBuilder_OidAtomSpace( 0 )
144 , mBuilder_ScopeAtomSpace( 0 )
146 , mBuilder_PortForm( 0 )
147 , mBuilder_PortRowScope( (mork_scope) 'r' )
148 , mBuilder_PortAtomScope( (mork_scope) 'v' )
150 , mBuilder_TableForm( 0 )
151 , mBuilder_TableRowScope( (mork_scope) 'r' )
152 , mBuilder_TableAtomScope( (mork_scope) 'v' )
153 , mBuilder_TableKind( 0 )
155 , mBuilder_TablePriority( morkPriority_kLo )
156 , mBuilder_TableIsUnique( morkBool_kFalse )
157 , mBuilder_TableIsVerbose( morkBool_kFalse )
158 , mBuilder_TablePadByte( 0 )
160 , mBuilder_RowForm( 0 )
161 , mBuilder_RowRowScope( (mork_scope) 'r' )
162 , mBuilder_RowAtomScope( (mork_scope) 'v' )
164 , mBuilder_CellForm( 0 )
165 , mBuilder_CellAtomScope( (mork_scope) 'v' )
167 , mBuilder_DictForm( 0 )
168 , mBuilder_DictAtomScope( (mork_scope) 'v' )
170 , mBuilder_MetaTokenSlot( 0 )
172 , mBuilder_DoCutRow( morkBool_kFalse )
173 , mBuilder_DoCutCell( morkBool_kFalse )
174 , mBuilder_CellsVecFill( 0 )
176 if ( ev->Good() )
178 if ( ioStore )
180 morkStore::SlotWeakStore(ioStore, ev, &mBuilder_Store);
181 if ( ev->Good() )
182 mNode_Derived = morkDerived_kBuilder;
184 else
185 ev->NilPointerError();
190 /*public non-poly*/ void
191 morkBuilder::CloseBuilder(morkEnv* ev) // called by CloseMorkNode();
193 if ( this )
195 if ( this->IsNode() )
197 mBuilder_Row = 0;
198 mBuilder_Cell = 0;
199 mBuilder_MetaTokenSlot = 0;
201 morkTable::SlotStrongTable((morkTable*) 0, ev, &mBuilder_Table);
202 morkStore::SlotWeakStore((morkStore*) 0, ev, &mBuilder_Store);
204 morkRowSpace::SlotStrongRowSpace((morkRowSpace*) 0, ev,
205 &mBuilder_RowSpace);
207 morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*) 0, ev,
208 &mBuilder_AtomSpace);
210 morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*) 0, ev,
211 &mBuilder_OidAtomSpace);
213 morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*) 0, ev,
214 &mBuilder_ScopeAtomSpace);
215 this->CloseParser(ev);
216 this->MarkShut();
218 else
219 this->NonNodeError(ev);
221 else
222 ev->NilPointerError();
225 // } ===== end morkNode methods =====
226 // ````` ````` ````` ````` `````
228 /*static*/ void
229 morkBuilder::NonBuilderTypeError(morkEnv* ev)
231 ev->NewError("non morkBuilder");
234 /*static*/ void
235 morkBuilder::NilBuilderCellError(morkEnv* ev)
237 ev->NewError("nil mBuilder_Cell");
240 /*static*/ void
241 morkBuilder::NilBuilderRowError(morkEnv* ev)
243 ev->NewError("nil mBuilder_Row");
246 /*static*/ void
247 morkBuilder::NilBuilderTableError(morkEnv* ev)
249 ev->NewError("nil mBuilder_Table");
252 /*static*/ void
253 morkBuilder::NonColumnSpaceScopeError(morkEnv* ev)
255 ev->NewError("column space != 'c'");
258 void
259 morkBuilder::LogGlitch(morkEnv* ev, const morkGlitch& inGlitch,
260 const char* inKind)
262 MORK_USED_2(inGlitch,inKind);
263 ev->NewWarning("parsing glitch");
266 /*virtual*/ void
267 morkBuilder::MidToYarn(morkEnv* ev,
268 const morkMid& inMid, // typically an alias to concat with strings
269 mdbYarn* outYarn)
270 // The parser might ask that some aliases be turned into yarns, so they
271 // can be concatenated into longer blobs under some circumstances. This
272 // is an alternative to using a long and complex callback for many parts
273 // for a single cell value.
275 mBuilder_Store->MidToYarn(ev, inMid, outYarn);
278 /*virtual*/ void
279 morkBuilder::OnNewPort(morkEnv* ev, const morkPlace& inPlace)
280 // mp:Start ::= OnNewPort mp:PortItem* OnPortEnd
281 // mp:PortItem ::= mp:Content | mp:Group | OnPortGlitch
282 // mp:Content ::= mp:PortRow | mp:Dict | mp:Table | mp:Row
284 MORK_USED_2(ev,inPlace);
285 // mParser_InPort = morkBool_kTrue;
286 mBuilder_PortForm = 0;
287 mBuilder_PortRowScope = (mork_scope) 'r';
288 mBuilder_PortAtomScope = (mork_scope) 'v';
291 /*virtual*/ void
292 morkBuilder::OnPortGlitch(morkEnv* ev, const morkGlitch& inGlitch)
294 this->LogGlitch(ev, inGlitch, "port");
297 /*virtual*/ void
298 morkBuilder::OnPortEnd(morkEnv* ev, const morkSpan& inSpan)
299 // mp:Start ::= OnNewPort mp:PortItem* OnPortEnd
301 MORK_USED_2(ev,inSpan);
302 // ev->StubMethodOnlyError();
303 // nothing to do?
304 // mParser_InPort = morkBool_kFalse;
307 /*virtual*/ void
308 morkBuilder::OnNewGroup(morkEnv* ev, const morkPlace& inPlace, mork_gid inGid)
310 MORK_USED_1(inPlace);
311 // mParser_InGroup = morkBool_kTrue;
312 mork_pos startPos = inPlace.mPlace_Pos;
314 morkStore* store = mBuilder_Store;
315 if ( store )
317 if ( inGid >= store->mStore_CommitGroupIdentity )
318 store->mStore_CommitGroupIdentity = inGid + 1;
320 if ( !store->mStore_FirstCommitGroupPos )
321 store->mStore_FirstCommitGroupPos = startPos;
322 else if ( !store->mStore_SecondCommitGroupPos )
323 store->mStore_SecondCommitGroupPos = startPos;
327 /*virtual*/ void
328 morkBuilder::OnGroupGlitch(morkEnv* ev, const morkGlitch& inGlitch)
330 this->LogGlitch(ev, inGlitch, "group");
333 /*virtual*/ void
334 morkBuilder::OnGroupCommitEnd(morkEnv* ev, const morkSpan& inSpan)
336 MORK_USED_2(ev,inSpan);
337 // mParser_InGroup = morkBool_kFalse;
338 // ev->StubMethodOnlyError();
341 /*virtual*/ void
342 morkBuilder::OnGroupAbortEnd(morkEnv* ev, const morkSpan& inSpan)
344 MORK_USED_1(inSpan);
345 // mParser_InGroup = morkBool_kFalse;
346 ev->StubMethodOnlyError();
349 /*virtual*/ void
350 morkBuilder::OnNewPortRow(morkEnv* ev, const morkPlace& inPlace,
351 const morkMid& inMid, mork_change inChange)
353 MORK_USED_3(inMid,inPlace,inChange);
354 // mParser_InPortRow = morkBool_kTrue;
355 ev->StubMethodOnlyError();
358 /*virtual*/ void
359 morkBuilder::OnPortRowGlitch(morkEnv* ev, const morkGlitch& inGlitch)
361 this->LogGlitch(ev, inGlitch, "port row");
364 /*virtual*/ void
365 morkBuilder::OnPortRowEnd(morkEnv* ev, const morkSpan& inSpan)
367 MORK_USED_1(inSpan);
368 // mParser_InPortRow = morkBool_kFalse;
369 ev->StubMethodOnlyError();
372 /*virtual*/ void
373 morkBuilder::OnNewTable(morkEnv* ev, const morkPlace& inPlace,
374 const morkMid& inMid, mork_bool inCutAllRows)
375 // mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
376 // mp:TableItem ::= mp:Row | mp:MetaTable | OnTableGlitch
377 // mp:MetaTable ::= OnNewMeta mp:MetaItem* mp:Row OnMetaEnd
378 // mp:Meta ::= OnNewMeta mp:MetaItem* OnMetaEnd
379 // mp:MetaItem ::= mp:Cell | OnMetaGlitch
381 MORK_USED_1(inPlace);
382 // mParser_InTable = morkBool_kTrue;
383 mBuilder_TableForm = mBuilder_PortForm;
384 mBuilder_TableRowScope = mBuilder_PortRowScope;
385 mBuilder_TableAtomScope = mBuilder_PortAtomScope;
386 mBuilder_TableKind = morkStore_kNoneToken;
388 mBuilder_TablePriority = morkPriority_kLo;
389 mBuilder_TableIsUnique = morkBool_kFalse;
390 mBuilder_TableIsVerbose = morkBool_kFalse;
392 morkTable* table = mBuilder_Store->MidToTable(ev, inMid);
393 morkTable::SlotStrongTable(table, ev, &mBuilder_Table);
394 if ( table )
396 if ( table->mTable_RowSpace )
397 mBuilder_TableRowScope = table->mTable_RowSpace->SpaceScope();
399 if ( inCutAllRows )
400 table->CutAllRows(ev);
404 /*virtual*/ void
405 morkBuilder::OnTableGlitch(morkEnv* ev, const morkGlitch& inGlitch)
407 this->LogGlitch(ev, inGlitch, "table");
410 /*virtual*/ void
411 morkBuilder::OnTableEnd(morkEnv* ev, const morkSpan& inSpan)
412 // mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
414 MORK_USED_1(inSpan);
415 // mParser_InTable = morkBool_kFalse;
416 if ( mBuilder_Table )
418 mBuilder_Table->mTable_Priority = mBuilder_TablePriority;
420 if ( mBuilder_TableIsUnique )
421 mBuilder_Table->SetTableUnique();
423 if ( mBuilder_TableIsVerbose )
424 mBuilder_Table->SetTableVerbose();
426 morkTable::SlotStrongTable((morkTable*) 0, ev, &mBuilder_Table);
428 else
429 this->NilBuilderTableError(ev);
431 mBuilder_Row = 0;
432 mBuilder_Cell = 0;
435 mBuilder_TablePriority = morkPriority_kLo;
436 mBuilder_TableIsUnique = morkBool_kFalse;
437 mBuilder_TableIsVerbose = morkBool_kFalse;
439 if ( mBuilder_TableKind == morkStore_kNoneToken )
440 ev->NewError("missing table kind");
442 mBuilder_CellAtomScope = mBuilder_RowAtomScope =
443 mBuilder_TableAtomScope = mBuilder_PortAtomScope;
445 mBuilder_DoCutCell = morkBool_kFalse;
446 mBuilder_DoCutRow = morkBool_kFalse;
449 /*virtual*/ void
450 morkBuilder::OnNewMeta(morkEnv* ev, const morkPlace& inPlace)
451 // mp:Meta ::= OnNewMeta mp:MetaItem* OnMetaEnd
452 // mp:MetaItem ::= mp:Cell | OnMetaGlitch
453 // mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
454 // mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
455 // mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
457 MORK_USED_2(ev,inPlace);
458 // mParser_InMeta = morkBool_kTrue;
462 /*virtual*/ void
463 morkBuilder::OnMetaGlitch(morkEnv* ev, const morkGlitch& inGlitch)
465 this->LogGlitch(ev, inGlitch, "meta");
468 /*virtual*/ void
469 morkBuilder::OnMetaEnd(morkEnv* ev, const morkSpan& inSpan)
470 // mp:Meta ::= OnNewMeta mp:MetaItem* OnMetaEnd
472 MORK_USED_2(ev,inSpan);
473 // mParser_InMeta = morkBool_kFalse;
476 /*virtual*/ void
477 morkBuilder::OnMinusRow(morkEnv* ev)
479 MORK_USED_1(ev);
480 mBuilder_DoCutRow = morkBool_kTrue;
483 /*virtual*/ void
484 morkBuilder::OnNewRow(morkEnv* ev, const morkPlace& inPlace,
485 const morkMid& inMid, mork_bool inCutAllCols)
486 // mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
487 // mp:TableItem ::= mp:Row | mp:MetaTable | OnTableGlitch
488 // mp:MetaTable ::= OnNewMeta mp:MetaItem* mp:Row OnMetaEnd
489 // mp:Row ::= OnMinusRow? OnNewRow mp:RowItem* OnRowEnd
490 // mp:RowItem ::= mp:Cell | mp:Meta | OnRowGlitch
491 // mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
492 // mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
493 // mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
495 MORK_USED_1(inPlace);
496 // mParser_InRow = morkBool_kTrue;
498 mBuilder_CellForm = mBuilder_RowForm = mBuilder_TableForm;
499 mBuilder_CellAtomScope = mBuilder_RowAtomScope = mBuilder_TableAtomScope;
500 mBuilder_RowRowScope = mBuilder_TableRowScope;
501 morkStore* store = mBuilder_Store;
503 if ( !inMid.mMid_Buf && !inMid.mMid_Oid.mOid_Scope )
505 morkMid mid(inMid);
506 mid.mMid_Oid.mOid_Scope = mBuilder_RowRowScope;
507 mBuilder_Row = store->MidToRow(ev, mid);
509 else
511 mBuilder_Row = store->MidToRow(ev, inMid);
513 morkRow* row = mBuilder_Row;
514 if ( row && inCutAllCols )
516 row->CutAllColumns(ev);
519 morkTable* table = mBuilder_Table;
520 if ( table )
522 if ( row )
524 if ( mParser_InMeta )
526 morkRow* metaRow = table->mTable_MetaRow;
527 if ( !metaRow )
529 table->mTable_MetaRow = row;
530 table->mTable_MetaRowOid = row->mRow_Oid;
531 row->AddRowGcUse(ev);
533 else if ( metaRow != row ) // not identical?
534 ev->NewError("duplicate table meta row");
536 else
538 if ( mBuilder_DoCutRow )
539 table->CutRow(ev, row);
540 else
541 table->AddRow(ev, row);
545 // else // it is now okay to have rows outside a table:
546 // this->NilBuilderTableError(ev);
548 mBuilder_DoCutRow = morkBool_kFalse;
551 /*virtual*/ void
552 morkBuilder::OnRowPos(morkEnv* ev, mork_pos inRowPos)
554 if ( mBuilder_Row && mBuilder_Table && !mParser_InMeta )
556 mork_pos hintFromPos = 0; // best hint when we don't know position
557 mBuilder_Table->MoveRow(ev, mBuilder_Row, hintFromPos, inRowPos);
561 /*virtual*/ void
562 morkBuilder::OnRowGlitch(morkEnv* ev, const morkGlitch& inGlitch)
564 this->LogGlitch(ev, inGlitch, "row");
567 void
568 morkBuilder::FlushBuilderCells(morkEnv* ev)
570 if ( mBuilder_Row )
572 morkPool* pool = mBuilder_Store->StorePool();
573 morkCell* cells = mBuilder_CellsVec;
574 mork_fill fill = mBuilder_CellsVecFill;
575 mBuilder_Row->TakeCells(ev, cells, fill, mBuilder_Store);
577 morkCell* end = cells + fill;
578 --cells; // prepare for preincrement
579 while ( ++cells < end )
581 if ( cells->mCell_Atom )
582 cells->SetAtom(ev, (morkAtom*) 0, pool);
584 mBuilder_CellsVecFill = 0;
586 else
587 this->NilBuilderRowError(ev);
590 /*virtual*/ void
591 morkBuilder::OnRowEnd(morkEnv* ev, const morkSpan& inSpan)
592 // mp:Row ::= OnMinusRow? OnNewRow mp:RowItem* OnRowEnd
594 MORK_USED_1(inSpan);
595 // mParser_InRow = morkBool_kFalse;
596 if ( mBuilder_Row )
598 this->FlushBuilderCells(ev);
600 else
601 this->NilBuilderRowError(ev);
603 mBuilder_Row = 0;
604 mBuilder_Cell = 0;
606 mBuilder_DoCutCell = morkBool_kFalse;
607 mBuilder_DoCutRow = morkBool_kFalse;
610 /*virtual*/ void
611 morkBuilder::OnNewDict(morkEnv* ev, const morkPlace& inPlace)
612 // mp:Dict ::= OnNewDict mp:DictItem* OnDictEnd
613 // mp:DictItem ::= OnAlias | OnAliasGlitch | mp:Meta | OnDictGlitch
615 MORK_USED_2(ev,inPlace);
616 // mParser_InDict = morkBool_kTrue;
618 mBuilder_CellForm = mBuilder_DictForm = mBuilder_PortForm;
619 mBuilder_CellAtomScope = mBuilder_DictAtomScope = mBuilder_PortAtomScope;
622 /*virtual*/ void
623 morkBuilder::OnDictGlitch(morkEnv* ev, const morkGlitch& inGlitch)
625 this->LogGlitch(ev, inGlitch, "dict");
628 /*virtual*/ void
629 morkBuilder::OnDictEnd(morkEnv* ev, const morkSpan& inSpan)
630 // mp:Dict ::= OnNewDict mp:DictItem* OnDictEnd
632 MORK_USED_2(ev,inSpan);
633 // mParser_InDict = morkBool_kFalse;
635 mBuilder_DictForm = 0;
636 mBuilder_DictAtomScope = 0;
639 /*virtual*/ void
640 morkBuilder::OnAlias(morkEnv* ev, const morkSpan& inSpan,
641 const morkMid& inMid)
643 MORK_USED_1(inSpan);
644 if ( mParser_InDict )
646 morkMid mid = inMid; // local copy for modification
647 mid.mMid_Oid.mOid_Scope = mBuilder_DictAtomScope;
648 mBuilder_Store->AddAlias(ev, mid, mBuilder_DictForm);
650 else
651 ev->NewError("alias not in dict");
654 /*virtual*/ void
655 morkBuilder::OnAliasGlitch(morkEnv* ev, const morkGlitch& inGlitch)
657 this->LogGlitch(ev, inGlitch, "alias");
661 morkCell*
662 morkBuilder::AddBuilderCell(morkEnv* ev,
663 const morkMid& inMid, mork_change inChange)
665 morkCell* outCell = 0;
666 mork_column column = inMid.mMid_Oid.mOid_Id;
668 if ( ev->Good() )
670 if ( mBuilder_CellsVecFill >= morkBuilder_kCellsVecSize )
671 this->FlushBuilderCells(ev);
672 if ( ev->Good() )
674 if ( mBuilder_CellsVecFill < morkBuilder_kCellsVecSize )
676 mork_fill indx = mBuilder_CellsVecFill++;
677 outCell = mBuilder_CellsVec + indx;
678 outCell->SetColumnAndChange(column, inChange);
679 outCell->mCell_Atom = 0;
681 else
682 ev->NewError("out of builder cells");
685 return outCell;
688 /*virtual*/ void
689 morkBuilder::OnMinusCell(morkEnv* ev)
691 MORK_USED_1(ev);
692 mBuilder_DoCutCell = morkBool_kTrue;
695 /*virtual*/ void
696 morkBuilder::OnNewCell(morkEnv* ev, const morkPlace& inPlace,
697 const morkMid* inMid, const morkBuf* inBuf)
698 // Exactly one of inMid and inBuf is nil, and the other is non-nil.
699 // When hex ID syntax is used for a column, then inMid is not nil, and
700 // when a naked string names a column, then inBuf is not nil.
702 // mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
703 // mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
704 // mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
706 MORK_USED_1(inPlace);
707 // mParser_InCell = morkBool_kTrue;
709 mork_change cellChange = ( mBuilder_DoCutCell )?
710 morkChange_kCut : morkChange_kAdd;
712 mBuilder_DoCutCell = morkBool_kFalse;
714 mBuilder_CellAtomScope = mBuilder_RowAtomScope;
716 mBuilder_Cell = 0; // nil until determined for a row
717 morkStore* store = mBuilder_Store;
718 mork_scope scope = morkStore_kColumnSpaceScope;
719 morkMid tempMid; // space for local and modifiable cell mid
720 morkMid* cellMid = &tempMid; // default to local if inMid==0
722 if ( inMid ) // mid parameter is actually provided?
724 *cellMid = *inMid; // bitwise copy for modifiable local mid
726 if ( !cellMid->mMid_Oid.mOid_Scope )
728 if ( cellMid->mMid_Buf )
730 scope = store->BufToToken(ev, cellMid->mMid_Buf);
731 cellMid->mMid_Buf = 0; // don't do scope lookup again
732 ev->NewWarning("column mids need column scope");
734 cellMid->mMid_Oid.mOid_Scope = scope;
737 else if ( inBuf ) // buf points to naked column string name?
739 cellMid->ClearMid();
740 cellMid->mMid_Oid.mOid_Id = store->BufToToken(ev, inBuf);
741 cellMid->mMid_Oid.mOid_Scope = scope; // kColumnSpaceScope
743 else
744 ev->NilPointerError(); // either inMid or inBuf must be non-nil
746 mork_column column = cellMid->mMid_Oid.mOid_Id;
748 if ( mBuilder_Row && ev->Good() ) // this cell must be inside a row
750 // mBuilder_Cell = this->AddBuilderCell(ev, *cellMid, cellChange);
752 if ( mBuilder_CellsVecFill >= morkBuilder_kCellsVecSize )
753 this->FlushBuilderCells(ev);
754 if ( ev->Good() )
756 if ( mBuilder_CellsVecFill < morkBuilder_kCellsVecSize )
758 mork_fill ix = mBuilder_CellsVecFill++;
759 morkCell* cell = mBuilder_CellsVec + ix;
760 cell->SetColumnAndChange(column, cellChange);
762 cell->mCell_Atom = 0;
763 mBuilder_Cell = cell;
765 else
766 ev->NewError("out of builder cells");
770 else if ( mParser_InMeta && ev->Good() ) // cell is in metainfo structure?
772 if ( scope == morkStore_kColumnSpaceScope )
774 if ( mParser_InTable ) // metainfo for table?
776 if ( column == morkStore_kKindColumn )
777 mBuilder_MetaTokenSlot = &mBuilder_TableKind;
778 else if ( column == morkStore_kStatusColumn )
779 mBuilder_MetaTokenSlot = &mBuilder_TableStatus;
780 else if ( column == morkStore_kRowScopeColumn )
781 mBuilder_MetaTokenSlot = &mBuilder_TableRowScope;
782 else if ( column == morkStore_kAtomScopeColumn )
783 mBuilder_MetaTokenSlot = &mBuilder_TableAtomScope;
784 else if ( column == morkStore_kFormColumn )
785 mBuilder_MetaTokenSlot = &mBuilder_TableForm;
787 else if ( mParser_InDict ) // metainfo for dict?
789 if ( column == morkStore_kAtomScopeColumn )
790 mBuilder_MetaTokenSlot = &mBuilder_DictAtomScope;
791 else if ( column == morkStore_kFormColumn )
792 mBuilder_MetaTokenSlot = &mBuilder_DictForm;
794 else if ( mParser_InRow ) // metainfo for row?
796 if ( column == morkStore_kAtomScopeColumn )
797 mBuilder_MetaTokenSlot = &mBuilder_RowAtomScope;
798 else if ( column == morkStore_kRowScopeColumn )
799 mBuilder_MetaTokenSlot = &mBuilder_RowRowScope;
800 else if ( column == morkStore_kFormColumn )
801 mBuilder_MetaTokenSlot = &mBuilder_RowForm;
804 else
805 ev->NewWarning("expected column scope");
809 /*virtual*/ void
810 morkBuilder::OnCellGlitch(morkEnv* ev, const morkGlitch& inGlitch)
812 this->LogGlitch(ev, inGlitch, "cell");
815 /*virtual*/ void
816 morkBuilder::OnCellForm(morkEnv* ev, mork_cscode inCharsetFormat)
818 morkCell* cell = mBuilder_Cell;
819 if ( cell )
821 mBuilder_CellForm = inCharsetFormat;
823 else
824 this->NilBuilderCellError(ev);
827 /*virtual*/ void
828 morkBuilder::OnCellEnd(morkEnv* ev, const morkSpan& inSpan)
829 // mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
831 MORK_USED_2(ev,inSpan);
832 // mParser_InCell = morkBool_kFalse;
834 mBuilder_MetaTokenSlot = 0;
835 mBuilder_CellAtomScope = mBuilder_RowAtomScope;
838 /*virtual*/ void
839 morkBuilder::OnValue(morkEnv* ev, const morkSpan& inSpan,
840 const morkBuf& inBuf)
841 // mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
842 // mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
844 MORK_USED_1(inSpan);
845 morkStore* store = mBuilder_Store;
846 morkCell* cell = mBuilder_Cell;
847 if ( cell )
849 mdbYarn yarn;
850 yarn.mYarn_Buf = inBuf.mBuf_Body;
851 yarn.mYarn_Fill = yarn.mYarn_Size = inBuf.mBuf_Fill;
852 yarn.mYarn_More = 0;
853 yarn.mYarn_Form = mBuilder_CellForm;
854 yarn.mYarn_Grow = 0;
855 morkAtom* atom = store->YarnToAtom(ev, &yarn, PR_TRUE /* create */);
856 cell->SetAtom(ev, atom, store->StorePool());
858 else if ( mParser_InMeta )
860 mork_token* metaSlot = mBuilder_MetaTokenSlot;
861 if ( metaSlot )
863 if ( metaSlot == &mBuilder_TableStatus ) // table status?
865 if ( mParser_InTable && mBuilder_Table )
867 const char* body = (const char*) inBuf.mBuf_Body;
868 mork_fill bufFill = inBuf.mBuf_Fill;
869 if ( body && bufFill )
871 const char* bodyEnd = body + bufFill;
872 while ( body < bodyEnd )
874 int c = *body++;
875 switch ( c )
877 case '0':
878 case '1':
879 case '2':
880 case '3':
881 case '4':
882 case '5':
883 case '6':
884 case '7':
885 case '8':
886 case '9':
887 mBuilder_TablePriority = (mork_priority) ( c - '0' );
888 break;
890 case 'u':
891 case 'U':
892 mBuilder_TableIsUnique = morkBool_kTrue;
893 break;
895 case 'v':
896 case 'V':
897 mBuilder_TableIsVerbose = morkBool_kTrue;
898 break;
904 else
906 mork_token token = store->BufToToken(ev, &inBuf);
907 if ( token )
909 *metaSlot = token;
910 if ( metaSlot == &mBuilder_TableKind ) // table kind?
912 if ( mParser_InTable && mBuilder_Table )
913 mBuilder_Table->mTable_Kind = token;
919 else
920 this->NilBuilderCellError(ev);
923 /*virtual*/ void
924 morkBuilder::OnValueMid(morkEnv* ev, const morkSpan& inSpan,
925 const morkMid& inMid)
926 // mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
927 // mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
929 MORK_USED_1(inSpan);
930 morkStore* store = mBuilder_Store;
931 morkCell* cell = mBuilder_Cell;
933 morkMid valMid; // local mid for modifications
934 mdbOid* valOid = &valMid.mMid_Oid; // ref to oid inside mid
935 *valOid = inMid.mMid_Oid; // bitwise copy inMid's oid
937 if ( inMid.mMid_Buf )
939 if ( !valOid->mOid_Scope )
940 store->MidToOid(ev, inMid, valOid);
942 else if ( !valOid->mOid_Scope )
943 valOid->mOid_Scope = mBuilder_CellAtomScope;
945 if ( cell )
947 morkBookAtom* atom = store->MidToAtom(ev, valMid);
948 if ( atom )
949 cell->SetAtom(ev, atom, store->StorePool());
950 else
951 ev->NewError("undefined cell value alias");
953 else if ( mParser_InMeta )
955 mork_token* metaSlot = mBuilder_MetaTokenSlot;
956 if ( metaSlot )
958 mork_scope valScope = valOid->mOid_Scope;
959 if ( !valScope || valScope == morkStore_kColumnSpaceScope )
961 if ( ev->Good() && valMid.HasSomeId() )
963 *metaSlot = valOid->mOid_Id;
964 if ( metaSlot == &mBuilder_TableKind ) // table kind?
966 if ( mParser_InTable && mBuilder_Table )
968 mBuilder_Table->mTable_Kind = valOid->mOid_Id;
970 else
971 ev->NewWarning("mBuilder_TableKind not in table");
973 else if ( metaSlot == &mBuilder_TableStatus ) // table status?
975 if ( mParser_InTable && mBuilder_Table )
977 // $$ what here??
979 else
980 ev->NewWarning("mBuilder_TableStatus not in table");
984 else
985 this->NonColumnSpaceScopeError(ev);
988 else
989 this->NilBuilderCellError(ev);
992 /*virtual*/ void
993 morkBuilder::OnRowMid(morkEnv* ev, const morkSpan& inSpan,
994 const morkMid& inMid)
995 // mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
996 // mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
998 MORK_USED_1(inSpan);
999 morkStore* store = mBuilder_Store;
1000 morkCell* cell = mBuilder_Cell;
1001 if ( cell )
1003 mdbOid rowOid = inMid.mMid_Oid;
1004 if ( inMid.mMid_Buf )
1006 if ( !rowOid.mOid_Scope )
1007 store->MidToOid(ev, inMid, &rowOid);
1009 else if ( !rowOid.mOid_Scope )
1010 rowOid.mOid_Scope = mBuilder_RowRowScope;
1012 if ( ev->Good() )
1014 morkPool* pool = store->StorePool();
1015 morkAtom* atom = pool->NewRowOidAtom(ev, rowOid, &store->mStore_Zone);
1016 if ( atom )
1018 cell->SetAtom(ev, atom, pool);
1019 morkRow* row = store->OidToRow(ev, &rowOid);
1020 if ( row ) // found or created such a row?
1021 row->AddRowGcUse(ev);
1025 else
1026 this->NilBuilderCellError(ev);
1029 /*virtual*/ void
1030 morkBuilder::OnTableMid(morkEnv* ev, const morkSpan& inSpan,
1031 const morkMid& inMid)
1032 // mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
1033 // mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
1035 MORK_USED_1(inSpan);
1036 morkStore* store = mBuilder_Store;
1037 morkCell* cell = mBuilder_Cell;
1038 if ( cell )
1040 mdbOid tableOid = inMid.mMid_Oid;
1041 if ( inMid.mMid_Buf )
1043 if ( !tableOid.mOid_Scope )
1044 store->MidToOid(ev, inMid, &tableOid);
1046 else if ( !tableOid.mOid_Scope )
1047 tableOid.mOid_Scope = mBuilder_RowRowScope;
1049 if ( ev->Good() )
1051 morkPool* pool = store->StorePool();
1052 morkAtom* atom = pool->NewTableOidAtom(ev, tableOid, &store->mStore_Zone);
1053 if ( atom )
1055 cell->SetAtom(ev, atom, pool);
1056 morkTable* table = store->OidToTable(ev, &tableOid,
1057 /*optionalMetaRowOid*/ (mdbOid*) 0);
1058 if ( table ) // found or created such a table?
1059 table->AddTableGcUse(ev);
1063 else
1064 this->NilBuilderCellError(ev);
1068 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789