Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libpz/pzpart.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1998-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
* partition support
24
*/
25
26
static const char usage[] =
27
"[-1i?\n@(#)$Id: pz library 2.4 (AT&T Research) 2011-03-07 $\n]"
28
"[a:append]"
29
"[c:comment]:[text]"
30
"[x:crc]"
31
"[d:debug]#[level]"
32
"[D:dump]"
33
"[G!:gzip]"
34
"[i:include]:[file]"
35
"[l:library]:[library]"
36
"[n:name]:[name]"
37
"[X:prefix?]:[count[*terminator]]]"
38
"[O:sort]"
39
"[P!:pzip]"
40
"[Q:regress]"
41
"[r:row]#[row-size]"
42
"[S:split]:?[pattern]"
43
"[s:summary]"
44
"[T:test]#[mask]"
45
"[v:verbose]"
46
;
47
48
#include "pzlib.h"
49
50
#define VECTOR(z,p,n) (((z)->flags&PZ_OVERSIZE)?(p)->row:(n))
51
52
/*
53
* return partition pointer given name
54
*/
55
56
Pzpart_t*
57
pzpartget(Pz_t* pz, const char* name)
58
{
59
if (!name || !*name || !pz->partdict)
60
return pz->mainpart;
61
pz->flags &= ~PZ_MAINONLY;
62
return (Pzpart_t*)dtmatch(pz->partdict, name);
63
}
64
65
/*
66
* partition iterator
67
* return the next partition after pp
68
* first call should set pp to 0
69
* 0 returned after all partitions visited
70
*/
71
72
Pzpart_t*
73
pzpartnext(Pz_t* pz, Pzpart_t* pp)
74
{
75
if (pz->partdict)
76
return pp ? (Pzpart_t*)dtnext(pz->partdict, pp) : (Pzpart_t*)dtfirst(pz->partdict);
77
return pp ? (Pzpart_t*)0 : pz->mainpart;
78
}
79
80
/*
81
* set the current partition to pp
82
* old partition returned
83
*/
84
85
Pzpart_t*
86
pzpartset(Pz_t* pz, Pzpart_t* pp)
87
{
88
Pzpart_t* op;
89
90
pz->flags &= ~PZ_MAINONLY;
91
if (pzsync(pz))
92
return 0;
93
op = pz->part;
94
pz->part = pp;
95
return op;
96
}
97
98
/*
99
* parse a column range at s
100
* return
101
* -1 error
102
* 0 not a range
103
* 1 ok
104
*/
105
106
static int
107
range(Pz_t* pz, register Pzpart_t* pp, char* s, char** p, int* beg, int* end)
108
{
109
int n;
110
int m;
111
char* e;
112
113
for (; isspace(*s) || *s == ','; s++);
114
if (*s == '-')
115
n = 0;
116
else
117
{
118
n = (int)strtol(s, &e, 10);
119
if (s == e)
120
{
121
if (p)
122
*p = e;
123
return 0;
124
}
125
if (pp && n >= pp->row)
126
{
127
if (pz->disc->errorf)
128
(*pz->disc->errorf)(pz, pz->disc, 2, "column %d is larger than row %d", n, pp->row);
129
return -1;
130
}
131
for (s = e; isspace(*s); s++);
132
}
133
if (*s == '-')
134
{
135
if (!*++s || isspace(*s) || *s == ',')
136
{
137
e = s;
138
m = (pp ? pp->row : INT_MAX) - 1;
139
}
140
else
141
{
142
m = (int)strtol(s, &e, 10);
143
if (m < n || pp && m >= pp->row)
144
{
145
if (pz->disc->errorf)
146
(*pz->disc->errorf)(pz, pz->disc, 2, "invalid column range %d-%d", n, m);
147
return -1;
148
}
149
}
150
}
151
else
152
m = n;
153
if (p)
154
{
155
for (s = e; isspace(*s) || *s == ','; s++);
156
*p = s;
157
}
158
if (beg)
159
*beg = n;
160
if (end)
161
*end = m;
162
return 1;
163
}
164
165
/*
166
* parse a character value at s
167
*/
168
169
static int
170
value(Pz_t* pz, char* s, char** p)
171
{
172
char* e;
173
int q;
174
int v;
175
176
for (; isspace(*s); s++);
177
if (!(q = *s++) || ((v = chresc(s, &e)), s == e))
178
{
179
if (pz->disc->errorf)
180
(*pz->disc->errorf)(pz, pz->disc, 2, "value expected");
181
return -1;
182
}
183
s = e;
184
if (*s++ != q)
185
{
186
if (pz->disc->errorf)
187
(*pz->disc->errorf)(pz, pz->disc, 2, "unbalanced %c quote in value", q);
188
return -1;
189
}
190
if (*p)
191
*p = s;
192
return v;
193
}
194
195
/*
196
* add fixed column range value to pz
197
*/
198
199
static int
200
fixed(Pz_t* pz, register Pzpart_t* pp, int n, int m, int k)
201
{
202
int i;
203
int v;
204
205
if (!pp->value)
206
{
207
if (!(pp->value = vmnewof(pz->vm, 0, int, pp->row, 0)))
208
return pznospace(pz);
209
for (i = 0; i < pp->row; i++)
210
pp->value[i] = -1;
211
}
212
v = k < 0 ? ' ' : k;
213
for (; n <= m; n++)
214
{
215
if (pp->value[n] < 0)
216
pp->nfix++;
217
else if (k < 0)
218
continue;
219
pp->value[n] = v;
220
}
221
return 0;
222
}
223
224
/*
225
* initialize the partition map from pp.{<map,nmap>,<grp,ngrp>}
226
*/
227
228
int
229
pzpartmap(Pz_t* pz, register Pzpart_t* pp)
230
{
231
int i;
232
int j;
233
int k;
234
235
k = 0;
236
for (i = 0; i < pp->ngrp; i++)
237
for (j = 0; j < pp->grp[i]; j++)
238
{
239
if (k >= pp->nmap)
240
{
241
if (pz->disc->errorf)
242
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: invalid group", pz->path);
243
return -1;
244
}
245
pp->lab[k] = i;
246
pp->inc[k++] = pp->grp[i];
247
}
248
if (k != pp->nmap)
249
{
250
if (pz->disc->errorf)
251
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: invalid group", pz->path);
252
return -1;
253
}
254
memset(pp->low, 1, pp->row);
255
for (i = 0; i < pp->nmap; i++)
256
pp->low[pp->map[i]] = 0;
257
for (i = 0; i < pp->nfix; i++)
258
pp->low[pp->fix[i]] = 0;
259
if ((pz->flags & PZ_READ) && pp->value)
260
for (i = j = 0; i < pp->nmap; i++)
261
if (pp->value[i] < 0)
262
pp->map[j++] = pp->map[i];
263
pp->flags |= PZ_UPDATE;
264
return 0;
265
}
266
267
/*
268
* initialize the partition workspace
269
*/
270
271
int
272
pzpartinit(Pz_t* pz, Pzpart_t* pp, const char* name)
273
{
274
char* s;
275
int i;
276
int j;
277
int k;
278
size_t m;
279
size_t n;
280
281
m = 0;
282
if (!(pz->flags & PZ_FORCE) || (pz->flags & PZ_SPLIT))
283
{
284
if (!pp->row)
285
{
286
if (pz->disc->errorf)
287
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: partition header corrupted", pz->path);
288
return -1;
289
}
290
if (!pp->name)
291
{
292
if (!name)
293
sfprintf(pz->tmp, "%s:%d:%d", PZ_PART_SUF, pp->row, pp->nmap);
294
else
295
{
296
if (s = strrchr(name, '/'))
297
name = (const char*)s + 1;
298
if ((s = strrchr(name, '.')) && streq(s + 1, PZ_PART_SUF))
299
n = s - (char*)name;
300
else
301
n = strlen(name);
302
sfprintf(pz->tmp, "%.*s", n, name);
303
}
304
if (!(s = sfstruse(pz->tmp)) || !(pp->name = vmstrdup(pz->vm, s)))
305
return -1;
306
}
307
if (!pp->nmap)
308
{
309
pp->nmap = pp->row;
310
if (!(pp->map = vmnewof(pz->vm, pp->map, size_t, VECTOR(pz, pp, pp->nmap), 0)))
311
return pznospace(pz);
312
for (i = 0; i < pp->nmap; i++)
313
pp->map[i] = i;
314
}
315
if (!pp->ngrp)
316
{
317
pp->ngrp = 1;
318
if (!(pp->grp = vmnewof(pz->vm, pp->grp, size_t, VECTOR(pz, pp, pp->ngrp), 0)))
319
return pznospace(pz);
320
pp->grp[0] = pp->row;
321
}
322
pp->loq = ((pz->win / 8 / pp->row) + 8) * pp->row;
323
k = VECTOR(pz, pp, pp->nmap);
324
if (!(pp->low = vmnewof(pz->vm, 0, unsigned char, pp->row, 0)) ||
325
!(pp->mix = vmnewof(pz->vm, 0, unsigned char*, k, 0)) ||
326
!(pp->inc = vmnewof(pz->vm, 0, size_t, k, 0)) ||
327
!(pp->lab = vmnewof(pz->vm, 0, size_t, k, 0)))
328
return pznospace(pz);
329
if (pp->nfix)
330
{
331
if (!(pp->fix = vmnewof(pz->vm, 0, size_t, VECTOR(pz, pp, pp->nfix), 0)))
332
return pznospace(pz);
333
for (i = k = 0; i < pp->row; i++)
334
if (pp->value[i] >= 0)
335
pp->fix[k++] = i;
336
}
337
if (pzpartmap(pz, pp))
338
return -1;
339
if (!(j = pp->nmap))
340
j = 1;
341
k = pp->row * j;
342
pp->col = ((pz->win / k) * k) / j;
343
344
/*
345
* allocate the global tables
346
*/
347
348
if (pp->row > pz->mrow)
349
{
350
m = pz->mrow = roundof(pp->row, 1024);
351
n = ((pz->win / 8 / m) + 8 ) * m;
352
if (!(pz->val = vmnewof(pz->vm, pz->val, unsigned char, n, 0)) ||
353
!(pz->pat = vmnewof(pz->vm, pz->pat, unsigned char, m, 0)))
354
return pznospace(pz);
355
}
356
}
357
if (pz->win > pz->mwin)
358
{
359
if (pz->disc->errorf)
360
(*pz->disc->errorf)(pz, pz->disc, -1, "%s: pzpartinit: win=%I*u mwin=%I*u buf=%p", pz->path, sizeof(pz->win), pz->win, sizeof(pz->mwin), pz->mwin, pz->buf);
361
pz->mwin = roundof(pz->win, 32);
362
n = pz->mwin;
363
if (pz->flags & PZ_WRITE)
364
n *= 2;
365
if (!(pz->buf = vmnewof(pz->vm, pz->buf, unsigned char, n, 0)))
366
return pznospace(pz);
367
if (pz->flags & PZ_WRITE)
368
pz->wrk = pz->buf + pz->mwin;
369
}
370
if (m && !(pz->flags & PZ_WRITE) && !(pz->wrk = vmnewof(pz->vm, pz->wrk, unsigned char, m, 0)))
371
return pznospace(pz);
372
373
/*
374
* the discipline functions may change the partition name
375
*/
376
377
n = pp->nfix;
378
pz->part = pp;
379
if (pz->options && pzoptions(pz, pp, pz->options, 0))
380
return -1;
381
if (pz->disc->eventf && (*pz->disc->eventf)(pz, PZ_PARTITION, pp, 0, pz->disc) < 0)
382
return -1;
383
if (pp->flags & PZ_VARIABLE)
384
return 0;
385
if (pp->nfix != n)
386
{
387
if (!(pp->fix = vmnewof(pz->vm, pp->fix, size_t, VECTOR(pz, pp, pp->nfix), 0)))
388
return pznospace(pz);
389
for (i = k = 0; i < pp->row; i++)
390
if (pp->value[i] >= 0)
391
pp->low[pp->fix[k++] = i] = 0;
392
}
393
394
/*
395
* update the partition dictionary
396
* no dictionary if there's only one part
397
*/
398
399
if (pz->mainpart)
400
{
401
if (!pz->partdict)
402
{
403
pz->partdisc.key = offsetof(Pzpart_t, name);
404
pz->partdisc.size = -1;
405
pz->partdisc.link = offsetof(Pzpart_t, link);
406
if (!(pz->partdict = dtopen(&pz->partdisc, Dtoset)))
407
{
408
if (pz->disc->errorf)
409
(*pz->disc->errorf)(pz, pz->disc, 2, "partition dictionary open error");
410
return -1;
411
}
412
dtinsert(pz->partdict, pz->mainpart);
413
}
414
dtinsert(pz->partdict, pp);
415
}
416
else
417
{
418
pz->mainpart = pp;
419
if ((pz->flags & (PZ_DUMP|PZ_VERBOSE)) && !(pz->flags & PZ_SPLIT))
420
pzheadprint(pz, sfstderr, 0);
421
}
422
if ((pz->flags & PZ_DUMP) && !(pz->flags & PZ_SPLIT))
423
pzpartprint(pz, pp, sfstderr);
424
return 0;
425
}
426
427
/*
428
* parse the run time options
429
*/
430
431
int
432
pzoptions(register Pz_t* pz, register Pzpart_t* pp, char* options, int must)
433
{
434
register char* s = options;
435
char* e;
436
char* b;
437
int i;
438
int k;
439
int n;
440
int r;
441
int x;
442
int skip;
443
Sfio_t* sp;
444
Pzpart_t* opp;
445
446
optget(NiL, usage);
447
skip = 0;
448
for (;;)
449
{
450
for (; isspace(*s) || *s == ','; s++);
451
if (!*s)
452
break;
453
switch (range(pz, pp, s, &e, &n, &x))
454
{
455
case -1:
456
return -1;
457
case 1:
458
s = e;
459
if (*s++ != '=')
460
s = "";
461
if ((k = value(pz, s, &e)) < 0)
462
return -1;
463
s = e;
464
if (pp && fixed(pz, pp, n, x, k))
465
return -1;
466
continue;
467
}
468
b = s;
469
opt_info.offset = 0;
470
switch (optstr(s, NiL))
471
{
472
case 0:
473
break;
474
case '#':
475
skip = !streq(opt_info.name, "pzip");
476
continue;
477
default:
478
if (pz->disc->errorf)
479
(*pz->disc->errorf)(pz, pz->disc, -2, "pzoptions: %-.*s", opt_info.offset, s);
480
s += opt_info.offset;
481
if (skip)
482
continue;
483
484
/*
485
* the discipline gets the first crack
486
*
487
* -1 error
488
* 0 noticed but not consumed
489
* 1 consumed
490
*/
491
492
if (pz->disc->eventf)
493
{
494
opp = pz->part;
495
pz->part = pp;
496
x = (*pz->disc->eventf)(pz, PZ_OPTION, opt_info.argv[1] + 2, 0, pz->disc);
497
pz->part = opp;
498
if (x < 0)
499
return -1;
500
}
501
else
502
x = 0;
503
if (!x)
504
{
505
x = 2;
506
switch (optstr(NiL, usage))
507
{
508
case 'a':
509
if (opt_info.num)
510
pz->flags |= PZ_APPEND;
511
else
512
pz->flags &= ~PZ_APPEND;
513
break;
514
case 'c':
515
if (!pz->disc->comment && !(pz->disc->comment = vmstrdup(pz->vm, opt_info.arg)))
516
return pznospace(pz);
517
break;
518
case 'x':
519
if (opt_info.num)
520
pz->flags |= PZ_CRC;
521
else
522
pz->flags &= ~PZ_CRC;
523
break;
524
case 'd':
525
error_info.trace = -opt_info.num;
526
break;
527
case 'D':
528
if (opt_info.num)
529
pz->flags |= PZ_DUMP;
530
else
531
pz->flags &= ~PZ_DUMP;
532
break;
533
case 'G':
534
if (!opt_info.num)
535
pz->flags |= PZ_NOGZIP;
536
else
537
pz->flags &= ~PZ_NOGZIP;
538
break;
539
case 'i':
540
if (pz->pin && (sp = pzfind(pz, opt_info.arg, PZ_PART_SUF, "r")))
541
{
542
sfstack(pz->pin, sp);
543
return 0;
544
}
545
break;
546
case 'l':
547
if (!pz->pin || !sfstacked(pz->pin))
548
{
549
if (i = pz->options == options)
550
pz->options = 0;
551
r = pzlib(pz, opt_info.arg, 0);
552
if (pz->disc->errorf)
553
(*pz->disc->errorf)(pz, pz->disc, -2, "pzlib: %s status=%d", opt_info.arg, r);
554
if (i)
555
pz->options = options;
556
if (r < 0)
557
return -1;
558
}
559
break;
560
case 'n':
561
pz->partname = vmstrdup(pz->vm, opt_info.arg);
562
break;
563
case 'X':
564
if (pz->prefix.count = strton(opt_info.arg, &e, NiL, 0))
565
{
566
pz->prefix.terminator = -1;
567
if (*e == 'x' || *e == 'X' || *e == '*' || *e == '-')
568
e++;
569
if (*e == 'l' || *e == 'L')
570
pz->prefix.terminator = '\n';
571
else
572
{
573
if (*e == '"' || *e == '\'')
574
{
575
pz->prefix.terminator = chresc(e + 1, &e);
576
for (s = e; *s && !isspace(*s) && *s != ','; s++);
577
}
578
else if (*e)
579
{
580
pz->prefix.count = 0;
581
if (pz->disc->errorf)
582
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: prefix expression expected", opt_info.arg);
583
return -1;
584
}
585
}
586
}
587
else if (e > opt_info.arg)
588
pz->prefix.skip = 1;
589
break;
590
case 'O':
591
if (opt_info.num)
592
pz->flags |= PZ_SORT;
593
else
594
pz->flags &= ~PZ_SORT;
595
break;
596
case 'P':
597
if (!opt_info.num)
598
pz->flags |= PZ_NOPZIP;
599
else
600
pz->flags &= ~PZ_NOPZIP;
601
break;
602
case 'Q':
603
if (opt_info.num)
604
pz->flags |= PZ_REGRESS;
605
else
606
pz->flags &= ~PZ_REGRESS;
607
break;
608
case 'r':
609
pz->row = opt_info.num;
610
break;
611
case 'S':
612
if (opt_info.num)
613
{
614
pz->flags |= PZ_FORCE|PZ_SPLIT|PZ_SECTION;
615
if (opt_info.arg)
616
pz->split.match = vmstrdup(pz->vm, opt_info.arg);
617
}
618
else
619
pz->flags &= ~PZ_SPLIT;
620
break;
621
case 's':
622
if (opt_info.num)
623
pz->flags |= PZ_SUMMARY;
624
else
625
pz->flags &= ~PZ_SUMMARY;
626
break;
627
case 'T':
628
pz->test |= opt_info.num;
629
break;
630
case 'v':
631
if (opt_info.num)
632
pz->flags |= PZ_VERBOSE;
633
else
634
pz->flags &= ~PZ_VERBOSE;
635
break;
636
case '?':
637
error(ERROR_USAGE|4, "%s", opt_info.arg);
638
return -1;
639
case ':':
640
if (must && !(pz->flags & PZ_PUSHED))
641
{
642
if (pz->disc->errorf)
643
(*pz->disc->errorf)(pz, pz->disc, 2, "%s", opt_info.arg);
644
return -1;
645
}
646
x = 0;
647
break;
648
}
649
}
650
651
/*
652
* save consumed options for the header and
653
* clear so they are not processed again
654
*/
655
656
if (must >= 0 && (x > 1 || x && must))
657
{
658
if (pz->det)
659
{
660
if (sfstrtell(pz->det))
661
sfputc(pz->det, ' ');
662
sfwrite(pz->det, b, s - b);
663
}
664
memset(b, ' ', s - b);
665
}
666
continue;
667
}
668
break;
669
}
670
return 0;
671
}
672
673
static char*
674
partline(Pz_t* pz, Sfio_t* sp)
675
{
676
char* s;
677
678
if ((s = sfgetr(sp, '\n', 1)) && pz->disc->errorf)
679
error_info.line++;
680
return s;
681
}
682
683
/*
684
* parse and load a partition file
685
*/
686
687
int
688
pzpartition(register Pz_t* pz, const char* partition)
689
{
690
register Pzpart_t* pp;
691
int i;
692
int k;
693
int m;
694
char* s;
695
char* e;
696
char* t;
697
char* np;
698
int n;
699
int g;
700
int gi;
701
int x;
702
int* cv;
703
int* ce;
704
int* cp;
705
int* gv;
706
int* hv;
707
int line;
708
long f;
709
char* file;
710
Sfio_t* sp;
711
Vmalloc_t* vm;
712
char buf[PATH_MAX];
713
714
if (pz->disc->errorf)
715
{
716
file = error_info.file;
717
line = error_info.line;
718
}
719
sp = 0;
720
vm = 0;
721
if (!(s = (char*)partition))
722
{
723
if (pz->disc->errorf)
724
(*pz->disc->errorf)(pz, pz->disc, 2, "partition file omitted");
725
goto bad;
726
}
727
if (s[0] == '/' && s[i=strlen(s)-1] == '/')
728
{
729
if (streq(s, "/") || streq(s, "//") || streq(s, "/gzip/"))
730
n = sfsprintf(buf, sizeof(buf), "nopzip\n1\n0-0\n");
731
else
732
{
733
n = (int)strtol(s + 1, &e, 10);
734
if (e[0] == '/' && !e[1])
735
n = sfsprintf(buf, sizeof(buf), "%d\n0-%d\n", n, n - 1);
736
else
737
{
738
n = sfsprintf(buf, sizeof(buf), "%.*s\n", i - 1, s + 1);
739
for (s = buf; *s; s++)
740
if (isspace(*s) || *s == ',')
741
*s = '\n';
742
}
743
}
744
if (!(sp = sfstropen()) || sfstrbuf(sp, buf, n, 0))
745
{
746
if (pz->disc->errorf)
747
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: string stream open error", s);
748
goto bad;
749
}
750
}
751
else
752
{
753
/*
754
* consume url-ish options
755
*/
756
757
if ((e = strchr(s, '?')) || (e = strchr(s, '#')))
758
{
759
if (!(t = vmoldof(pz->vm, 0, char, e - s, 1)))
760
goto bad;
761
memcpy(t, s, e - s);
762
t[e - s] = 0;
763
s = t;
764
if (*e == '#' && !(pz->partname = vmstrdup(pz->vm, e + 1)) || *e == '?' && pzoptions(pz, NiL, e + 1, 1))
765
goto bad;
766
}
767
if (!(sp = pzfind(pz, s, PZ_PART_SUF, "r")))
768
goto bad;
769
}
770
if (pz->disc->errorf)
771
{
772
error_info.file = s;
773
error_info.line = 0;
774
}
775
if (!(vm = vmopen(&pz->vmdisc, Vmlast, 0)))
776
{
777
if (pz->disc->errorf)
778
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "partition temporary vmalloc region open error");
779
goto bad;
780
}
781
np = 0;
782
pp = 0;
783
s = "";
784
pz->pin = sp;
785
do
786
{
787
vmclear(vm);
788
do
789
{
790
if (*s != '"' && !(s = partline(pz, sp)))
791
{
792
if (pz->disc->errorf)
793
(*pz->disc->errorf)(pz, pz->disc, 2, "invalid partition file");
794
goto bad;
795
}
796
for (; isspace(*s); s++);
797
if (*s == '"')
798
{
799
if (np)
800
{
801
if (pz->disc->errorf)
802
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: partition already named", np);
803
goto bad;
804
}
805
for (e = ++s; *s && *s != '"'; s++);
806
if (!*s)
807
{
808
if (pz->disc->errorf)
809
(*pz->disc->errorf)(pz, pz->disc, 2, "unbalanced \" in partition name");
810
goto bad;
811
}
812
*s++ = 0;
813
if (!(np = vmstrdup(pz->vm, e)))
814
goto bad;
815
for (; isspace(*s); s++);
816
}
817
if (isalpha(*s))
818
{
819
if (pzoptions(pz, pp, s, 1))
820
goto bad;
821
s = "";
822
}
823
} while (!(n = strtol(s, &t, 10)));
824
if (*t == '@')
825
{
826
switch (m = strtol(t + 1, &t, 10))
827
{
828
case 1:
829
m = 0;
830
break;
831
case 2:
832
m = 1;
833
break;
834
case 4:
835
m = 2;
836
break;
837
case 8:
838
m = 3;
839
break;
840
default:
841
if (pz->disc->errorf)
842
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: %d: invalid size -- power of 2 from 1..8 expected", s, m);
843
goto bad;
844
}
845
n |= (m << 14);
846
f = PZ_VARIABLE;
847
}
848
else
849
f = 0;
850
if (pz->flags & PZ_ROWONLY)
851
{
852
if (!np || !pz->partname || streq(np, pz->partname))
853
{
854
vmclose(vm);
855
pz->row = n;
856
return 0;
857
}
858
np = 0;
859
do
860
{
861
if (!(s = partline(pz, sp)))
862
{
863
if (pz->disc->errorf)
864
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: partition not found", pz->partname);
865
goto bad;
866
}
867
for (; isspace(*s); s++);
868
} while (*s != '"');
869
continue;
870
}
871
if (!(pp = vmnewof(pz->vm, 0, Pzpart_t, 1, 0)))
872
goto nope;
873
pp->row = n;
874
pp->flags = f;
875
if (np)
876
{
877
pp->name = np;
878
np = 0;
879
}
880
if (!(cv = vmnewof(vm, 0, int, (pp->row + 1) * 4, 0)))
881
goto nope;
882
cp = cv;
883
ce = hv = cv + (pp->row + 1) * 2;
884
gv = hv + pp->row + 1;
885
m = 0;
886
g = 0;
887
for (s = t; isspace(*s); s++);
888
if (*s != '-')
889
s = partline(pz, sp);
890
for (; s; s = partline(pz, sp))
891
{
892
for (; isspace(*s); s++);
893
if (*s == '"')
894
break;
895
else if (isalpha(*s))
896
{
897
if (pzoptions(pz, pp, s, 1))
898
goto bad;
899
continue;
900
}
901
gi = 0;
902
for (;;)
903
{
904
if (range(pz, pp, s, &e, &n, &x) <= 0)
905
{
906
if (*e && *e != '#')
907
goto bad;
908
break;
909
}
910
s = e;
911
if (*s == '=')
912
{
913
if ((k = value(pz, ++s, &e)) < 0)
914
return -1;
915
s = e;
916
if (fixed(pz, pp, n, x, k))
917
goto bad;
918
continue;
919
}
920
if (cp >= ce)
921
{
922
if (pz->disc->errorf)
923
(*pz->disc->errorf)(pz, pz->disc, 2, "too many columns");
924
goto bad;
925
}
926
for (; n <= x; n++)
927
if (!pp->value || pp->value[n] < 0)
928
{
929
if (hv[n])
930
{
931
if (pz->disc->errorf)
932
(*pz->disc->errorf)(pz, pz->disc, 2, "column %d already specified", n);
933
goto bad;
934
}
935
hv[n] = 1;
936
*cp++ = n;
937
gv[m] = g;
938
m++;
939
gi = 1;
940
}
941
}
942
if (gi)
943
{
944
if (cp >= ce)
945
{
946
if (pz->disc->errorf)
947
(*pz->disc->errorf)(pz, pz->disc, 2, "too many columns");
948
goto bad;
949
}
950
*cp++ = -1;
951
g += gi;
952
}
953
}
954
if (cp >= ce)
955
{
956
if (pz->disc->errorf)
957
(*pz->disc->errorf)(pz, pz->disc, 2, "too many columns");
958
goto bad;
959
}
960
*cp++ = -1;
961
962
/*
963
* allocate the map data and work space
964
*/
965
966
pp->nmap = m;
967
if (!(pp->ngrp = g))
968
pp->ngrp = 1;
969
if (!(pp->map = vmnewof(pz->vm, 0, size_t, VECTOR(pz, pp, pp->nmap), 0)) ||
970
!(pp->grp = vmnewof(pz->vm, 0, size_t, VECTOR(pz, pp, pp->ngrp), 0)))
971
goto nope;
972
m = 0;
973
cp = cv;
974
g = 0;
975
k = 0;
976
while ((i = *cp++) >= 0)
977
do
978
{
979
if (g != gv[m])
980
{
981
pp->grp[g] = k;
982
g = gv[m];
983
k = 0;
984
}
985
pp->map[m] = i;
986
k++;
987
m++;
988
} while ((i = *cp++) >= 0);
989
pp->grp[g] = k;
990
if (pzpartinit(pz, pp, partition))
991
goto bad;
992
} while (s);
993
sfclose(sp);
994
sp = 0;
995
vmclose(vm);
996
vm = 0;
997
if (pz->partname)
998
{
999
if (!(pp = pzpartget(pz, pz->partname)))
1000
{
1001
if (pz->disc->errorf)
1002
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: partition not found", pz->partname);
1003
goto bad;
1004
}
1005
pz->flags |= PZ_MAINONLY;
1006
pz->part = pz->mainpart = pp;
1007
}
1008
if (pz->disc->errorf)
1009
{
1010
error_info.file = file;
1011
error_info.line = line;
1012
}
1013
pz->pin = 0;
1014
return 0;
1015
nope:
1016
pznospace(pz);
1017
bad:
1018
pz->pin = 0;
1019
if (sp)
1020
sfclose(sp);
1021
if (vm)
1022
vmclose(vm);
1023
if (pz->disc->errorf)
1024
{
1025
error_info.file = file;
1026
error_info.line = line;
1027
}
1028
return -1;
1029
}
1030
1031
/*
1032
* allocate and read an array from the input partition header
1033
*/
1034
1035
static int
1036
array(register Pz_t* pz, Pzpart_t* pp, size_t** pv, size_t* pn, size_t check)
1037
{
1038
register size_t n;
1039
register size_t m;
1040
register size_t* v;
1041
1042
n = sfgetu(pz->io);
1043
if (check && n > check)
1044
return -1;
1045
if (pv)
1046
{
1047
if (!n)
1048
v = 0;
1049
else if (!(v = vmnewof(pz->vm, *pv, size_t, VECTOR(pz, pp, n), 0)))
1050
return pznospace(pz);
1051
*pv = v;
1052
if (pn)
1053
*pn = n;
1054
while (n--)
1055
{
1056
m = sfgetu(pz->io);
1057
if (check && m >= check)
1058
return -1;
1059
*v++ = m;
1060
}
1061
}
1062
else
1063
while (n--)
1064
{
1065
m = sfgetu(pz->io);
1066
if (check && m >= check)
1067
return -1;
1068
}
1069
return 0;
1070
}
1071
1072
/*
1073
* allocate and read a buffer from the input partition header
1074
*/
1075
1076
static int
1077
buffer(register Pz_t* pz, Pzpart_t* pp, char** pv, size_t* pn)
1078
{
1079
register size_t n;
1080
register char* v;
1081
1082
if (!(n = sfgetu(pz->io)))
1083
{
1084
if (pz->disc->errorf)
1085
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: partition header corrupted", pz->path);
1086
return -1;
1087
}
1088
if (pv)
1089
{
1090
if (!(v = vmnewof(pz->vm, *pv, char, n, 0)))
1091
return pznospace(pz);
1092
*pv = v;
1093
if (pn)
1094
*pn = n;
1095
sfread(pz->io, v, n);
1096
}
1097
else
1098
sfseek(pz->io, (Sflong_t)n, SEEK_CUR);
1099
return 0;
1100
}
1101
1102
/*
1103
* read a pz partition header(s) from pz->io
1104
*/
1105
1106
int
1107
pzpartread(register Pz_t* pz)
1108
{
1109
register Pzpart_t* pp;
1110
register int i;
1111
Pzpart_t* po;
1112
1113
if (pz->major > 1)
1114
{
1115
if (!(i = sfgetc(pz->io)))
1116
return 0;
1117
if (i == EOF)
1118
return -1;
1119
sfungetc(pz->io, i);
1120
}
1121
if (!(pp = vmnewof(pz->vm, 0, Pzpart_t, 1, 0)))
1122
return pznospace(pz);
1123
if (pz->major == 1)
1124
{
1125
pp->row = sfgetu(pz->io);
1126
pp->col = sfgetu(pz->io);
1127
pz->win = sfgetu(pz->io);
1128
}
1129
po = 0;
1130
for (;;)
1131
{
1132
switch (i = sfgetc(pz->io))
1133
{
1134
case EOF:
1135
goto bad;
1136
case 0:
1137
if (!po && pzpartinit(pz, pp, NiL))
1138
return -1;
1139
break;
1140
case PZ_HDR_comment:
1141
buffer(pz, pp, (char**)&pz->disc->comment, NiL);
1142
continue;
1143
case PZ_HDR_fix:
1144
if (array(pz, pp, &pp->fix, &pp->nfix, pp->row))
1145
goto bad;
1146
if (!pp->value)
1147
{
1148
if (!(pp->value = vmnewof(pz->vm, 0, int, pp->row, 0)))
1149
return pznospace(pz);
1150
for (i = 0; i < pp->row; i++)
1151
pp->value[i] = -1;
1152
}
1153
for (i = 0; i < pp->nfix; i++)
1154
if (pp->value[pp->fix[i]] < 0)
1155
pp->value[pp->fix[i]] = ' ';
1156
continue;
1157
case PZ_HDR_grp:
1158
if (array(pz, pp, &pp->grp, &pp->ngrp, pp->row + 1))
1159
goto bad;
1160
continue;
1161
case PZ_HDR_map:
1162
if (array(pz, pp, &pp->map, &pp->nmap, pp->row))
1163
goto bad;
1164
continue;
1165
case PZ_HDR_options:
1166
buffer(pz, pp, (char**)&pz->headoptions, NiL);
1167
continue;
1168
case PZ_HDR_prefix:
1169
buffer(pz, pp, &pz->prefix.data, &pz->prefix.count);
1170
pz->prefix.terminator = -1;
1171
continue;
1172
case PZ_HDR_part:
1173
if (pp->row)
1174
{
1175
if (!po && pzpartinit(pz, pp, NiL))
1176
return -1;
1177
if (pp = pz->freepart)
1178
pz->freepart = 0;
1179
else if (!(pp = vmnewof(pz->vm, 0, Pzpart_t, 1, 0)))
1180
return pznospace(pz);
1181
}
1182
buffer(pz, pp, (char**)&pp->name, NiL);
1183
pp->row = sfgetu(pz->io);
1184
pp->col = sfgetu(pz->io);
1185
if (pz->partdict && (po = (Pzpart_t*)dtsearch(pz->partdict, pp)) || (po = pz->mainpart) && streq(pp->name, po->name))
1186
{
1187
if (pp->row != po->row || pp->col != po->col)
1188
{
1189
if (pz->disc->errorf)
1190
(*pz->disc->errorf)(pz, pz->disc, 1, "%s: %s: partition redefinition ignored", pz->path, pp->name);
1191
}
1192
else if (pz->flags & PZ_DUMP)
1193
sfprintf(sfstderr, "\n# %s benign redefinition\n", pp->name);
1194
vmfree(pz->vm, pp->name);
1195
pz->freepart = pp;
1196
pp->name = 0;
1197
pp = po;
1198
for (;;)
1199
{
1200
switch (i = sfgetc(pz->io))
1201
{
1202
case EOF:
1203
break;
1204
case 0:
1205
case PZ_HDR_part:
1206
sfungetc(pz->io, i);
1207
break;
1208
default:
1209
if (PZ_HDR_ARR(i))
1210
array(pz, pp, NiL, NiL, 0);
1211
else if (PZ_HDR_BUF(i))
1212
buffer(pz, pp, NiL, NiL);
1213
else
1214
goto bad;
1215
continue;
1216
}
1217
break;
1218
}
1219
}
1220
else
1221
po = 0;
1222
continue;
1223
case PZ_HDR_split:
1224
array(pz, pp, &pz->split.data, &pz->split.size, 0);
1225
pz->split.flags |= PZ_SPLIT_INFLATE;
1226
pz->flags |= PZ_SECTION;
1227
continue;
1228
default:
1229
if (PZ_HDR_ARR(i))
1230
array(pz, pp, NiL, NiL, 0);
1231
else if (PZ_HDR_BUF(i))
1232
buffer(pz, pp, NiL, NiL);
1233
else
1234
goto bad;
1235
continue;
1236
}
1237
break;
1238
}
1239
return 0;
1240
bad:
1241
if (pz->disc->errorf)
1242
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: partition header corrupted", pz->path);
1243
return -1;
1244
}
1245
1246
/*
1247
* write any new pz partition headers to op
1248
*/
1249
1250
int
1251
pzpartwrite(Pz_t* pz, Sfio_t* op)
1252
{
1253
register Pzpart_t* pp;
1254
register int i;
1255
register size_t m;
1256
int all;
1257
1258
if (pz->flags & PZ_MAINONLY)
1259
{
1260
pz->flags &= ~PZ_MAINONLY;
1261
all = 0;
1262
pp = pz->mainpart;
1263
}
1264
else if (pz->partdict)
1265
{
1266
all = 1;
1267
pp = (Pzpart_t*)dtfirst(pz->partdict);
1268
}
1269
else
1270
{
1271
all = 0;
1272
pp = pz->part;
1273
}
1274
while (pp)
1275
{
1276
if ((pp->flags & (PZ_UPDATE|PZ_HEAD)) == PZ_UPDATE)
1277
{
1278
pp->flags |= PZ_HEAD;
1279
sfputc(op, PZ_HDR_part);
1280
m = strlen(pp->name) + 1;
1281
sfputu(op, m);
1282
sfwrite(op, pp->name, m);
1283
sfputu(op, pp->row);
1284
sfputu(op, pp->col);
1285
if (pp->nmap != pp->row || pp->ngrp != 1)
1286
{
1287
sfputc(op, PZ_HDR_map);
1288
sfputu(op, pp->nmap);
1289
for (i = 0; i < pp->nmap; i++)
1290
sfputu(op, pp->map[i]);
1291
sfputc(op, PZ_HDR_grp);
1292
sfputu(op, pp->ngrp);
1293
for (i = 0; i < pp->ngrp; i++)
1294
sfputu(op, pp->grp[i]);
1295
}
1296
if (pp->nfix)
1297
{
1298
sfputc(op, PZ_HDR_fix);
1299
sfputu(op, pp->nfix);
1300
for (i = 0; i < pp->nfix; i++)
1301
sfputu(op, pp->fix[i]);
1302
}
1303
if ((pz->split.flags & (PZ_SPLIT_DEFLATE|PZ_SPLIT_HEADER)) == PZ_SPLIT_DEFLATE)
1304
{
1305
pz->split.flags |= PZ_SPLIT_HEADER;
1306
sfputc(op, PZ_HDR_split);
1307
sfputu(op, 0);
1308
}
1309
}
1310
if (!all)
1311
break;
1312
pp = (Pzpart_t*)dtnext(pz->partdict, pp);
1313
}
1314
sfputc(op, 0);
1315
return 0;
1316
}
1317
1318
/*
1319
* pretty print pp on op
1320
*/
1321
1322
int
1323
pzpartprint(Pz_t* pz, register Pzpart_t* pp, register Sfio_t* op)
1324
{
1325
register int i;
1326
register int j;
1327
register int g;
1328
register char* s;
1329
char esc[2];
1330
1331
sfprintf(op, "\n\"%s\"\n", pp->name);
1332
sfprintf(op, "\n%I*u\t# high frequency %I*u\n", sizeof(pp->row), pp->row, sizeof(pp->nmap), pp->nmap);
1333
if (pp->nfix)
1334
{
1335
sfprintf(op, "\n");
1336
esc[1] = 0;
1337
for (i = 0; i < pp->nfix; i++)
1338
{
1339
for (j = i + 1; j < pp->nfix && pp->fix[j] == pp->fix[j - 1] + 1 && pp->value[pp->fix[j]] == pp->value[pp->fix[j - 1]]; j++);
1340
sfprintf(op, "%I*u", sizeof(pp->fix[i]), pp->fix[i]);
1341
if (j > (i + 2))
1342
{
1343
i = j - 1;
1344
sfprintf(op, "-%I*u", sizeof(pp->fix[i]), pp->fix[i]);
1345
}
1346
s = fmtesc((esc[0] = pp->value[pp->fix[i]], esc));
1347
j = *s == '\'' ? '"' : '\'';
1348
sfprintf(op, "=%c%s%c\n", j, s, j);
1349
}
1350
}
1351
g = -1;
1352
for (i = 0; i < pp->nmap; i++)
1353
{
1354
if (g != pp->lab[i])
1355
{
1356
g = pp->lab[i];
1357
sfprintf(op, "\n");
1358
}
1359
else
1360
sfprintf(op, " ");
1361
for (j = i + 1; j < pp->nmap && pp->map[j] == pp->map[j - 1] + 1 && pp->lab[j] == g; j++);
1362
sfprintf(op, "%I*u", sizeof(pp->map[i]), pp->map[i]);
1363
if (j > (i + 2))
1364
{
1365
i = j - 1;
1366
sfprintf(op, "-%I*u", sizeof(pp->map[i]), pp->map[i]);
1367
}
1368
}
1369
sfprintf(op, "\n");
1370
return sferror(op) ? -1 : 0;
1371
}
1372
1373