~ubuntu-branches/debian/jessie/eso-midas/jessie

« back to all changes in this revision

Viewing changes to libsrc/tbl/tcc.c

  • Committer: Package Import Robot
  • Author(s): Ole Streicher
  • Date: 2014-04-22 14:44:58 UTC
  • Revision ID: package-import@ubuntu.com-20140422144458-okiwi1assxkkiz39
Tags: upstream-13.09pl1.2+dfsg
ImportĀ upstreamĀ versionĀ 13.09pl1.2+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*===========================================================================
 
2
  Copyright (C) 1995-2010 European Southern Observatory (ESO)
 
3
 
 
4
  This program is free software; you can redistribute it and/or 
 
5
  modify it under the terms of the GNU General Public License as 
 
6
  published by the Free Software Foundation; either version 2 of 
 
7
  the License, or (at your option) any later version.
 
8
 
 
9
  This program is distributed in the hope that it will be useful,
 
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
  GNU General Public License for more details.
 
13
 
 
14
  You should have received a copy of the GNU General Public 
 
15
  License along with this program; if not, write to the Free 
 
16
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
 
17
  MA 02139, USA.
 
18
 
 
19
  Correspondence concerning ESO-MIDAS should be addressed as follows:
 
20
        Internet e-mail: midas@eso.org
 
21
        Postal address: European Southern Observatory
 
22
                        Data Management Division 
 
23
                        Karl-Schwarzschild-Strasse 2
 
24
                        D 85748 Garching bei Muenchen 
 
25
                        GERMANY
 
26
===========================================================================*/
 
27
 
 
28
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
29
.TYPE           Module
 
30
.NAME           tcc.c
 
31
.LANGUAGE       C
 
32
.AUTHOR         J.D.Ponz  IPG-ESO - Garching
 
33
.CATEGORY       table interface (Design 2.0)
 
34
.VERSION  1.0   25-Mar-1987   Implementation     JDP
 
35
.VERSION  1.1   20-Oct-1987   Modify calling sequence 
 
36
.VERSION  1.2   23-Nov-1987   New SC calling sequence
 
37
.VERSION  1.3   11-Apr-1988   Include new routines without type conversion.
 
38
                                Character string always ending with a '\0'.
 
39
                                New SC calling sequence.
 
40
.VERSION  1.4   26-Sep-1988   Modify calling sequence in TCCINI to 
 
41
                               include data types and array length.
 
42
.VERSION  3.0   01-Jul-1990     New Version with Arrays / Elementary IO
 
43
                                Added TCCSEL routine (selection of Columns)
 
44
.VERSION  3.1   26-Sep-1990     Removed bug in TCCSRT 
 
45
.VERSION  3.2   06-Dec-1990     Force New Version as soon as something modified.
 
46
.VERSION  3.3   18-Dec-1990 FO: Take into account the number of selected rows.
 
47
.VERSION  3.4   23-Feb-1991     Sort always writes NULL values at the end.
 
48
.VERSION  3.5   29-Apr-1991:    TCCINI must work whatever the table size is ...
 
49
.VERSION  3.6   10-Jun-1991:    Added TCCPAM (Partial Column Mapping)
 
50
.VERSION  3.7   22-Sep-1992:    treats in a proper way NULL values (i.e convex)
 
51
 
 
52
 100818         last modif 
 
53
 
 
54
 
 
55
.COMMENTS    
 
56
 
 
57
This module contains the routines to handle columns in a table. 
 
58
Access to the table is done through the table identifier,
 
59
returned by the routines TCTOPN and TCTINI.
 
60
Access to a column is done through the column number, given
 
61
by the routines TCCINI, TCCSER and TCLSER.
 
62
 
 
63
The following main functions are defined in this module:
 
64
 create a column in the table (TCCINI), 
 
65
 delete a column from the table (TCCDEL),
 
66
 map a column (TCCMAP),
 
67
 unmap a column (TCCUNM),
 
68
 table sorting according to column values (TCCSRT),
 
69
 search the column number (TCCSER).
 
70
 
 
71
Main arguments used by the routines are:
 
72
[alen] array length. 
 
73
            Integer number to define the number of items in a multiple 
 
74
            column.
 
75
            In the case of character strings 'alen' defines the maximum 
 
76
            length of the string.
 
77
[colref] reference to the column by label or by number.
 
78
            It is a character string containing the ':label'
 
79
            if the column is referenced by label, or '\#n' if the
 
80
            column is referenced by its sequential number.                   
 
81
[column] sequential column number. It is an integer number 
 
82
            provided by the system when a new column is created or
 
83
            defined by the user.
 
84
[dtype] column data type. 
 
85
            The system file 'midas\_def.h' in 'MID\_INCLUDE:' provides the
 
86
            symbols D\_xx\_FORMAT where 'xx' is 'I4' for integer data, 
 
87
            'R4' for float, 'R8' for double precision and 
 
88
            'C' for character. 
 
89
[form] column format. 
 
90
            Display format associated to the column. 
 
91
            The format is defined like in standard FORTRAN.
 
92
[label] column label. Character string (up to 16 characters)
 
93
            provided by the use when the column is created. 
 
94
            Valid characters are letters, digits and the underscore 
 
95
            symbol '\_'. 
 
96
            In the current version labels are NOT case independent.
 
97
[tid] table identifier. It is an integer number provided
 
98
            by the system when the table is created or opened.
 
99
[unit] column unit. Character string (up to 16 characters)
 
100
            to define the units of the column.
 
101
 
 
102
------------------------------------------------------------*/
 
103
 
 
104
#include <midas_def.h>          /* ANSI-C Prototyping           */
 
105
#include <computer.h>
 
106
#include <tblsys.h>             /* Table System parameters      */
 
107
#include <tbldef.h>             /* Symbols used for Tables      */
 
108
#include <tblerr.h>             /* List of Table Errors         */
 
109
 
 
110
#include <atype.h>              /* Character classification     */
 
111
#include <macrogen.h>           /* Classical macros             */
 
112
 
 
113
#include <stdlib.h>             /* Classical macros             */
 
114
 
 
115
 
 
116
 
 
117
static int dunit;               /* Not yet used */
 
118
 
 
119
 
 
120
#define SELW    sizeof(int)     /* Length of Selection Column   */
 
121
 
 
122
char    *osmmget(), *osmmexp();
 
123
        
 
124
/*
 
125
 
 
126
*/
 
127
 
 
128
/*===================================================================
 
129
 *              Private Routines
 
130
 *===================================================================*/
 
131
#ifdef __STDC__
 
132
static int strloc(char *str, char c)
 
133
#else
 
134
static int strloc(str, c)
 
135
/*+++++++
 
136
.PURPOSE Locate the first occurence of character `c'
 
137
.RETURNS Index of `c' in str; length of str if `c' not found.
 
138
---------*/
 
139
        char *str;      /* IN: string to scan   */
 
140
        char c;         /* IN: char to locate   */
 
141
#endif
 
142
{
 
143
        register char *p;
 
144
 
 
145
  for (p=str; *p; p++)
 
146
        if (*p == c)    break;
 
147
  return(p-str);
 
148
}
 
149
 
 
150
/*
 
151
 
 
152
*/
 
153
 
 
154
#ifdef __STDC__
 
155
static int find_space (TABLE *tp, int align, int bytes)
 
156
#else
 
157
static int find_space (tp, align, bytes)
 
158
 
 
159
/*+++++++
 
160
.PURPOSE Find an offset where a new column can be added
 
161
.RETURNS Where it can be added.
 
162
.METHOD  A template record is filled with x for used parts, zeroes
 
163
        for empty parts. It is then scanned for a suitable position.
 
164
---------*/
 
165
 
 
166
TABLE   *tp;    /* IN: Table Concerned  */
 
167
int     align;  /* IN: Alignment requirement    */
 
168
int     bytes;  /* IN: Bytes required   */
 
169
#endif
 
170
 
 
171
{
 
172
static char *record;
 
173
char *ptr;
 
174
 
 
175
int     lim, totbytes;
 
176
register int  ir, jr;
 
177
static int alloc_size=0;
 
178
 
 
179
 
 
180
 
 
181
totbytes = tp->reclen;
 
182
if (alloc_size < totbytes)
 
183
   {
 
184
   if (alloc_size > 0) free(record);
 
185
   alloc_size = totbytes;
 
186
   ptr = record = (char *) malloc((size_t) alloc_size);
 
187
   for (ir=0; ir<4; ir++) *ptr++ = 'x';         /* The Selection Column */
 
188
   }
 
189
 
 
190
memset ((void *) (record+4),0,(size_t) (totbytes-4));
 
191
 
 
192
for (ir=0; ir<tp->cols; ir++)   
 
193
   memset((void *)(record + tp->offset[ir]),'x',(size_t)tp->bytes[ir]);
 
194
  
 
195
if (align == 1)
 
196
   {
 
197
   for (ir=4; ir<totbytes; ir++)                /* 1st 4 bytes always set... */
 
198
      {
 
199
      if (record[ir]) continue;
 
200
 
 
201
      lim = ir + bytes;
 
202
      if (lim > totbytes) lim = totbytes;
 
203
   
 
204
      for (jr=ir; (jr<lim) && (record[jr]==0); jr++) ;
 
205
      if (jr == lim) break;
 
206
      ir = jr;
 
207
      }
 
208
   }
 
209
 
 
210
else
 
211
   {
 
212
   for (ir=4; ir<totbytes; ir++) 
 
213
      {
 
214
      if (record[ir]) continue;
 
215
      if (ir%align) continue;
 
216
 
 
217
      lim = ir + bytes;
 
218
      if (lim > totbytes) lim = totbytes;
 
219
   
 
220
      for (jr=ir; (jr<lim) && (record[jr]==0); jr++) ;
 
221
      if (jr == lim) break;
 
222
      ir = jr;
 
223
      }
 
224
   }
 
225
 
 
226
  
 
227
return(ir);
 
228
}
 
229
/*
 
230
 
 
231
*/
 
232
 
 
233
/*===================================================================
 
234
 *              Public Routines
 
235
 *===================================================================*/
 
236
 
 
237
int TCCDEL(tid, column, ncol)
 
238
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
239
.PURPOSE Delete column in a  table
 
240
.RETURNS status
 
241
.REMARKS This implementation FORCES the table version to TBL_VERSION.
 
242
.METHOD  Just modify Descriptors.
 
243
-------------------------------------------------------------*/
 
244
int     tid;                    /* IN: table id number          */
 
245
int     column;                 /* IN: column number            */
 
246
int     *ncol;                  /* OUT:actual number of columns */
 
247
 
 
248
{
 
249
TABLE   *tp;
 
250
 
 
251
int     status, i, i1, lenl, lenf, got;
 
252
 
 
253
char    buf[TBL_DESLAB+1];
 
254
 
 
255
 
 
256
                                                /* checks arguments     */
 
257
 
 
258
 
 
259
tp = TBL_ptr(tid);
 
260
if ((status = CheckTable(tp)))
 
261
   return(TBL_errs(tid, status,0));
 
262
 
 
263
if ((status = CheckTrueColumn(tp, column)))
 
264
   return(TBL_errs(tid, status, column));
 
265
 
 
266
 
 
267
/* Force New Version    */
 
268
 
 
269
if (tp->version == 0)   tp->version = TBL_VERSION;
 
270
  
 
271
 
 
272
/* Modifs in Memory     */
 
273
 
 
274
lenl = 1+TBL_LABLEN; 
 
275
lenf = 1+TBL_FORLEN; 
 
276
 
 
277
i1 = column - 1;
 
278
for (i=column; i<tp->cols; i++) 
 
279
   {
 
280
   tp->dtypes[i1] = tp->dtypes[i];
 
281
   tp->bytes[i1]  = tp->bytes[i];
 
282
   tp->offset[i1] = tp->offset[i];
 
283
   tp->abytes[i1] = tp->abytes[i];
 
284
   oscopy (tp->label+(i1*lenl),tp->label+(i*lenl),lenl);
 
285
   oscopy (tp->format+(i1*lenf),tp->format+(i*lenf),lenf);
 
286
   i1 ++;
 
287
   }
 
288
  
 
289
/* Modify sorting & ref column  */
 
290
 
 
291
if (tp->scol == column) 
 
292
   tp->scol = 0;
 
293
else if (tp->scol > column)
 
294
   tp->scol -= 1;
 
295
 
 
296
if (tp->kcol == column) 
 
297
   tp->kcol = 0;
 
298
else if (tp->kcol > column)
 
299
   tp->kcol -= 1;
 
300
 
 
301
*ncol = tp->cols - 1;
 
302
 
 
303
if (tp->tflags & TBL__READONLY)
 
304
   {
 
305
   tp->cols --;
 
306
   return(status);
 
307
   }
 
308
  
 
309
/* Update Descriptors   */
 
310
 
 
311
dunit = -1;
 
312
for (i=column; i<tp->cols; i++) 
 
313
   {
 
314
   if ((status = SCDGETC(tp->imno,TBL_Dlab(i+1),1,TBL_DESLAB,&got,buf)))
 
315
      goto error;
 
316
   if ((status = SCDWRC(tp->imno,TBL_Dlab(i),1,buf,1,got,&dunit)))
 
317
      goto error;
 
318
  }
 
319
 
 
320
/* finally delete last descriptor, and update table information */
 
321
 
 
322
if ((status = SCDDEL(tp->imno,TBL_Dlab(tp->cols)))) goto error;
 
323
 
 
324
tp->dtypes[--tp->cols] = 0;
 
325
tp->offset[tp->cols] = 0;
 
326
 
 
327
if ((status = SCDWRI(tp->imno,TBL_Ddtypes,tp->dtypes,1,tp->colitems,&dunit)))
 
328
   goto error;
 
329
if ((status = SCDWRI(tp->imno,TBL_Doffset,tp->offset,1,tp->colitems,&dunit)))
 
330
   goto error;
 
331
if ((status = SCDWRI(tp->imno,TBL_Dmain, &tp->acols,1,TBL_Dmain_SIZE,&dunit)))
 
332
   goto error;
 
333
 
 
334
return(status);
 
335
 
 
336
 
 
337
error:                                  /* error in SC routines */
 
338
TBL_errs(tid, status, 0);
 
339
return (status);
 
340
}
 
341
/*
 
342
 
 
343
*/
 
344
 
 
345
int TCCINI(tid, dtype, alen, form, unit, label, column)
 
346
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
347
.PURPOSE Initializes table column. Elements in the column are
 
348
        initialized as undefined (null values).
 
349
.METHOD  Check if column has been already  defined,
 
350
        otherwise add the new column descriptors.
 
351
        
 
352
        The routine provides an overflow mechanism when the
 
353
        new column exceeds the allocated space. 
 
354
.RETURNS Status 
 
355
------------------------------------------------------------------*/
 
356
int     tid;            /* IN: table id number          */
 
357
int     dtype;          /* IN: column data type (Midas) */
 
358
int     alen;           /* IN: no. of array items       */
 
359
char    *form;          /* IN: column form              */
 
360
char    *unit;          /* IN: column unit              */
 
361
char    *label;         /* IN: column label             */
 
362
int     *column;        /* OUT:column number            */
 
363
 
 
364
{
 
365
TABLE   *tp;    
 
366
 
 
367
int     status, align, where;
 
368
int     ttype, nbytes, new_cols, i, j ,maxrows, mapped_rows, incr;
 
369
 
 
370
char    buf[TBL_DESLAB+1];
 
371
char    *x, *p;
 
372
char    *chptr;
 
373
char    check[TBL_LABLEN+4];            /* LABLEN .ge. UNILEN, FORLEN */
 
374
 
 
375
 
 
376
 
 
377
tp = TBL_ptr(tid);
 
378
if ((status = CheckTable(tp))   )
 
379
   return(TBL_errs(tid, status, 0));
 
380
 
 
381
if (tp->version == 0)
 
382
   tp->version = TBL_VERSION;           /* Force New Version */
 
383
 
 
384
 
 
385
/* check if column overflow */ 
 
386
 
 
387
if (tp->cols >= tp->colitems) 
 
388
   {
 
389
   i = tp->colitems;
 
390
   tp->colitems = tp->cols + 4;
 
391
 
 
392
   tp->dtypes = (int *)osmmexp((char *)tp->dtypes,2*sizeof(int)*tp->colitems);
 
393
   tp->offset = tp->dtypes + tp->colitems;
 
394
   oscopy ((char *)tp->offset, (char *)(tp->dtypes + i), i*sizeof(int));
 
395
 
 
396
   tp->bytes = (int *)osmmexp((char *)tp->bytes,2*sizeof(int)*tp->colitems);
 
397
   tp->abytes = tp->bytes + tp->colitems;
 
398
   oscopy ((char *)tp->abytes,(char *)(tp->bytes + i),i*sizeof(int));
 
399
   for (j=i; j<tp->colitems; j++)
 
400
      {
 
401
      tp->dtypes[j] = tp->offset[j] = tp->bytes[j] = tp->abytes[j] = 0;
 
402
      }
 
403
   tp->label = osmmexp(tp->label,(2+TBL_LABLEN+TBL_FORLEN)*tp->colitems);
 
404
   tp->format = tp->label + tp->colitems*(1+TBL_LABLEN);
 
405
   oscopy (tp->format, tp->label + i*(1+TBL_LABLEN), i*(1+TBL_FORLEN));
 
406
   }
 
407
 
 
408
                                        /* check type of column */
 
409
if ((status = TBL_TYPCHK(dtype,alen,&ttype)))
 
410
   return(status);
 
411
                                        /* check column label */
 
412
j = (int) strlen(label);
 
413
i = TBL_LABLEN;
 
414
if (*label != ':') i --;                /* without ':' => 1 char. less */
 
415
 
 
416
if (j > i)
 
417
   {                                    /* truncate if necessary */
 
418
   (void) strncpy(check,label,i);
 
419
   check[i] = '\0';
 
420
   chptr = check;
 
421
   (void) SCTPUT("(I/W) - column label truncated..");
 
422
   }
 
423
else
 
424
   chptr = label;
 
425
 
 
426
p = buf;
 
427
if ((status = TBL_LABCHK(chptr,p)))
 
428
   return(status);
 
429
 
 
430
                                        /* Check Unit           */
 
431
j = (int) strlen(unit);
 
432
if (j > TBL_UNILEN)
 
433
   {                                    /* truncate if necessary */
 
434
   (void) strncpy(check,unit,TBL_UNILEN);
 
435
   check[TBL_UNILEN] = '\0';
 
436
   chptr = check;
 
437
   (void) SCTPUT("(I/W) - column unit truncated..");
 
438
   }
 
439
else
 
440
   chptr = label;
 
441
 
 
442
p += TBL_LABLEN;
 
443
if ((status = TBL_UNICHK(unit,p)))
 
444
   return(status);
 
445
 
 
446
                                        /* check format         */
 
447
p += TBL_UNILEN;
 
448
if ((status = TBL_FMTCHK(form, ttype, p)))
 
449
   return(status);
 
450
 
 
451
 
 
452
/* Adjust parameters    */
 
453
 
 
454
nbytes  = TBL_ElementSize(ttype);
 
455
                                        /**** NEW: Align Offset */
 
456
align = (tp->swise == F_RECORD ? nbytes : 1);
 
457
nbytes *= TBL_Items(ttype);
 
458
where = find_space(tp,align,nbytes);
 
459
 
 
460
*column = tp->cols + 1;
 
461
                                        /* allocate column(s) if overflow */
 
462
new_cols = (where + nbytes + 3)/4 - 1;
 
463
if (new_cols > tp->acols) 
 
464
   {
 
465
   if ((status = TBL_ALLOCOL(tid, new_cols))) return(status);
 
466
   tp = TBL_ptr(tid);
 
467
  }
 
468
 
 
469
/* force NULL terminated string,  write descriptor      */
 
470
 
 
471
buf[TBL_DESLAB] = '\0';
 
472
if ((status = SCDWRC(tp->imno,TBL_Dlab(*column),1,buf,1,TBL_DESLAB,&dunit)))
 
473
   return (TBL_errf(status, "table %s", tp->phname));
 
474
  
 
475
/* Update Header Info   */
 
476
 
 
477
i = tp->cols;
 
478
tp->dtypes[i] = ttype;
 
479
tp->bytes[i]  = nbytes;
 
480
tp->offset[i] = where;
 
481
tp->abytes[i] = -1;                             /* uninitialized...*/
 
482
tp->label [i*(1+TBL_LABLEN)] = '\0';
 
483
tp->format[i*(1+TBL_FORLEN)] = '\0';
 
484
 
 
485
tp->cols = *column;
 
486
 
 
487
 
 
488
/* Initialize to NULL values    */
 
489
 
 
490
incr = TBL_offset (tp, 2, *column) - TBL_offset (tp, 1, *column);
 
491
maxrows = TBL_EIO_LIMIT / incr;
 
492
maxrows = MAX (maxrows, 1);
 
493
 
 
494
for (i=0; i<tp->arows; i+=maxrows)
 
495
   {
 
496
   mapped_rows = MIN ((tp->arows - i), maxrows);
 
497
   if_not (x = TBL_RDF (tp, TBL_offset(tp, i+1, *column),incr*mapped_rows, 1))
 
498
      return(TBL_RDst()); 
 
499
   TBL_toNULL (ttype, x);                       /* NULL first element   */
 
500
   for (p = x + incr; --mapped_rows > 0; p += incr) 
 
501
      oscopy(p ,x, nbytes); 
 
502
   }
 
503
 
 
504
return (status);
 
505
}
 
506
/*
 
507
 
 
508
*/
 
509
 
 
510
int TCCMAP(tid, col, address)
 
511
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
512
.PURPOSE
 
513
        Return the address of the column in the table.
 
514
.METHOD 
 
515
        Finds the position of the physical column and get address
 
516
        via the virtual memory mechanism.
 
517
 
 
518
        Note: This routine only works on tables stored by columns
 
519
        (transposed format, parameter F_TRANS in TCTINI).
 
520
.RETURNS
 
521
        status
 
522
------------------------------------------------------------------*/
 
523
        int     tid;            /* IN: table id number          */
 
524
        int     col;            /* IN: column number            */
 
525
        char    **address;      /* OUT:column address           */
 
526
{
 
527
        TABLE   *tp;
 
528
        int     status;
 
529
        int     ic, len;
 
530
 
 
531
  tp = TBL_ptr(tid);
 
532
  if ((status = CheckTable(tp)))  return(TBL_errs(tid, status, 0));
 
533
  if ((status = CheckColumn(tp, col)))  return(TBL_errs(tid, status, col));
 
534
 
 
535
  if (tp->swise != F_TRANS)     
 
536
        return (TBL_errf(ERR_TBLMAP, "Can't MAP column on RECORD table: %s",
 
537
                tp->phname));
 
538
  else {
 
539
        ic  = TBL_offset(tp, 1, col);
 
540
        len = TBL_offset(tp, tp->arows, col) -ic + ColumnWidth(tp, col);
 
541
        if_not(*address = TBL_RDF (tp, ic, len, TBL__MAPPED))
 
542
                return (TBL_RDst());
 
543
        if (col == 0)   tp->selected = -1;      /* Unknown */
 
544
  }
 
545
 
 
546
  return (status);
 
547
}
 
548
 
 
549
int TCCPAM(tid, col, starting_row, asked_rows, mapped_rows, address)
 
550
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
551
.PURPOSE Map a part of a table, namely up to asked_row from row # starting_row 
 
552
.REMARKS A value of zero for asked_rows provide some default.
 
553
.RETURNS status
 
554
------------------------------------------------------------------*/
 
555
        int     tid;            /* IN: table id number          */
 
556
        int     col;            /* IN: column number            */
 
557
        int     starting_row;   /* IN: First row to map (from 1)*/
 
558
        int     asked_rows;     /* IN: Number of rows to map,
 
559
                                   0 to map as many rows as possible    */
 
560
        int     *mapped_rows;   /* OUT: Number of rows mapped   */
 
561
        char    **address;      /* OUT: address of mapped first row */
 
562
{
 
563
        TABLE   *tp;
 
564
        int     status;
 
565
        int     i,ic, len;
 
566
         static unsigned char bit_mask[8] = { 0x80, 0x40, 0x20, 0x10,
 
567
                0x08, 0x04, 0x02, 0x01};
 
568
 
 
569
 
 
570
  tp = TBL_ptr(tid);
 
571
  *mapped_rows = 0;             /* Default return */
 
572
  if ((status = CheckTable(tp)))                return(TBL_errs(tid, status, 0));
 
573
 
 
574
  if (tp->swise != F_TRANS)     
 
575
        return (TBL_errf(ERR_TBLMAP, "Can't MAP column on RECORD table: %s",
 
576
                tp->phname));
 
577
 
 
578
  if ((status = CheckColumn(tp, col)))  return(TBL_errs(tid, status, col));
 
579
  if ((status = CheckRow(tp, starting_row)))
 
580
        return(TBL_errs(tid, status, starting_row));
 
581
 
 
582
  if (asked_rows <= 0) {        /* Compute Default number of Rows */
 
583
        len = ColumnWidth(tp, col);
 
584
        asked_rows = TBL_EIO_LIMIT/len/2;
 
585
        if (asked_rows < 1)     asked_rows = 1;
 
586
  }
 
587
 
 
588
                                /* Check the number of rows     */
 
589
  if ((starting_row + asked_rows) > tp->arows)
 
590
        asked_rows = 1 + tp->arows - starting_row;
 
591
 
 
592
  if (col == 0 && tp->usname != '\0') {
 
593
      *address = osmmget(asked_rows * sizeof(int));
 
594
      for (i=starting_row; i < starting_row+asked_rows; i++) {
 
595
           ic = (tp->vsel[i>>3] & bit_mask[i&7]);
 
596
           *(int *) (*address + (i-starting_row) *sizeof(int)) = (ic != 0);
 
597
           } 
 
598
      }
 
599
  else {                                /* Do now the mapping           */
 
600
      len = ColumnWidth(tp, col) * asked_rows;
 
601
      ic  = TBL_offset(tp, starting_row, col);
 
602
      if_not(*address = TBL_RDF (tp, ic, len, TBL__MAPPED))
 
603
      return (TBL_RDst());
 
604
      }                 
 
605
  
 
606
                                /* Write output parameters      */
 
607
  *mapped_rows = asked_rows;
 
608
  if (col == 0) tp->selected = -1;      /* Unknown */
 
609
 
 
610
  return (status);
 
611
}
 
612
 
 
613
int TCCSEL(tid, text, max_cols, cols, flags, found_cols)
 
614
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
615
.PURPOSE Searchs a set of columns column by references (their name).
 
616
.METHOD  A set of columns has the general syntax 
 
617
                col[(flag)][,col]...
 
618
                
 
619
        where "col" may be #number or :label.
 
620
        The Sequence column may be designated by # or :
 
621
.RETURNS  Status
 
622
-------------------------------------------------------------*/
 
623
int     tid;            /* IN : table id        */
 
624
char    *text;          /* IN : textual designation */
 
625
int     max_cols;       /* IN: Size of cols & flags arrays */
 
626
int     *cols;          /* OUT: column numbers  */
 
627
int     *flags;         /* OUT: column flags (in brackets) */
 
628
int     *found_cols;    /* OUT: How many columns were found */
 
629
 
 
630
{     
 
631
int    mm,status;
 
632
int    k, j, ic, ib, id;
 
633
int    temp,dummy;
 
634
 
 
635
char   *p, b, c, d;
 
636
 
 
637
 
 
638
 
 
639
 
 
640
status = ERR_NORMAL;
 
641
if (*text == '\0') 
 
642
   {
 
643
   status = TCIGET(tid,found_cols,&dummy,&dummy,&dummy,&dummy);
 
644
   for (j=1; j <= *found_cols; j++) cols[j-1] = j;
 
645
   return(status);
 
646
   }
 
647
 
 
648
                                /* Tokenize from commas, then from brackets */
 
649
for (j=0, p=text; (*p) && (j < max_cols) && (status == ERR_NORMAL); j++) 
 
650
   {
 
651
   ic = strloc (p, ','); c = p[ic]; p[ic] = '\0';
 
652
   id = strloc(p,'.'); 
 
653
   if ( p[id] && p[id+1] == '.')  
 
654
      { 
 
655
      d = p[id]; 
 
656
      p[id] = '\0';
 
657
      }
 
658
   else d = '\0';
 
659
 
 
660
   ib = strloc (p, '('); b = p[ib]; p[ib] = '\0';
 
661
   flags[j] = 1;                                /* Default Flag */
 
662
   if ((status = TCCSER (tid, p, &cols[j]))) continue;   /* Get Label*/
 
663
 
 
664
   if (cols[j] < 0) 
 
665
      {
 
666
      status = ERR_TBLCOL;
 
667
      TBL_errf(status, "unknown column %s", p);
 
668
      }
 
669
 
 
670
   if (b) 
 
671
      {
 
672
      p += ib; ic -= ib;
 
673
      *p = b;    p++; ic--;
 
674
      flags[j] = atoi(p);
 
675
      if (flags[j] == 0) flags[j] = (*p == '-' ? -1 : 1);
 
676
      }
 
677
 
 
678
   if (d) 
 
679
      {                                 /* column interval: #m..n */ 
 
680
      p += id+1; 
 
681
      *p = '#';
 
682
      ic -= ib+1;
 
683
      if ((status = TCCSER (tid, p, &temp))) continue;
 
684
 
 
685
      if (temp < 0) {
 
686
         status = ERR_TBLCOL;
 
687
         TBL_errf(status,"unknown column %s",p);
 
688
         }
 
689
 
 
690
      temp = temp-cols[j];              /* no. of cols in interval */
 
691
      mm = max_cols - j - 1;            /* no. of cols still available */
 
692
/*
 
693
printf("temp = %d, cols[%d] = %d, mm = %d\n",temp,j,cols[j],mm);
 
694
*/
 
695
      if (temp > mm) temp = mm;
 
696
      for (k=1; k<= temp; k++) *(cols+j+k) = *(cols+j)+k;     
 
697
 
 
698
      j = j + temp;                     /* last filled column */
 
699
      *p = d;
 
700
      }    
 
701
 
 
702
   p += ic;  *p = c;
 
703
   if (c) p++;
 
704
   }
 
705
 
 
706
                                        /* Check if not too many cols */
 
707
if ( (j >= max_cols) && (isgraph(*p)) && (status == ERR_NORMAL) )
 
708
   TBL_errf (-1, "list truncated to %d items: %s", max_cols, text);
 
709
 
 
710
  
 
711
*found_cols = j;
 
712
return (status);
 
713
}
 
714
 
 
715
 
 
716
 
 
717
int TCCSER(tid, colref, column)
 
718
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
719
.PURPOSE Searchs column by reference (its name).
 
720
        The column may be designated as #number or :name or name 
 
721
        The Sequence column may be designated by # or :
 
722
.METHOD Sequential search for the column label.
 
723
        The routine returns the column number as the last
 
724
        argument or -1 if the column is not found.
 
725
.RETURNS Status
 
726
-------------------------------------------------------------*/
 
727
int     tid;            /* IN : table id        */
 
728
char    *colref;        /* IN : column reference */
 
729
int     *column;        /* OUT: column number   */
 
730
 
 
731
{     
 
732
TABLE   *tp;    
 
733
int     status, i;
 
734
 
 
735
char    *p, *q;
 
736
char   *chptr, check[TBL_LABLEN+4];
 
737
 
 
738
 
 
739
 
 
740
 
 
741
tp = TBL_ptr(tid);
 
742
if ((status = CheckTable(tp)))
 
743
   return(TBL_errs(tid, status, 0));
 
744
 
 
745
                                        /* init variables */
 
746
p = colref;
 
747
*column = -1;
 
748
 
 
749
switch (*p)
 
750
   {                  
 
751
   case '#' :                           /* column by number */
 
752
        p++;
 
753
        for (i = 0; isdigit(p[i]); i++) ;
 
754
        if (isalpha(p[i]))
 
755
           {
 
756
           i = -1;
 
757
           status = ERR_TBLCOL;
 
758
           TBL_errf(status, "invalid number #'%s', table: %s", p, 
 
759
                        tp->phname);
 
760
           }
 
761
        else    
 
762
           {
 
763
           i = atoi(p);
 
764
           if ((i > tp->cols) || (i < 0)) 
 
765
              {
 
766
              status = ERR_TBLCOL;
 
767
              TBL_errs(tid, status, i);
 
768
              }
 
769
           else 
 
770
              *column = i;
 
771
           }
 
772
        break;
 
773
 
 
774
   case 's' : case 'S' :               /* column sequence */
 
775
        q = p + 1;                     /* check at least for SEQ */
 
776
        if ((*q != 'e') && (*q != 'E')) break; 
 
777
        q++;
 
778
        if ((*q == 'q') || (*q == 'Q')) *column = 0;
 
779
        break;                          
 
780
 
 
781
   case ':' :                           /* column by label */
 
782
        p++;
 
783
 
 
784
   default :                            /* assume it's name */
 
785
        if (isspace(*p) || (*p == '\0'))
 
786
           *column = 0;                 /* use sequence no. */
 
787
        else
 
788
           {
 
789
           i = TBL_LABLEN - 1;                  /* :name is checked... */
 
790
           if ((int) strlen(p) > i)
 
791
              {                                 /* truncate if necessary */
 
792
              (void) strncpy(check,p,i);
 
793
              check[i] = '\0';
 
794
              chptr = check;
 
795
              }
 
796
           else
 
797
              {
 
798
              chptr = p;
 
799
              }
 
800
 
 
801
           status = TCLSER (tid, chptr, column);        /* without : */
 
802
           }
 
803
        break;
 
804
 
 
805
 
 
806
 
 
807
  }
 
808
 
 
809
  return (status);
 
810
}
 
811
/*
 
812
 
 
813
*/
 
814
 
 
815
/*====================================================================
 
816
 *              Internal Routines for Sort
 
817
 *====================================================================*/
 
818
 
 
819
/* When several sort parameters are given, the address of the other
 
820
   parameters to test are computed from the address of the first parameter
 
821
   Let @  be the address of line i of the first parameter,
 
822
       @0    the address of line 1 of the first parameter
 
823
   the address @n of the 2nd parameter of line i can be computed via
 
824
   @n = (@-@0)*a/l0 + Cte where   a = difference of widths
 
825
                                  l0= width of first parameter column
 
826
 
 
827
   The parameters are stored as         Cte: in sort_offset
 
828
                                        a  : in sort_factor
 
829
                                        l0 : in sort_width
 
830
  */
 
831
 
 
832
 
 
833
typedef int     (*FUNCTION)();  /* Just to simplify the declarations....*/
 
834
 
 
835
static char     *sort_astart;   /* Origin of 1st sort parameter         */
 
836
static int      sort_width;     /* Width of first column to be sorted   */
 
837
static int      sort_order;     /* 1 for ascending, -1 for descending   */
 
838
static int      sort_len;       /* Number of items in Table             */
 
839
static FUNCTION diff;
 
840
                                /* Several parameters used for sorting  */
 
841
static FUNCTION sort_list[SORT_MAX];
 
842
static int      sort_array[SORT_MAX],  sort_items[SORT_MAX];
 
843
static int      sort_offset[SORT_MAX], sort_factor[SORT_MAX];
 
844
static int      sort_keys = 0;
 
845
 
 
846
/*
 
847
 
 
848
*/
 
849
static int diff_m(s1, s2)
 
850
/*++++++++++++++++
 
851
.PURPOSE Compute differences when several keys are used.
 
852
.RETURNS Negative value if s1<s2, positive value if s1>s2, null if s1=s2)
 
853
-----------------*/
 
854
        char *s1, *s2;
 
855
{
 
856
        int     result, i;
 
857
        FUNCTION what_to_do;
 
858
 
 
859
  sort_order = sort_array[0];
 
860
  sort_len   = sort_items[0];
 
861
  what_to_do = sort_list[0];
 
862
 
 
863
  result = (*what_to_do)(s1, s2);
 
864
 
 
865
  for (i = 1; (i < sort_keys) && (result == 0); i++) {
 
866
        sort_order = sort_array[i];
 
867
        sort_len   = sort_items[i];
 
868
        what_to_do = sort_list[i];
 
869
        result = (*what_to_do)(
 
870
                s1+sort_offset[i] + sort_factor[i]*(s1-sort_astart)/sort_width,
 
871
                s2+sort_offset[i] + sort_factor[i]*(s2-sort_astart)/sort_width);
 
872
   }
 
873
   return(result);
 
874
}
 
875
 
 
876
static int diffi1 (s1, s2)
 
877
/*++++++++++++++++
 
878
.PURPOSE Compute difference between two char strings
 
879
.RETURNS s1-s2 (negative value if s1<s2, positive if s1>s2, null if s1=s2)
 
880
.REMARKS NULL values always at end
 
881
-----------------*/
 
882
        char *s1, *s2;
 
883
{
 
884
        int     i;
 
885
        
 
886
   for (i = sort_len; --i >= 0; s1++, s2++){
 
887
        if (*s1 == *s2)         continue;
 
888
        if (*s1 == NULL1)       return(1);      /* NULL value at end */
 
889
        if (*s2 == NULL1)       return(-1);     /* NULL value at end */
 
890
        if (*s1 > *s2)  return (sort_order);
 
891
        if (*s1 < *s2)  return (-sort_order);
 
892
   }
 
893
   return(0);
 
894
}
 
895
static int diffi2 (s1, s2)
 
896
/*++++++++++++++++
 
897
.PURPOSE Compute difference between two short arrays
 
898
.RETURNS s1-s2 (negative value if s1<s2, positive if s1>s2, null if s1=s2)
 
899
.REMARKS NULL values always at end
 
900
-----------------*/
 
901
        short *s1, *s2;
 
902
{
 
903
        int     i;
 
904
        
 
905
   for (i = sort_len; --i >= 0; s1++, s2++){
 
906
        if (*s1 == *s2)         continue;
 
907
        if (*s1 == NULL2)       return(1);      /* NULL value at end */
 
908
        if (*s2 == NULL2)       return(-1);     /* NULL value at end */
 
909
        if (*s1 > *s2)  return (sort_order);
 
910
        if (*s1 < *s2)  return (-sort_order);
 
911
   }
 
912
   return(0);
 
913
}
 
914
static int diffi4 (s1, s2)
 
915
/*++++++++++++++++
 
916
.PURPOSE Compute difference between two int arrays
 
917
.RETURNS s1-s2 (negative value if s1<s2, positive if s1>s2, null if s1=s2)
 
918
.REMARKS NULL values always at end
 
919
-----------------*/
 
920
        int *s1, *s2;
 
921
{
 
922
        int     i;
 
923
        
 
924
   for (i = sort_len; --i >= 0; s1++, s2++){
 
925
        if (*s1 == *s2)         continue;
 
926
        if (*s1 == NULL4)       return(1);      /* NULL value at end */
 
927
        if (*s2 == NULL4)       return(-1);     /* NULL value at end */
 
928
        if (*s1 > *s2)  return (sort_order);
 
929
        if (*s1 < *s2)  return (-sort_order);
 
930
   }
 
931
   return(0);
 
932
}
 
933
 
 
934
static int diffa1 (s1, s2)
 
935
/*++++++++++++++++
 
936
.PURPOSE Compute difference between two unsigned chars
 
937
.RETURNS s1-s2 (negative value if s1<s2, positive if s1>s2, null if s1=s2)
 
938
.REMARKS No NULL values...
 
939
-----------------*/
 
940
        unsigned char *s1, *s2;
 
941
{
 
942
        int     i;
 
943
        
 
944
   for (i = sort_len; --i >= 0; s1++, s2++){
 
945
        if (*s1 > *s2)  return (sort_order);
 
946
        if (*s1 < *s2)  return (-sort_order);
 
947
   }
 
948
   return(0);
 
949
}
 
950
static int diffa2 (s1, s2)
 
951
/*++++++++++++++++
 
952
.PURPOSE Compute difference between two unsigned shorts
 
953
.RETURNS s1-s2 (negative value if s1<s2, positive if s1>s2, null if s1=s2)
 
954
-----------------*/
 
955
        unsigned short *s1, *s2;
 
956
{
 
957
        int     i;
 
958
        
 
959
   for (i = sort_len; --i >= 0; s1++, s2++){
 
960
        if (*s1 > *s2)  return (sort_order);
 
961
        if (*s1 < *s2)  return (-sort_order);
 
962
   }
 
963
   return(0);
 
964
}
 
965
static int diffa4 (s1, s2)
 
966
/*++++++++++++++++
 
967
.PURPOSE Compute difference between two unsigned ints
 
968
.RETURNS s1-s2 (negative value if s1<s2, positive if s1>s2, null if s1=s2)
 
969
-----------------*/
 
970
        unsigned int *s1, *s2;
 
971
{
 
972
        int     i;
 
973
        
 
974
   for (i = sort_len; --i >= 0; s1++, s2++){
 
975
        if (*s1 > *s2)  return (sort_order);
 
976
        if (*s1 < *s2)  return (-sort_order);
 
977
   }
 
978
   return(0);
 
979
}
 
980
 
 
981
static int diffr4 (s1, s2)
 
982
/*++++++++++++++++
 
983
.PURPOSE Compute difference between two floats
 
984
.RETURNS s1-s2 (negative value if s1<s2, positive if s1>s2, null if s1=s2)
 
985
.REMARKS NULL values always at end
 
986
-----------------*/
 
987
        float *s1, *s2;
 
988
{
 
989
        int     i;
 
990
        
 
991
   for (i = sort_len; --i >= 0; s1++, s2++){
 
992
        if (*s1 == *s2)         continue;
 
993
        if (isNULLF(s1))        return(1);      /* NULL value at end */
 
994
        if (isNULLF(s2))        return(-1);     /* NULL value at end */
 
995
        if (*s1 > *s2)  return (sort_order);
 
996
        if (*s1 < *s2)  return (-sort_order);
 
997
   }
 
998
   return(0);
 
999
}
 
1000
 
 
1001
static int diffr8 (s1, s2)
 
1002
/*++++++++++++++++
 
1003
.PURPOSE Compute difference between two doubles
 
1004
.RETURNS s1-s2 (negative value if s1<s2, positive if s1>s2, null if s1=s2)
 
1005
.REMARKS NULL values always at end
 
1006
-----------------*/
 
1007
        double *s1, *s2;
 
1008
{
 
1009
        int     i;
 
1010
        
 
1011
   for (i = sort_len; --i >= 0; s1++, s2++){
 
1012
        if (*s1 == *s2)         continue;
 
1013
        if (isNULLD(s1))        return(1);      /* NULL value at end */
 
1014
        if (isNULLD(s2))        return(-1);     /* NULL value at end */
 
1015
        if (*s1 > *s2)  return (sort_order);
 
1016
        if (*s1 < *s2)  return (-sort_order);
 
1017
   }
 
1018
   return(0);
 
1019
}
 
1020
 
 
1021
/*===================================================================*/
 
1022
 
 
1023
static void Qsort(data, first, last)
 
1024
/*++++++++++++++++
 
1025
.PURPOSE        Quick Sort 
 
1026
.METHOD         
 
1027
                Quick sort modified with insert sort for small partitions. 
 
1028
                The routine sorts the array of pointers to actual data.
 
1029
                
 
1030
                The comparison routine is external.
 
1031
.RETURNS        ---
 
1032
-----------------*/
 
1033
        char **data;            /* MOD: The arrays of pointers to sort  */
 
1034
        int first, last;        /* IN: Indexes of first / last pointer  */
 
1035
{
 
1036
        char *px, *t;
 
1037
        int i,j;
 
1038
 
 
1039
  i = first; j = last;
 
1040
  px = data[(first+last)/2];
 
1041
  
 
1042
  do {
 
1043
        while ( (i < last ) && ((*diff)(data[i], px) < 0))      i++;
 
1044
        while ( (j > first) && ((*diff)(data[j], px) > 0))      j--;
 
1045
        if (i <= j) {
 
1046
                if (i < j)
 
1047
                        t = data[i], data[i] = data[j], data[j] = t;
 
1048
                i++; j--;
 
1049
        }
 
1050
  } while (i <= j);
 
1051
 
 
1052
  if (first < j)        Qsort (data, first, j);
 
1053
  if (i < last)         Qsort (data, i, last );
 
1054
}
 
1055
 
 
1056
int TCCSRT(tid, nc, column, sortfl)
 
1057
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1058
.PURPOSE  Sort table.
 
1059
.METHOD   Use Quick sort algorithm to sort the table data
 
1060
                in ascending (sort flag > 0) or descending 
 
1061
                (sort flag < 0) sequence.
 
1062
.RETURNS  Status
 
1063
-------------------------------------------------------------*/
 
1064
int     tid;            /* IN : table id        */
 
1065
int     nc;             /* IN : number of columns*/
 
1066
int     column[];       /* IN : column numbers  */
 
1067
int     sortfl[];       /* IN : sort flags      */
 
1068
 
 
1069
{
 
1070
TABLE   *tp;
 
1071
int     status;
 
1072
int     i, j, len, icol, ic, dtype, incr, mapped_bytes;
 
1073
long int  lolo;
 
1074
 
 
1075
char    **data;
 
1076
char    *x, *copy, *root[SORT_MAX];
 
1077
 
 
1078
 
 
1079
 
 
1080
tp = TBL_ptr(tid);
 
1081
if ((status = CheckTable(tp)))  return(TBL_errs(tid, status,0));
 
1082
 
 
1083
if (tp->rows <= 1)      return (status);  
 
1084
 
 
1085
data = (char **)0;
 
1086
 
 
1087
/* Check the list of sort keys  */
 
1088
 
 
1089
sort_keys = nc;
 
1090
if (sort_keys < 1) 
 
1091
   {
 
1092
   TBL_errf(-1, "value %d of SORT parameters assumed to be 1, table: %s",
 
1093
                sort_keys, tp->phname);
 
1094
   sort_keys = 1;
 
1095
   }
 
1096
 
 
1097
if (sort_keys > SORT_MAX) 
 
1098
   {
 
1099
   TBL_errf(-1, "Number %d of SORT parameters truncated to %d, table: %s",
 
1100
                sort_keys, SORT_MAX, tp->phname);
 
1101
   sort_keys = SORT_MAX;
 
1102
   }
 
1103
        
 
1104
 
 
1105
/* check column numbers */
 
1106
 
 
1107
for (i=0; i<sort_keys; i++) 
 
1108
   {
 
1109
   icol = column[i];
 
1110
   if (icol > tp->cols || icol <= 0) 
 
1111
      return (TBL_errs (ERR_TBLCOL, tid, icol));
 
1112
   }
 
1113
 
 
1114
icol = column[0];
 
1115
sort_width = ColumnWidth(tp, icol);
 
1116
 
 
1117
 
 
1118
/* All existing data will be modified   */
 
1119
 
 
1120
for (i=0,ic=0; i<tp->cols; i++) 
 
1121
   {
 
1122
   if (tp->offset[i] > tp->offset[ic])  ic = i;
 
1123
   }
 
1124
ic += 1;
 
1125
 
 
1126
if (tp->swise == F_TRANS) 
 
1127
   {
 
1128
   int offset, *perm;
 
1129
   int  *asInt;
 
1130
   short int *asShort;
 
1131
 
 
1132
   char *from;
 
1133
 
 
1134
 
 
1135
   offset = 0;
 
1136
   for (i=0; i<sort_keys;i++)
 
1137
      {
 
1138
      icol = column[i];
 
1139
      sort_offset[i] = offset;
 
1140
      mapped_bytes = ColumnWidth(tp,icol)*tp->rows;
 
1141
      offset = offset + mapped_bytes;
 
1142
      if_not (root[i] = TBL_RDF (tp, TBL_offset(tp,1,icol), mapped_bytes, 2))
 
1143
              return(TBL_RDst());
 
1144
      }
 
1145
 
 
1146
   lolo = (long int) offset;
 
1147
   copy = osmmget(lolo);
 
1148
   ic = TBL_offset (tp, 1, column[0]);
 
1149
   for (i=0; i<sort_keys; i++) 
 
1150
      {
 
1151
      icol = column[i];
 
1152
      dtype  = ColumnType (tp, icol);
 
1153
      oscopy(copy+sort_offset[i],root[i],ColumnWidth(tp,icol)*tp->rows);
 
1154
      sort_array[i] = sortfl[i];
 
1155
      sort_items[i] = TBL_Items(dtype);
 
1156
      sort_factor[i]= ColumnWidth(tp, icol) - sort_width;
 
1157
 
 
1158
      /* Choose the comparison function */  
 
1159
      switch (TBL_ElementType(dtype)) 
 
1160
         {
 
1161
         case TBL_D_I1: diff = diffi1;  break;
 
1162
         case TBL_D_I2: diff = diffi2;  break;
 
1163
         case TBL_D_I4: diff = diffi4;  break;
 
1164
         case TBL_D_A1: diff = diffa1;  break;
 
1165
         case TBL_D_A2: diff = diffa2;  break;
 
1166
         case TBL_D_A4: diff = diffa4;  break;
 
1167
         case TBL_D_R4: diff = diffr4;  break;
 
1168
         case TBL_D_R8: diff = diffr8;  break;
 
1169
         default:       diff = diffr4;
 
1170
         }
 
1171
         sort_list[i] = diff;
 
1172
      }
 
1173
  
 
1174
   /* Take Values if sort_keys == 1*/
 
1175
 
 
1176
   icol   = column[0];
 
1177
   sort_order = sort_array[0];
 
1178
   sort_len   = sort_items[0];
 
1179
   if (sort_keys > 1)   diff = diff_m;
 
1180
 
 
1181
   /* Create the array of pointers to data */
 
1182
 
 
1183
   lolo = (long int)(sizeof(char *) * tp->rows);
 
1184
   data = (char **)osmmget(lolo);
 
1185
   incr = TBL_offset (tp, 2, icol) - ic;
 
1186
   for (i=0, x = copy ; i < tp->rows; i++, x += incr) data[i] = x;
 
1187
   sort_astart = data[0];       
 
1188
 
 
1189
   /* Sort the data array       */
 
1190
   Qsort (data,0,tp->rows-1);
 
1191
 
 
1192
 
 
1193
   /* Follow the permutation    */
 
1194
   for (i = 0, perm = (int *)data; i < tp->rows; i++, perm++)
 
1195
      *perm = (data[i]-sort_astart)/sort_width;
 
1196
 
 
1197
   perm = (int *)data;
 
1198
 
 
1199
   len = SELW; incr = 0; 
 
1200
   for (j = 0; j < tp->cols; j++) 
 
1201
      {
 
1202
      len = tp->bytes[j];
 
1203
      incr= tp->offset[j]*tp->arows;
 
1204
 
 
1205
      mapped_bytes = ColumnWidth(tp,j+1)*tp->rows;
 
1206
      root[0] = TBL_RDF (tp, TBL_offset(tp,1,j+1), mapped_bytes, 1);
 
1207
      lolo = (long int) mapped_bytes;
 
1208
      copy = osmmget(lolo);
 
1209
      oscopy (copy, root[0], mapped_bytes);
 
1210
      from = copy ;     
 
1211
      x = root[0] ;     
 
1212
      asShort = (short *)from;  asInt = (int *)from;
 
1213
      for (i=0; i < tp->rows; i++, x += len) switch (len) 
 
1214
         {
 
1215
         case sizeof(char):  *x = from[perm[i]]; continue;
 
1216
         case sizeof(short): *(short *)x = asShort[perm[i]]; continue;
 
1217
         case sizeof(int):  *(int *)x  = asInt[perm[i]]; continue;
 
1218
         default: oscopy (x, from + len*perm[i], len); continue;
 
1219
         }
 
1220
      osmmfree(copy);
 
1221
      }
 
1222
   }    
 
1223
else 
 
1224
   {
 
1225
   mapped_bytes = tp->reclen * tp->rows;
 
1226
   if_not(root[0] = TBL_RDF (tp, 0, mapped_bytes, 1))   return (TBL_RDst());
 
1227
 
 
1228
   /* Copy a table to a new piece  */
 
1229
   lolo = (long int) mapped_bytes;
 
1230
   copy = osmmget (lolo);
 
1231
   oscopy (copy, root[0], mapped_bytes);
 
1232
   ic = TBL_offset (tp, 1, icol);
 
1233
 
 
1234
   for (i=0; i<sort_keys; i++) 
 
1235
      {
 
1236
      icol = column[i];
 
1237
      dtype  = ColumnType (tp, icol);
 
1238
      sort_offset[i] = TBL_offset (tp, 1, icol) - ic;
 
1239
      sort_array[i]  = sortfl[i];
 
1240
      sort_items[i]  = TBL_Items(dtype);
 
1241
      sort_factor[i] = ColumnWidth(tp, icol) - sort_width;
 
1242
 
 
1243
      /* Choose the comparison function       */
 
1244
      switch (TBL_ElementType(dtype)) 
 
1245
         {
 
1246
         case TBL_D_I1:       diff = diffi1;  break;
 
1247
         case TBL_D_I2:       diff = diffi2;  break;
 
1248
         case TBL_D_I4:       diff = diffi4;  break;
 
1249
         case TBL_D_A1:       diff = diffa1;  break;
 
1250
         case TBL_D_A2:       diff = diffa2;  break;
 
1251
         case TBL_D_A4:       diff = diffa4;  break;
 
1252
         case TBL_D_R4:       diff = diffr4;  break;
 
1253
         case TBL_D_R8:       diff = diffr8;  break;
 
1254
         default: diff = diffr4;
 
1255
         }
 
1256
      sort_list[i] = diff;
 
1257
      }
 
1258
   icol   = column[0];
 
1259
   sort_order = sort_array[0];
 
1260
   sort_len   = sort_items[0];
 
1261
   if (sort_keys > 1)    diff = diff_m;
 
1262
 
 
1263
   /* Create the array of pointers to data */
 
1264
   lolo = (long int) (sizeof(char *) * tp->rows);
 
1265
   data = (char **)osmmget(lolo);
 
1266
   incr = TBL_offset (tp, 2, icol) - ic;
 
1267
   for (i=0, x=copy + ic; i<tp->rows; i++, x += incr)  data[i] = x;
 
1268
 
 
1269
   sort_astart = data[0];
 
1270
   Qsort (data,0,tp->rows-1);
 
1271
   len = tp->reclen;
 
1272
   for (i=0, x=root[0]; i<tp->rows; i++, x += len) 
 
1273
        oscopy (x, data[i] - ic, len); 
 
1274
   osmmfree (copy);
 
1275
   }
 
1276
 
 
1277
/* update table descriptors */
 
1278
 
 
1279
tp->scol = icol;
 
1280
 
 
1281
osmmfree ((char *)data);
 
1282
return (status);
 
1283
}
 
1284
 
 
1285
int TCCUNM(tid, address)
 
1286
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1287
.PURPOSE        Unmap the part of a file that was mapped before.
 
1288
.METHOD         Identical to TCEUNM
 
1289
.RETURNS        status (-1 if address not found)
 
1290
------------------------------------------------------------------*/
 
1291
        int     tid;            /* IN: table id number          */
 
1292
        char    *address;       /* IN: column address           */
 
1293
{
 
1294
  return (TCEUNM(tid, address));
 
1295
}
 
1296