Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/builtin/pr.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1992-2012 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
* David Korn <[email protected]> *
19
* *
20
***********************************************************************/
21
#pragma prototyped
22
/*
23
* pr
24
* Written by David Korn
25
* Mon Mar 30 15:07:41 EST 1992
26
*/
27
28
static const char usage[] =
29
"[-n?\n@(#)$Id: pr (AT&T Research) 2004-07-01 $\n]"
30
USAGE_LICENSE
31
"[+NAME?pr - print files]"
32
"[+DESCRIPTION?\bpr\b formats and prints files to the standard output."
33
" If \afile\a is \b-\b or if no files are specified then the"
34
" standard input is read.]"
35
36
"[a:across?Print columns across rather than down; \b-\b\acolumns\a must be >1.]"
37
"[c:control?Print control characters in hat (^G) and octal form.]"
38
"[C:columns|cols?Print \acolumns\a columns of output. Can also be entered"
39
" as -\acolumns\a. May not be used with \b-m\b.]#[columns:=1]"
40
"[d:double-space?Double space the output.]"
41
"[e:expand?Expand \achar\a to \awidth\a.]:?[char[width]]:=\\t8]"
42
"[f:formfeed?Use formfeeds instead of newlines to separate pages with"
43
" a 3 line page header.]"
44
"[F:bigformfeed?Use formfeeds instead of newlines to separate pages with"
45
" a 5 line page header and trailer.]"
46
"[h:header?Use \aheader\a instead of the file name in header text.]:[header]"
47
"[i:replace?Replace spaces with \achar\as to tab \awidth\a.]:?"
48
" [char[width]]:=\\t8]"
49
"[j:join?Merge full lines.]"
50
"[l:lines?The page length in lines. 10 lines are reserved for the header"
51
" and trailer.]#[lines:=66]"
52
"[m:multiple?Print the input files one per column, truncating lines to fit.]"
53
"[n:number?Number lines with \adigits\a digits followed by \asep\a.]:?"
54
" [sep[digits]]:=\\t5]"
55
"[o:indent|margin|offset?Indent each line with \aindent\a spaces.]#[indent:=0]"
56
"[p:pause?Pause before printing each page if the output is to a terminal."
57
" \apr\a prinst a BEL on the terminal and reads one line of input"
58
" before continuing. (Not implemented.)]"
59
"[P:page?Start printing with page \apage\a. Can also be entered as +\apage\a.]"
60
" #[page:=1]"
61
"[r!:warn?Warn about unreadable input files.]"
62
"[s:separate?Separate columns with \astring\a.]:?[string]"
63
"[t|T!:headers?Generate headers and trailers and pass form feeds in the input"
64
" to the output.]"
65
"[w:width?The page width in characters.]#[width:=72]"
66
"[v:literal?Print control characters in C-style form.]"
67
"[X:test?Canonicalize output for testing.]"
68
69
"\n"
70
"\n[ file ... ]\n"
71
"\n"
72
"[+SEE ALSO?\bcat\b(1), \bfold\b(1), \bless\b(1), \bmore\b(1)]"
73
;
74
75
#include <cmd.h>
76
#include <ctype.h>
77
#include <ccode.h>
78
#include <ls.h>
79
#include <tm.h>
80
81
#define A_FLAG 0x0001
82
#define D_FLAG 0x0002
83
#define F_FLAG 0x0004
84
#define M_FLAG 0x0008
85
#define R_FLAG 0x0010
86
#define T_FLAG 0x0020
87
#define P_FLAG 0x0040
88
#define X_FLAG 0x0080
89
90
#define S_NL 1
91
#define S_TAB 2
92
#define S_SPACE 4
93
94
#define DATESZ 50
95
#define SWIDTH 512
96
#define WIDTH 72
97
#define NWIDTH 5
98
#define HDRSZ 5
99
#define TABSZ 8
100
#define PAGESZ 66
101
102
typedef struct _pr_
103
{
104
Sfdisc_t disc; /* first! */
105
char state[1<<CHAR_BIT];
106
Sfio_t *outfile;
107
Sfio_t *infile;
108
Sfio_t **streams;
109
long pageno;
110
long pageskip;
111
long lineno;
112
int pagelen;
113
int offset;
114
int offlen;
115
int numwidth;
116
int columns;
117
int colno;
118
int width;
119
int flags;
120
int nopen;
121
int pageodd;
122
int igap, ogap;
123
int itab, otab;
124
int imod, omod;
125
int nchar, schar;
126
char **fieldlist;
127
char *fieldbuff;
128
char *fieldptr;
129
char **fieldlast;
130
char *header;
131
char *margin;
132
char *filename;
133
char *date;
134
struct
135
{
136
Sfdisc_t*disc;
137
char *buf;
138
char *cur;
139
char *end;
140
size_t siz;
141
unsigned char *map;
142
} control;
143
} Pr_t;
144
145
/*
146
* allocate and initialize pr global data
147
*/
148
static Pr_t *prinit(void)
149
{
150
register Pr_t *pp;
151
if(!(pp = (Pr_t*)stakalloc(DATESZ+sizeof(Pr_t))))
152
return 0;
153
pp->columns = 1;
154
pp->pageskip = pp->pageno = 0;
155
pp->pagelen = PAGESZ;
156
pp->numwidth = 0;
157
pp->flags = 0;
158
pp->igap = pp->ogap = 0;
159
pp->nchar = pp->itab = pp->otab= '\t';
160
pp->schar = 0;
161
pp->numwidth = pp->width = pp->offset = 0;
162
pp->header = 0;
163
pp->date = (char*)(pp+1);
164
memset(pp->state, 0, 1<<CHAR_BIT);
165
return pp;
166
}
167
168
/*
169
* print the page header
170
*/
171
static int prheader(register Pr_t *pp)
172
{
173
char *header = "";
174
if(pp->header)
175
header = pp->header;
176
else if(!(pp->flags&M_FLAG) && pp->filename)
177
header = pp->filename;
178
sfputc(pp->outfile,'\n');
179
sfputc(pp->outfile,'\n');
180
if(pp->offset)
181
sfwrite(pp->outfile,pp->margin,pp->offlen);
182
if(sfprintf(pp->outfile,"%s %s Page %d\n\n\n",pp->date,header,pp->pageno)<0)
183
return -1;
184
return 0;
185
}
186
187
/*
188
* print the page trailer
189
*/
190
static int prtrailer(register Pr_t *pp,int line)
191
{
192
register int n= pp->pagelen-line;
193
if(pp->flags&D_FLAG)
194
{
195
if(n==0)
196
n = !pp->pageodd;
197
else
198
n = 2*n-pp->pageodd;
199
}
200
if(pp->flags&F_FLAG)
201
{
202
if(sfputc(pp->outfile,'\f') < 0)
203
return -1;
204
}
205
else
206
{
207
if(sfnputc(pp->outfile, '\n',n+HDRSZ) < 0)
208
return -1;
209
}
210
return 0;
211
}
212
213
/*
214
* fastest version, process a page at a time
215
*/
216
static void prpage(register Pr_t *pp)
217
{
218
register int n, tflag = !(pp->flags&T_FLAG);
219
register Sfio_t *out = 0;
220
while(1)
221
{
222
if(pp->pageno++ >= pp->pageskip)
223
out = pp->outfile;
224
if(out && tflag)
225
prheader(pp);
226
if((n=sfmove(pp->infile,out,pp->pagelen,'\n')) != pp->pagelen)
227
break;
228
if(out && tflag)
229
{
230
if(!sfreserve(pp->infile,0,0)||sfvalue(pp->infile)<0)
231
break;
232
sfnputc(pp->outfile,'\n',HDRSZ);
233
}
234
}
235
if(out && tflag)
236
prtrailer(pp,n);
237
}
238
239
/*
240
* write <space> space characters into output buffer using
241
* tab characters where appropriae.
242
* <col> is the number of columns until the next tab position
243
* The number of characters written is returned
244
*/
245
static int outspaces(register Pr_t* pp,register int spaces, register int col)
246
{
247
register int n=0;
248
if(pp->ogap)
249
{
250
/* changes spaces <pp->otab> */
251
while(spaces >= col)
252
{
253
if(sfputc(pp->outfile,pp->otab) < 0)
254
return -1;
255
n++;
256
spaces -= col;
257
col = pp->ogap;
258
}
259
}
260
if(spaces>0)
261
if(sfnputc(pp->outfile,' ',spaces) < 0)
262
return -1;
263
return n+=spaces;
264
}
265
266
/*
267
* Output one column which could be the complete line
268
* Do tab canonicalization if necessary
269
* <spaces> give the number of spaces that precede the field
270
* This routine returns the number of spaces at end of field
271
*/
272
static int outcol(register Pr_t *pp,char *buff, register int size, int spaces)
273
{
274
register char *state=pp->state;
275
register int n=S_NL,col=0;
276
register char *cp, *buffend;
277
register int omod=0;
278
if(pp->igap || pp->ogap)
279
{
280
cp = buff;
281
buffend = cp+size;
282
if(size=spaces)
283
{
284
if(pp->ogap)
285
omod = pp->ogap - (pp->colno-size)%pp->ogap;
286
if(n = state[*(unsigned char*)cp++])
287
goto skip;
288
outspaces(pp,size,omod);
289
}
290
while(1)
291
{
292
/* skip over regular characters */
293
while((n=state[*(unsigned char*)cp++])==0);
294
size= cp-buff;
295
col += (size-1);
296
if(pp->width && col >= pp->width)
297
{
298
size -= (col+1-pp->width);
299
if(buffend[-1]=='\n')
300
{
301
buff[size-1] = '\n';
302
break;
303
}
304
}
305
if(n==S_NL)
306
break;
307
if(sfwrite(pp->outfile,buff,--size)< 0)
308
return -1;
309
if(pp->width && col >= pp->width)
310
return 1;
311
size = 0;
312
if(pp->ogap)
313
omod = pp->ogap - (pp->colno+col)%pp->ogap;
314
skip:
315
while(n>S_NL && cp < buffend)
316
{
317
if(n==S_SPACE)
318
n = 1;
319
else
320
n= (pp->igap-(col%pp->igap));
321
size += n;
322
col += n;
323
n = state[*(unsigned char*)cp++];
324
}
325
if(n==S_NL)
326
{
327
/* delete trailing white-space */
328
sfputc(pp->outfile,'\n');
329
return 0;
330
331
}
332
if(cp>=buffend || (pp->width && col>=pp->width))
333
{
334
/* return spaces needed to complete field */
335
if(col>=pp->width)
336
{
337
if(buffend[-1]=='\n')
338
{
339
sfputc(pp->outfile,'\n');
340
return 0;
341
}
342
size -= (col-pp->width);
343
}
344
else
345
size += pp->width-col;
346
return size;
347
}
348
outspaces(pp,size,omod);
349
size = 0;
350
buff = cp-1;
351
}
352
}
353
if(size>0 && sfwrite(pp->outfile,buff,size)< 0)
354
return -1;
355
return 0;
356
}
357
358
/*
359
* print a line at a time
360
*/
361
static int prline(register Pr_t *pp)
362
{
363
register int n, line = pp->pagelen;
364
register char *cp;
365
pp->colno = pp->offset;
366
if(pp->pageskip > 0)
367
{
368
n = pp->pageskip*pp->pagelen;
369
if(sfmove(pp->infile, NiL, n, '\n')!=n)
370
return 0;
371
}
372
while(cp = sfgetr(pp->infile,'\n',0))
373
{
374
n = sfvalue(pp->infile);
375
if(line >= pp->pagelen)
376
{
377
line = 0;
378
pp->pageno++;
379
if(!(pp->flags&T_FLAG) && prheader(pp)<0)
380
return -1;
381
}
382
if(pp->offset)
383
sfwrite(pp->outfile,pp->margin,pp->offlen);
384
if(pp->numwidth)
385
sfprintf(pp->outfile,"%*d%c",pp->numwidth,++pp->lineno,pp->nchar);
386
if(outcol(pp,cp,n,0) < 0)
387
return -1;
388
if(++line >= pp->pagelen && !(pp->flags&T_FLAG))
389
{
390
if(pp->flags&F_FLAG)
391
sfputc(pp->outfile,'\f');
392
else
393
sfnputc(pp->outfile, '\n',HDRSZ);
394
}
395
else if(pp->flags&D_FLAG)
396
sfputc(pp->outfile,'\n');
397
}
398
if(!(pp->flags&T_FLAG))
399
prtrailer(pp,line);
400
return 0;
401
}
402
403
/*
404
* output page containing <n> fields
405
*/
406
static int outpage(register Pr_t *pp,int n)
407
{
408
register char *cp,**next = pp->fieldlist;
409
register int line=0, incr, size,j, c, old;
410
if(pp->pageno++ < pp->pageskip)
411
{
412
pp->lineno += pp->pagelen;
413
return 0;
414
}
415
if(!(pp->flags&T_FLAG))
416
prheader(pp);
417
if(pp->flags&A_FLAG)
418
incr = 1;
419
else
420
incr = (n+pp->columns-1)/pp->columns;
421
while(1)
422
{
423
/* print out a line */
424
if(!(pp->flags&A_FLAG))
425
{
426
if(line>=incr)
427
break;
428
next = pp->fieldlist + line;
429
}
430
else if(next >= pp->fieldlast)
431
break;
432
if(pp->offset)
433
sfwrite(pp->outfile,pp->margin,pp->offlen);
434
if(pp->numwidth)
435
sfprintf(pp->outfile,"%*d%c",pp->numwidth,++pp->lineno,pp->nchar);
436
pp->colno = pp->offset;
437
for(old=0,j=pp->columns; --j>=0; )
438
{
439
if(next+incr >= pp->fieldlast)
440
j=0;
441
cp = *next;
442
size = next[1]-cp;
443
if(j==0)
444
c = '\n';
445
else
446
c = ' ';
447
cp[size-1] = c;
448
if((old=outcol(pp,cp,size,old))<0)
449
return -1;
450
pp->colno += pp->width;
451
if(j>0 && pp->schar)
452
{
453
sfputc(pp->outfile,pp->schar);
454
pp->colno = old;
455
if(pp->schar==pp->otab && pp->ogap)
456
pp->colno += pp->ogap - pp->colno%pp->ogap;
457
else
458
pp->colno++;
459
old = 0;
460
}
461
next += incr;
462
}
463
if(++line >= pp->pagelen)
464
break;
465
if(pp->flags&D_FLAG)
466
sfputc(pp->outfile,'\n');
467
}
468
if(!(pp->flags&T_FLAG))
469
prtrailer(pp,line);
470
return 0;
471
}
472
473
/*
474
* This routine processes multi-column and merged files
475
* The data is put into in array and printed when the page fills.
476
*/
477
static int prcol(register Pr_t *pp)
478
{
479
register char *cp, **next, **nextmax;
480
register int n=0, size;
481
register Sfio_t *fp=pp->infile;
482
int nstream,r=0, skip=pp->pageskip;
483
nextmax = pp->fieldlist + pp->columns*pp->pagelen;
484
do
485
{
486
next = pp->fieldlist;
487
*next = pp->fieldptr = pp->fieldbuff;
488
if(pp->streams)
489
{
490
nstream = 0;
491
fp = *pp->streams;
492
}
493
while(1)
494
{
495
if(fp && (cp = sfgetr(fp,'\n',0)))
496
{
497
if((size=sfvalue(fp)) > pp->width)
498
size = pp->width;
499
if(!skip)
500
memcpy(pp->fieldptr,cp,size);
501
}
502
else if(pp->streams)
503
{
504
if(fp)
505
{
506
if(fp!=sfstdin)
507
sfclose(fp);
508
pp->streams[nstream] = 0;
509
if(--pp->nopen<=0)
510
{
511
next -= (pp->columns-1);
512
break;
513
}
514
}
515
size=1;
516
}
517
else
518
break;
519
pp->fieldptr +=size;
520
*++next = pp->fieldptr;
521
if(next >= nextmax)
522
break;
523
if(pp->streams)
524
{
525
if(++nstream>=pp->columns)
526
nstream = 0;
527
fp = pp->streams[nstream];
528
}
529
}
530
if(skip>0)
531
{
532
skip--;
533
break;
534
}
535
pp->fieldlast = next;
536
if((n = next - pp->fieldlist) > 0)
537
r=outpage(pp,n);
538
}
539
while(cp);
540
return r;
541
}
542
543
static ssize_t
544
c_read(Sfio_t* fp, void* buf, size_t n, Sfdisc_t* dp)
545
{
546
register Pr_t* pp = (Pr_t*)dp;
547
register char* s = (char*)buf;
548
register char* e = s + n;
549
register int c;
550
ssize_t z;
551
552
static const char hat[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
553
554
if (pp->control.cur >= pp->control.end)
555
{
556
if (n > pp->control.siz)
557
{
558
pp->control.siz = roundof(n, 1024);
559
if (!(pp->control.buf = newof(pp->control.buf, char, pp->control.siz, 0)))
560
error(ERROR_exit(1), "out of space");
561
}
562
if ((z = sfrd(fp, pp->control.buf, n, dp)) <= 0)
563
return z;
564
pp->control.cur = pp->control.buf;
565
pp->control.end = pp->control.buf + z;
566
}
567
while (pp->control.cur < pp->control.end && s < e)
568
{
569
if ((c = mbsize(pp->control.cur)) > 1)
570
{
571
if (c > (e - s))
572
break;
573
while (c--)
574
*s++ = *pp->control.cur++;
575
}
576
else
577
{
578
c = ccmapchr(pp->control.map, *pp->control.cur);
579
if (c > 040 || c == 011 || c == 012)
580
*s++ = *pp->control.cur++;
581
else if ((e - s) < 2)
582
break;
583
else
584
{
585
pp->control.cur++;
586
*s++ = '^';
587
*s++ = hat[c];
588
}
589
}
590
}
591
return s - (char*)buf;
592
}
593
594
static ssize_t
595
v_read(Sfio_t* fp, void* buf, size_t n, Sfdisc_t* dp)
596
{
597
register Pr_t* pp = (Pr_t*)dp;
598
register char* s = (char*)buf;
599
register char* e = s + n;
600
register char* t;
601
register int c;
602
ssize_t z;
603
604
if (pp->control.cur >= pp->control.end)
605
{
606
if (n > pp->control.siz)
607
{
608
pp->control.siz = roundof(n, 1024);
609
if (!(pp->control.buf = newof(pp->control.buf, char, pp->control.siz, 0)))
610
error(ERROR_exit(1), "out of space");
611
}
612
if ((z = sfrd(fp, pp->control.buf, n, dp)) <= 0)
613
return z;
614
pp->control.cur = pp->control.buf;
615
pp->control.end = pp->control.buf + z;
616
}
617
while (pp->control.cur < pp->control.end && s < e)
618
{
619
if ((c = mbsize(pp->control.cur)) > 1)
620
{
621
if (c > (e - s))
622
break;
623
while (c--)
624
*s++ = *pp->control.cur++;
625
}
626
else
627
{
628
c = *pp->control.cur++;
629
if ((iscntrl(c) || !isprint(c)) && c != '\t' && c != '\n' || c == '\\')
630
{
631
t = fmtquote(pp->control.cur - 1, NiL, NiL, 1, 0);
632
if (strlen(t) > (e - s))
633
{
634
pp->control.cur--;
635
break;
636
}
637
while (*s = *t++)
638
s++;
639
}
640
else
641
*s++ = c;
642
}
643
}
644
return s - (char*)buf;
645
}
646
647
int
648
b_pr(int argc, char** argv, Shbltin_t* context)
649
{
650
register int n;
651
register Pr_t *pp;
652
register char *cp;
653
register Sfio_t *fp;
654
struct stat statb;
655
656
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
657
pp = prinit();
658
for (;;)
659
{
660
switch (n = optget(argv, usage))
661
{
662
case 0:
663
break;
664
case 'a':
665
pp->flags |= A_FLAG;
666
continue;
667
case 'c':
668
pp->control.disc = &pp->disc;
669
pp->control.disc->readf = c_read;
670
pp->control.map = ccmap(CC_NATIVE, CC_ASCII);
671
continue;
672
case 'd':
673
pp->flags |= D_FLAG;
674
continue;
675
case 'f':
676
pp->flags |= (P_FLAG|F_FLAG);
677
continue;
678
case 'F':
679
pp->flags |= F_FLAG;
680
continue;
681
case 'm':
682
pp->flags |= M_FLAG;
683
continue;
684
case 'p':
685
pp->flags |= P_FLAG;
686
continue;
687
case 'r':
688
pp->flags |= R_FLAG;
689
continue;
690
case 't':
691
case 'T':
692
pp->flags |= T_FLAG;
693
continue;
694
case 'C':
695
if(opt_info.option[0]=='-')
696
pp->columns = opt_info.num;
697
else
698
pp->pageskip = opt_info.num-1;
699
continue;
700
case 'h':
701
pp->header = opt_info.arg;
702
continue;
703
case 'w':
704
pp->width = opt_info.num;
705
continue;
706
case 'l':
707
pp->pagelen = opt_info.num;
708
continue;
709
case 'o':
710
pp->offset = opt_info.num;
711
continue;
712
case 'P':
713
pp->pageskip = opt_info.num-1;
714
continue;
715
case 'n':
716
case 'i':
717
case 'e':
718
if(opt_info.arg && opt_info.arg==argv[opt_info.index-1] && (!(cp=argv[opt_info.index]) || *cp!='-'))
719
{
720
/* space allowed only if next argument
721
* begins with - */
722
opt_info.index--;
723
opt_info.arg = 0;
724
}
725
if(n=='e')
726
pp->igap = TABSZ;
727
else if(n=='i')
728
pp->ogap = TABSZ;
729
else
730
pp->numwidth = NWIDTH;
731
if(opt_info.arg)
732
{
733
if(!isdigit(*opt_info.arg))
734
{
735
if(n=='e')
736
pp->itab = *opt_info.arg++;
737
else if(n=='i')
738
pp->otab = *opt_info.arg++;
739
else
740
pp->nchar = *opt_info.arg++;
741
}
742
if(*opt_info.arg)
743
{
744
long l = strtol(opt_info.arg,&opt_info.arg,10);
745
if(l<0 || *opt_info.arg)
746
error(2,"-%c: requires positive integer",n);
747
if(n=='e')
748
pp->igap = l;
749
else if(n=='i')
750
pp->ogap = l;
751
else
752
pp->numwidth = l;
753
}
754
}
755
continue;
756
case 's':
757
if(opt_info.arg && opt_info.arg==argv[opt_info.index-1] && (!(cp=argv[opt_info.index]) || *cp!='-'))
758
{
759
/* space allowed only if next argument
760
* begins with - */
761
opt_info.index--;
762
opt_info.arg = 0;
763
}
764
if(opt_info.arg)
765
pp->schar = *opt_info.arg;
766
else
767
pp->schar = '\t';
768
continue;
769
case 'v':
770
pp->control.disc = &pp->disc;
771
pp->control.disc->readf = v_read;
772
continue;
773
case 'X':
774
pp->flags |= X_FLAG;
775
continue;
776
case ':':
777
error(2, "%s", opt_info.arg);
778
break;
779
case '?':
780
error(ERROR_usage(2), "%s", opt_info.arg);
781
break;
782
default:
783
error(2, "-%c: not implemented", n);
784
continue;
785
}
786
break;
787
}
788
argv += opt_info.index;
789
if(error_info.errors)
790
error(ERROR_usage(2), "%s", optusage(NiL));
791
pp->outfile = sfstdout;
792
if(pp->pagelen<=(2*HDRSZ))
793
pp->flags |= T_FLAG;
794
if(!(pp->flags&T_FLAG))
795
pp->pagelen -= (2*HDRSZ);
796
pp->pageodd = (pp->pagelen&1);
797
if(pp->flags&D_FLAG)
798
pp->pagelen = (pp->pagelen+1)/2;
799
if(pp->flags&M_FLAG)
800
{
801
pp->columns = argc-opt_info.index;
802
pp->flags |= A_FLAG;
803
}
804
#if 0
805
if(pp->width)
806
pp->width -= pp->offset;
807
#endif
808
if(pp->columns > 0)
809
{
810
if(pp->columns==1)
811
{
812
pp->columns = 0;
813
pp->flags &= ~(M_FLAG|A_FLAG);
814
}
815
else
816
{
817
if(pp->igap==0)
818
pp->igap = TABSZ;
819
if(pp->ogap==0)
820
pp->ogap = TABSZ;
821
if((n=pp->width)==0)
822
#if 0
823
n = (pp->schar?SWIDTH:(WIDTH-pp->offset));
824
#else
825
n = (pp->schar?SWIDTH:WIDTH);
826
#endif
827
n -= pp->numwidth;
828
if((pp->width = ((n+1)/pp->columns)) <=0)
829
error(ERROR_exit(1),"width too small");
830
n = (pp->pagelen*pp->columns+1);
831
if(!(pp->fieldlist = (char**)stakalloc(n*(sizeof(char*)+pp->width))))
832
error(ERROR_exit(1),"not enough memory");
833
pp->fieldbuff = pp->fieldptr = (char*)(pp->fieldlist+n);
834
}
835
}
836
if(pp->igap)
837
pp->state[pp->itab] = S_TAB;
838
pp->state[' '] |= S_SPACE;
839
pp->state['\n'] = S_NL;
840
if(pp->ogap)
841
pp->omod = (pp->numwidth+pp->numwidth>0)%pp->ogap;
842
if(pp->offset)
843
{
844
/* pre-compute leading margin */
845
if(pp->ogap)
846
{
847
n = pp->offset/pp->ogap;
848
pp->offlen = pp->offset - n*(pp->ogap-1);
849
}
850
else
851
n = 0;
852
if(!(pp->margin = (char*)stakalloc(pp->offset)))
853
error(ERROR_exit(1),"not enough memory");
854
for(cp=pp->margin; cp < pp->margin+pp->offlen; cp++)
855
{
856
if(n-- > 0)
857
*cp = pp->otab;
858
else
859
*cp = ' ';
860
}
861
}
862
if(cp = *argv)
863
argv++;
864
do
865
{
866
pp->filename = cp;
867
if(!cp || strcmp(cp,"-")==0)
868
fp = sfstdin;
869
else if(!(fp = sfopen(NiL,cp,"r")))
870
{
871
if(!(pp->flags&R_FLAG))
872
error(ERROR_system(0),"%s: cannot open",cp);
873
error_info.errors = 1;
874
continue;
875
}
876
if (pp->control.disc && !sfdisc(fp, pp->control.disc))
877
error(2, "cannot push control character discipline");
878
if(pp->streams)
879
pp->streams[n++] = fp;
880
else
881
{
882
if(!(pp->flags&T_FLAG))
883
{
884
if(pp->flags&X_FLAG)
885
strcpy(pp->date, "- Date/Time --");
886
else
887
tmfmt(pp->date, DATESZ, "%b %e %H:%M %Y", fstat(sffileno(fp), &statb) ? (time_t*)0 : &statb.st_mtime);
888
}
889
pp->lineno = pp->pageno = 0;
890
pp->infile = fp;
891
if(pp->flags&M_FLAG)
892
{
893
pp->streams = (Sfio_t**)stakalloc(pp->columns*sizeof(Sfio_t*));
894
*pp->streams = fp;
895
n=1;
896
continue;
897
}
898
if(pp->columns)
899
prcol(pp);
900
else if(pp->width || pp->igap || pp->ogap || pp->offset || pp->numwidth || (pp->flags&D_FLAG))
901
prline(pp);
902
else
903
prpage(pp);
904
if(fp!=sfstdin)
905
sfclose(fp);
906
}
907
}
908
while(cp= *argv++);
909
if(pp->streams)
910
{
911
pp->nopen = n;
912
prcol(pp);
913
}
914
if (pp->control.buf)
915
free(pp->control.buf);
916
return error_info.errors != 0;
917
}
918
919