Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/sortlib/sync/ss.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2003-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* ibm dfsort control file parser and library support
24
*/
25
26
#include <ast.h>
27
#include <error.h>
28
#include <ccode.h>
29
#include <ctype.h>
30
#include <dlldefs.h>
31
#include <ls.h>
32
33
#ifndef DEBUG_TRACE
34
#define DEBUG_TRACE 0
35
#endif
36
37
#define _SS_PRIVATE_ \
38
Sfio_t* io; \
39
Sfio_t* key; \
40
Sfio_t* xio; \
41
char* xsum; \
42
unsigned char* n2a; \
43
unsigned char* n2e; \
44
char* data; \
45
char* peek; \
46
char* peekpeek; \
47
int ch; \
48
int item; \
49
int part; \
50
char acex[16]; \
51
char chex[16]; \
52
unsigned char acin[UCHAR_MAX+1]; \
53
unsigned char chin[UCHAR_MAX+1];
54
55
#define _SS_FILE_PRIVATE_ \
56
Ssgroup_t* lastgroup;
57
58
#define _SS_GROUP_PRIVATE_ \
59
unsigned char* beg; \
60
unsigned char* cur; \
61
unsigned char* end;
62
63
#include <ss.h>
64
65
struct Dd_s; typedef struct Dd_s Dd_t;
66
67
struct Dd_s
68
{
69
Dd_t* next;
70
char* id;
71
char* alt;
72
char* name;
73
};
74
75
static struct State_s
76
{
77
Dd_t* dd;
78
} state;
79
80
#define LEX_COND (1<<0)
81
#define LEX_COPY (1<<1)
82
#define LEX_GROUP (1<<2)
83
#define LEX_JOIN (1<<3)
84
#define LEX_NONE (1<<4)
85
86
#define SS_BLOCK 1024
87
#define SS_RESERVE (128*SS_BLOCK)
88
89
static char null[] = "";
90
91
static char CO[] = ":";
92
static char CP[] = ")";
93
static char EQ[] = "=";
94
static char OP[] = "(";
95
static char SC[] = ";";
96
97
/*
98
* bcd_pack[x] is bcd byte for 0<=x<=99
99
*/
100
101
static const unsigned char bcd_pack[] =
102
{
103
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
104
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,
105
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,
106
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,
107
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
108
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
109
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
110
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,
111
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
112
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,
113
};
114
115
/*
116
* bcd_unit[x] is bcd units (last byte with no sign) byte for 0<=x<=9
117
*/
118
119
static const unsigned char bcd_unit[] =
120
{
121
0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,
122
};
123
124
/*
125
* bcd_unpack[x] is the binary value for bcd byte x
126
* invalid codes convert to 0
127
*/
128
129
static const unsigned char bcd_unpack[] =
130
{
131
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
132
10,11,12,13,14,15,16,17,18,19, 0, 0, 1, 1, 0, 0,
133
20,21,22,23,24,25,26,27,28,29, 0, 0, 2, 2, 0, 0,
134
30,31,32,33,34,35,36,37,38,39, 0, 0, 3, 3, 0, 0,
135
40,41,42,43,44,45,46,47,48,49, 0, 0, 4, 4, 0, 0,
136
50,51,52,53,54,55,56,57,58,59, 0, 0, 5, 5, 0, 0,
137
60,61,62,63,64,65,66,67,68,69, 0, 0, 6, 6, 0, 0,
138
70,71,72,73,74,75,76,77,78,79, 0, 0, 7, 7, 0, 0,
139
80,81,82,83,84,85,86,87,88,89, 0, 0, 8, 8, 0, 0,
140
90,91,92,93,94,95,96,97,98,99, 0, 0, 9, 9, 0, 0,
141
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
142
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
143
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
145
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
146
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
147
};
148
149
/*
150
* bcd_negative[x]!=0 if bcd sign is negative
151
*/
152
153
static const unsigned char bcd_negative[] =
154
{
155
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
156
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
157
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
158
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
159
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
160
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
161
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
162
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
163
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
164
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
165
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
166
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
167
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
168
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
169
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
170
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
171
};
172
173
/*
174
* common syntax error message
175
*/
176
177
static void
178
syntax(Ss_t* ss, char* s)
179
{
180
if (ss->disc->errorf)
181
{
182
if (s)
183
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: unknown keyword", s);
184
else
185
(*ss->disc->errorf)(NiL, ss->disc, 2, "unexpected EOF");
186
}
187
}
188
189
/*
190
* push back one token
191
*/
192
193
#define xel(o,s) ((o)->peekpeek=(o)->peek,(o)->peek=(s))
194
195
static void listexpr(Ss_t*, Sfio_t*, Ssexpr_t*);
196
197
/*
198
* return the next token
199
*/
200
201
static char*
202
lex(register Ss_t* ss)
203
{
204
register char* s;
205
register char* t;
206
register int q;
207
208
if (s = ss->peek)
209
{
210
ss->peek = ss->peekpeek;
211
ss->peekpeek = 0;
212
ss->item++;
213
#if DEBUG_TRACE
214
sfprintf(sfstderr, "xel: %s\n", s);
215
#endif
216
return s;
217
}
218
for (;;)
219
{
220
switch (*ss->data)
221
{
222
case ',':
223
ss->data++;
224
ss->part = 1;
225
continue;
226
case ' ':
227
case '\t':
228
case '\r':
229
if (ss->item < 2)
230
{
231
ss->data++;
232
continue;
233
}
234
/*FALLTHROUGH*/
235
case '*':
236
case 0:
237
if (!ss->part)
238
{
239
ss->part = 1;
240
ss->data = null;
241
#if DEBUG_TRACE
242
sfprintf(sfstderr, "lex: null\n");
243
#endif
244
return SC;
245
}
246
do
247
{
248
if (!(ss->data = sfgetr(ss->io, '\n', 1)))
249
{
250
ss->data = null;
251
return 0;
252
}
253
error_info.line++;
254
} while ((q = sfvalue(ss->io)) <= 0);
255
if (q > 72)
256
ss->data[72] = 0;
257
ss->item = 0;
258
#if DEBUG_TRACE
259
sfprintf(sfstderr, "lex: line=`%s'\n", ss->data);
260
#endif
261
continue;
262
}
263
break;
264
}
265
ss->part = 0;
266
s = ss->data;
267
q = 0;
268
for (;;)
269
{
270
switch (*ss->data++)
271
{
272
case 0:
273
ss->data = null;
274
ss->item++;
275
return s;
276
case '=':
277
if (!q)
278
{
279
if ((ss->data - s) == 1)
280
{
281
ss->item++;
282
return EQ;
283
}
284
xel(ss, EQ);
285
break;
286
}
287
continue;
288
case ':':
289
if (!q)
290
{
291
if ((ss->data - s) == 1)
292
{
293
ss->item++;
294
return CO;
295
}
296
xel(ss, CO);
297
break;
298
}
299
continue;
300
case '(':
301
if (!q)
302
{
303
if ((ss->data - s) == 1)
304
{
305
ss->item++;
306
return OP;
307
}
308
xel(ss, OP);
309
break;
310
}
311
continue;
312
case ')':
313
if (!q)
314
{
315
if ((ss->data - s) == 1)
316
{
317
ss->item++;
318
return CP;
319
}
320
xel(ss, CP);
321
break;
322
}
323
continue;
324
case ',':
325
if (!q)
326
{
327
ss->part = 1;
328
break;
329
}
330
continue;
331
case ' ':
332
case '\t':
333
case '\r':
334
if (!q)
335
break;
336
continue;
337
case '\'':
338
if (q && *ss->data == '\'')
339
{
340
for (t = ++s; t < ss->data; t++)
341
*t = *(t - 1);
342
ss->data++;
343
}
344
else
345
q = !q;
346
continue;
347
default:
348
continue;
349
}
350
break;
351
}
352
*(ss->data - 1) = 0;
353
ss->item++;
354
#if DEBUG_TRACE
355
sfprintf(sfstderr, "lex: %s part=%d item=%d\n", s, ss->part, ss->item);
356
#endif
357
return s;
358
}
359
360
/*
361
* return the first variable value token
362
* '=' and '(' if (flags&LEX_GROUP) are eaten
363
*/
364
365
static char*
366
value(Ss_t* ss, int flags)
367
{
368
register char* s;
369
370
if (!(s = lex(ss)) || (flags & LEX_COND) && streq(s, "COND") && !(s = lex(ss)))
371
{
372
syntax(ss, s);
373
return 0;
374
}
375
if (s == OP && (flags & LEX_GROUP))
376
/* apparently accepted by dfsort */;
377
else if (s != EQ || !(s = lex(ss)) ||
378
(flags & LEX_GROUP) && s != OP &&
379
(!(flags & LEX_NONE) || streq(s, "NONE") && (s = 0)) &&
380
(!(flags & LEX_COPY) || streq(s, "COPY") && (s = 0)))
381
{
382
if (ss->disc->errorf)
383
{
384
if (s)
385
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: %svalue expected", s, (flags & LEX_GROUP) ? "group " : null);
386
else
387
(*ss->disc->errorf)(NiL, ss->disc, 2, "unexpected EOF");
388
}
389
return 0;
390
}
391
return s;
392
}
393
394
/*
395
* return the type in s
396
*/
397
398
#define CH(a,b,c) (((a)<<16)|((b)<<8)|(c))
399
400
static int
401
type(Ss_t* ss, char* s, int silent)
402
{
403
int n;
404
405
switch (CH(toupper(s[0]),toupper(s[0]?s[1]:0),toupper(s[1]?s[2]:0)))
406
{
407
case CH('A','C',0):
408
n = SS_ascii;
409
break;
410
case CH('A','D',0):
411
n = SS_AC_dec;
412
break;
413
case CH('A','H',0):
414
n = SS_AC_hex;
415
break;
416
case CH('A','O',0):
417
n = SS_AC_oct;
418
break;
419
case CH('A','Q',0):
420
n = SS_AC_alt;
421
break;
422
case CH('B','I',0):
423
n = SS_bit;
424
break;
425
case CH('C','H',0):
426
n = ss->ch;
427
break;
428
case CH('C','S','F'):
429
case CH('E','D',0):
430
case CH('F','S',0):
431
n = ss->ch == CC_ASCII ? SS_AC_dec : SS_CH_dec;
432
break;
433
case CH('C','T','O'):
434
case CH('O','T',0):
435
case CH('Z','D',0):
436
n = SS_zd;
437
break;
438
case CH('E','H',0):
439
n = ss->ch == CC_ASCII ? SS_AC_hex : SS_CH_hex;
440
break;
441
case CH('E','O',0):
442
n = ss->ch == CC_ASCII ? SS_AC_oct : SS_CH_oct;
443
break;
444
case CH('F','I',0):
445
n = SS_be;
446
break;
447
case CH('L','I',0):
448
n = SS_le;
449
break;
450
case CH('P','D',0):
451
case CH('P','D','O'):
452
n = SS_bcd;
453
break;
454
case CH('S','S',0):
455
n = SS_ss;
456
break;
457
default:
458
if (silent)
459
xel(ss, s);
460
else if (ss->disc->errorf)
461
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: invalid type", s);
462
n = 0;
463
break;
464
}
465
return n;
466
}
467
468
/*
469
* set the ch codeset to n
470
*/
471
472
static void
473
codeset(register Ss_t* ss, register int n)
474
{
475
register char* s;
476
register int c;
477
478
if (!n)
479
n = CC_EBCDIC_O;
480
ss->n2a = ccmap(CC_NATIVE, CC_ASCII);
481
ss->n2e = ccmap(CC_NATIVE, n);
482
ss->ch = n == CC_ASCII ? SS_ascii : SS_ebcdic;
483
memset(ss->acin, UCHAR_MAX, UCHAR_MAX + 1);
484
memset(ss->chin, UCHAR_MAX, UCHAR_MAX + 1);
485
for (n = 0, s = "0123456789"; *s; s++, n++)
486
{
487
c = ccmapchr(ss->n2a, *s);
488
ss->acin[c] = n;
489
ss->acex[n] = c;
490
c = ccmapchr(ss->n2e, *s);
491
ss->chin[c] = n;
492
ss->chex[n] = c;
493
}
494
for (n = 10, s = "abcdef"; *s; s++, n++)
495
{
496
c = ccmapchr(ss->n2a, *s);
497
ss->acin[c] = n;
498
ss->acex[n] = c;
499
c = ccmapchr(ss->n2e, *s);
500
ss->chin[c] = n;
501
ss->chex[n] = c;
502
}
503
for (n = 10, s = "ABCDEF"; *s; s++, n++)
504
{
505
c = ccmapchr(ss->n2a, *s);
506
ss->acin[c] = n;
507
c = ccmapchr(ss->n2e, *s);
508
ss->chin[c] = n;
509
}
510
}
511
512
/*
513
* eat the remainder of a =(...) value
514
*/
515
516
static int
517
eat(Ss_t* ss)
518
{
519
register char* s;
520
521
while (s = lex(ss))
522
{
523
if (s == CP)
524
return 0;
525
if (s == SC)
526
{
527
xel(ss, s);
528
return 0;
529
}
530
}
531
syntax(ss, s);
532
return -1;
533
}
534
535
/*
536
* parse a field tuple list
537
* (flags & LEX_JOIN) collapses adjacent fields
538
* zp!=0 is set to the total size
539
*/
540
541
static Ssfield_t*
542
fields(Ss_t* ss, int tuple, int flags, size_t* zp)
543
{
544
register char* s;
545
register char* v;
546
char* e;
547
unsigned char* map;
548
register Ssfield_t* dp;
549
register Ssfield_t* bp;
550
register Ssfield_t* ep;
551
size_t n;
552
size_t z;
553
int a;
554
int c;
555
int x;
556
557
if (!(s = value(ss, flags|LEX_GROUP|LEX_NONE)))
558
return 0;
559
if ((flags & LEX_COPY) && streq(s, "COPY"))
560
{
561
ss->copy = 1;
562
return 0;
563
}
564
z = 0;
565
bp = dp = 0;
566
if (s == OP)
567
{
568
if (!(s = lex(ss)))
569
goto msg;
570
if (isdigit(*s))
571
{
572
a = tuple;
573
do
574
{
575
if (s == CO)
576
a = 0;
577
else
578
{
579
if (++a > tuple && (a != 3 || !isalpha(*s) || !isalpha(*(s + 1))))
580
{
581
if (!bp)
582
{
583
bp = ep = dp;
584
dp = 0;
585
}
586
else if ((flags & LEX_JOIN) && (ep->offset + ep->size) == dp->offset && !dp->value && !ep->value && dp->reverse == ep->reverse)
587
ep->size += dp->size;
588
else
589
{
590
ep = ep->next = dp;
591
dp = 0;
592
}
593
if (!dp && !(dp = vmnewof(ss->vm, 0, Ssfield_t, 1, 0)))
594
{
595
if (ss->disc->errorf)
596
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
597
return 0;
598
}
599
a = 1;
600
}
601
switch (a)
602
{
603
case 1:
604
case 2:
605
if ((x = toupper(*s)) == 'E' && streq(s, "EDIT"))
606
{
607
if (ss->disc->errorf)
608
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: not supported", s);
609
if (!(s = value(ss, LEX_GROUP)) || eat(ss))
610
return 0;
611
}
612
else if (x == 'L' && streq(s, "LENGTH"))
613
{
614
if (ss->disc->errorf)
615
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: not supported", s);
616
if (!(s = value(ss, 0)))
617
return 0;
618
}
619
else if (x == 'S' && streq(s, "SIGNS"))
620
{
621
if (ss->disc->errorf)
622
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: not supported", s);
623
if (!(s = value(ss, LEX_GROUP)) || eat(ss))
624
return 0;
625
}
626
else
627
{
628
n = strtoul(s, &e, 10);
629
if (((x = toupper(*e)) == 'A' || x == 'B' || x == 'C' || x == 'X') && *(e + 1) == '\'' && *(v = e + strlen(e) - 1) == '\'')
630
{
631
s = e + 2;
632
e = v;
633
c = e - s;
634
if (!n)
635
n = 1;
636
if (!(dp->value = vmnewof(ss->vm, 0, char, n * c, 1)))
637
{
638
if (ss->disc->errorf)
639
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
640
return 0;
641
}
642
if (x == 'B')
643
{
644
for (v = dp->value; s < e; s += 8)
645
*v++ = (unsigned char)strntoul(s, 8, NiL, 2);
646
c = v - dp->value;
647
}
648
else if (x == 'X')
649
{
650
for (v = dp->value; s < e; s += 2)
651
*v++ = (unsigned char)strntoul(s, 2, NiL, 16);
652
c = v - dp->value;
653
}
654
else
655
{
656
strcpy(dp->value, s);
657
dp->value[c] = 0;
658
c = stresc(dp->value);
659
if (x == 'C' && (map = ss->n2e) || x == 'A' && (map = ss->n2a))
660
ccmapcpy(map, dp->value, dp->value, c);
661
}
662
z += (dp->size = n * c);
663
s = dp->value;
664
while (--n)
665
memcpy(s += c, dp->value, c);
666
a = 2;
667
}
668
else if ((x == 'X' || x == 'Z') && !*(e + 1))
669
{
670
if (x == 'X')
671
c = ' ';
672
else
673
c = 0;
674
if (!n)
675
n = 1;
676
if (!(dp->value = vmnewof(ss->vm, 0, char, n, 0)))
677
{
678
if (ss->disc->errorf)
679
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
680
return 0;
681
}
682
z += (dp->size = n);
683
while (n--)
684
dp->value[n] = c;
685
a = 2;
686
}
687
else
688
{
689
switch (a)
690
{
691
case 1:
692
dp->offset = n - 1;
693
break;
694
case 2:
695
z += (dp->size = n);
696
break;
697
}
698
if (*e)
699
{
700
if (ss->disc->errorf)
701
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: invalid number", s);
702
return 0;
703
}
704
}
705
}
706
break;
707
case 3:
708
if (tuple != 3)
709
{
710
if (tuple > 3 && !bp && !*(s + 1))
711
tuple = 3;
712
else if (dp->type = type(ss, s, 0))
713
break;
714
else
715
return 0;
716
tuple = 3;
717
}
718
/*FALLTHROUGH*/
719
case 4:
720
switch (*s)
721
{
722
case 'a':
723
case 'A':
724
break;
725
case 'd':
726
case 'D':
727
dp->reverse = 1;
728
break;
729
default:
730
if (ss->disc->errorf)
731
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: invalid sort attribute", s);
732
return 0;
733
}
734
}
735
}
736
if (!(s = lex(ss)))
737
goto msg;
738
} while (s != CP);
739
}
740
else if ((flags & LEX_COPY) && streq(s, "COPY"))
741
{
742
if ((s = lex(ss)) != CP)
743
goto msg;
744
ss->copy = 1;
745
return 0;
746
}
747
else
748
xel(ss, s);
749
}
750
if (!bp)
751
bp = dp;
752
else if ((flags & LEX_JOIN) && (ep->offset + ep->size) == dp->offset && !dp->value && !ep->value && dp->reverse == ep->reverse)
753
ep->size += dp->size;
754
else
755
ep->next = dp;
756
if (zp)
757
*zp = z;
758
return bp;
759
msg:
760
syntax(ss, s);
761
return 0;
762
}
763
764
/*
765
* parse a field option list
766
*/
767
768
static int
769
options(Ss_t* ss, int flags, Ssfile_t* fp, Ssfield_t** dp, int tuple, size_t* zp)
770
{
771
register char* s;
772
register Ssfield_t* ip;
773
char* e;
774
int n;
775
776
if (dp)
777
*dp = 0;
778
while (s = lex(ss))
779
{
780
if (s == SC)
781
break;
782
else if (s == OP || s == CP)
783
;
784
else if (streq(s, "CODE") || streq(s, "CODESET"))
785
{
786
if (!(s = value(ss, 0)))
787
return -1;
788
if ((n = ccmapid(s)) < 0)
789
{
790
if (ss->disc->errorf)
791
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: invalid codeset name", s);
792
return -1;
793
}
794
codeset(ss, n);
795
}
796
else if (streq(s, "COPY"))
797
ss->copy = 1;
798
else if (streq(s, "CONVERT") || streq(s, "VTOF"))
799
{
800
if (!fp)
801
goto msg;
802
fp->format = REC_F_TYPE(0);
803
}
804
else if (streq(s, "EQUALS"))
805
ss->stable = 'Y';
806
else if (streq(s, "NOEQUALS"))
807
ss->stable = 'N';
808
else if (streq(s, "FIELDS"))
809
{
810
n = ss->copy;
811
if (dp && !(*dp = fields(ss, tuple, flags, zp)) && ss->copy == n)
812
return -1;
813
}
814
else if (streq(s, "FORMAT"))
815
{
816
if (!(s = value(ss, 0)) || !(n = type(ss, s, 0)))
817
return -1;
818
for (ip = *dp; ip; ip = ip->next)
819
ip->type = n;
820
}
821
else if (streq(s, "FTOV"))
822
{
823
if (!fp)
824
goto msg;
825
fp->format = SS_V_IBM;
826
}
827
else if (streq(s, "LENGTH"))
828
{
829
if (!(s = value(ss, 0)))
830
return -1;
831
if ((n = s == OP) && !(s = lex(ss)))
832
goto msg;
833
ss->size = strtoul(s, &e, 10);
834
if (*e)
835
{
836
if (ss->disc->errorf)
837
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: invalid number", s);
838
return -1;
839
}
840
if (n && eat(ss))
841
return -1;
842
}
843
else if (streq(s, "TYPE"))
844
{
845
if (!(s = value(ss, 0)))
846
return -1;
847
switch (*(e = s))
848
{
849
case 'd':
850
case 'D':
851
ss->type = 'D';
852
e++;
853
break;
854
case 'f':
855
case 'F':
856
ss->type = 'F';
857
e++;
858
break;
859
case 'v':
860
case 'V':
861
if (*++e == 'b' || *e == 'B')
862
{
863
e++;
864
ss->type = 'B';
865
}
866
else
867
ss->type = 'V';
868
break;
869
}
870
if (*e)
871
{
872
if (ss->disc->errorf)
873
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: invalid record type", s);
874
return -1;
875
}
876
}
877
else if (streq(s, "SIZE"))
878
{
879
if (!(s = value(ss, 0)))
880
return -1;
881
}
882
else if (streq(s, "SKIPREC"))
883
{
884
if (!(s = value(ss, 0)))
885
return -1;
886
ss->skip = strtoull(s, &e, 10);
887
if (*e)
888
{
889
if (ss->disc->errorf)
890
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: invalid number", s);
891
return -1;
892
}
893
}
894
else if (streq(s, "STOPAFT"))
895
{
896
if (!(s = value(ss, 0)))
897
return -1;
898
ss->stop = strtoull(s, &e, 10) + 1;
899
if (*e)
900
{
901
if (ss->disc->errorf)
902
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: invalid number", s);
903
return -1;
904
}
905
}
906
else if (ss->disc->errorf)
907
(*ss->disc->errorf)(NiL, ss->disc, 1, "%s: unknown option", s);
908
}
909
return 0;
910
msg:
911
syntax(ss, s);
912
return -1;
913
}
914
915
static Ssexpr_t* compile(Ss_t*, int);
916
917
/*
918
* return the next expression operand
919
*/
920
921
static Ssexpr_t*
922
operand(Ss_t* ss, Ssexpr_t* lp)
923
{
924
register Ssexpr_t* xp;
925
register Ssfield_t* dp;
926
register char* s;
927
register char* v;
928
char* e;
929
unsigned char* map;
930
int c;
931
932
if (!(s = lex(ss)))
933
{
934
syntax(ss, s);
935
return 0;
936
}
937
else if (s == OP)
938
{
939
if (!(xp = compile(ss, 1)))
940
return 0;
941
if ((s = lex(ss)) != CP)
942
{
943
if (ss->disc->errorf)
944
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: ) expected", s);
945
return 0;
946
}
947
}
948
else if (!(xp = vmnewof(ss->vm, 0, Ssexpr_t, 1, 0)))
949
{
950
if (ss->disc->errorf)
951
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
952
return 0;
953
}
954
else if (streq(s, "NOT"))
955
{
956
xp->op = SS_OP_not;
957
if (!(xp->left.expr = compile(ss, 13)))
958
return 0;
959
}
960
else if (!(dp = vmnewof(ss->vm, 0, Ssfield_t, 1, 0)))
961
{
962
if (ss->disc->errorf)
963
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
964
return 0;
965
}
966
else
967
{
968
xp->left.field = dp;
969
if (isdigit(*s))
970
{
971
xp->op = SS_OP_field;
972
dp->offset = strtol(s, &e, 10);
973
if (*e)
974
{
975
if (ss->disc->errorf)
976
{
977
if (lp)
978
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: invalid number", s);
979
else
980
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: field offset expected", s);
981
}
982
return 0;
983
}
984
if (!(s = lex(ss)))
985
{
986
syntax(ss, s);
987
return 0;
988
}
989
if (isdigit(*s))
990
{
991
dp->offset--;
992
dp->size = strtoul(s, &e, 10);
993
if (*e)
994
{
995
if (ss->disc->errorf)
996
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: field size expected", s);
997
return 0;
998
}
999
if (!(s = lex(ss)))
1000
{
1001
syntax(ss, s);
1002
return 0;
1003
}
1004
dp->type = type(ss, s, 1);
1005
}
1006
else
1007
{
1008
xel(ss, s);
1009
if (lp)
1010
{
1011
dp->type = lp->left.field->type;
1012
dp->size = lp->left.field->size;
1013
}
1014
xp->op = SS_OP_value;
1015
}
1016
}
1017
else if (((c = toupper(*s)) == 'C' || c == 'A') && *(s + 1) == '\'')
1018
{
1019
e = s + strlen(s) - 1;
1020
if (*e != '\'' || *(e + 1))
1021
{
1022
if (ss->disc->errorf)
1023
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: invalid string constant", s);
1024
return 0;
1025
}
1026
s += 2;
1027
dp->size = e - s;
1028
if (!(dp->value = vmnewof(ss->vm, 0, char, dp->size, 1)))
1029
{
1030
if (ss->disc->errorf)
1031
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
1032
return 0;
1033
}
1034
memcpy(dp->value, s, dp->size);
1035
dp->size = stresc(dp->value);
1036
if (map = c == 'C' ? ss->n2e : ss->n2a)
1037
ccmapstr(map, dp->value, dp->size);
1038
xp->op = SS_OP_value;
1039
}
1040
else if (c == 'X' && *(s + 1) == '\'')
1041
{
1042
e = s + strlen(s) - 1;
1043
if (*e != '\'')
1044
{
1045
if (ss->disc->errorf)
1046
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "%s: invalid hex constant", s);
1047
return 0;
1048
}
1049
s += 2;
1050
dp->size = (e - s + 1) / 2;
1051
if (!(dp->value = vmnewof(ss->vm, 0, char, dp->size, 0)))
1052
{
1053
if (ss->disc->errorf)
1054
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
1055
return 0;
1056
}
1057
for (v = dp->value; s < e; s += 2)
1058
*v++ = strntoul(s, 2, NiL, 16);
1059
xp->op = SS_OP_value;
1060
}
1061
else if (c == 'B' && *(s + 1) == '\'')
1062
{
1063
e = s + strlen(s) - 1;
1064
if (*e != '\'')
1065
{
1066
if (ss->disc->errorf)
1067
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "%s: invalid hex constant", s);
1068
return 0;
1069
}
1070
s += 2;
1071
dp->size = (e - s + 7) / 8;
1072
if (!(dp->value = vmnewof(ss->vm, 0, char, dp->size, 0)))
1073
{
1074
if (ss->disc->errorf)
1075
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
1076
return 0;
1077
}
1078
for (v = dp->value; s < e; s += 8)
1079
*v++ = strntoul(s, 8, NiL, 2);
1080
xp->op = SS_OP_value;
1081
}
1082
else
1083
{
1084
if (ss->disc->errorf)
1085
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: operand expected", s);
1086
return 0;
1087
}
1088
}
1089
return xp;
1090
}
1091
1092
/*
1093
* compile an expression or subexpression
1094
*/
1095
1096
static Ssexpr_t*
1097
compile(Ss_t* ss, int precedence)
1098
{
1099
register Ssexpr_t* xp;
1100
register Ssexpr_t* lp;
1101
register Ssexpr_t* rp;
1102
register char* s;
1103
int op;
1104
int pr;
1105
1106
if (!(xp = operand(ss, NiL)))
1107
return 0;
1108
for (;;)
1109
{
1110
#if DEBUG_TRACE
1111
sfprintf(sfstderr, "compile(%d) ", precedence); listexpr(ss, sfstderr, xp); sfprintf(sfstderr, "\n");
1112
#endif
1113
if (!(s = lex(ss)))
1114
{
1115
if (precedence)
1116
syntax(ss, s);
1117
break;
1118
}
1119
else if (s == CP)
1120
{
1121
xel(ss, s);
1122
break;
1123
}
1124
else
1125
{
1126
if (streq(s, "AND"))
1127
{
1128
pr = 4;
1129
op = SS_OP_and;
1130
}
1131
else if (streq(s, "OR"))
1132
{
1133
pr = 3;
1134
op = SS_OP_or;
1135
}
1136
else if (streq(s, "EQ"))
1137
{
1138
pr = 8;
1139
op = SS_OP_eq;
1140
}
1141
else if (streq(s, "NE"))
1142
{
1143
pr = 8;
1144
op = SS_OP_ne;
1145
}
1146
else if (streq(s, "LT"))
1147
{
1148
pr = 8;
1149
op = SS_OP_lt;
1150
}
1151
else if (streq(s, "LE"))
1152
{
1153
pr = 8;
1154
op = SS_OP_le;
1155
}
1156
else if (streq(s, "GE"))
1157
{
1158
pr = 8;
1159
op = SS_OP_ge;
1160
}
1161
else if (streq(s, "GT"))
1162
{
1163
pr = 8;
1164
op = SS_OP_gt;
1165
}
1166
else
1167
{
1168
if (ss->disc->errorf)
1169
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: operator expected", s);
1170
return 0;
1171
}
1172
if (precedence >= pr)
1173
{
1174
xel(ss, s);
1175
break;
1176
}
1177
lp = xp;
1178
if (ssopexpr(op))
1179
{
1180
if (!(rp = compile(ss, pr)))
1181
return 0;
1182
if (ssopdata(lp->op) || ssopdata(rp->op))
1183
{
1184
if (ss->disc->errorf)
1185
(*ss->disc->errorf)(NiL, ss->disc, 2, "expression operand expected");
1186
return 0;
1187
}
1188
}
1189
else if (!ssopdata(lp->op))
1190
{
1191
if (ss->disc->errorf)
1192
(*ss->disc->errorf)(NiL, ss->disc, 2, "data operand expected");
1193
return 0;
1194
}
1195
else if (!(rp = operand(ss, lp)))
1196
return 0;
1197
else if (!ssopdata(rp->op))
1198
{
1199
if (ss->disc->errorf)
1200
(*ss->disc->errorf)(NiL, ss->disc, 2, "data operand expected");
1201
return 0;
1202
}
1203
if (!(xp = vmnewof(ss->vm, 0, Ssexpr_t, 1, 0)))
1204
{
1205
if (ss->disc->errorf)
1206
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
1207
return 0;
1208
}
1209
xp->op = op;
1210
xp->left.expr = lp;
1211
xp->right.expr = rp;
1212
}
1213
}
1214
return xp;
1215
}
1216
1217
/*
1218
* finalize constant values
1219
* set default operand types
1220
* migrate easy operands left
1221
*/
1222
1223
static int
1224
finalize(Ss_t* ss, register Ssexpr_t* xp, int type)
1225
{
1226
register Ssexpr_t* tp;
1227
register Ssfield_t* dp;
1228
register char* s;
1229
register char* v;
1230
register long n;
1231
1232
switch (xp->op)
1233
{
1234
case SS_OP_false:
1235
case SS_OP_true:
1236
return 0;
1237
case SS_OP_and:
1238
case SS_OP_or:
1239
if (ssopexpr(xp->left.expr->op) && !ssopexpr(xp->right.expr->op))
1240
{
1241
tp = xp->left.expr;
1242
xp->left.expr = xp->right.expr;
1243
xp->right.expr = tp;
1244
}
1245
if (finalize(ss, xp->right.expr, type))
1246
return -1;
1247
/*FALLTHROUGH*/
1248
case SS_OP_not:
1249
return finalize(ss, xp->left.expr, type);
1250
}
1251
if (!xp->left.expr->left.field->type)
1252
xp->left.expr->left.field->type = type;
1253
dp = xp->right.expr->left.field;
1254
if (!dp->type)
1255
dp->type = xp->left.expr->left.field->type;
1256
if (xp->right.expr->op == SS_OP_value && !dp->value)
1257
{
1258
if (!(v = vmnewof(ss->vm, 0, char, dp->size, 1)))
1259
{
1260
if (ss->disc->errorf)
1261
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
1262
return -1;
1263
}
1264
dp->value = v;
1265
s = v + dp->size - 1;
1266
n = dp->offset;
1267
dp->offset = 0;
1268
switch (dp->type)
1269
{
1270
case SS_bcd:
1271
if (n < 0)
1272
{
1273
n = -n;
1274
*s = 0x0D;
1275
}
1276
else
1277
*s = 0x0C;
1278
*s |= bcd_unit[n % 10];
1279
n /= 10;
1280
while (s-- > v)
1281
{
1282
*s = bcd_pack[n % 100];
1283
n /= 100;
1284
}
1285
break;
1286
case SS_be:
1287
do
1288
{
1289
*s = n & 0xFF;
1290
n >>= 8;
1291
} while (s-- > v);
1292
break;
1293
case SS_le:
1294
do
1295
{
1296
*v = n & 0xFF;
1297
n >>= 8;
1298
} while (v++ < s);
1299
break;
1300
case SS_zd:
1301
if (n < 0)
1302
{
1303
n = -n;
1304
*s = 0xD0;
1305
}
1306
else
1307
*s = 0xC0;
1308
*s |= n % 10;
1309
n /= 10;
1310
while (s-- > v)
1311
{
1312
*s = n % 10;
1313
n /= 10;
1314
}
1315
break;
1316
case 0:
1317
dp->type = SS_void;
1318
/*FALLTHROUGH*/
1319
default:
1320
if (ss->disc->errorf)
1321
(*ss->disc->errorf)(NiL, ss->disc, 2, "%c: numeric constant type not supported", dp->type);
1322
return -1;
1323
}
1324
}
1325
return 0;
1326
}
1327
1328
/*
1329
* parse a conditional expression
1330
*/
1331
1332
static Ssexpr_t*
1333
cond(Ss_t* ss)
1334
{
1335
register Ssexpr_t* xp;
1336
register char* s;
1337
int n;
1338
1339
if (!(s = value(ss, LEX_COND)))
1340
return 0;
1341
else if (streq(s, "ALL"))
1342
{
1343
if (!(xp = vmnewof(ss->vm, 0, Ssexpr_t, 1, 0)))
1344
{
1345
if (ss->disc->errorf)
1346
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
1347
return 0;
1348
}
1349
xp->op = SS_OP_true;
1350
}
1351
else if (streq(s, "NONE"))
1352
{
1353
if (!(xp = vmnewof(ss->vm, 0, Ssexpr_t, 1, 0)))
1354
{
1355
if (ss->disc->errorf)
1356
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
1357
return 0;
1358
}
1359
xp->op = SS_OP_false;
1360
}
1361
else if (s != OP)
1362
{
1363
syntax(ss, s);
1364
return 0;
1365
}
1366
else if (!(xp = compile(ss, 0)))
1367
return 0;
1368
else if ((s = lex(ss)) != CP)
1369
{
1370
if (ss->disc->errorf)
1371
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: ) expected", s);
1372
return 0;
1373
}
1374
else if (s = lex(ss))
1375
{
1376
if (!streq(s, "FORMAT"))
1377
{
1378
xel(ss, s);
1379
n = SS_be;
1380
}
1381
else if (!(s = value(ss, 0)) || !(n = type(ss, s, 0)))
1382
return 0;
1383
if (finalize(ss, xp, n))
1384
return 0;
1385
}
1386
return xp;
1387
}
1388
1389
/*
1390
* add a file group member to the circular group list
1391
*/
1392
1393
static int
1394
group(Ss_t* ss, Ssfile_t* fp, const char* id)
1395
{
1396
Ssgroup_t* gp;
1397
1398
if (!(gp = vmnewof(ss->vm, 0, Ssgroup_t, 1, strlen(id) + 1)))
1399
{
1400
if (ss->disc->errorf)
1401
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
1402
return -1;
1403
}
1404
strcpy(gp->id = (char*)(gp + 1), id);
1405
if (fp->lastgroup)
1406
fp->lastgroup->next = gp;
1407
else
1408
fp->group = gp;
1409
fp->lastgroup = gp;
1410
gp->next = fp->group;
1411
return 0;
1412
}
1413
1414
/*
1415
* load user exit usr function fun from library lib
1416
*/
1417
1418
static int
1419
load(Ss_t* ss, const char* usr, const char* fun, const char* lib, Ssdisc_t* disc)
1420
{
1421
int i;
1422
char* e;
1423
char* s;
1424
char* t;
1425
void* dll;
1426
Ssexit_f exitf;
1427
Ssintercept_f interceptf;
1428
char path[PATH_MAX];
1429
1430
static const char* sys[] = { "syncsort", "sort" };
1431
1432
for (i = 0; i < elementsof(sys); i++)
1433
if (dll = dllplugin(sys[i], lib, NiL, RS_PLUGIN_VERSION, NiL, RTLD_LAZY, path, sizeof(path)))
1434
break;
1435
if (!dll)
1436
{
1437
if ((e = getenv(lib)) && (e = strdup(e)))
1438
{
1439
s = e;
1440
while (*s)
1441
{
1442
while (isspace(*s))
1443
s++;
1444
t = s;
1445
while (*s && !isspace(*s))
1446
s++;
1447
if (*s)
1448
*s++ = 0;
1449
if (*t)
1450
{
1451
for (i = 0; i < elementsof(sys); i++)
1452
if (dll = dllplugin(sys[i], t, NiL, RS_PLUGIN_VERSION, NiL, RTLD_LAZY, path, sizeof(path)))
1453
break;
1454
if (dll)
1455
break;
1456
}
1457
}
1458
free(e);
1459
}
1460
if (!dll)
1461
{
1462
if (disc->errorf)
1463
(*disc->errorf)(NiL, disc, 2, "%s: cannot find library for %s callout %s", lib, usr, fun);
1464
return -1;
1465
}
1466
}
1467
if (!(exitf = (Ssexit_f)dlllook(dll, fun)))
1468
{
1469
if (disc->errorf)
1470
(*disc->errorf)(NiL, disc, 2, "%s: %s: cannot find %s callout library", path, fun, usr);
1471
return -1;
1472
}
1473
if ((interceptf = (Ssintercept_f)dlllook(dll, "rs_intercept")) || (interceptf = (Ssintercept_f)dlllook(NiL, "rs_intercept")))
1474
ss->intercept = interceptf;
1475
switch ((int)strtol(usr + 1, NiL, 10))
1476
{
1477
case 11:
1478
case 21:
1479
case 31:
1480
ss->initexit = exitf;
1481
break;
1482
case 14:
1483
case 15:
1484
case 16:
1485
ss->readexit = exitf;
1486
break;
1487
case 25:
1488
case 32:
1489
case 35:
1490
ss->writeexit = exitf;
1491
break;
1492
case 17:
1493
case 27:
1494
case 37:
1495
case 38:
1496
case 39:
1497
ss->doneexit = exitf;
1498
break;
1499
default:
1500
if (disc->errorf)
1501
(*disc->errorf)(NiL, disc, 2, "%s: %s: unknown %s user exit function", path, fun, usr);
1502
return -1;
1503
}
1504
return 0;
1505
}
1506
1507
/*
1508
* open a handle to the control file and parse it
1509
*/
1510
1511
Ss_t*
1512
ssopen(const char* file, Ssdisc_t* disc)
1513
{
1514
register Ss_t* ss;
1515
register char* s;
1516
Vmalloc_t* vm;
1517
Ssfile_t* fp;
1518
Ssfile_t* ep;
1519
Ssfield_t* dp;
1520
char* ofile;
1521
int oline;
1522
int n;
1523
1524
if (!(vm = vmopen(Vmdcheap, Vmbest, 0)))
1525
{
1526
if (disc->errorf)
1527
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
1528
return 0;
1529
}
1530
if (!(ss = vmnewof(vm, 0, Ss_t, 1, sizeof(Ssfile_t))))
1531
{
1532
if (disc->errorf)
1533
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
1534
vmclose(vm);
1535
return 0;
1536
}
1537
ss->vm = vm;
1538
ss->disc = disc;
1539
ss->format = REC_N_TYPE();
1540
codeset(ss, disc->code);
1541
oline = error_info.line;
1542
ofile = error_info.file;
1543
if (!(ss->key = sfstropen()))
1544
{
1545
if (ss->disc->errorf)
1546
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
1547
goto bad;
1548
}
1549
if (!file || !*file || streq(file, "-"))
1550
{
1551
file = 0;
1552
ss->io = sfstdin;
1553
}
1554
else if (!(ss->io = sfopen(NiL, file, "r")))
1555
{
1556
if (disc->errorf)
1557
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "%s: cannot read", file);
1558
goto bad;
1559
}
1560
ss->file = fp = ep = (Ssfile_t*)(ss + 1);
1561
fp->format = REC_N_TYPE();
1562
ss->data = null;
1563
error_info.line = 0;
1564
error_info.file = (char*)file;
1565
while (s = lex(ss))
1566
{
1567
if (s == SC)
1568
;
1569
else if (streq(s, "ALTSEQ"))
1570
{
1571
while (s = lex(ss))
1572
{
1573
if (s == SC)
1574
break;
1575
else if (streq(s, "CODE"))
1576
{
1577
if (!(s = value(ss, LEX_GROUP)))
1578
goto bad;
1579
while (s = lex(ss))
1580
{
1581
if (s == SC)
1582
goto msg;
1583
else if (s == CP)
1584
break;
1585
else if (disc->errorf)
1586
(*disc->errorf)(NiL, disc, 2, "ALTSEQ: not supported (CODE=%s)", s);
1587
}
1588
}
1589
else
1590
goto msg;
1591
}
1592
}
1593
else if (streq(s, "END"))
1594
break;
1595
else if (streq(s, "INCLUDE") || streq(s, "OMIT") && (ss->omit = 1))
1596
{
1597
if (!(ss->expr = cond(ss)))
1598
goto bad;
1599
}
1600
else if (streq(s, "INREC"))
1601
{
1602
if (options(ss, LEX_JOIN, NiL, &ss->in, 2, &ss->insize))
1603
goto bad;
1604
}
1605
else if (streq(s, "MODS"))
1606
{
1607
while (s = lex(ss))
1608
{
1609
if (s == SC)
1610
break;
1611
else if (s[0] == 'E' && isdigit(s[1]) && isdigit(s[2]) && !s[3])
1612
{
1613
char* usr[4];
1614
1615
usr[0] = s;
1616
if (!(s = value(ss, LEX_GROUP)))
1617
goto bad;
1618
n = 1;
1619
while (s = lex(ss))
1620
{
1621
if (s == SC)
1622
goto msg;
1623
else if (s == CP)
1624
break;
1625
else if (n < elementsof(usr))
1626
usr[n++] = s;
1627
}
1628
if (n != 4)
1629
goto msg;
1630
if (load(ss, usr[0], usr[1], usr[3], disc))
1631
goto bad;
1632
}
1633
else
1634
goto msg;
1635
}
1636
}
1637
else if (streq(s, "OPTION"))
1638
{
1639
while (s = lex(ss))
1640
{
1641
if (s == SC)
1642
break;
1643
else if (streq(s, "EQUALS"))
1644
ss->stable = 'Y';
1645
else if (streq(s, "NOEQUALS"))
1646
ss->stable = 'N';
1647
else
1648
goto msg;
1649
}
1650
}
1651
else if (streq(s, "OUTFIL"))
1652
{
1653
if (!(fp = vmnewof(ss->vm, 0, Ssfile_t, 1, 0)))
1654
{
1655
if (disc->errorf)
1656
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
1657
goto bad;
1658
}
1659
ep = ep->next = fp;
1660
fp->format = REC_N_TYPE();
1661
while (s = lex(ss))
1662
{
1663
if (s == SC)
1664
break;
1665
else if (streq(s, "FILES") || streq(s, "FNAMES"))
1666
{
1667
if (!(s = value(ss, 0)))
1668
goto bad;
1669
if (s == OP)
1670
{
1671
while ((s = lex(ss)) && s != CP)
1672
if (group(ss, fp, s))
1673
goto bad;
1674
if (s != CP)
1675
goto msg;
1676
}
1677
else if (group(ss, fp, s))
1678
goto bad;
1679
}
1680
else if (streq(s, "INCLUDE") || streq(s, "OMIT") && (fp->omit = 1))
1681
{
1682
if (!(fp->expr = cond(ss)))
1683
goto bad;
1684
}
1685
else if (streq(s, "OUTREC"))
1686
{
1687
if (!(fp->out = fields(ss, 2, LEX_JOIN, &fp->size)))
1688
goto bad;
1689
}
1690
else if (streq(s, "SAVE"))
1691
fp->save = 1;
1692
else
1693
goto msg;
1694
}
1695
if (!fp->group)
1696
{
1697
if (disc->errorf)
1698
(*disc->errorf)(NiL, disc, 2, "FILES or FNAMES expected in OUTFIL group");
1699
goto bad;
1700
}
1701
}
1702
else if (streq(s, "OUTREC"))
1703
{
1704
if (options(ss, LEX_JOIN, fp, &fp->out, 2, &fp->size))
1705
goto bad;
1706
}
1707
else if (streq(s, "RECORD"))
1708
{
1709
if (options(ss, 0, NiL, NiL, 0, NiL))
1710
goto bad;
1711
}
1712
else if (streq(s, "SORT") || streq(s, "MERGE") && (ss->merge = 1))
1713
{
1714
if (options(ss, LEX_COPY|LEX_JOIN, NiL, &ss->sort, 4, NiL))
1715
goto bad;
1716
}
1717
else if (streq(s, "SUM"))
1718
{
1719
while (s = lex(ss))
1720
{
1721
if (s == SC)
1722
break;
1723
else if (streq(s, "FIELDS"))
1724
{
1725
ss->sum = fields(ss, 2, 0, NiL);
1726
ss->uniq = 1;
1727
}
1728
else if (streq(s, "FORMAT"))
1729
{
1730
if (!(s = value(ss, 0)) || !(n = type(ss, s, 0)))
1731
goto bad;
1732
for (dp = ss->sum; dp; dp = dp->next)
1733
if (!dp->type)
1734
dp->type = n;
1735
}
1736
else if (streq(s, "XSUM"))
1737
{
1738
if ((s = getenv(SS_DD_XSUM)) && *s)
1739
ss->xsum = vmstrdup(ss->vm, s);
1740
}
1741
else
1742
goto msg;
1743
}
1744
}
1745
else if (s[0] == '/' && (s[1] == '*' || s[1] == '/' && s[2] == '*'))
1746
{
1747
/*
1748
* kosher comment?
1749
*/
1750
1751
while ((s = lex(ss)) && s != SC);
1752
}
1753
else
1754
goto msg;
1755
}
1756
error_info.line = oline;
1757
error_info.file = ofile;
1758
if (ss->io != sfstdin)
1759
sfclose(ss->io);
1760
ss->io = 0;
1761
if (!ss->file->group && group(ss, ss->file, "out"))
1762
goto bad;
1763
return ss;
1764
msg:
1765
syntax(ss, s);
1766
bad:
1767
error_info.line = oline;
1768
error_info.file = ofile;
1769
ssclose(ss);
1770
return 0;
1771
}
1772
1773
/*
1774
* return sort(1) key for dp
1775
* dp==0 returns the fixed record key
1776
* 0 return means no key, no error
1777
*/
1778
1779
char*
1780
sskey(Ss_t* ss, Ssfield_t* dp)
1781
{
1782
char* s;
1783
1784
if (dp)
1785
{
1786
sfprintf(ss->key, ".%u.%u", dp->offset + 1, dp->size);
1787
switch (dp->type)
1788
{
1789
case SS_bcd:
1790
sfprintf(ss->key, "p");
1791
break;
1792
case SS_zd:
1793
sfprintf(ss->key, "Z");
1794
break;
1795
case SS_AC_dec:
1796
case SS_AC_oct:
1797
case SS_AC_hex:
1798
case SS_CH_dec:
1799
case SS_CH_oct:
1800
case SS_CH_hex:
1801
sfprintf(ss->key, "n");
1802
break;
1803
case SS_AC_flt:
1804
case SS_CH_flt:
1805
sfprintf(ss->key, "g");
1806
break;
1807
}
1808
if (dp->reverse)
1809
sfprintf(ss->key, "r");
1810
}
1811
else if (ss->size)
1812
sfprintf(ss->key, ".%u", ss->size);
1813
else
1814
return 0;
1815
if (!(s = sfstruse(ss->key)) && ss->disc->errorf)
1816
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
1817
return s;
1818
}
1819
1820
static const char* opname[] =
1821
{
1822
"FALSE",
1823
"TRUE",
1824
"FIELD",
1825
"VALUE",
1826
"<",
1827
"<=",
1828
"==",
1829
"!=",
1830
">=",
1831
">",
1832
"&&",
1833
"||",
1834
"!",
1835
};
1836
1837
/*
1838
* list an expression
1839
*/
1840
1841
static void
1842
listexpr(Ss_t* ss, Sfio_t* io, Ssexpr_t* xp)
1843
{
1844
register unsigned char* s;
1845
register unsigned char* e;
1846
1847
if (xp)
1848
switch (xp->op)
1849
{
1850
case SS_OP_field:
1851
sfprintf(io, "[%u,%u,%c]", xp->left.field->offset, xp->left.field->size, xp->left.field->type);
1852
break;
1853
case SS_OP_value:
1854
sfprintf(io, "'");
1855
for (e = (s = (unsigned char*)xp->left.field->value) + xp->left.field->size; s < e; s++)
1856
sfprintf(io, "%02x", *s);
1857
sfprintf(io, "'");
1858
break;
1859
case SS_OP_not:
1860
sfprintf(io, "%s", opname[xp->op]);
1861
listexpr(ss, io, xp->left.expr);
1862
break;
1863
default:
1864
if (ssopexpr(xp->op))
1865
sfprintf(io, "(");
1866
listexpr(ss, io, xp->left.expr);
1867
sfprintf(io, "%s", opname[xp->op]);
1868
listexpr(ss, io, xp->right.expr);
1869
if (ssopexpr(xp->op))
1870
sfprintf(io, ")");
1871
break;
1872
}
1873
}
1874
1875
/*
1876
* list a field list
1877
*/
1878
1879
static void
1880
listfields(Ss_t* ss, Sfio_t* io, Ssfield_t* dp, const char* label)
1881
{
1882
register unsigned char* v;
1883
register unsigned char* e;
1884
1885
if (dp)
1886
{
1887
sfprintf(io, " %s\n", label);
1888
do
1889
{
1890
sfprintf(io, " %4lu %4lu %c %u", dp->offset, dp->size, dp->type ? dp->type : SS_void, dp->reverse);
1891
if (v = (unsigned char*)dp->value)
1892
{
1893
sfprintf(io, " ");
1894
for (e = v + dp->size; v < e; v++)
1895
sfprintf(io, "%02x", *v);
1896
}
1897
sfprintf(io, "\n");
1898
} while (dp = dp->next);
1899
}
1900
}
1901
1902
/*
1903
* list file info
1904
*/
1905
1906
static void
1907
listfile(Ss_t* ss, Sfio_t* io, Ssfile_t* fp)
1908
{
1909
Ssgroup_t* gp;
1910
1911
sfprintf(io, "FILE");
1912
if (fp->size)
1913
sfprintf(io, " size=%u", fp->size);
1914
if (fp->format != REC_N_TYPE())
1915
sfprintf(io, " format=%s", fmtrec(fp->format, 1));
1916
if (!fp->out)
1917
sfprintf(io, " COPY");
1918
if (gp = fp->group)
1919
do
1920
{
1921
sfprintf(io, " %s", gp->id);
1922
if (gp->name)
1923
sfprintf(io, "=%s", gp->name);
1924
} while ((gp = gp->next) != fp->group);
1925
sfprintf(io, "\n");
1926
if (fp->expr)
1927
{
1928
sfprintf(io, " %s=", fp->omit ? "OMIT" : "INCLUDE");
1929
listexpr(ss, io, fp->expr);
1930
sfprintf(io, "\n");
1931
}
1932
listfields(ss, io, fp->out, "OUT");
1933
}
1934
1935
/*
1936
* list all control file info
1937
*/
1938
1939
int
1940
sslist(Ss_t* ss, Sfio_t* io)
1941
{
1942
Ssfile_t* fp;
1943
Ssfield_t* dp;
1944
char* s;
1945
1946
if (ss->in)
1947
{
1948
sfprintf(io, "FILE");
1949
if (ss->insize)
1950
sfprintf(io, " size=%u", ss->insize);
1951
sfprintf(io, " in\n");
1952
listfields(ss, io, ss->in, "INREC");
1953
}
1954
fp = ss->file;
1955
listfile(ss, io, fp);
1956
if (ss->copy)
1957
sfprintf(io, " COPY\n");
1958
if (ss->skip)
1959
sfprintf(io, " SKIPREC %I*u\n", sizeof(ss->skip), ss->skip);
1960
if (ss->stop)
1961
sfprintf(io, " STOPAFT %I*u\n", sizeof(ss->stop), ss->stop - 1);
1962
if (ss->size)
1963
sfprintf(io, " SIZE %u\n", ss->size);
1964
if (ss->expr)
1965
{
1966
sfprintf(io, " %s=", ss->omit ? "OMIT" : "INCLUDE");
1967
listexpr(ss, io, ss->expr);
1968
sfprintf(io, "\n");
1969
}
1970
if (ss->sort)
1971
{
1972
if (ss->stable == 'Y')
1973
sfprintf(io, " EQUALS\n");
1974
sfprintf(io, " KEY");
1975
if (s = sskey(ss, NiL))
1976
sfprintf(io, " -k%s", s);
1977
for (dp = ss->sort; dp; dp = dp->next)
1978
if (s = sskey(ss, dp))
1979
sfprintf(io, " -k%s", s);
1980
sfprintf(io, "\n");
1981
listfields(ss, io, ss->sort, "SORT");
1982
}
1983
if (ss->sum)
1984
listfields(ss, io, ss->sum, "SUM");
1985
if (ss->xsum)
1986
sfprintf(io, " XSUM %s\n", ss->xsum);
1987
while (fp = fp->next)
1988
listfile(ss, io, fp);
1989
return !sferror(io);
1990
}
1991
1992
/*
1993
* copy <buf,bsize> to <out,osize> according to fp->out
1994
* if return value > osize then copy not done but
1995
* subsequent call with osize >= return value will work
1996
*/
1997
1998
ssize_t
1999
sscopy(Ss_t* ss, Ssfile_t* fp, const char* buf, size_t bsize, char* out, size_t osize)
2000
{
2001
register unsigned char* s;
2002
register unsigned char* t;
2003
register Ssfield_t* dp;
2004
size_t rsize;
2005
int v;
2006
2007
v = fp->format == SS_V_IBM ? 4 : 0;
2008
if (!(dp = fp->out))
2009
{
2010
if (v && bsize >= 4 && (t = (unsigned char*)buf)[2] == 0 && t[3] == 0 && ((t[0]<<8)|t[1]) == bsize)
2011
v = 0;
2012
if ((rsize = bsize + v) > osize)
2013
return rsize;
2014
memcpy(out + v, buf, bsize);
2015
}
2016
else if ((rsize = fp->size + v) > osize)
2017
return rsize;
2018
else
2019
{
2020
t = (unsigned char*)out + v;
2021
do
2022
{
2023
s = dp->value ? (unsigned char*)dp->value : ((unsigned char*)buf + dp->offset);
2024
switch (dp->size)
2025
{
2026
case 7: *t++ = *s++;
2027
case 6: *t++ = *s++;
2028
case 5: *t++ = *s++;
2029
case 4: *t++ = *s++;
2030
case 3: *t++ = *s++;
2031
case 2: *t++ = *s++;
2032
case 1: *t++ = *s++;
2033
break;
2034
default:
2035
memcpy(t, s, dp->size);
2036
t += dp->size;
2037
break;
2038
}
2039
} while (dp = dp->next);
2040
}
2041
if (v)
2042
{
2043
t = (unsigned char*)out;
2044
*t++ = (rsize>>8)&0xff;
2045
*t++ = rsize&0xff;
2046
*t++ = 0;
2047
*t = 0;
2048
}
2049
return rsize;
2050
}
2051
2052
/*
2053
* write buf according to <fp->out,fp->size>
2054
*/
2055
2056
ssize_t
2057
sswrite(Ss_t* ss, Ssfile_t* fp, const char* buf, size_t size)
2058
{
2059
register unsigned char* s;
2060
register unsigned char* t;
2061
register Ssgroup_t* gp;
2062
register Ssfield_t* dp;
2063
size_t v;
2064
size_t r;
2065
ssize_t z;
2066
2067
if ((gp = fp->group) != fp->group)
2068
fp->group = gp->next;
2069
v = fp->format == SS_V_IBM ? 4 : 0;
2070
if (dp = fp->out)
2071
size = fp->size;
2072
else if (fp->format == SS_V_IBM && (size < 4 || (t = (unsigned char*)buf)[2] == 0 && t[3] == 0 && ((t[0]<<8)|t[1]) == size))
2073
v = 0;
2074
r = size + v;
2075
if ((gp->end - gp->cur) < r)
2076
{
2077
if ((z = gp->cur - gp->beg) && sfwrite(gp->io, gp->beg, z) != z)
2078
{
2079
if (ss->disc->errorf)
2080
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "%s: write error", gp->name);
2081
return -1;
2082
}
2083
z = (r < SS_RESERVE) ? SS_RESERVE : roundof(z, SS_BLOCK);
2084
if (!(gp->beg = (unsigned char*)sfreserve(gp->io, z, SF_LOCKR)))
2085
{
2086
if ((z = sfvalue(gp->io)) < r)
2087
z = r;
2088
if (!(gp->beg = (unsigned char*)sfreserve(gp->io, z, SF_LOCKR)))
2089
{
2090
if (ss->disc->errorf)
2091
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|1, "%s: write buffer error", gp->name);
2092
return -1;
2093
}
2094
}
2095
gp->end = (gp->cur = gp->beg) + z;
2096
}
2097
t = gp->cur + v;
2098
if (dp)
2099
{
2100
do
2101
{
2102
s = dp->value ? (unsigned char*)dp->value : ((unsigned char*)buf + dp->offset);
2103
switch (dp->size)
2104
{
2105
case 7: *t++ = *s++;
2106
case 6: *t++ = *s++;
2107
case 5: *t++ = *s++;
2108
case 4: *t++ = *s++;
2109
case 3: *t++ = *s++;
2110
case 2: *t++ = *s++;
2111
case 1: *t++ = *s++;
2112
break;
2113
default:
2114
memcpy(t, s, dp->size);
2115
t += dp->size;
2116
break;
2117
}
2118
} while (dp = dp->next);
2119
}
2120
else
2121
{
2122
memcpy(t, buf, size);
2123
t += size;
2124
}
2125
if (v)
2126
{
2127
s = gp->cur;
2128
r = t - s;
2129
*s++ = (r>>8)&0xff;
2130
*s++ = (r)&0xff;
2131
*s++ = 0;
2132
*s = 0;
2133
}
2134
gp->cur = t;
2135
return size;
2136
}
2137
2138
/*
2139
* sum buf into out according to field list dp
2140
*/
2141
2142
int
2143
sssum(Ss_t* ss, register Ssfield_t* dp, const char* buf, size_t size, char* out)
2144
{
2145
register unsigned char* s;
2146
register unsigned char* se;
2147
register unsigned char* t;
2148
register unsigned char* te;
2149
register intmax_t n;
2150
register int i;
2151
register int j;
2152
2153
do
2154
{
2155
s = (unsigned char*)buf + dp->offset;
2156
t = (unsigned char*)out + dp->offset;
2157
switch (dp->type)
2158
{
2159
case SS_bcd:
2160
se = s + dp->size - 1;
2161
te = t + dp->size - 1;
2162
if (bcd_negative[*se] == bcd_negative[*te])
2163
{
2164
if ((j = bcd_unpack[*te] + bcd_unpack[*se]) >= 10)
2165
{
2166
j -= 10;
2167
i = 1;
2168
}
2169
else
2170
i = 0;
2171
*te = bcd_unit[j] | (*se & 0x0F);
2172
while (te-- > t)
2173
{
2174
se--;
2175
if ((j = bcd_unpack[*te] + bcd_unpack[*se] + i) >= 100)
2176
{
2177
j -= 100;
2178
i = 1;
2179
}
2180
else
2181
i = 0;
2182
*te = bcd_pack[j];
2183
}
2184
if (i && ss->disc->errorf)
2185
(*ss->disc->errorf)(NiL, ss->disc, 1, "sum overflow");
2186
}
2187
else
2188
{
2189
if ((j = (int)bcd_unpack[*te] - (int)bcd_unpack[*se]) < 0)
2190
{
2191
j += 10;
2192
i = 1;
2193
}
2194
else
2195
i = 0;
2196
*te = bcd_unit[j] | (*te & 0x0F);
2197
while (se-- > s)
2198
{
2199
te--;
2200
if ((j = (int)bcd_unpack[*te] - (int)bcd_unpack[*se] - i) < 0)
2201
{
2202
j += 100;
2203
i = 1;
2204
}
2205
else
2206
i = 0;
2207
*te = bcd_pack[j];
2208
}
2209
if (i)
2210
{
2211
te = t + dp->size - 1;
2212
if ((j = (int)0 - (int)bcd_unpack[*te]) < 0)
2213
{
2214
j += 10;
2215
i = 1;
2216
}
2217
else
2218
i = 0;
2219
*te = bcd_unit[j] | ((*te & 0x0F) == 0x0C ? 0x0D : 0x0C);
2220
while (te-- > t)
2221
{
2222
if ((j = (int)0 - (int)bcd_unpack[*te] - i) < 0)
2223
{
2224
j += 100;
2225
i = 1;
2226
}
2227
else
2228
i = 0;
2229
*te = bcd_pack[j];
2230
}
2231
}
2232
}
2233
break;
2234
case SS_be:
2235
n = 0;
2236
for (i = 0; i < dp->size; i++)
2237
n = (n << 8) + s[i] + t[i];
2238
for (i = dp->size - 1; i >= 0; i--)
2239
{
2240
t[i] = (n & 0xFF);
2241
n >>= 8;
2242
}
2243
break;
2244
case SS_le:
2245
n = 0;
2246
for (i = dp->size - 1; i >= 0; i--)
2247
n = (n << 8) + s[i] + t[i];
2248
for (i = 0; i < dp->size; i++)
2249
{
2250
t[i] = (n & 0xFF);
2251
n >>= 8;
2252
}
2253
break;
2254
case SS_zd:
2255
se = s + dp->size - 1;
2256
te = t + dp->size - 1;
2257
if ((*se ^ *te) & 0x10)
2258
{
2259
if ((j = (int)(*te & 0x0F) - (int)(*se & 0x0F)) < 0)
2260
{
2261
j += 10;
2262
i = 1;
2263
}
2264
else
2265
i = 0;
2266
*te = (*te & 0xF0) | j;
2267
while (se-- > s)
2268
{
2269
te--;
2270
if ((j = (int)(*te & 0x0F) - (int)(*se & 0x0F) - i) < 0)
2271
{
2272
j += 10;
2273
i = 1;
2274
}
2275
else
2276
i = 0;
2277
*te = 0xF0 | j;
2278
}
2279
if (i)
2280
{
2281
te = t + dp->size - 1;
2282
if ((j = (int)0 - (int)(*te & 0x0F)) < 0)
2283
{
2284
j += 10;
2285
i = 1;
2286
}
2287
else
2288
i = 0;
2289
*te = ((*te & 0x10) ? 0xC0 : 0xD0) | j;
2290
while (te-- > t)
2291
{
2292
if ((j = (int)0 - (int)(*te & 0x0F) - i) < 0)
2293
{
2294
j += 10;
2295
i = 1;
2296
}
2297
else
2298
i = 0;
2299
*te = 0xF0 | j;
2300
}
2301
}
2302
}
2303
else
2304
{
2305
if ((j = (*te & 0x0F) + (*se & 0x0F)) >= 10)
2306
{
2307
j -= 10;
2308
i = 1;
2309
}
2310
else
2311
i = 0;
2312
*te = (*se & 0xF0) | j;
2313
while (te-- > t)
2314
{
2315
se--;
2316
if ((j = (*te & 0x0F) + (*se & 0x0F) + i) >= 10)
2317
{
2318
j -= 10;
2319
i = 1;
2320
}
2321
else
2322
i = 0;
2323
*te = 0xF0 | j;
2324
}
2325
if (i && ss->disc->errorf)
2326
(*ss->disc->errorf)(NiL, ss->disc, 1, "sum overflow");
2327
}
2328
break;
2329
case SS_AC_dec:
2330
n = 0;
2331
for (i = 0; i < dp->size; i++)
2332
n = n * 10 + ss->acin[s[i]] + ss->acin[t[i]];
2333
while (i-- > 0)
2334
{
2335
t[i] = ss->acex[n % 10];
2336
n /= 10;
2337
}
2338
break;
2339
case SS_AC_oct:
2340
n = 0;
2341
for (i = 0; i < dp->size; i++)
2342
n = (n << 3) + ss->acin[s[i]] + ss->acin[t[i]];
2343
while (i-- > 0)
2344
{
2345
t[i] = ss->acex[n & 07];
2346
n >>= 3;
2347
}
2348
break;
2349
case SS_AC_hex:
2350
n = 0;
2351
for (i = 0; i < dp->size; i++)
2352
n = (n << 4) + ss->acin[s[i]] + ss->acin[t[i]];
2353
while (i-- > 0)
2354
{
2355
t[i] = ss->acex[n & 0x0F];
2356
n >>= 4;
2357
}
2358
break;
2359
case SS_CH_dec:
2360
n = 0;
2361
for (i = 0; i < dp->size; i++)
2362
n = n * 10 + ss->chin[s[i]] + ss->chin[t[i]];
2363
while (i-- > 0)
2364
{
2365
t[i] = ss->chex[n % 10];
2366
n /= 10;
2367
}
2368
break;
2369
case SS_CH_oct:
2370
n = 0;
2371
for (i = 0; i < dp->size; i++)
2372
n = (n << 3) + ss->chin[s[i]] + ss->chin[t[i]];
2373
while (i-- > 0)
2374
{
2375
t[i] = ss->chex[n & 07];
2376
n >>= 3;
2377
}
2378
break;
2379
case SS_CH_hex:
2380
n = 0;
2381
for (i = 0; i < dp->size; i++)
2382
n = (n << 4) + ss->chin[s[i]] + ss->chin[t[i]];
2383
while (i-- > 0)
2384
{
2385
t[i] = ss->chex[n & 0x0F];
2386
n >>= 4;
2387
}
2388
break;
2389
default:
2390
if (ss->disc->errorf)
2391
(*ss->disc->errorf)(NiL, ss->disc, 2, "%c: sum type not supported", dp->type);
2392
return -1;
2393
}
2394
} while (dp = dp->next);
2395
if (ss->xio && sfwrite(ss->xio, buf, size) != size)
2396
{
2397
if (ss->disc->errorf)
2398
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "%s: XSUM write error", ss->xsum);
2399
return -1;
2400
}
2401
return 0;
2402
}
2403
2404
/*
2405
* evaluate expression xp on buf
2406
*/
2407
2408
int
2409
sseval(Ss_t* ss, register Ssexpr_t* xp, const char* buf, size_t size)
2410
{
2411
register unsigned char* a;
2412
register unsigned char* b;
2413
register unsigned char* e;
2414
register int r;
2415
2416
switch (xp->op)
2417
{
2418
case SS_OP_false:
2419
return 0;
2420
case SS_OP_true:
2421
return 1;
2422
case SS_OP_not:
2423
return !sseval(ss, xp->left.expr, buf, size);
2424
case SS_OP_and:
2425
return sseval(ss, xp->left.expr, buf, size) && sseval(ss, xp->right.expr, buf, size);
2426
case SS_OP_or:
2427
return sseval(ss, xp->left.expr, buf, size) || sseval(ss, xp->right.expr, buf, size);
2428
}
2429
a = xp->left.expr->left.field->value ? (unsigned char*)xp->left.expr->left.field->value : ((unsigned char*)buf + xp->left.expr->left.field->offset);
2430
e = a + xp->left.expr->left.field->size;
2431
b = xp->right.expr->left.field->value ? (unsigned char*)xp->right.expr->left.field->value : ((unsigned char*)buf + xp->right.expr->left.field->offset);
2432
while (a < e && !(r = (int)*a++ - (int)*b++));
2433
switch (xp->op)
2434
{
2435
case SS_OP_lt:
2436
return r < 0;
2437
case SS_OP_le:
2438
return r <= 0;
2439
case SS_OP_eq:
2440
return r == 0;
2441
case SS_OP_ne:
2442
return r != 0;
2443
case SS_OP_ge:
2444
return r >= 0;
2445
case SS_OP_gt:
2446
return r > 0;
2447
}
2448
return 0;
2449
}
2450
2451
int
2452
ssdd(const char* id, const char* name, Ssdisc_t* disc)
2453
{
2454
Dd_t* dd;
2455
2456
if (!(dd = newof(0, Dd_t, 1, strlen(id) + strlen(name) + 2)))
2457
{
2458
if (disc->errorf)
2459
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
2460
return -1;
2461
}
2462
dd->id = (char*)(dd + 1);
2463
dd->name = strcopy(dd->id, id) + 1;
2464
strcopy(dd->name, name);
2465
dd->alt = dd->id + 3;
2466
if (*dd->alt == '-' || *dd->alt == '_')
2467
dd->alt++;
2468
dd->next = state.dd;
2469
state.dd = dd;
2470
return 0;
2471
}
2472
2473
#define SAME(a,b) ((a)->st_dev==(b)->st_dev&&(a)->st_ino==(b)->st_ino)
2474
2475
/*
2476
* initialize io to active files
2477
*/
2478
2479
int
2480
ssio(Ss_t* ss, int list)
2481
{
2482
register Ssfile_t* fp;
2483
register Ssgroup_t* ep;
2484
register Ssgroup_t* gp;
2485
register Ssgroup_t* pg;
2486
register Dd_t* dd;
2487
register Dd_t* pd;
2488
register char* s;
2489
register int n;
2490
char* e;
2491
struct stat ns;
2492
struct stat ws;
2493
2494
if (stat("/dev/null", &ns))
2495
{
2496
ns.st_dev = 0;
2497
ns.st_ino = 0;
2498
}
2499
fp = ss->file;
2500
if (!fp->group->io)
2501
fp->group->io = sfstdout;
2502
if (!fstat(sffileno(fp->group->io), &ws) && SAME(&ws, &ns))
2503
fp->group->io = 0;
2504
for (n = 0; fp; fp = fp->next)
2505
if (gp = ep = fp->group)
2506
{
2507
pg = fp->group = 0;
2508
do
2509
{
2510
if (!gp->io)
2511
{
2512
for (s = 0, pd = 0, dd = state.dd; dd; pd = dd, dd = dd->next)
2513
if (streq(gp->id, dd->id) || streq(gp->id, dd->alt))
2514
{
2515
if (gp->name)
2516
{
2517
if (ss->disc->errorf)
2518
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: auxiliary file %s already named %s", dd->name, gp->id, gp->name);
2519
return -1;
2520
}
2521
s = dd->name;
2522
break;
2523
}
2524
if (!gp->name && (s || (s = getenv(sfprints("%s%s", SS_DD_OUT, gp->id)))))
2525
{
2526
if (ss->mark && !strmatch(s, SS_MARKED) && !strmatch(s, "/dev/*"))
2527
{
2528
if (fp->size || !fp->out && ss->size)
2529
{
2530
if ((e = strrchr(s, '.')) && strmatch(e, SS_SUFFIX))
2531
s = sfprints("%-.*s%%%d%s", e - s, s, fp->size ? fp->size : ss->size, e);
2532
else
2533
s = sfprints("%s%%%d%s", s, fp->size ? fp->size : ss->size, ss->suffix);
2534
}
2535
else if (ss->format != REC_N_TYPE())
2536
{
2537
if ((e = strrchr(s, '.')) && strmatch(e, SS_SUFFIX))
2538
s = sfprints("%-.*s%%%s%s", e - s, s, fmtrec(ss->format, 1), e);
2539
else
2540
s = sfprints("%s%%%s%s", s, fmtrec(ss->format, 1), ss->suffix);
2541
}
2542
}
2543
if (!(gp->name = vmstrdup(ss->vm, s)))
2544
{
2545
if (ss->disc->errorf)
2546
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "out of space");
2547
return -1;
2548
}
2549
else if (!list && !(gp->io = sfopen(NiL, gp->name, "w")))
2550
{
2551
if (ss->disc->errorf)
2552
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "%s: cannot write auxiliary file %s", gp->name, gp->id);
2553
return -1;
2554
}
2555
}
2556
if (dd)
2557
{
2558
if (pd)
2559
pd->next = dd->next;
2560
else
2561
state.dd = dd->next;
2562
free(dd);
2563
}
2564
}
2565
if (gp->io && !fstat(sffileno(gp->io), &ws) && SAME(&ws, &ns))
2566
{
2567
sfclose(gp->io);
2568
gp->io = 0;
2569
}
2570
if (gp->io || list)
2571
{
2572
if (gp->io != sfstdout)
2573
n++;
2574
if (pg)
2575
pg->next = gp;
2576
else
2577
fp->group = gp;
2578
pg = gp;
2579
}
2580
} while ((gp = gp->next) != ep);
2581
if (pg)
2582
pg->next = fp->group;
2583
}
2584
if (dd = state.dd)
2585
{
2586
n = -1;
2587
do
2588
{
2589
if (ss->disc->errorf)
2590
(*ss->disc->errorf)(NiL, ss->disc, 2, "%s: unknown auxiliary file", dd->id);
2591
pd = dd;
2592
dd = dd->next;
2593
free(pd);
2594
} while (dd);
2595
}
2596
if (!list && ss->xsum && !(ss->xio = sfopen(NiL, ss->xsum, "w")))
2597
{
2598
if (ss->disc->errorf)
2599
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "%s: cannot write XSUM file", ss->xsum);
2600
n = -1;
2601
}
2602
return n;
2603
}
2604
2605
/*
2606
* announce ss io to recsort
2607
*/
2608
2609
int
2610
ssannounce(Ss_t* ss, Rs_t* rs)
2611
{
2612
register Ssfile_t* fp;
2613
register Ssgroup_t* ep;
2614
register Ssgroup_t* gp;
2615
register Ssgroup_t* pg;
2616
2617
for (fp = ss->file; fp; fp = fp->next)
2618
if (gp = ep = fp->group)
2619
{
2620
pg = fp->group = 0;
2621
do
2622
{
2623
if (gp->io)
2624
{
2625
if (rsfilewrite(rs, gp->io, gp->name))
2626
return -1;
2627
if (pg)
2628
pg->next = gp;
2629
else
2630
fp->group = gp;
2631
pg = gp;
2632
}
2633
} while ((gp = gp->next) != ep);
2634
if (pg)
2635
pg->next = fp->group;
2636
}
2637
if (ss->xsum && ss->xio && rsfilewrite(rs, ss->xio, ss->xsum))
2638
return -1;
2639
return 0;
2640
}
2641
2642
/*
2643
* close handle ss
2644
*/
2645
2646
int
2647
ssclose(Ss_t* ss)
2648
{
2649
register Ssfile_t* fp;
2650
register Ssgroup_t* gp;
2651
ssize_t z;
2652
int r;
2653
2654
if (!ss)
2655
return -1;
2656
r = 0;
2657
for (fp = ss->file; fp; fp = fp->next)
2658
if (gp = fp->group)
2659
do
2660
{
2661
if (gp->io && ((z = gp->cur - gp->beg) >= 0 && sfwrite(gp->io, gp->beg, z) != z || ((fp == ss->file || gp->io == sfstdout) ? sfsync(gp->io) : sfclose(gp->io))))
2662
{
2663
if (ss->disc->errorf)
2664
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "%s: write error", gp->name);
2665
r = -1;
2666
}
2667
} while ((gp = gp->next) != fp->group);
2668
if (ss->xio && sfclose(ss->xio))
2669
{
2670
if (ss->disc->errorf)
2671
(*ss->disc->errorf)(NiL, ss->disc, ERROR_SYSTEM|2, "%s: XSUM write error", ss->xsum);
2672
return -1;
2673
}
2674
if (ss->io && ss->io != sfstdin)
2675
sfclose(ss->io);
2676
if (ss->key)
2677
sfstrclose(ss->key);
2678
vmclose(ss->vm);
2679
return r;
2680
}
2681
2682