~ubuntu-branches/ubuntu/wily/afnix/wily

« back to all changes in this revision

Viewing changes to .pc/support-gcc-5.x.patch/src/mod/sps/shl/Sheet.cpp

  • Committer: Package Import Robot
  • Author(s): Nobuhiro Iwamatsu
  • Date: 2015-07-11 02:00:35 UTC
  • mfrom: (10.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20150711020035-2nhpztq7s15qyc0v
Tags: 2.5.1-1
* New upstream release. (Closes: #789968)
* Update debian/control.
  - Update Standards-Version to 3.9.6.
* Add support mips64(el) and ppc64el. (Closes: #741508, #748146)
* Add patches/support-gcc-5.x.patch. (Closes: #777767)
  - Fix build with gcc-5.x.
* Add patches/Disable-NET0001.als.patch.
  - Disable test of NET0001.als.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ---------------------------------------------------------------------------
 
2
// - Sheet.cpp                                                               -
 
3
// - afnix:sps module - sheet class implementation                           -
 
4
// ---------------------------------------------------------------------------
 
5
// - This program is free software;  you can redistribute it  and/or  modify -
 
6
// - it provided that this copyright notice is kept intact.                  -
 
7
// -                                                                         -
 
8
// - This program  is  distributed in  the hope  that it will be useful, but -
 
9
// - without  any  warranty;  without  even   the   implied    warranty   of -
 
10
// - merchantability or fitness for a particular purpose.  In no event shall -
 
11
// - the copyright holder be liable for any  direct, indirect, incidental or -
 
12
// - special damages arising in any way out of the use of this software.     -
 
13
// ---------------------------------------------------------------------------
 
14
// - copyright (c) 1999-2015 amaury darsch                                   -
 
15
// ---------------------------------------------------------------------------
 
16
 
 
17
#include "Sheet.hpp"
 
18
#include "Spssid.hxx"
 
19
#include "Boolean.hpp"
 
20
#include "Integer.hpp"
 
21
#include "Importer.hpp"
 
22
#include "Runnable.hpp"
 
23
#include "QuarkZone.hpp"
 
24
#include "Exception.hpp"
 
25
#include "InputStream.hpp"
 
26
#include "OutputStream.hpp"
 
27
 
 
28
namespace afnix {
 
29
 
 
30
  // -------------------------------------------------------------------------
 
31
  // - private section                                                       -
 
32
  // -------------------------------------------------------------------------
 
33
 
 
34
  class SheetSorter {
 
35
  private:
 
36
    // the column index
 
37
    long d_col;
 
38
    // the sorting mode
 
39
    bool d_mode;
 
40
 
 
41
    // compare two objects for ascending order
 
42
    bool cmplth (Object* ref, Object* slv) const {
 
43
      // check that we have a object records
 
44
      Record* rref = dynamic_cast <Record*> (ref);
 
45
      Record* rslv = dynamic_cast <Record*> (slv);
 
46
      // map the cell to their object
 
47
      Object* robj = nilp;
 
48
      try {
 
49
        robj = (rref == nilp) ? nilp : rref->map (d_col);
 
50
      } catch (...) {
 
51
        robj = nilp;
 
52
      }
 
53
      Object* sobj = nilp;
 
54
      try {
 
55
        sobj = (rslv == nilp) ? nilp : rslv->map (d_col);
 
56
      } catch (...) {
 
57
        sobj = nilp;
 
58
      }
 
59
      // compare with operator
 
60
      if (robj == nilp) return true;
 
61
      Object*   obj = robj->oper (Object::LTH, sobj);
 
62
      Boolean* bobj = dynamic_cast <Boolean*> (obj);
 
63
      bool result   = (bobj == nilp) ? false : bobj->tobool ();
 
64
      Object::cref (obj);
 
65
      return result;
 
66
    }
 
67
 
 
68
    // compare two objects for descending order
 
69
    bool cmpgth (Object* ref, Object* slv) const {
 
70
      // check that we have a object records
 
71
      Record* rref = dynamic_cast <Record*> (ref);
 
72
      Record* rslv = dynamic_cast <Record*> (slv);
 
73
      // map the cell to their object
 
74
      Object* robj = nilp;
 
75
      try {
 
76
        robj = (rref == nilp) ? nilp : rref->map (d_col);
 
77
      } catch (...) {
 
78
        robj = nilp;
 
79
      }
 
80
      Object* sobj = nilp;
 
81
      try {
 
82
        sobj = (rslv == nilp) ? nilp : rslv->map (d_col);
 
83
      } catch (...) {
 
84
        sobj = nilp;
 
85
      }
 
86
      // compare with operator
 
87
      if ((robj == nilp) && (sobj == nilp)) return true;
 
88
      if ((robj == nilp) && (sobj != nilp)) return false;
 
89
      Object*   obj = robj->oper (Object::GTH, sobj);
 
90
      Boolean* bobj = dynamic_cast <Boolean*> (obj);
 
91
      bool result   = (bobj == nilp) ? false : bobj->tobool ();
 
92
      Object::cref (obj);
 
93
      return result;
 
94
    }
 
95
 
 
96
    // partition the vector and returns the pivot index
 
97
 
 
98
    long partition (Vector& argv, const long first, const long last) const {
 
99
      // initialize the pivot index, last index and next (unknown) index
 
100
      long pidx = first;
 
101
      long lidx = first;
 
102
      long uidx = lidx + 1;
 
103
      // get the pivot object - and protect it
 
104
      Object* pvt = Object::iref (argv.get (pidx));
 
105
      // swap until we have reached the last element
 
106
      while (uidx <= last) {
 
107
        Object* ref = Object::iref (argv.get (uidx));
 
108
        bool   cflg = d_mode ? cmplth (ref, pvt) : cmpgth (ref, pvt);
 
109
        if (cflg == true) {
 
110
          lidx++;
 
111
          argv.set (uidx, argv.get (lidx));
 
112
          argv.set (lidx, ref);
 
113
        }
 
114
        Object::tref (ref);
 
115
        // the intel is in the other region
 
116
        uidx++;
 
117
      }
 
118
      // place the pivot in proper position
 
119
      argv.set (first, argv.get (lidx));
 
120
      argv.set (lidx,  pvt);
 
121
      Object::tref (pvt);
 
122
      // the pivot index is now the last index
 
123
      return lidx;
 
124
    }
 
125
    
 
126
    // this function performs a recursive quick sort
 
127
 
 
128
    void quicksort (Vector& argv, const long first, const long last) const {
 
129
      if (first >= last) return;
 
130
      long pidx = partition (argv, first, last);
 
131
      quicksort (argv, first, pidx - 1);
 
132
      quicksort (argv, pidx + 1, last);
 
133
    }
 
134
 
 
135
  public:
 
136
    // create a default sheet sorter
 
137
    SheetSorter (void) {
 
138
      d_col  = 0;
 
139
      d_mode = false;
 
140
    }
 
141
 
 
142
    // create a sorting object by index
 
143
    SheetSorter (const long col, const bool mode) {
 
144
      d_col  = col;
 
145
      d_mode = mode;
 
146
    }
 
147
 
 
148
    // sort a vector
 
149
 
 
150
    void qsort (Vector& argv) const {
 
151
      // sort the vector in place
 
152
      argv.wrlock ();
 
153
      try {
 
154
        long argc = argv.length ();
 
155
        quicksort (argv, 0, argc - 1);
 
156
        argv.unlock ();
 
157
      } catch (...) {
 
158
        argv.unlock ();
 
159
        throw;
 
160
      }
 
161
    }
 
162
  };
 
163
 
 
164
  // this function computes the maximum between two numbers
 
165
  static inline long max (const long x, const long y) {
 
166
    return (x < y) ? y : x;
 
167
  }
 
168
 
 
169
  // this procedure returns a new sheet object for deserialization
 
170
  static Serial* mksob (void) {
 
171
    return new Sheet;
 
172
  }
 
173
  // register this cell serial id
 
174
  static const t_byte SERIAL_ID = Serial::setsid (SERIAL_SHTT_ID, mksob);
 
175
 
 
176
 
 
177
  // -------------------------------------------------------------------------
 
178
  // - class section                                                         -
 
179
  // -------------------------------------------------------------------------
 
180
 
 
181
  // create a nil sheet
 
182
 
 
183
  Sheet::Sheet (void) {
 
184
    reset ();
 
185
  }
 
186
 
 
187
  // create a new sheet by name
 
188
 
 
189
  Sheet::Sheet (const String& name) {
 
190
    d_name = name;
 
191
    reset ();
 
192
  }
 
193
 
 
194
  // create a new sheet by name and info
 
195
 
 
196
  Sheet::Sheet (const String& name, const String& info) {
 
197
    d_name = name;
 
198
    d_info = info;
 
199
    reset ();
 
200
  }
 
201
 
 
202
  // copy construct this sheet
 
203
 
 
204
  Sheet::Sheet (const Sheet& that) {
 
205
    that.rdlock ();
 
206
    try {
 
207
      d_name = that.d_name;
 
208
      d_info = that.d_info;
 
209
      d_tags = that.d_tags;
 
210
      d_sign = that.d_sign;
 
211
      d_mark = that.d_mark;
 
212
      d_head = that.d_head;
 
213
      d_foot = that.d_foot;
 
214
      long hlen = that.d_hstl.length ();
 
215
      for (long k = 0L; k < hlen; k++) {
 
216
        Style* obj = dynamic_cast <Style*> (that.d_hstl.get (k));
 
217
        Style* stl = (obj == nilp) ? nilp : new Style (*obj);
 
218
        d_hstl.add (stl);
 
219
      }
 
220
      long slen = that.length ();
 
221
      for (long i = 0; i < slen; i++) {
 
222
        Record* rcd = that.get (i);
 
223
        add (new Record (*rcd));
 
224
      }
 
225
      that.unlock ();
 
226
    } catch (...) {
 
227
      that.unlock ();
 
228
      throw;
 
229
    }
 
230
  }
 
231
 
 
232
  // return the object name
 
233
 
 
234
  String Sheet::repr (void) const {
 
235
    return "Sheet";
 
236
  }
 
237
 
 
238
  // return a clone of this object
 
239
 
 
240
  Object* Sheet::clone (void) const {
 
241
    return new Sheet (*this);
 
242
  }
 
243
                               
 
244
  // return the sheet serial id
 
245
 
 
246
  t_byte Sheet::serialid (void) const {
 
247
    return SERIAL_SHTT_ID;
 
248
  }
 
249
 
 
250
  // serialize a sheet
 
251
 
 
252
  void Sheet::wrstream (OutputStream& os) const {
 
253
    rdlock ();
 
254
    try {
 
255
      // save the sheet name
 
256
      d_name.wrstream (os);
 
257
      // save the sheet info
 
258
      d_info.wrstream (os);
 
259
      /// save the tags
 
260
      d_tags.wrstream (os);
 
261
      // save the signature
 
262
      d_sign.wrstream (os);
 
263
      // save the header style
 
264
      d_hstl.wrstream (os);
 
265
      // save the marker
 
266
      d_mark.wrstream (os);
 
267
      // save the header
 
268
      d_head.wrstream (os);
 
269
      // save the footer
 
270
      d_foot.wrstream (os);
 
271
      // save the vector
 
272
      d_body.wrstream (os);
 
273
      unlock ();
 
274
    } catch (...) {
 
275
      unlock ();
 
276
      throw;
 
277
    }
 
278
  }
 
279
 
 
280
  // deserialize this sheet
 
281
 
 
282
  void Sheet::rdstream (InputStream& is) {
 
283
    wrlock ();
 
284
    try {
 
285
      // get the sheet name
 
286
      d_name.rdstream (is);
 
287
      // get the sheet info
 
288
      d_info.rdstream (is);
 
289
      // get the tags
 
290
      d_tags.rdstream (is);
 
291
      // get the signature
 
292
      d_sign.rdstream (is);
 
293
      // get the header style
 
294
      d_hstl.rdstream (is);
 
295
      // get the marker
 
296
      d_mark.rdstream (is);
 
297
      // get the header
 
298
      d_head.rdstream (is);
 
299
      // get the footer
 
300
      d_foot.rdstream (is);
 
301
      // get the vector
 
302
      d_body.rdstream (is);
 
303
      unlock ();
 
304
    } catch (...) {
 
305
      unlock ();
 
306
      throw;
 
307
    }
 
308
  }
 
309
 
 
310
  // assign a sheet to this one
 
311
 
 
312
  Sheet& Sheet::operator = (const Sheet& that) {
 
313
    // check for self assignation
 
314
    if (this == &that) return *this;
 
315
    // lock and assign
 
316
    wrlock ();
 
317
    that.rdlock ();
 
318
    try {
 
319
      reset ();
 
320
      d_name = that.d_name;
 
321
      d_info = that.d_info;
 
322
      d_tags = that.d_tags;
 
323
      d_sign = that.d_sign;
 
324
      d_mark = that.d_mark;
 
325
      d_head = that.d_head;
 
326
      d_foot = that.d_foot;
 
327
      long hlen = that.d_hstl.length ();
 
328
      for (long k = 0L; k < hlen; k++) {
 
329
        Style* obj = dynamic_cast <Style*> (that.d_hstl.get (k));
 
330
        Style* stl = (obj == nilp) ? nilp : new Style (*obj);
 
331
        d_hstl.add (stl);
 
332
      }
 
333
      long slen = that.length ();
 
334
      for (long i = 0; i < slen; i++) {
 
335
        Record* rcd = that.get (i);
 
336
        add (new Record (*rcd));
 
337
      }
 
338
      unlock ();
 
339
      that.unlock ();
 
340
      return *this;
 
341
    } catch (...) {
 
342
      unlock ();
 
343
      that.unlock ();
 
344
      throw;
 
345
    }
 
346
  }
 
347
 
 
348
  // reset the sheet
 
349
 
 
350
  void Sheet::reset (void) {
 
351
    wrlock ();
 
352
    try {
 
353
      d_sign = "";
 
354
      d_tags.reset ();
 
355
      d_mark.clear ();
 
356
      d_head.reset ();
 
357
      d_foot.reset ();
 
358
      d_body.reset ();
 
359
      unlock ();
 
360
    } catch (...) {
 
361
      unlock ();
 
362
      throw;
 
363
    }
 
364
  }
 
365
 
 
366
  // clear the sheet
 
367
 
 
368
  void Sheet::clear (void) {
 
369
    wrlock ();
 
370
    try {
 
371
      d_sign = "";
 
372
      d_mark.clear ();
 
373
      long blen = d_body.length ();
 
374
      for (long k = 0L; k < blen; k++) {
 
375
        Record* rcd = get (k);
 
376
        if (rcd != nilp) rcd->clear ();
 
377
      }
 
378
      unlock ();
 
379
    } catch (...) {
 
380
      unlock ();
 
381
      throw;
 
382
    }
 
383
  }
 
384
 
 
385
  // return the sheet name
 
386
 
 
387
  String Sheet::getname (void) const {
 
388
    rdlock ();
 
389
    try {
 
390
      String result = d_name;
 
391
      unlock ();
 
392
      return result;
 
393
    } catch (...) {
 
394
      unlock ();
 
395
      throw;
 
396
    }
 
397
  }
 
398
 
 
399
  // set the sheet name
 
400
 
 
401
  void Sheet::setname (const String& name) {
 
402
    wrlock ();
 
403
    try {
 
404
      d_name = name;
 
405
      unlock ();
 
406
    } catch (...) {
 
407
      unlock ();
 
408
      throw;
 
409
    }
 
410
  }
 
411
 
 
412
  // return the sheet info
 
413
 
 
414
  String Sheet::getinfo (void) const {
 
415
    rdlock ();
 
416
    try {
 
417
      String result = d_info;
 
418
      unlock ();
 
419
      return result;
 
420
    } catch (...) {
 
421
      unlock ();
 
422
      throw;
 
423
    }
 
424
  }
 
425
 
 
426
  // set the sheet info
 
427
 
 
428
  void Sheet::setinfo (const String& info) {
 
429
    wrlock ();
 
430
    try {
 
431
      d_info = info;
 
432
      unlock ();
 
433
    } catch (...) {
 
434
      unlock ();
 
435
      throw;
 
436
    }
 
437
  }
 
438
    
 
439
  // add a sheet tag
 
440
 
 
441
  void Sheet::addtag (const String& tag) {
 
442
    wrlock ();
 
443
    try {
 
444
      if (d_tags.exists (tag) == false) d_tags.add (tag);
 
445
      unlock ();
 
446
    } catch (...) {
 
447
      unlock ();
 
448
      throw;
 
449
    }
 
450
  }
 
451
 
 
452
  // add a vector of literals in the tags descriptor
 
453
 
 
454
  void Sheet::addtag (const Vector* argv) {
 
455
    long argc = (argv == nilp) ? 0 : argv->length ();
 
456
    if (argc == 0) return;
 
457
    wrlock ();
 
458
    try {
 
459
      for (long i = 0; i < argc; i++) {
 
460
        Object*   obj = argv->get (i);
 
461
        Literal* lobj = dynamic_cast <Literal*> (obj);
 
462
        if (lobj == nilp) {
 
463
          throw Exception ("type-error", 
 
464
                           "non literal object with sheet add-tag",
 
465
                           Object::repr (obj));
 
466
        }
 
467
        d_tags.add (lobj->tostring ());
 
468
      }
 
469
      unlock ();
 
470
    } catch (...) {
 
471
      unlock ();
 
472
      throw;
 
473
    }
 
474
  }
 
475
 
 
476
  // return the tag descriptor length
 
477
 
 
478
  long Sheet::tagslen (void) const {
 
479
    rdlock ();
 
480
    try {
 
481
      long result = d_tags.length ();
 
482
      unlock ();
 
483
      return result;
 
484
    } catch (...) {
 
485
      unlock ();
 
486
      throw;
 
487
    }
 
488
  }
 
489
 
 
490
  // check if a tag exists
 
491
 
 
492
  bool Sheet::istag (const String& tag) const {
 
493
    rdlock ();
 
494
    try {
 
495
      bool result = d_tags.exists (tag);
 
496
      unlock ();
 
497
      return result;
 
498
    } catch (...) {
 
499
      unlock ();
 
500
      throw;
 
501
    }
 
502
  }
 
503
 
 
504
  // get a tag by index
 
505
  
 
506
  String Sheet::gettag (const long index) const {
 
507
    wrlock ();
 
508
    try {
 
509
      String result = d_tags.get (index);
 
510
      unlock ();
 
511
      return result;
 
512
    } catch (...) {
 
513
      unlock ();
 
514
      throw;
 
515
    }
 
516
  }
 
517
 
 
518
  // set the sheet tag by index
 
519
  
 
520
  void Sheet::settag (const long index, Literal* lobj) {
 
521
    wrlock ();
 
522
    try {
 
523
      String value = (lobj == nilp) ? "" : lobj->tostring ();
 
524
      d_tags.set (index, value);
 
525
      unlock ();
 
526
    } catch (...) {
 
527
      unlock ();
 
528
      throw;
 
529
    }
 
530
  }
 
531
 
 
532
  // find a tag index by tag
 
533
 
 
534
  long Sheet::findtag (const String& tag) const {
 
535
    rdlock ();
 
536
    try {
 
537
      long result = d_tags.lookup (tag);
 
538
      unlock ();
 
539
      return result;
 
540
    } catch (...) {
 
541
      unlock ();
 
542
      throw;
 
543
    }
 
544
  }
 
545
 
 
546
  // set a sheet signature
 
547
  
 
548
  void Sheet::setsign (const String& sign) {
 
549
    wrlock ();
 
550
    try {
 
551
      d_sign = sign;
 
552
      unlock ();
 
553
    } catch (...) {
 
554
      unlock ();
 
555
      throw;
 
556
    }
 
557
  }
 
558
 
 
559
  // get a sheet signature
 
560
  
 
561
  String Sheet::getsign (void) const {
 
562
    wrlock ();
 
563
    try {
 
564
      String result = d_sign;
 
565
      unlock ();
 
566
      return result;
 
567
    } catch (...) {
 
568
      unlock ();
 
569
      throw;
 
570
    }
 
571
  }
 
572
 
 
573
  // set a header style by index
 
574
 
 
575
  void Sheet::sethstl (const long index, const Style& hstl) {
 
576
    wrlock ();
 
577
    try {
 
578
      d_hstl.add (index, new Style (hstl));
 
579
      unlock ();
 
580
    } catch (...) {
 
581
      unlock ();
 
582
      throw;
 
583
    }
 
584
  }
 
585
 
 
586
  // get a header style
 
587
 
 
588
  Style* Sheet::gethstl (const long index) const {
 
589
    rdlock ();
 
590
    try {
 
591
      long hlen = d_hstl.length ();
 
592
      Style* result = (index < hlen) 
 
593
        ? dynamic_cast <Style*> (d_hstl.get (index))
 
594
        : nilp;
 
595
      unlock ();
 
596
      return result;
 
597
    } catch (...) {
 
598
      unlock ();
 
599
      throw;
 
600
    }
 
601
  }
 
602
 
 
603
  // add a boolean marker
 
604
 
 
605
  void Sheet::addmark (const bool bval) {
 
606
    wrlock ();
 
607
    try {
 
608
      d_mark.add (bval);
 
609
      unlock ();
 
610
    } catch (...) {
 
611
      unlock ();
 
612
      throw;
 
613
    }
 
614
  }
 
615
 
 
616
  // add an integer marker
 
617
 
 
618
  void Sheet::addmark (const long ival) {
 
619
    wrlock ();
 
620
    try {
 
621
      d_mark.add (ival);
 
622
      unlock ();
 
623
    } catch (...) {
 
624
      unlock ();
 
625
      throw;
 
626
    }
 
627
  }
 
628
 
 
629
  // add a real marker
 
630
 
 
631
  void Sheet::addmark (const t_real rval) {
 
632
    wrlock ();
 
633
    try {
 
634
      d_mark.add (rval);
 
635
      unlock ();
 
636
    } catch (...) {
 
637
      unlock ();
 
638
      throw;
 
639
    }
 
640
  }
 
641
 
 
642
  // add a literal marker
 
643
 
 
644
  void Sheet::addmark (Literal* mark) {
 
645
    wrlock ();
 
646
    try {
 
647
      d_mark.add (mark);
 
648
      unlock ();
 
649
    } catch (...) {
 
650
      unlock ();
 
651
      throw;
 
652
    }
 
653
  }
 
654
 
 
655
  // get the sheet marker
 
656
 
 
657
  Literal* Sheet::getmark (void) const {
 
658
    rdlock ();
 
659
    try {
 
660
      Literal* result = d_mark.get (d_mark.getlidx ());
 
661
      unlock ();
 
662
      return result;
 
663
     } catch (...) {
 
664
      unlock ();
 
665
      throw;
 
666
    }
 
667
  }
 
668
 
 
669
  // add an object in the header record
 
670
  
 
671
  void Sheet::addhead (Object* object) {
 
672
    wrlock ();
 
673
    try {
 
674
      d_head.add (object);
 
675
      unlock ();
 
676
    } catch (...) {
 
677
      unlock ();
 
678
      throw;
 
679
    }
 
680
  }
 
681
 
 
682
  // add a vector of objects in the header record
 
683
 
 
684
  void Sheet::addhead (const Vector* argv) {
 
685
    long argc = (argv == nilp) ? 0 : argv->length ();
 
686
    if (argc == 0) return;
 
687
    wrlock ();
 
688
    try {
 
689
      for (long i = 0; i < argc; i++) d_head.add (argv->get (i));
 
690
      unlock ();
 
691
    } catch (...) {
 
692
      unlock ();
 
693
      throw;
 
694
    }
 
695
  }
 
696
 
 
697
  // get a header cell by index
 
698
 
 
699
  Cell* Sheet::gethead (const long index) const {
 
700
    rdlock ();
 
701
    try {
 
702
      Cell* result = d_head.get (index);
 
703
      unlock ();
 
704
      return result;
 
705
    } catch (...) {
 
706
      unlock ();
 
707
      throw;
 
708
    }
 
709
  }
 
710
 
 
711
  // evaluate a header cell by index
 
712
 
 
713
  Literal* Sheet::maphead (const long index) const {
 
714
    rdlock ();
 
715
    try {
 
716
      Cell* cell = gethead (index);
 
717
      Literal* result = (cell == nilp) ? nilp : cell->get ();
 
718
      unlock ();
 
719
      return result;
 
720
    } catch (...) {
 
721
      unlock ();
 
722
      throw;
 
723
    }
 
724
  }
 
725
 
 
726
  // set a record header by index and literal
 
727
  
 
728
  Cell* Sheet::sethead (const long index, Literal* lobj) {
 
729
    wrlock ();
 
730
    try {
 
731
      Cell* cell = d_head.set (index, lobj);
 
732
      unlock ();
 
733
      return cell;
 
734
    } catch (...) {
 
735
      unlock ();
 
736
      throw;
 
737
    }
 
738
  }
 
739
 
 
740
  // add an object in the footer record
 
741
  
 
742
  void Sheet::addfoot (Object* object) {
 
743
    wrlock ();
 
744
    try {
 
745
      d_foot.add (object);
 
746
      unlock ();
 
747
    } catch (...) {
 
748
      unlock ();
 
749
      throw;
 
750
    }
 
751
  }
 
752
 
 
753
  // add a vector of objects in the footer record
 
754
 
 
755
  void Sheet::addfoot (const Vector* argv) {
 
756
    long argc = (argv == nilp) ? 0 : argv->length ();
 
757
    if (argc == 0) return;
 
758
    wrlock ();
 
759
    try {
 
760
      for (long i = 0; i < argc; i++) d_foot.add (argv->get (i));
 
761
      unlock ();
 
762
    } catch (...) {
 
763
      unlock ();
 
764
      throw;
 
765
    }
 
766
  }
 
767
 
 
768
  // get a footer cell by index
 
769
 
 
770
  Cell* Sheet::getfoot (const long index) const {
 
771
    rdlock ();
 
772
    try {
 
773
      Cell* result = dynamic_cast <Cell*> (d_foot.get (index));
 
774
      unlock ();
 
775
      return result;
 
776
    } catch (...) {
 
777
      unlock ();
 
778
      throw;
 
779
    }
 
780
  }
 
781
 
 
782
  // evaluate a footer cell by index
 
783
 
 
784
  Literal* Sheet::mapfoot (const long index) const {
 
785
    rdlock ();
 
786
    try {
 
787
      Cell* cell = getfoot (index);
 
788
      Literal* result = (cell == nilp) ? nilp : cell->get ();
 
789
      unlock ();
 
790
      return result;
 
791
    } catch (...) {
 
792
      unlock ();
 
793
      throw;
 
794
    }
 
795
  }
 
796
 
 
797
  // set a record footer by index and literal
 
798
  
 
799
  Cell* Sheet::setfoot (const long index, Literal* lobj) {
 
800
    wrlock ();
 
801
    try {
 
802
      Cell* cell = dynamic_cast <Cell*> (d_foot.get (index)); 
 
803
      if (cell != nilp) cell->set (lobj);
 
804
      unlock ();
 
805
      return cell;
 
806
    } catch (...) {
 
807
      unlock ();
 
808
      throw;
 
809
    }
 
810
  }
 
811
 
 
812
  // return the length of the sheet list
 
813
 
 
814
  long Sheet::length (void) const {
 
815
    rdlock ();
 
816
    try {
 
817
      long result = d_body.length ();
 
818
      unlock ();
 
819
      return result;
 
820
    } catch (...) {
 
821
      unlock ();
 
822
      throw;
 
823
    }
 
824
  }
 
825
 
 
826
  // return the number of columns
 
827
  
 
828
  long Sheet::getcols (void) const {
 
829
    rdlock ();
 
830
    try {
 
831
      // get the sheet length
 
832
      long tlen = length ();
 
833
      // compute the maximum columns
 
834
      long result = 0;
 
835
      for (long i = 0; i < tlen; i++) {
 
836
        Record* rcd = get (i);
 
837
        if (rcd == nilp) continue;
 
838
        result = max (result, rcd->length ());
 
839
      }
 
840
      unlock ();
 
841
      return result;
 
842
    } catch (...) {
 
843
      unlock ();
 
844
      throw;
 
845
    }
 
846
  }
 
847
 
 
848
  // add a record in this sheet
 
849
 
 
850
  void Sheet::add (Record* rcd) {
 
851
    if (rcd == nilp) return;
 
852
    wrlock ();
 
853
    try {
 
854
      d_body.add (rcd);
 
855
      unlock ();
 
856
    } catch (...) {
 
857
      unlock ();
 
858
      throw;
 
859
    }
 
860
  }
 
861
 
 
862
  // get a record by index
 
863
 
 
864
  Record* Sheet::get (const long index) const {
 
865
    rdlock ();
 
866
    try {
 
867
      Record* result = dynamic_cast <Record*> (d_body.get (index));
 
868
      unlock ();
 
869
      return result;
 
870
    } catch (...) {
 
871
      unlock ();
 
872
      throw;
 
873
    }
 
874
  }
 
875
 
 
876
  // get a cell by row and column
 
877
 
 
878
  Cell* Sheet::get (const long row, const long col) const {
 
879
    rdlock ();
 
880
    try {
 
881
      // get the record
 
882
      Record* rcd = get (row);
 
883
      if (rcd == nilp) {
 
884
        unlock ();
 
885
        return nilp;
 
886
      }
 
887
      // get the cell
 
888
      Cell* cell = rcd->get (col);
 
889
      unlock ();
 
890
      return cell;
 
891
    } catch (...) {
 
892
      unlock ();
 
893
      throw;
 
894
    }
 
895
  }
 
896
 
 
897
  // map a cell literal by ow and column
 
898
 
 
899
  Literal* Sheet::map (const long row, const long col) const {
 
900
    rdlock ();
 
901
    try {
 
902
      Cell* cell = get (row, col);
 
903
      Literal* lobj = (cell == nilp) ? nilp : cell->get ();
 
904
      unlock ();
 
905
      return lobj;
 
906
    } catch (...) {
 
907
      unlock ();
 
908
      throw;
 
909
    }
 
910
  }
 
911
 
 
912
  // set a record in this sheet by index
 
913
 
 
914
  void Sheet::set (const long index, Record* rcd) {
 
915
    wrlock ();
 
916
    try {
 
917
      d_body.set (index, rcd);
 
918
      unlock ();
 
919
    } catch (...) {
 
920
      unlock ();
 
921
      throw;
 
922
    }
 
923
  }
 
924
 
 
925
  // set an object in this sheet by row and column
 
926
 
 
927
  Cell* Sheet::set (const long row, const long col, Object* object) {
 
928
    wrlock ();
 
929
    try {
 
930
      // check if we have enough record
 
931
      long slen = length ();
 
932
      if (row >= slen) {
 
933
        for (long k = slen; k <= row; k++) add (new Record);
 
934
      }
 
935
      // get the record
 
936
      Record* rcd = get (row);
 
937
      // set the cell
 
938
      Cell* cell = rcd->set (col, object);
 
939
      unlock ();
 
940
      return cell;
 
941
    } catch (...) {
 
942
      unlock ();
 
943
      throw;
 
944
    }
 
945
  }
 
946
 
 
947
  // add a vector of literal as a record
 
948
 
 
949
  void Sheet::adddata (const Vector* argv) {
 
950
    long argc = (argv == nilp) ? 0 : argv->length ();
 
951
    if (argc == 0) return;
 
952
    wrlock ();
 
953
    Record* rcd = new Record;
 
954
    try {
 
955
      for (long i = 0; i < argc; i++) rcd->add (argv->get (i));
 
956
      d_body.add (rcd);
 
957
      unlock ();
 
958
    } catch (...) {
 
959
      Object::cref (rcd);
 
960
      unlock ();
 
961
      throw;
 
962
    }
 
963
  }
 
964
 
 
965
  // remove a record by index
 
966
 
 
967
  void Sheet::remove (const long index) {
 
968
    wrlock ();
 
969
    try {
 
970
      d_body.remove (index);
 
971
    } catch (...) {
 
972
      unlock ();
 
973
      throw;
 
974
    }
 
975
  }
 
976
 
 
977
  // import data in this sheet
 
978
 
 
979
  void Sheet::import (InputStream* is) {
 
980
    // do nothing if nil
 
981
    if (is == nilp) return;
 
982
    // protect us during the importation
 
983
    wrlock ();
 
984
    Object::iref (this);
 
985
    // create a new importer
 
986
    try {
 
987
      Sheeting si (this);
 
988
      si.import (is);
 
989
      Object::tref (this);
 
990
      unlock ();
 
991
    } catch (...) {
 
992
      Object::tref (this);
 
993
      unlock ();
 
994
      throw;
 
995
    }
 
996
  }
 
997
 
 
998
  // convert this sheet into a print sheet
 
999
 
 
1000
  PrintTable* Sheet::convert (long max, long start, bool flag) const {
 
1001
    rdlock ();
 
1002
    PrintTable* result = nilp;
 
1003
    try {
 
1004
      // get the number of rows
 
1005
      long rows = length ();
 
1006
      // check for start index
 
1007
      if ((rows != 0) && ((start < 0) || (start >= rows))) {
 
1008
        throw Exception ("sheet-error", "start index out of range for convert");
 
1009
      }
 
1010
      // check for max index
 
1011
      long tlen = start + ((max == 0) ? rows : max);
 
1012
      if (tlen > rows) {
 
1013
        throw Exception ("sheet-error", 
 
1014
                         "max index is out of range for convert");
 
1015
      }
 
1016
      // create the print table
 
1017
      long cols = getcols ();
 
1018
      result = new PrintTable (cols);
 
1019
      // set the column style if any
 
1020
      for (long k = 0L; k < cols; k++) {
 
1021
        Style* hstl = gethstl (k);
 
1022
        if (hstl != nilp) result->setstyle (k, *hstl);
 
1023
      }
 
1024
      // set the header if any
 
1025
      for (long k = 0L; k < cols; k++) {
 
1026
        Literal* lobj = maphead (k);
 
1027
        if (lobj == nilp) {
 
1028
          if (flag == false) result->sethead (k, "nil");
 
1029
        } else {
 
1030
          String data = flag ? lobj->tostring () : lobj->toliteral ();
 
1031
          result->sethead (k, data);
 
1032
        }
 
1033
      }
 
1034
      // set the footer if any
 
1035
      for (long k = 0L; k < cols; k++) {
 
1036
        Literal* lobj = mapfoot (k);
 
1037
        if (lobj == nilp) {
 
1038
          if (flag == false) result->sethead (k, "nil");
 
1039
        } else {
 
1040
          String data = flag ? lobj->tostring () : lobj->toliteral ();
 
1041
          result->setfoot (k, data);
 
1042
        }
 
1043
      }
 
1044
      // iterate through the record
 
1045
      for (long i = start; i < tlen; i++) {
 
1046
        Record* rcd = get (i);
 
1047
        if (rcd == nilp) continue;
 
1048
        long row = result->add ();
 
1049
        // get the record length
 
1050
        long rlen = rcd->length ();
 
1051
        for (long j = 0; j < rlen; j++) {
 
1052
          // get the literal
 
1053
          Literal* lobj = rcd->map (j);
 
1054
          // get the associated style
 
1055
          Style* cstl = rcd->getstyle (j);
 
1056
          if (cstl == nilp) cstl = gethstl (j);
 
1057
          // translate the literal
 
1058
          if (lobj == nilp) {
 
1059
            String data = flag ? "" : "nil";
 
1060
            result->set (row, j, data);
 
1061
          } else {
 
1062
            if (cstl == nilp) {
 
1063
              String data = flag ? lobj->tostring () : lobj->toliteral ();
 
1064
              result->set (row, j, data);
 
1065
            } else {
 
1066
              String data = flag ? lobj->format (*cstl) : lobj->toliteral ();
 
1067
              result->set (row, j, data);
 
1068
            }
 
1069
          }
 
1070
        }
 
1071
        // fill the rest of the sheet
 
1072
        String text = flag ? "" : "nil";
 
1073
        for (long j = rlen; j < cols; j++) result->set (row, j, text);
 
1074
      }
 
1075
      unlock ();
 
1076
      return result;
 
1077
    } catch (...) {
 
1078
      delete result;
 
1079
      unlock ();
 
1080
      throw;
 
1081
    }
 
1082
  }
 
1083
 
 
1084
  // sort this sheet by column index and mode
 
1085
 
 
1086
  void Sheet::sort (const long col, const bool mode) {
 
1087
    wrlock ();
 
1088
    try {
 
1089
      // build the sorter object
 
1090
      SheetSorter sorter (col, mode);
 
1091
      // sort the vector
 
1092
      sorter.qsort (d_body);
 
1093
      unlock ();
 
1094
    } catch (...) {
 
1095
      unlock ();
 
1096
      throw;
 
1097
    }
 
1098
  }
 
1099
 
 
1100
  // link a sheet column into this sheet
 
1101
 
 
1102
  void Sheet::lkcol (const Sheet* sheet, const long col) {
 
1103
    // check for a sheet and lock
 
1104
    if ((sheet == nilp) || (sheet == this)) return;
 
1105
    sheet->rdlock ();
 
1106
    wrlock ();
 
1107
    try {
 
1108
      // get the insert column
 
1109
      long cidx = getcols ();
 
1110
      // get the column size
 
1111
      long size = sheet->length ();
 
1112
      // copy the column
 
1113
      for (long i = 0; i < size; i++) {
 
1114
        Cell* cell = sheet->get (i, col);
 
1115
        set (i, cidx, cell);
 
1116
      }
 
1117
    } catch (...) {
 
1118
      unlock ();
 
1119
      sheet->unlock ();
 
1120
      throw;
 
1121
    }
 
1122
  }
 
1123
 
 
1124
  // check if a row exists by column index and literal
 
1125
 
 
1126
  bool Sheet::isrow (const long col, const Literal& lobj) const {
 
1127
    rdlock ();
 
1128
    try {
 
1129
      // get the number of rows
 
1130
      long rows = length ();
 
1131
      // initialize result
 
1132
      bool result = false;
 
1133
      // loop in the sheet and check
 
1134
      for (long row = 0; row < rows; row++) {
 
1135
        Record* rcd = get (row);
 
1136
        if (rcd == nilp) continue;
 
1137
        if (rcd->isequal (col, lobj) == true) {
 
1138
          result = true;
 
1139
          break;
 
1140
        }
 
1141
      }
 
1142
      unlock ();
 
1143
      return result;
 
1144
    } catch (...) {
 
1145
      unlock ();
 
1146
      throw;
 
1147
    }
 
1148
  }
 
1149
 
 
1150
  // find a row by column index and literal
 
1151
 
 
1152
  long Sheet::rfind (const long col, const Literal& lobj) const {
 
1153
    rdlock ();
 
1154
    try {
 
1155
      // get the number of rows
 
1156
      long rows = length ();
 
1157
      // initialize result
 
1158
      long result = -1;
 
1159
      // loop in the sheet and check
 
1160
      for (long row = 0; row < rows; row++) {
 
1161
        Record* rcd = get (row);
 
1162
        if (rcd == nilp) continue;
 
1163
        if (rcd->isequal (col, lobj) == true) {
 
1164
          result = row;
 
1165
          break;
 
1166
        }
 
1167
      }
 
1168
      unlock ();
 
1169
      return result;
 
1170
    } catch (...) {
 
1171
      unlock ();
 
1172
      throw;
 
1173
    }
 
1174
  }
 
1175
 
 
1176
 // find a row by column index and literal or throw an exception
 
1177
 
 
1178
  long Sheet::rlookup (const long col, const Literal& lobj) const {
 
1179
    rdlock ();
 
1180
    try {
 
1181
      long result = rfind (col, lobj);
 
1182
      if (result == -1) {
 
1183
        throw Exception ("lookup-error", "cannot find row by literal",
 
1184
                         lobj.tostring ());
 
1185
      }
 
1186
      unlock ();
 
1187
      return result;
 
1188
    } catch (...) {
 
1189
      unlock ();
 
1190
      throw;
 
1191
    }
 
1192
  }
 
1193
 
 
1194
  // -------------------------------------------------------------------------
 
1195
  // - object section                                                        -
 
1196
  // -------------------------------------------------------------------------
 
1197
 
 
1198
  // the quark zone
 
1199
  static const long QUARK_ZONE_LENGTH = 38;
 
1200
  static QuarkZone  zone (QUARK_ZONE_LENGTH);
 
1201
 
 
1202
  // the sheet supported quarks
 
1203
  static const long QUARK_ADD     = zone.intern ("add");
 
1204
  static const long QUARK_GET     = zone.intern ("get");
 
1205
  static const long QUARK_MAP     = zone.intern ("map");
 
1206
  static const long QUARK_SET     = zone.intern ("set");
 
1207
  static const long QUARK_SORT    = zone.intern ("sort");
 
1208
  static const long QUARK_RESET   = zone.intern ("reset");
 
1209
  static const long QUARK_CLEAR   = zone.intern ("clear");
 
1210
  static const long QUARK_RFIND   = zone.intern ("find-row");
 
1211
  static const long QUARK_REMOVE  = zone.intern ("remove");
 
1212
  static const long QUARK_ISROWP  = zone.intern ("row-p");
 
1213
  static const long QUARK_IMPORT  = zone.intern ("import");
 
1214
  static const long QUARK_LENGTH  = zone.intern ("length");
 
1215
  static const long QUARK_COLLEN  = zone.intern ("column-length");
 
1216
  static const long QUARK_ADDTAG  = zone.intern ("add-tag");
 
1217
  static const long QUARK_TAGLEN  = zone.intern ("tag-length");
 
1218
  static const long QUARK_ISTAGP  = zone.intern ("tag-p");
 
1219
  static const long QUARK_GETTAG  = zone.intern ("get-tag");
 
1220
  static const long QUARK_SETTAG  = zone.intern ("set-tag");
 
1221
  static const long QUARK_FINDTAG = zone.intern ("find-tag");
 
1222
  static const long QUARK_CONVERT = zone.intern ("convert");
 
1223
  static const long QUARK_SETNAME = zone.intern ("set-name");
 
1224
  static const long QUARK_GETINFO = zone.intern ("get-info");
 
1225
  static const long QUARK_SETINFO = zone.intern ("set-info");
 
1226
  static const long QUARK_GETSIGN = zone.intern ("get-signature");
 
1227
  static const long QUARK_SETSIGN = zone.intern ("set-signature");
 
1228
  static const long QUARK_ADDMARK = zone.intern ("add-marker");
 
1229
  static const long QUARK_GETMARK = zone.intern ("get-marker");
 
1230
  static const long QUARK_ADDHEAD = zone.intern ("add-header");
 
1231
  static const long QUARK_GETHEAD = zone.intern ("get-header");
 
1232
  static const long QUARK_MAPHEAD = zone.intern ("map-header");
 
1233
  static const long QUARK_SETHEAD = zone.intern ("set-header");
 
1234
  static const long QUARK_ADDFOOT = zone.intern ("add-footer");
 
1235
  static const long QUARK_GETFOOT = zone.intern ("get-footer");
 
1236
  static const long QUARK_MAPFOOT = zone.intern ("map-footer");
 
1237
  static const long QUARK_SETFOOT = zone.intern ("set-footer");
 
1238
  static const long QUARK_ADDDATA = zone.intern ("add-data");
 
1239
  static const long QUARK_LINKCOL = zone.intern ("link-column");
 
1240
  static const long QUARK_RLOOKUP = zone.intern ("lookup-row");
 
1241
 
 
1242
  // create a new object in a generic way
 
1243
 
 
1244
  Object* Sheet::mknew (Vector* argv) {
 
1245
    // get number of arguments
 
1246
    long argc = (argv == nilp) ? 0 : argv->length ();
 
1247
    // check for 0 argument
 
1248
    if (argc == 0) return new Sheet;
 
1249
    // check for 1 argument
 
1250
    if (argc == 1) {
 
1251
      String name = argv->getstring (0);
 
1252
      return new Sheet (name);
 
1253
    }
 
1254
    // check for 2 arguments
 
1255
    if (argc == 2) {
 
1256
      String name = argv->getstring (0);
 
1257
      String info = argv->getstring (1);
 
1258
      return new Sheet (name, info);
 
1259
    }
 
1260
    throw Exception ("argument-error", "too many argument with sheet");
 
1261
  }
 
1262
 
 
1263
  // return true if the given quark is defined
 
1264
 
 
1265
  bool Sheet::isquark (const long quark, const bool hflg) const {
 
1266
    rdlock ();
 
1267
    if (zone.exists (quark) == true) {
 
1268
      unlock ();
 
1269
      return true;
 
1270
    }
 
1271
    bool result = hflg ? Saveas::isquark (quark, hflg) : false;
 
1272
    unlock ();
 
1273
    return result;
 
1274
  }
 
1275
 
 
1276
  // apply this object with a set of arguments and a quark
 
1277
 
 
1278
  Object* Sheet::apply (Runnable* robj, Nameset* nset, const long quark,
 
1279
                        Vector* argv) {
 
1280
    // check for generic quark
 
1281
    if (quark == QUARK_ADDDATA) {
 
1282
      adddata (argv);
 
1283
      return nilp;
 
1284
    }
 
1285
    if (quark == QUARK_ADDTAG) {
 
1286
      addtag (argv);
 
1287
      return nilp;
 
1288
    }
 
1289
    if (quark == QUARK_ADDHEAD) {
 
1290
      addhead (argv);
 
1291
      return nilp;
 
1292
    }
 
1293
    if (quark == QUARK_ADDFOOT) {
 
1294
      addfoot (argv);
 
1295
      return nilp;
 
1296
    }
 
1297
 
 
1298
    // get the number of arguments
 
1299
    long argc = (argv == nilp) ? 0 : argv->length ();
 
1300
 
 
1301
    // dispatch 0 argument
 
1302
    if (argc == 0) {
 
1303
      if (quark == QUARK_LENGTH ) return new Integer (length  ());
 
1304
      if (quark == QUARK_COLLEN ) return new Integer (getcols ());
 
1305
      if (quark == QUARK_TAGLEN ) return new Integer (tagslen ());
 
1306
      if (quark == QUARK_GETINFO) return new String  (getinfo ());
 
1307
      if (quark == QUARK_GETSIGN) return new String  (getsign ());
 
1308
      if (quark == QUARK_GETMARK) return getmark ();
 
1309
      if (quark == QUARK_CONVERT) return convert (0, 0, true);
 
1310
      if (quark == QUARK_RESET) {
 
1311
        reset ();
 
1312
        return nilp;
 
1313
      }
 
1314
      if (quark == QUARK_CLEAR) {
 
1315
        clear ();
 
1316
        return nilp;
 
1317
      }
 
1318
      if (quark == QUARK_SORT) {
 
1319
        sort (0, true);
 
1320
        return nilp;
 
1321
      }
 
1322
    }
 
1323
 
 
1324
    // dispatch 1 argument
 
1325
    if (argc == 1) {
 
1326
      if (quark == QUARK_SETNAME) {
 
1327
        String name = argv->getstring (0);
 
1328
        setname (name);
 
1329
        return nilp;
 
1330
      }
 
1331
      if (quark == QUARK_SETINFO) {
 
1332
        String info = argv->getstring (0);
 
1333
        setinfo (info);
 
1334
        return nilp;
 
1335
      }
 
1336
      if (quark == QUARK_ADDMARK) {
 
1337
        Object*   obj = argv->get (0);
 
1338
        Literal* lobj = dynamic_cast <Literal*> (obj);
 
1339
        if ((obj != nilp) && (lobj == nilp)) {
 
1340
          throw Exception ("type-error", "non literal object with add-marker",
 
1341
                           Object::repr (obj));
 
1342
        }         
 
1343
        addmark (lobj);
 
1344
        return nilp;
 
1345
      }
 
1346
      if (quark == QUARK_SETSIGN) {
 
1347
        String sign = argv->getstring (0);
 
1348
        setsign (sign);
 
1349
        return nilp;
 
1350
      }
 
1351
      if (quark == QUARK_ISTAGP) {
 
1352
        Object*   obj = argv->get (0);
 
1353
        Literal* lobj = dynamic_cast <Literal*> (obj);
 
1354
        if (lobj == nilp) {
 
1355
          throw Exception ("type-error", "non literal object with tag-p",
 
1356
                           Object::repr (obj));
 
1357
        }         
 
1358
        String tag = lobj->tostring ();
 
1359
        return new Boolean (istag (tag));
 
1360
      }
 
1361
      if (quark == QUARK_GETTAG) {
 
1362
        long index = argv->getlong (0);
 
1363
        return new String (gettag (index));
 
1364
      }
 
1365
      if (quark == QUARK_FINDTAG) {
 
1366
        Object*   obj = argv->get (0);
 
1367
        Literal* lobj = dynamic_cast <Literal*> (obj);
 
1368
        if (lobj == nilp) {
 
1369
          throw Exception ("type-error", "non literal object with find-tag",
 
1370
                           Object::repr (obj));
 
1371
        }         
 
1372
        String tag = lobj->tostring ();
 
1373
        return new Integer (findtag (tag));
 
1374
      }
 
1375
      if (quark == QUARK_GET) {
 
1376
        long idx = argv->getlong (0);
 
1377
        rdlock ();
 
1378
        try {
 
1379
          Object* result = get (idx);
 
1380
          robj->post (result);
 
1381
          unlock ();
 
1382
          return result;
 
1383
        } catch (...) {
 
1384
          unlock ();
 
1385
          throw;
 
1386
        }
 
1387
      }
 
1388
      if (quark == QUARK_ADD) {
 
1389
        Object* obj = argv->get (0);
 
1390
        Record* rcd = dynamic_cast <Record*> (obj);
 
1391
        if (rcd != nilp) {
 
1392
          add (rcd);
 
1393
          return nilp;
 
1394
        }
 
1395
        throw Exception ("type-error", "invalid object to add in sheet",
 
1396
                         Object::repr (obj));
 
1397
      }
 
1398
      if (quark == QUARK_GETHEAD) {
 
1399
        long index = argv->getlong (0);
 
1400
        rdlock ();
 
1401
        try {
 
1402
          Object* result = gethead (index);
 
1403
          robj->post (result);
 
1404
          unlock ();
 
1405
          return result;
 
1406
        } catch (...) {
 
1407
          unlock ();
 
1408
          throw;
 
1409
        }
 
1410
      }
 
1411
      if (quark == QUARK_MAPHEAD) {
 
1412
        long index = argv->getlong (0);
 
1413
        rdlock ();
 
1414
        try {
 
1415
          Object* result = maphead (index);
 
1416
          robj->post (result);
 
1417
          unlock ();
 
1418
          return result;
 
1419
        } catch (...) {
 
1420
          unlock ();
 
1421
          throw;
 
1422
        }
 
1423
      }
 
1424
      if (quark == QUARK_GETFOOT) {
 
1425
        long index = argv->getlong (0);
 
1426
        rdlock ();
 
1427
        try {
 
1428
          Object* result = getfoot (index);
 
1429
          robj->post (result);
 
1430
          unlock ();
 
1431
          return result;
 
1432
        } catch (...) {
 
1433
          unlock ();
 
1434
          throw;
 
1435
        }
 
1436
      }
 
1437
      if (quark == QUARK_MAPFOOT) {
 
1438
        long index = argv->getlong (0);
 
1439
        rdlock ();
 
1440
        try {
 
1441
          Object* result = mapfoot (index);
 
1442
          robj->post (result);
 
1443
          unlock ();
 
1444
          return result;
 
1445
        } catch (...) {
 
1446
          unlock ();
 
1447
          throw;
 
1448
        }
 
1449
      }
 
1450
      if (quark == QUARK_REMOVE) {
 
1451
        long index= argv->getlong (0);
 
1452
        remove (index);
 
1453
        return nilp;
 
1454
      }
 
1455
      if (quark == QUARK_IMPORT) {
 
1456
        Object* obj = argv->get (0);
 
1457
        InputStream* is = dynamic_cast <InputStream*> (obj);
 
1458
        if (is != nilp) {
 
1459
          import (is);
 
1460
          return nilp;
 
1461
        }
 
1462
        throw Exception ("type-error", "invalid object for sheet importation",
 
1463
                         Object::repr (obj));
 
1464
      }
 
1465
      if (quark == QUARK_CONVERT) {
 
1466
        long max = argv->getlong (0);
 
1467
        return convert (max, 0, true);
 
1468
      }
 
1469
      if (quark == QUARK_SORT) {
 
1470
        Object* obj = argv->get (0);
 
1471
        // check for integer
 
1472
        Integer* col = dynamic_cast <Integer*> (obj);
 
1473
        if (col != nilp) {
 
1474
          sort (col->tolong (), true);
 
1475
          return nilp;
 
1476
        }
 
1477
        // check for boolean
 
1478
        Boolean* mode = dynamic_cast <Boolean*> (obj);
 
1479
        if (mode != nilp) {
 
1480
          sort (0, mode->tobool ());
 
1481
          return nilp;
 
1482
        }
 
1483
        // invalid arguments
 
1484
        throw Exception ("type-error", "invalid object for sorting ",
 
1485
                         Object::repr (obj));
 
1486
      }
 
1487
    }
 
1488
 
 
1489
    // dispatch 2 argument
 
1490
    if (argc == 2) {
 
1491
      if (quark == QUARK_SETTAG) {
 
1492
        long     idx  = argv->getlong (0);
 
1493
        Object*  obj  = argv->get (1);
 
1494
        Literal* lobj = dynamic_cast <Literal*> (obj);
 
1495
        if ((obj != nilp) && (lobj == nilp)) 
 
1496
          throw Exception ("type-error", "invalid object to set in tags",
 
1497
                           Object::repr (obj));
 
1498
        settag (idx, lobj);
 
1499
        return nilp;
 
1500
      }
 
1501
      if (quark == QUARK_SETHEAD) {
 
1502
        long    idx = argv->getlong (0);
 
1503
        Object*  obj  = argv->get (1);
 
1504
        Literal* lobj = dynamic_cast <Literal*> (obj);
 
1505
        if ((obj != nilp) && (lobj == nilp)) 
 
1506
          throw Exception ("type-error", "invalid object to set in header",
 
1507
                           Object::repr (obj));
 
1508
        wrlock ();
 
1509
        try {
 
1510
          Object* result = sethead (idx, lobj);
 
1511
          robj->post (result);
 
1512
          unlock ();
 
1513
          return result;
 
1514
        } catch (...) {
 
1515
          unlock ();
 
1516
          throw;
 
1517
        }
 
1518
      }
 
1519
      if (quark == QUARK_SETFOOT) {
 
1520
        long    idx = argv->getlong (0);
 
1521
        Object*  obj  = argv->get (1);
 
1522
        Literal* lobj = dynamic_cast <Literal*> (obj);
 
1523
        if ((obj != nilp) && (lobj == nilp)) 
 
1524
          throw Exception ("type-error", "invalid object to set in footer",
 
1525
                           Object::repr (obj));
 
1526
        wrlock ();
 
1527
        try {
 
1528
          Object* result = setfoot (idx, lobj);
 
1529
          robj->post (result);
 
1530
          unlock ();
 
1531
          return result;
 
1532
        } catch (...) {
 
1533
          unlock ();
 
1534
          throw;
 
1535
        }
 
1536
      }
 
1537
      if (quark == QUARK_GET) {
 
1538
        long row = argv->getlong (0);
 
1539
        long col = argv->getlong (1);
 
1540
        rdlock ();
 
1541
        try {
 
1542
          Object* result = get (row, col);
 
1543
          robj->post (result);
 
1544
          unlock ();
 
1545
          return result;
 
1546
        } catch (...) {
 
1547
          unlock ();
 
1548
          throw;
 
1549
        }
 
1550
      }
 
1551
      if (quark == QUARK_MAP) {
 
1552
        long row = argv->getlong (0);
 
1553
        long col = argv->getlong (1);
 
1554
        rdlock ();
 
1555
        try {
 
1556
          Object* result = map (row, col);
 
1557
          robj->post (result);
 
1558
          unlock ();
 
1559
          return result;
 
1560
        } catch (...) {
 
1561
          unlock ();
 
1562
          throw;
 
1563
        }
 
1564
      }
 
1565
      if (quark == QUARK_SET) {
 
1566
        long    idx = argv->getlong (0);
 
1567
        Object* obj = argv->get (1);
 
1568
        Record* rcd = dynamic_cast <Record*> (obj);
 
1569
        if ((obj != nilp) && (rcd == nilp)) 
 
1570
          throw Exception ("type-error", "invalid object to set in sheet",
 
1571
                           Object::repr (obj));
 
1572
        set (idx, rcd);
 
1573
        return nilp;
 
1574
      }
 
1575
      if (quark == QUARK_CONVERT) {
 
1576
        long max   = argv->getlong (0);
 
1577
        long start = argv->getlong (1);
 
1578
        return convert (max, start, true);
 
1579
      }
 
1580
      if (quark == QUARK_SORT) {
 
1581
        long col  = argv->getlong (0);
 
1582
        bool mode = argv->getbool (1);
 
1583
        sort (col, mode);
 
1584
        return nilp;
 
1585
      }
 
1586
      if (quark == QUARK_LINKCOL) {
 
1587
        Object* obj = argv->get (0);
 
1588
        Sheet*  sht = dynamic_cast <Sheet*> (obj);
 
1589
        if (sht == nilp) {
 
1590
          throw Exception ("type-error", "invalid object with link-column",
 
1591
                           Object::repr (obj));
 
1592
        }
 
1593
        long col = argv->getlong (1);
 
1594
        lkcol (sht, col);
 
1595
        return nilp;
 
1596
      }
 
1597
      if (quark == QUARK_ISROWP) {
 
1598
        long      col = argv->getlong (0);
 
1599
        Object*   obj = argv->get (1);
 
1600
        Literal* lobj = dynamic_cast <Literal*> (obj);
 
1601
        if ((obj != nilp) && (lobj == nilp)) 
 
1602
          throw Exception ("type-error", "invalid object for row check",
 
1603
                           Object::repr (obj));
 
1604
        bool result = isrow (col, *lobj);
 
1605
        return new Boolean (result);
 
1606
      }
 
1607
      if (quark == QUARK_RFIND) {
 
1608
        long      col = argv->getlong (0);
 
1609
        Object*   obj = argv->get (1);
 
1610
        Literal* lobj = dynamic_cast <Literal*> (obj);
 
1611
        if ((obj != nilp) && (lobj == nilp)) 
 
1612
          throw Exception ("type-error", "invalid object for row find",
 
1613
                           Object::repr (obj));
 
1614
        long result = rfind (col, *lobj);
 
1615
        return new Integer (result);
 
1616
      }
 
1617
      if (quark == QUARK_RLOOKUP) {
 
1618
        long      col = argv->getlong (0);
 
1619
        Object*   obj = argv->get (1);
 
1620
        Literal* lobj = dynamic_cast <Literal*> (obj);
 
1621
        if ((obj != nilp) && (lobj == nilp)) 
 
1622
          throw Exception ("type-error", "invalid object for row lookup",
 
1623
                           Object::repr (obj));
 
1624
        long result = rlookup (col, *lobj);
 
1625
        return new Integer (result);
 
1626
      }
 
1627
    }
 
1628
    // dispatch 3 arguments
 
1629
    if (argc == 3) {
 
1630
      if (quark == QUARK_CONVERT) {
 
1631
        long max   = argv->getlong (0);
 
1632
        long start = argv->getlong (1);
 
1633
        bool flag  = argv->getbool (2);
 
1634
        return convert (max, start, flag);
 
1635
      }
 
1636
      if (quark == QUARK_SET) {
 
1637
        long    row = argv->getlong (0);
 
1638
        long    col = argv->getlong (1);
 
1639
        Object* obj = argv->get    (2);
 
1640
        wrlock ();
 
1641
        try {
 
1642
          Object* result = set (row, col, obj);
 
1643
          robj->post (result);
 
1644
          unlock ();
 
1645
          return result;
 
1646
        } catch (...) {
 
1647
          unlock ();
 
1648
          throw;
 
1649
        }
 
1650
      }
 
1651
    }
 
1652
    // call the saveas method
 
1653
    return Saveas::apply (robj, nset, quark, argv);
 
1654
  }
 
1655
}