1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
|
include <ctype.h>
include "../../lib/ptkeysdef.h"
# PT_SORTNUM -- Decode the column used for the sort, compute the file
# record structure map, sort on the extracted column, reorder the
# input file and write the output file.
int procedure pt_sortnum (tp_in, tp_out, column, ascend)
pointer tp_in # input Table descriptor
pointer tp_out # output Table descriptor
char column[ARB] # column name for sort
int ascend # forward sort
int coltype, colwidth, nrecs
pointer key, colptr, colindex, recmap
int pt_colmap()
begin
# Initialize.
call pt_kyinit (key)
colptr = NULL
colindex = NULL
recmap = NULL
# Decode the sort column and map the record structure.
nrecs = pt_colmap (key, tp_in, tp_out, column, colptr, colindex,
coltype, colwidth, recmap)
# Sort the column and write the output file.
if (nrecs > 0) {
call pt_colsort (colptr, Memi[colindex], nrecs, coltype)
if (ascend == NO)
call pt_flipi (Memi[colindex], nrecs)
call pt_reorder (tp_in, tp_out, Memi[recmap], Memi[colindex], nrecs)
}
# Free space.
if (colptr != NULL)
call mfree (colptr, coltype)
if (colindex != NULL)
call mfree (colindex, TY_INT)
if (recmap != NULL)
call mfree (recmap, TY_INT)
call pt_kyfree (key)
return (nrecs)
end
define BUFSIZE 1000
# PT_COLMAP -- Decode the column to be sorted and compute the record
# structure of the file.
int procedure pt_colmap (key, tp_in, tp_out, column, colptr, colindex, coltype,
bufwidth, recmap)
pointer key # pointer to the database structure
int tp_in # the input text file descriptor
int tp_out # the output text file descriptor
char column[ARB] # column to be sorted
pointer colptr # pointer to extracted column array
pointer colindex # pointer to index array for extracted column
int coltype # data type of the column to be sorted
int bufwidth # column width if chars
pointer recmap # pointer to the record structure map
int first_rec, nunique, uunique, funique, record
int ncontinue, recptr, nchars, szbuf, colwidth, field, element
long loffset, roffset
pointer sp, line, name, value
int getline(), strncmp(), pt_kstati()
long note()
begin
call smark (sp)
call salloc (line, SZ_LINE, TY_CHAR)
call salloc (name, SZ_FNAME, TY_CHAR)
call salloc (value, SZ_FNAME, TY_CHAR)
# Initialize the file read.
first_rec = YES
nunique = 0
uunique = 0
funique = 0
record = 0
szbuf = 0
# Initilize the record read.
ncontinue = 0
recptr = 1
# Loop over the text file records.
repeat {
# Read in a line of the text file.
loffset = note (tp_in)
nchars = getline (tp_in, Memc[line])
if (nchars == EOF)
break
# Determine the type of record.
if (Memc[line] == KY_CHAR_POUND) {
if (strncmp (Memc[line], KY_CHAR_KEYWORD, KY_LEN_STR) == 0) {
call pt_kyadd (key, Memc[line], nchars)
if (first_rec == YES)
call putline (tp_out, Memc[line])
} else if (strncmp (Memc[line], KY_CHAR_NAME,
KY_LEN_STR) == 0) {
nunique = nunique + 1
call pt_kname (key, Memc[line], nchars, nunique)
call putline (tp_out, Memc[line])
} else if (strncmp (Memc[line], KY_CHAR_UNITS,
KY_LEN_STR) == 0) {
uunique = uunique + 1
call pt_knunits (key, Memc[line], nchars, uunique)
call putline (tp_out, Memc[line])
} else if (strncmp (Memc[line], KY_CHAR_FORMAT,
KY_LEN_STR) == 0) {
funique = funique + 1
call pt_knformats (key, Memc[line], nchars, funique)
call putline (tp_out, Memc[line])
} else {
# skip lines beginning with # sign
call putline (tp_out, Memc[line])
}
} else if (Memc[line] == KY_CHAR_NEWLINE) {
# skip blank lines
call putline (tp_out, Memc[line])
} else {
# Get the variable index.
if (first_rec == YES) {
call pt_kid (column, Memc[name], element)
field = pt_kstati (key, Memc[name], KY_INDEX)
if (field <= 0)
break
}
# Save the offset of the beginning of the current record.
if (recptr == 1)
roffset = loffset
# Construct the data record.
call pt_kgfield (key, field, element, Memc[line], nchars,
Memc[value], first_rec, recptr, ncontinue)
# Decode the selected fields.
if (Memc[line+nchars-2] != KY_CHAR_CONT) {
# Select the appropriate column, get its datatype and
# allocate the appropriate space.
if (first_rec == YES) {
element = pt_kstati (key, column, KY_ELEMENT)
if (IS_INDEFI(element))
break
coltype = pt_kstati (key, column, KY_DATATYPE)
if (IS_INDEFI(coltype))
break
colwidth = pt_kstati (key, column, KY_LENGTH)
if (coltype == TY_CHAR)
bufwidth = colwidth + 1
else
bufwidth = 1
}
# Reallocate buffer space if necessary.
if (record >= szbuf) {
szbuf = szbuf + BUFSIZE
if (coltype == TY_CHAR)
call realloc (colptr, szbuf * bufwidth, TY_CHAR)
else
call realloc (colptr, szbuf, coltype)
call realloc (colindex, szbuf, TY_INT)
call realloc (recmap, szbuf, TY_INT)
}
# Decode the selected column.
record = record + 1
Memi[colindex+record-1] = 1 + (record - 1) * bufwidth
Memi[recmap+record-1] = roffset
call pt_gsrt (Memc[value], colptr, coltype, bufwidth,
record)
first_rec = NO
# Reinitialize the record read.
ncontinue = 0
recptr = 1
}
}
}
# Cleanup.
call sfree (sp)
return (record)
end
# PT_KGFIELD -- Fetch a single fields from the input file.
procedure pt_kgfield (key, field, element, line, nchars, value, first_rec,
recptr, ncontinue)
pointer key # pointer to record structure
int field # field to be fetched
int element # field array element
char line[ARB] # input line
int nchars # length of line array
char value[ARB] # the field value
int first_rec # first record
int recptr # line per record index
int ncontinue # number of unique lines per record
int len, i, cip, nper_line, nokeys, nckeys, nkeys
begin
# Fetch the value if it is a #K parameter as this will already
# be sorted in the key structure.
if ((recptr == 1) && (field <= KY_NPKEYS(key))) {
len = Memi[KY_KINDICES(key)+field-1]
call amovc (Memc[Memi[KY_PTRS(key)+field-1]], value, len)
value[len+1] = EOS
}
# The number of header columns defined by #K at the beginning of
# the file is nokeys.
if (recptr == 1)
nokeys = KY_NPKEYS(key)
# Increment the continuation statement counter or reset to 0.
if (line[nchars-2] == '*')
ncontinue = ncontinue + 1
else
ncontinue = 0
# Fill in the record.
cip = 1
if (ncontinue < 1) {
nper_line = Memi[KY_NPLINE(key)+recptr-1]
nkeys = nokeys + nper_line
call amovki (int(1), Memi[KY_NELEMS(key)+nokeys], nper_line)
do i = nokeys + 1, nkeys {
len = Memi[KY_KINDICES(key)+i-1]
if (i == field) {
call amovc (line[cip], value, len)
value[len+1] = EOS
}
cip = cip + len
}
recptr = recptr + 1
nokeys = nkeys
} else if (ncontinue == 1) {
nckeys = nokeys + 1
nkeys = nokeys + Memi[KY_NPLINE(key)+recptr-1]
if (first_rec == YES) {
Memi[KY_NCONTINUE(key)+recptr-1] = KY_NLINES
do i = nckeys, nkeys
call malloc (Memi[KY_PTRS(key)+i-1], KY_NLINES *
Memi[KY_KINDICES(key)+i-1], TY_CHAR)
}
do i = nckeys, nkeys {
len = Memi[KY_KINDICES(key)+i-1]
if ((i == field) && (element == 1)) {
call amovc (line[cip], value, len)
value[len+1] = EOS
}
cip = cip + len
}
nokeys = nkeys
recptr = recptr + 1
} else {
if (ncontinue > Memi[KY_NCONTINUE(key)+recptr-2]) {
Memi[KY_NCONTINUE(key)+recptr-2] =
Memi[KY_NCONTINUE(key)+recptr-2] + KY_NLINES
do i = nckeys, nokeys
call realloc (Memi[KY_PTRS(key)+i-1],
Memi[KY_NCONTINUE(key)+recptr-2] *
Memi[KY_KINDICES(key)+i-1], TY_CHAR)
}
do i = nckeys, nkeys {
len = Memi[KY_KINDICES(key)+i-1]
if ((i == field) && (element == ncontinue)) {
call amovc (line[cip], value, len)
value[len+1] = EOS
}
Memi[KY_NELEMS(key)+i-1] = ncontinue
cip = cip + len
}
}
end
# PT_COLSORT -- Sort the column.
procedure pt_colsort (colptr, colindex, nrecs, coltype)
pointer colptr # array of column pointers
int colindex[ARB] # column indices
int nrecs # number of records
int coltype # column type
begin
# Sort the column.
switch (coltype) {
case TY_INT:
call pt_qsorti (Memi[colptr], colindex, colindex, nrecs)
case TY_REAL:
call pt_qsortr (Memr[colptr], colindex, colindex, nrecs)
case TY_CHAR:
call strsrt (colindex, Memc[colptr], nrecs)
case TY_BOOL:
call pt_qsortb (Memb[colptr], colindex, colindex, nrecs)
}
end
# PT_REORDER -- Reorder the input file and write it to the output file.
procedure pt_reorder (tp_in, tp_out, recmap, colindex, nrecs)
int tp_in # input table file descriptor
int tp_out # output file descriptor
int recmap[ARB] # record strucuture map
int colindex[ARB] # column index
int nrecs # number of records
int i
long lptr
pointer sp, line
begin
call smark (sp)
call salloc (line, SZ_LINE, TY_CHAR)
do i = 1, nrecs {
lptr = recmap[colindex[i]]
call seek (tp_in, lptr)
call pt_rwrecord (tp_in, tp_out, Memc[line])
}
call sfree (sp)
end
# PT_GSRT -- Decode the column to be sorted.
procedure pt_gsrt (value, colptr, coltype, colwidth, record)
char value[ARB] # value to be decoded
pointer colptr # pointer to the decode column
int coltype # the data type of the sort column
int colwidth # width of the column
int record # the current record number
int ip
int ctoi(), ctor(), ctowrd()
begin
# Decode the output value.
ip = 1
switch (coltype) {
case TY_INT:
if (ctoi (value, ip, Memi[colptr+record-1]) <= 0)
Memi[colptr+record-1] = INDEFI
case TY_REAL:
if (ctor (value, ip, Memr[colptr+record-1]) <= 0)
Memr[colptr+record-1] = INDEFR
case TY_BOOL:
while (IS_WHITE(value[ip]))
ip = ip + 1
switch (value[ip]) {
case 'Y', 'y':
Memb[colptr+record-1] = true
case 'N', 'n':
Memb[colptr+record-1] = false
default:
Memb[colptr+record-1] = false
}
case TY_CHAR:
if (ctowrd (value, ip, Memc[colptr+(record-1)*colwidth],
colwidth) <= 0)
Memc[colptr+(record-1)*colwidth] = EOS
default:
;
}
end
# PT_FLIPI -- Filp an integer array in place.
procedure pt_flipi (a, npix)
int a[ARB] # array to be flipped
int npix # number of pixels
int i, nhalf, ntotal, itemp
begin
nhalf = npix / 2
ntotal = npix + 1
do i = 1, nhalf {
itemp = a[i]
a[i] = a[ntotal-i]
a[ntotal-i] = itemp
}
end
# PT_RWRECORD -- Read a text record and write it out to the output file.
procedure pt_rwrecord (tp_in, tp_out, line)
int tp_in # input file descriptor
int tp_out # output file descriptor
char line[ARB] # line buffer
int nchars
int getline()
begin
nchars = getline (tp_in, line)
while (nchars != EOF) {
call putline (tp_out, line)
if (line[nchars-1] != KY_CHAR_CONT)
break
nchars = getline (tp_in, line)
}
end
|