13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier #include <ctype.h>
53e12c5d1SDavid du Colombier
63e12c5d1SDavid du Colombier /*
73e12c5d1SDavid du Colombier * PR command (print files in pages and columns, with headings)
83e12c5d1SDavid du Colombier * 2+head+2+page[56]+5
93e12c5d1SDavid du Colombier */
103e12c5d1SDavid du Colombier
11bd389b36SDavid du Colombier #define ISPRINT(c) ((c) >= ' ')
123e12c5d1SDavid du Colombier #define ESC '\033'
133e12c5d1SDavid du Colombier #define LENGTH 66
143e12c5d1SDavid du Colombier #define LINEW 72
153e12c5d1SDavid du Colombier #define NUMW 5
163e12c5d1SDavid du Colombier #define MARGIN 10
173e12c5d1SDavid du Colombier #define DEFTAB 8
18*208510e1SDavid du Colombier #define NFILES 20
193e12c5d1SDavid du Colombier #define HEAD "%12.12s %4.4s %s Page %d\n\n\n", date+4, date+24, head, Page
203e12c5d1SDavid du Colombier #define TOLOWER(c) (isupper(c) ? tolower(c) : c) /* ouch! */
213e12c5d1SDavid du Colombier #define cerror(S) fprint(2, "pr: %s", S)
223e12c5d1SDavid du Colombier #define STDINNAME() nulls
233e12c5d1SDavid du Colombier #define TTY "/dev/cons", 0
243e12c5d1SDavid du Colombier #define PROMPT() fprint(2, "\a") /* BEL */
253e12c5d1SDavid du Colombier #define TABS(N,C) if((N = intopt(argv, &C)) < 0) N = DEFTAB
263e12c5d1SDavid du Colombier #define ETABS (Inpos % Etabn)
27d9dc5dd1SDavid du Colombier #define ITABS (Itabn > 0 && Nspace > 1 && Nspace >= (nc = Itabn - Outpos % Itabn))
283e12c5d1SDavid du Colombier #define NSEPC '\t'
293e12c5d1SDavid du Colombier #define EMPTY 14 /* length of " -- empty file" */
303e12c5d1SDavid du Colombier
313e12c5d1SDavid du Colombier typedef struct Fils Fils;
323e12c5d1SDavid du Colombier typedef struct Colp* Colp;
333e12c5d1SDavid du Colombier typedef struct Err Err;
343e12c5d1SDavid du Colombier
353e12c5d1SDavid du Colombier struct Fils
363e12c5d1SDavid du Colombier {
373e12c5d1SDavid du Colombier Biobuf* f_f;
383e12c5d1SDavid du Colombier char* f_name;
39bd389b36SDavid du Colombier long f_nextc;
403e12c5d1SDavid du Colombier };
413e12c5d1SDavid du Colombier struct Colp
423e12c5d1SDavid du Colombier {
43bd389b36SDavid du Colombier Rune* c_ptr;
44bd389b36SDavid du Colombier Rune* c_ptr0;
453e12c5d1SDavid du Colombier long c_lno;
463e12c5d1SDavid du Colombier };
473e12c5d1SDavid du Colombier struct Err
483e12c5d1SDavid du Colombier {
493e12c5d1SDavid du Colombier Err* e_nextp;
503e12c5d1SDavid du Colombier char* e_mess;
513e12c5d1SDavid du Colombier };
523e12c5d1SDavid du Colombier
533e12c5d1SDavid du Colombier int Balance = 0;
543e12c5d1SDavid du Colombier Biobuf bout;
55bd389b36SDavid du Colombier Rune* Bufend;
56bd389b36SDavid du Colombier Rune* Buffer = 0;
57bd389b36SDavid du Colombier int C = '\0';
58bd389b36SDavid du Colombier Colp Colpts;
59bd389b36SDavid du Colombier int Colw;
60bd389b36SDavid du Colombier int Dblspace = 1;
61bd389b36SDavid du Colombier Err* err = 0;
62bd389b36SDavid du Colombier int error = 0;
63bd389b36SDavid du Colombier int Etabc = '\t';
64bd389b36SDavid du Colombier int Etabn = 0;
65bd389b36SDavid du Colombier Fils* Files;
66bd389b36SDavid du Colombier int Formfeed = 0;
67bd389b36SDavid du Colombier int Fpage = 1;
68bd389b36SDavid du Colombier char* Head = 0;
69bd389b36SDavid du Colombier int Inpos;
70bd389b36SDavid du Colombier int Itabc = '\t';
71bd389b36SDavid du Colombier int Itabn = 0;
72bd389b36SDavid du Colombier Err* Lasterr = (Err*)&err;
73bd389b36SDavid du Colombier int Lcolpos;
74bd389b36SDavid du Colombier int Len = LENGTH;
75bd389b36SDavid du Colombier int Line;
76bd389b36SDavid du Colombier int Linew = 0;
77bd389b36SDavid du Colombier long Lnumb = 0;
78bd389b36SDavid du Colombier int Margin = MARGIN;
79bd389b36SDavid du Colombier int Multi = 0;
80bd389b36SDavid du Colombier int Ncols = 1;
81bd389b36SDavid du Colombier int Nfiles = 0;
82bd389b36SDavid du Colombier int Nsepc = NSEPC;
83bd389b36SDavid du Colombier int Nspace;
84bd389b36SDavid du Colombier char nulls[] = "";
85bd389b36SDavid du Colombier int Numw;
86bd389b36SDavid du Colombier int Offset = 0;
87bd389b36SDavid du Colombier int Outpos;
887dd7cddfSDavid du Colombier int Padodd;
89bd389b36SDavid du Colombier int Page;
90bd389b36SDavid du Colombier int Pcolpos;
91bd389b36SDavid du Colombier int Plength;
92bd389b36SDavid du Colombier int Sepc = 0;
933e12c5d1SDavid du Colombier
943e12c5d1SDavid du Colombier extern int atoix(char**);
95bd389b36SDavid du Colombier extern void balance(int);
963e12c5d1SDavid du Colombier extern void die(char*);
973e12c5d1SDavid du Colombier extern void errprint(void);
98bd389b36SDavid du Colombier extern char* ffiler(char*);
99bd389b36SDavid du Colombier extern int findopt(int, char**);
100bd389b36SDavid du Colombier extern int get(int);
101bd389b36SDavid du Colombier extern void* getspace(ulong);
102bd389b36SDavid du Colombier extern int intopt(char**, int*);
103bd389b36SDavid du Colombier extern void main(int, char**);
104bd389b36SDavid du Colombier extern Biobuf* mustopen(char*, Fils*);
105bd389b36SDavid du Colombier extern void nexbuf(void);
106bd389b36SDavid du Colombier extern int pr(char*);
107bd389b36SDavid du Colombier extern void put(long);
108bd389b36SDavid du Colombier extern void putpage(void);
109bd389b36SDavid du Colombier extern void putspace(void);
1103e12c5d1SDavid du Colombier
1113e12c5d1SDavid du Colombier /*
1123e12c5d1SDavid du Colombier * return date file was last modified
1133e12c5d1SDavid du Colombier */
1143e12c5d1SDavid du Colombier char*
getdate(void)1153e12c5d1SDavid du Colombier getdate(void)
1163e12c5d1SDavid du Colombier {
1173e12c5d1SDavid du Colombier static char *now = 0;
1189a747e4fSDavid du Colombier static Dir *sbuf;
1199a747e4fSDavid du Colombier ulong mtime;
1203e12c5d1SDavid du Colombier
1213e12c5d1SDavid du Colombier if(Nfiles > 1 || Files->f_name == nulls) {
1223e12c5d1SDavid du Colombier if(now == 0) {
1239a747e4fSDavid du Colombier mtime = time(0);
1249a747e4fSDavid du Colombier now = ctime(mtime);
1253e12c5d1SDavid du Colombier }
1263e12c5d1SDavid du Colombier return now;
1273e12c5d1SDavid du Colombier }
1289a747e4fSDavid du Colombier mtime = 0;
1299a747e4fSDavid du Colombier sbuf = dirstat(Files->f_name);
1309a747e4fSDavid du Colombier if(sbuf){
1319a747e4fSDavid du Colombier mtime = sbuf->mtime;
1329a747e4fSDavid du Colombier free(sbuf);
1339a747e4fSDavid du Colombier }
1349a747e4fSDavid du Colombier return ctime(mtime);
1353e12c5d1SDavid du Colombier }
1363e12c5d1SDavid du Colombier
1373e12c5d1SDavid du Colombier char*
ffiler(char * s)1383e12c5d1SDavid du Colombier ffiler(char *s)
1393e12c5d1SDavid du Colombier {
1409a747e4fSDavid du Colombier return smprint("can't open %s\n", s);
1413e12c5d1SDavid du Colombier }
1423e12c5d1SDavid du Colombier
1433e12c5d1SDavid du Colombier void
main(int argc,char * argv[])1443e12c5d1SDavid du Colombier main(int argc, char *argv[])
1453e12c5d1SDavid du Colombier {
1463e12c5d1SDavid du Colombier Fils fstr[NFILES];
1473e12c5d1SDavid du Colombier int nfdone = 0;
1483e12c5d1SDavid du Colombier
1493e12c5d1SDavid du Colombier Binit(&bout, 1, OWRITE);
1503e12c5d1SDavid du Colombier Files = fstr;
1513e12c5d1SDavid du Colombier for(argc = findopt(argc, argv); argc > 0; --argc, ++argv)
1523e12c5d1SDavid du Colombier if(Multi == 'm') {
1533e12c5d1SDavid du Colombier if(Nfiles >= NFILES - 1)
1543e12c5d1SDavid du Colombier die("too many files");
1553e12c5d1SDavid du Colombier if(mustopen(*argv, &Files[Nfiles++]) == 0)
1563e12c5d1SDavid du Colombier nfdone++; /* suppress printing */
1573e12c5d1SDavid du Colombier } else {
1583e12c5d1SDavid du Colombier if(pr(*argv))
159219b2ee8SDavid du Colombier Bterm(Files->f_f);
1603e12c5d1SDavid du Colombier nfdone++;
1613e12c5d1SDavid du Colombier }
1623e12c5d1SDavid du Colombier if(!nfdone) /* no files named, use stdin */
1633e12c5d1SDavid du Colombier pr(nulls); /* on GCOS, use current file, if any */
1643e12c5d1SDavid du Colombier errprint(); /* print accumulated error reports */
1653e12c5d1SDavid du Colombier exits(error? "error": 0);
1663e12c5d1SDavid du Colombier }
1673e12c5d1SDavid du Colombier
1683e12c5d1SDavid du Colombier int
findopt(int argc,char * argv[])1693e12c5d1SDavid du Colombier findopt(int argc, char *argv[])
1703e12c5d1SDavid du Colombier {
1713e12c5d1SDavid du Colombier char **eargv = argv;
1723e12c5d1SDavid du Colombier int eargc = 0, c;
1733e12c5d1SDavid du Colombier
1743e12c5d1SDavid du Colombier while(--argc > 0) {
1753e12c5d1SDavid du Colombier switch(c = **++argv) {
1763e12c5d1SDavid du Colombier case '-':
177bd389b36SDavid du Colombier if((c = *++*argv) == '\0')
178bd389b36SDavid du Colombier break;
1793e12c5d1SDavid du Colombier case '+':
1803e12c5d1SDavid du Colombier do {
181bd389b36SDavid du Colombier if(isdigit(c)) {
182bd389b36SDavid du Colombier --*argv;
183bd389b36SDavid du Colombier Ncols = atoix(argv);
184bd389b36SDavid du Colombier } else
185bd389b36SDavid du Colombier switch(c = TOLOWER(c)) {
186bd389b36SDavid du Colombier case '+':
187bd389b36SDavid du Colombier if((Fpage = atoix(argv)) < 1)
1883e12c5d1SDavid du Colombier Fpage = 1;
1893e12c5d1SDavid du Colombier continue;
190bd389b36SDavid du Colombier case 'd':
191bd389b36SDavid du Colombier Dblspace = 2;
1923e12c5d1SDavid du Colombier continue;
193bd389b36SDavid du Colombier case 'e':
194bd389b36SDavid du Colombier TABS(Etabn, Etabc);
195bd389b36SDavid du Colombier continue;
196bd389b36SDavid du Colombier case 'f':
197bd389b36SDavid du Colombier Formfeed++;
198bd389b36SDavid du Colombier continue;
199bd389b36SDavid du Colombier case 'h':
200bd389b36SDavid du Colombier if(--argc > 0)
201bd389b36SDavid du Colombier Head = argv[1];
202bd389b36SDavid du Colombier continue;
203bd389b36SDavid du Colombier case 'i':
204bd389b36SDavid du Colombier TABS(Itabn, Itabc);
205bd389b36SDavid du Colombier continue;
206bd389b36SDavid du Colombier case 'l':
207bd389b36SDavid du Colombier Len = atoix(argv);
208bd389b36SDavid du Colombier continue;
2093e12c5d1SDavid du Colombier case 'a':
210bd389b36SDavid du Colombier case 'm':
211bd389b36SDavid du Colombier Multi = c;
212bd389b36SDavid du Colombier continue;
213bd389b36SDavid du Colombier case 'o':
214bd389b36SDavid du Colombier Offset = atoix(argv);
215bd389b36SDavid du Colombier continue;
2163e12c5d1SDavid du Colombier case 's':
2173e12c5d1SDavid du Colombier if((Sepc = (*argv)[1]) != '\0')
2183e12c5d1SDavid du Colombier ++*argv;
2193e12c5d1SDavid du Colombier else
2203e12c5d1SDavid du Colombier Sepc = '\t';
2213e12c5d1SDavid du Colombier continue;
222bd389b36SDavid du Colombier case 't':
223bd389b36SDavid du Colombier Margin = 0;
2243e12c5d1SDavid du Colombier continue;
225bd389b36SDavid du Colombier case 'w':
226bd389b36SDavid du Colombier Linew = atoix(argv);
227bd389b36SDavid du Colombier continue;
2283e12c5d1SDavid du Colombier case 'n':
229bd389b36SDavid du Colombier Lnumb++;
2303e12c5d1SDavid du Colombier if((Numw = intopt(argv, &Nsepc)) <= 0)
2313e12c5d1SDavid du Colombier Numw = NUMW;
232bd389b36SDavid du Colombier case 'b':
233bd389b36SDavid du Colombier Balance = 1;
234bd389b36SDavid du Colombier continue;
2357dd7cddfSDavid du Colombier case 'p':
2367dd7cddfSDavid du Colombier Padodd = 1;
2377dd7cddfSDavid du Colombier continue;
238bd389b36SDavid du Colombier default:
239bd389b36SDavid du Colombier die("bad option");
2403e12c5d1SDavid du Colombier }
2413e12c5d1SDavid du Colombier } while((c = *++*argv) != '\0');
2423e12c5d1SDavid du Colombier if(Head == argv[1])
2433e12c5d1SDavid du Colombier argv++;
2443e12c5d1SDavid du Colombier continue;
2453e12c5d1SDavid du Colombier }
2463e12c5d1SDavid du Colombier *eargv++ = *argv;
247bd389b36SDavid du Colombier eargc++;
2483e12c5d1SDavid du Colombier }
2493e12c5d1SDavid du Colombier if(Len == 0)
2503e12c5d1SDavid du Colombier Len = LENGTH;
2513e12c5d1SDavid du Colombier if(Len <= Margin)
2523e12c5d1SDavid du Colombier Margin = 0;
2533e12c5d1SDavid du Colombier Plength = Len - Margin/2;
2543e12c5d1SDavid du Colombier if(Multi == 'm')
2553e12c5d1SDavid du Colombier Ncols = eargc;
2563e12c5d1SDavid du Colombier switch(Ncols) {
2573e12c5d1SDavid du Colombier case 0:
2583e12c5d1SDavid du Colombier Ncols = 1;
2593e12c5d1SDavid du Colombier case 1:
2603e12c5d1SDavid du Colombier break;
2613e12c5d1SDavid du Colombier default:
2623e12c5d1SDavid du Colombier if(Etabn == 0) /* respect explicit tab specification */
2633e12c5d1SDavid du Colombier Etabn = DEFTAB;
2643e12c5d1SDavid du Colombier }
2653e12c5d1SDavid du Colombier if(Linew == 0)
2663e12c5d1SDavid du Colombier Linew = Ncols != 1 && Sepc == 0? LINEW: 512;
2673e12c5d1SDavid du Colombier if(Lnumb)
2683e12c5d1SDavid du Colombier Linew -= Multi == 'm'? Numw: Numw*Ncols;
2693e12c5d1SDavid du Colombier if((Colw = (Linew - Ncols + 1)/Ncols) < 1)
2703e12c5d1SDavid du Colombier die("width too small");
2713e12c5d1SDavid du Colombier if(Ncols != 1 && Multi == 0) {
2723e12c5d1SDavid du Colombier ulong buflen = ((ulong)(Plength/Dblspace + 1))*(Linew+1)*sizeof(char);
273bd389b36SDavid du Colombier Buffer = getspace(buflen*sizeof(*Buffer));
2743e12c5d1SDavid du Colombier Bufend = &Buffer[buflen];
275bd389b36SDavid du Colombier Colpts = getspace((Ncols+1)*sizeof(*Colpts));
2763e12c5d1SDavid du Colombier }
2773e12c5d1SDavid du Colombier return eargc;
2783e12c5d1SDavid du Colombier }
2793e12c5d1SDavid du Colombier
2803e12c5d1SDavid du Colombier int
intopt(char * argv[],int * optp)2813e12c5d1SDavid du Colombier intopt(char *argv[], int *optp)
2823e12c5d1SDavid du Colombier {
2833e12c5d1SDavid du Colombier int c;
2843e12c5d1SDavid du Colombier
2853e12c5d1SDavid du Colombier if((c = (*argv)[1]) != '\0' && !isdigit(c)) {
2863e12c5d1SDavid du Colombier *optp = c;
287bd389b36SDavid du Colombier (*argv)++;
2883e12c5d1SDavid du Colombier }
2893e12c5d1SDavid du Colombier c = atoix(argv);
2903e12c5d1SDavid du Colombier return c != 0? c: -1;
2913e12c5d1SDavid du Colombier }
2923e12c5d1SDavid du Colombier
2933e12c5d1SDavid du Colombier int
pr(char * name)2943e12c5d1SDavid du Colombier pr(char *name)
2953e12c5d1SDavid du Colombier {
2963e12c5d1SDavid du Colombier char *date = 0, *head = 0;
2973e12c5d1SDavid du Colombier
2983e12c5d1SDavid du Colombier if(Multi != 'm' && mustopen(name, &Files[0]) == 0)
2993e12c5d1SDavid du Colombier return 0;
3003e12c5d1SDavid du Colombier if(Buffer)
3013e12c5d1SDavid du Colombier Bungetc(Files->f_f);
3023e12c5d1SDavid du Colombier if(Lnumb)
3033e12c5d1SDavid du Colombier Lnumb = 1;
3043e12c5d1SDavid du Colombier for(Page = 0;; putpage()) {
3053e12c5d1SDavid du Colombier if(C == -1)
3063e12c5d1SDavid du Colombier break;
3073e12c5d1SDavid du Colombier if(Buffer)
3083e12c5d1SDavid du Colombier nexbuf();
3093e12c5d1SDavid du Colombier Inpos = 0;
3103e12c5d1SDavid du Colombier if(get(0) == -1)
3113e12c5d1SDavid du Colombier break;
3123e12c5d1SDavid du Colombier Bflush(&bout);
313bd389b36SDavid du Colombier Page++;
314bd389b36SDavid du Colombier if(Page >= Fpage) {
3153e12c5d1SDavid du Colombier if(Margin == 0)
3163e12c5d1SDavid du Colombier continue;
3173e12c5d1SDavid du Colombier if(date == 0)
3183e12c5d1SDavid du Colombier date = getdate();
3193e12c5d1SDavid du Colombier if(head == 0)
3203e12c5d1SDavid du Colombier head = Head != 0 ? Head :
3213e12c5d1SDavid du Colombier Nfiles < 2? Files->f_name: nulls;
3223e12c5d1SDavid du Colombier Bprint(&bout, "\n\n");
3233e12c5d1SDavid du Colombier Nspace = Offset;
3243e12c5d1SDavid du Colombier putspace();
3253e12c5d1SDavid du Colombier Bprint(&bout, HEAD);
3263e12c5d1SDavid du Colombier }
3273e12c5d1SDavid du Colombier }
3287dd7cddfSDavid du Colombier if(Padodd && (Page&1) == 1) {
3297dd7cddfSDavid du Colombier Line = 0;
3307dd7cddfSDavid du Colombier if(Formfeed)
3317dd7cddfSDavid du Colombier put('\f');
3327dd7cddfSDavid du Colombier else
3337dd7cddfSDavid du Colombier while(Line < Len)
3347dd7cddfSDavid du Colombier put('\n');
3357dd7cddfSDavid du Colombier }
3363e12c5d1SDavid du Colombier C = '\0';
3373e12c5d1SDavid du Colombier return 1;
3383e12c5d1SDavid du Colombier }
3393e12c5d1SDavid du Colombier
3403e12c5d1SDavid du Colombier void
putpage(void)3413e12c5d1SDavid du Colombier putpage(void)
3423e12c5d1SDavid du Colombier {
3433e12c5d1SDavid du Colombier int colno;
3443e12c5d1SDavid du Colombier
3453e12c5d1SDavid du Colombier for(Line = Margin/2;; get(0)) {
3463e12c5d1SDavid du Colombier for(Nspace = Offset, colno = 0, Outpos = 0; C != '\f';) {
3473e12c5d1SDavid du Colombier if(Lnumb && C != -1 && (colno == 0 || Multi == 'a')) {
3483e12c5d1SDavid du Colombier if(Page >= Fpage) {
3493e12c5d1SDavid du Colombier putspace();
3503e12c5d1SDavid du Colombier Bprint(&bout, "%*ld", Numw, Buffer?
3513e12c5d1SDavid du Colombier Colpts[colno].c_lno++: Lnumb);
3523e12c5d1SDavid du Colombier Outpos += Numw;
3533e12c5d1SDavid du Colombier put(Nsepc);
3543e12c5d1SDavid du Colombier }
355bd389b36SDavid du Colombier Lnumb++;
3563e12c5d1SDavid du Colombier }
357bd389b36SDavid du Colombier for(Lcolpos=0, Pcolpos=0; C!='\n' && C!='\f' && C!=-1; get(colno))
3583e12c5d1SDavid du Colombier put(C);
359bd389b36SDavid du Colombier if(C==-1 || ++colno==Ncols || C=='\n' && get(colno)==-1)
360bd389b36SDavid du Colombier break;
3613e12c5d1SDavid du Colombier if(Sepc)
3623e12c5d1SDavid du Colombier put(Sepc);
3633e12c5d1SDavid du Colombier else
3643e12c5d1SDavid du Colombier if((Nspace += Colw - Lcolpos + 1) < 1)
3653e12c5d1SDavid du Colombier Nspace = 1;
3663e12c5d1SDavid du Colombier }
3673e12c5d1SDavid du Colombier /*
3683e12c5d1SDavid du Colombier if(C == -1) {
3693e12c5d1SDavid du Colombier if(Margin != 0)
3703e12c5d1SDavid du Colombier break;
3713e12c5d1SDavid du Colombier if(colno != 0)
3723e12c5d1SDavid du Colombier put('\n');
3733e12c5d1SDavid du Colombier return;
3743e12c5d1SDavid du Colombier }
3753e12c5d1SDavid du Colombier */
3763e12c5d1SDavid du Colombier if(C == -1 && colno == 0) {
3773e12c5d1SDavid du Colombier if(Margin != 0)
3783e12c5d1SDavid du Colombier break;
3793e12c5d1SDavid du Colombier return;
3803e12c5d1SDavid du Colombier }
3813e12c5d1SDavid du Colombier if(C == '\f')
3823e12c5d1SDavid du Colombier break;
3833e12c5d1SDavid du Colombier put('\n');
3843e12c5d1SDavid du Colombier if(Dblspace == 2 && Line < Plength)
3853e12c5d1SDavid du Colombier put('\n');
3863e12c5d1SDavid du Colombier if(Line >= Plength)
3873e12c5d1SDavid du Colombier break;
3883e12c5d1SDavid du Colombier }
3893e12c5d1SDavid du Colombier if(Formfeed)
3903e12c5d1SDavid du Colombier put('\f');
3913e12c5d1SDavid du Colombier else
3923e12c5d1SDavid du Colombier while(Line < Len)
3933e12c5d1SDavid du Colombier put('\n');
3943e12c5d1SDavid du Colombier }
3953e12c5d1SDavid du Colombier
3963e12c5d1SDavid du Colombier void
nexbuf(void)3973e12c5d1SDavid du Colombier nexbuf(void)
3983e12c5d1SDavid du Colombier {
399bd389b36SDavid du Colombier Rune *s = Buffer;
4003e12c5d1SDavid du Colombier Colp p = Colpts;
4013e12c5d1SDavid du Colombier int j, c, bline = 0;
4023e12c5d1SDavid du Colombier
4033e12c5d1SDavid du Colombier for(;;) {
4043e12c5d1SDavid du Colombier p->c_ptr0 = p->c_ptr = s;
4053e12c5d1SDavid du Colombier if(p == &Colpts[Ncols])
4063e12c5d1SDavid du Colombier return;
4073e12c5d1SDavid du Colombier (p++)->c_lno = Lnumb + bline;
408bd389b36SDavid du Colombier for(j = (Len - Margin)/Dblspace; --j >= 0; bline++)
4093e12c5d1SDavid du Colombier for(Inpos = 0;;) {
410bd389b36SDavid du Colombier if((c = Bgetrune(Files->f_f)) == -1) {
411bd389b36SDavid du Colombier for(*s = -1; p <= &Colpts[Ncols]; p++)
4123e12c5d1SDavid du Colombier p->c_ptr0 = p->c_ptr = s;
4133e12c5d1SDavid du Colombier if(Balance)
4143e12c5d1SDavid du Colombier balance(bline);
4153e12c5d1SDavid du Colombier return;
4163e12c5d1SDavid du Colombier }
417bd389b36SDavid du Colombier if(ISPRINT(c))
418bd389b36SDavid du Colombier Inpos++;
4193e12c5d1SDavid du Colombier if(Inpos <= Colw || c == '\n') {
4203e12c5d1SDavid du Colombier *s = c;
4213e12c5d1SDavid du Colombier if(++s >= Bufend)
4223e12c5d1SDavid du Colombier die("page-buffer overflow");
4233e12c5d1SDavid du Colombier }
4243e12c5d1SDavid du Colombier if(c == '\n')
4253e12c5d1SDavid du Colombier break;
4263e12c5d1SDavid du Colombier switch(c) {
427bd389b36SDavid du Colombier case '\b':
428bd389b36SDavid du Colombier if(Inpos == 0)
429bd389b36SDavid du Colombier s--;
430bd389b36SDavid du Colombier case ESC:
431bd389b36SDavid du Colombier if(Inpos > 0)
432bd389b36SDavid du Colombier Inpos--;
4333e12c5d1SDavid du Colombier }
4343e12c5d1SDavid du Colombier }
4353e12c5d1SDavid du Colombier }
4363e12c5d1SDavid du Colombier }
4373e12c5d1SDavid du Colombier
4383e12c5d1SDavid du Colombier /*
4393e12c5d1SDavid du Colombier * line balancing for last page
4403e12c5d1SDavid du Colombier */
4413e12c5d1SDavid du Colombier void
balance(int bline)4423e12c5d1SDavid du Colombier balance(int bline)
4433e12c5d1SDavid du Colombier {
444bd389b36SDavid du Colombier Rune *s = Buffer;
4453e12c5d1SDavid du Colombier Colp p = Colpts;
4463e12c5d1SDavid du Colombier int colno = 0, j, c, l;
4473e12c5d1SDavid du Colombier
4483e12c5d1SDavid du Colombier c = bline % Ncols;
4493e12c5d1SDavid du Colombier l = (bline + Ncols - 1)/Ncols;
4503e12c5d1SDavid du Colombier bline = 0;
4513e12c5d1SDavid du Colombier do {
4523e12c5d1SDavid du Colombier for(j = 0; j < l; ++j)
453bd389b36SDavid du Colombier while(*s++ != '\n')
454bd389b36SDavid du Colombier ;
4553e12c5d1SDavid du Colombier (++p)->c_lno = Lnumb + (bline += l);
4563e12c5d1SDavid du Colombier p->c_ptr0 = p->c_ptr = s;
4573e12c5d1SDavid du Colombier if(++colno == c)
458bd389b36SDavid du Colombier l--;
4593e12c5d1SDavid du Colombier } while(colno < Ncols - 1);
4603e12c5d1SDavid du Colombier }
4613e12c5d1SDavid du Colombier
4623e12c5d1SDavid du Colombier int
get(int colno)4633e12c5d1SDavid du Colombier get(int colno)
4643e12c5d1SDavid du Colombier {
4653e12c5d1SDavid du Colombier static int peekc = 0;
4663e12c5d1SDavid du Colombier Colp p;
4673e12c5d1SDavid du Colombier Fils *q;
468bd389b36SDavid du Colombier long c;
4693e12c5d1SDavid du Colombier
4703e12c5d1SDavid du Colombier if(peekc) {
4713e12c5d1SDavid du Colombier peekc = 0;
4723e12c5d1SDavid du Colombier c = Etabc;
473bd389b36SDavid du Colombier } else
4743e12c5d1SDavid du Colombier if(Buffer) {
4753e12c5d1SDavid du Colombier p = &Colpts[colno];
4763e12c5d1SDavid du Colombier if(p->c_ptr >= (p+1)->c_ptr0)
4773e12c5d1SDavid du Colombier c = -1;
4783e12c5d1SDavid du Colombier else
4793e12c5d1SDavid du Colombier if((c = *p->c_ptr) != -1)
480bd389b36SDavid du Colombier p->c_ptr++;
4813e12c5d1SDavid du Colombier } else
4823e12c5d1SDavid du Colombier if((c = (q = &Files[Multi == 'a'? 0: colno])->f_nextc) == -1) {
4833e12c5d1SDavid du Colombier for(q = &Files[Nfiles]; --q >= Files && q->f_nextc == -1;)
4843e12c5d1SDavid du Colombier ;
4853e12c5d1SDavid du Colombier if(q >= Files)
4863e12c5d1SDavid du Colombier c = '\n';
4873e12c5d1SDavid du Colombier } else
488bd389b36SDavid du Colombier q->f_nextc = Bgetrune(q->f_f);
4893e12c5d1SDavid du Colombier if(Etabn != 0 && c == Etabc) {
490bd389b36SDavid du Colombier Inpos++;
4913e12c5d1SDavid du Colombier peekc = ETABS;
4923e12c5d1SDavid du Colombier c = ' ';
4933e12c5d1SDavid du Colombier } else
494bd389b36SDavid du Colombier if(ISPRINT(c))
495bd389b36SDavid du Colombier Inpos++;
4963e12c5d1SDavid du Colombier else
4973e12c5d1SDavid du Colombier switch(c) {
4983e12c5d1SDavid du Colombier case '\b':
4993e12c5d1SDavid du Colombier case ESC:
500bd389b36SDavid du Colombier if(Inpos > 0)
501bd389b36SDavid du Colombier Inpos--;
5023e12c5d1SDavid du Colombier break;
5033e12c5d1SDavid du Colombier case '\f':
504bd389b36SDavid du Colombier if(Ncols == 1)
505bd389b36SDavid du Colombier break;
5063e12c5d1SDavid du Colombier c = '\n';
5073e12c5d1SDavid du Colombier case '\n':
5083e12c5d1SDavid du Colombier case '\r':
5093e12c5d1SDavid du Colombier Inpos = 0;
5103e12c5d1SDavid du Colombier }
5113e12c5d1SDavid du Colombier return C = c;
5123e12c5d1SDavid du Colombier }
5133e12c5d1SDavid du Colombier
5143e12c5d1SDavid du Colombier void
put(long c)515bd389b36SDavid du Colombier put(long c)
5163e12c5d1SDavid du Colombier {
5173e12c5d1SDavid du Colombier int move;
5183e12c5d1SDavid du Colombier
5193e12c5d1SDavid du Colombier switch(c) {
5203e12c5d1SDavid du Colombier case ' ':
521bd389b36SDavid du Colombier Nspace++;
522bd389b36SDavid du Colombier Lcolpos++;
5233e12c5d1SDavid du Colombier return;
5243e12c5d1SDavid du Colombier case '\b':
5253e12c5d1SDavid du Colombier if(Lcolpos == 0)
5263e12c5d1SDavid du Colombier return;
5273e12c5d1SDavid du Colombier if(Nspace > 0) {
528bd389b36SDavid du Colombier Nspace--;
529bd389b36SDavid du Colombier Lcolpos--;
5303e12c5d1SDavid du Colombier return;
5313e12c5d1SDavid du Colombier }
5323e12c5d1SDavid du Colombier if(Lcolpos > Pcolpos) {
533bd389b36SDavid du Colombier Lcolpos--;
5343e12c5d1SDavid du Colombier return;
5353e12c5d1SDavid du Colombier }
5363e12c5d1SDavid du Colombier case ESC:
5373e12c5d1SDavid du Colombier move = -1;
5383e12c5d1SDavid du Colombier break;
5393e12c5d1SDavid du Colombier case '\n':
540bd389b36SDavid du Colombier Line++;
5413e12c5d1SDavid du Colombier case '\r':
5423e12c5d1SDavid du Colombier case '\f':
543bd389b36SDavid du Colombier Pcolpos = 0;
544bd389b36SDavid du Colombier Lcolpos = 0;
545bd389b36SDavid du Colombier Nspace = 0;
546bd389b36SDavid du Colombier Outpos = 0;
5473e12c5d1SDavid du Colombier default:
548bd389b36SDavid du Colombier move = (ISPRINT(c) != 0);
5493e12c5d1SDavid du Colombier }
5503e12c5d1SDavid du Colombier if(Page < Fpage)
5513e12c5d1SDavid du Colombier return;
5523e12c5d1SDavid du Colombier if(Lcolpos > 0 || move > 0)
5533e12c5d1SDavid du Colombier Lcolpos += move;
5543e12c5d1SDavid du Colombier if(Lcolpos <= Colw) {
5553e12c5d1SDavid du Colombier putspace();
556bd389b36SDavid du Colombier Bputrune(&bout, c);
5573e12c5d1SDavid du Colombier Pcolpos = Lcolpos;
5583e12c5d1SDavid du Colombier Outpos += move;
5593e12c5d1SDavid du Colombier }
5603e12c5d1SDavid du Colombier }
5613e12c5d1SDavid du Colombier
5623e12c5d1SDavid du Colombier void
putspace(void)5633e12c5d1SDavid du Colombier putspace(void)
5643e12c5d1SDavid du Colombier {
5653e12c5d1SDavid du Colombier int nc;
5663e12c5d1SDavid du Colombier
5673e12c5d1SDavid du Colombier for(; Nspace > 0; Outpos += nc, Nspace -= nc)
5683e12c5d1SDavid du Colombier if(ITABS)
5693e12c5d1SDavid du Colombier Bputc(&bout, Itabc);
5703e12c5d1SDavid du Colombier else {
5713e12c5d1SDavid du Colombier nc = 1;
5723e12c5d1SDavid du Colombier Bputc(&bout, ' ');
5733e12c5d1SDavid du Colombier }
5743e12c5d1SDavid du Colombier }
5753e12c5d1SDavid du Colombier
5763e12c5d1SDavid du Colombier int
atoix(char ** p)5773e12c5d1SDavid du Colombier atoix(char **p)
5783e12c5d1SDavid du Colombier {
5793e12c5d1SDavid du Colombier int n = 0, c;
5803e12c5d1SDavid du Colombier
5813e12c5d1SDavid du Colombier while(isdigit(c = *++*p))
5823e12c5d1SDavid du Colombier n = 10*n + c - '0';
583bd389b36SDavid du Colombier (*p)--;
5843e12c5d1SDavid du Colombier return n;
5853e12c5d1SDavid du Colombier }
5863e12c5d1SDavid du Colombier
5873e12c5d1SDavid du Colombier /*
5883e12c5d1SDavid du Colombier * Defer message about failure to open file to prevent messing up
5893e12c5d1SDavid du Colombier * alignment of page with tear perforations or form markers.
5903e12c5d1SDavid du Colombier * Treat empty file as special case and report as diagnostic.
5913e12c5d1SDavid du Colombier */
5923e12c5d1SDavid du Colombier Biobuf*
mustopen(char * s,Fils * f)5933e12c5d1SDavid du Colombier mustopen(char *s, Fils *f)
5943e12c5d1SDavid du Colombier {
5959a747e4fSDavid du Colombier char *tmp;
5969a747e4fSDavid du Colombier
5973e12c5d1SDavid du Colombier if(*s == '\0') {
5983e12c5d1SDavid du Colombier f->f_name = STDINNAME();
5993e12c5d1SDavid du Colombier f->f_f = malloc(sizeof(Biobuf));
6003e12c5d1SDavid du Colombier if(f->f_f == 0)
6013e12c5d1SDavid du Colombier cerror("no memory");
6023e12c5d1SDavid du Colombier Binit(f->f_f, 0, OREAD);
6033e12c5d1SDavid du Colombier } else
6043e12c5d1SDavid du Colombier if((f->f_f = Bopen(f->f_name = s, OREAD)) == 0) {
6059a747e4fSDavid du Colombier tmp = ffiler(f->f_name);
6069a747e4fSDavid du Colombier s = strcpy((char*)getspace(strlen(tmp) + 1), tmp);
6079a747e4fSDavid du Colombier free(tmp);
6083e12c5d1SDavid du Colombier }
6093e12c5d1SDavid du Colombier if(f->f_f != 0) {
610bd389b36SDavid du Colombier if((f->f_nextc = Bgetrune(f->f_f)) >= 0 || Multi == 'm')
6113e12c5d1SDavid du Colombier return f->f_f;
612bd389b36SDavid du Colombier sprint(s = (char*)getspace(strlen(f->f_name) + 1 + EMPTY),
6133e12c5d1SDavid du Colombier "%s -- empty file\n", f->f_name);
614219b2ee8SDavid du Colombier Bterm(f->f_f);
6153e12c5d1SDavid du Colombier }
6163e12c5d1SDavid du Colombier error = 1;
6173e12c5d1SDavid du Colombier cerror(s);
618219b2ee8SDavid du Colombier fprint(2, "\n");
6193e12c5d1SDavid du Colombier return 0;
6203e12c5d1SDavid du Colombier }
6213e12c5d1SDavid du Colombier
6223e12c5d1SDavid du Colombier void*
getspace(ulong n)6233e12c5d1SDavid du Colombier getspace(ulong n)
6243e12c5d1SDavid du Colombier {
6253e12c5d1SDavid du Colombier void *t;
6263e12c5d1SDavid du Colombier
6273e12c5d1SDavid du Colombier if((t = malloc(n)) == 0)
6283e12c5d1SDavid du Colombier die("out of space");
6293e12c5d1SDavid du Colombier return t;
6303e12c5d1SDavid du Colombier }
6313e12c5d1SDavid du Colombier
6323e12c5d1SDavid du Colombier void
die(char * s)6333e12c5d1SDavid du Colombier die(char *s)
6343e12c5d1SDavid du Colombier {
635bd389b36SDavid du Colombier error++;
6363e12c5d1SDavid du Colombier errprint();
6373e12c5d1SDavid du Colombier cerror(s);
6383e12c5d1SDavid du Colombier Bputc(&bout, '\n');
6393e12c5d1SDavid du Colombier exits("error");
6403e12c5d1SDavid du Colombier }
6413e12c5d1SDavid du Colombier
6423e12c5d1SDavid du Colombier /*
6433e12c5d1SDavid du Colombier void
6443e12c5d1SDavid du Colombier onintr(void)
6453e12c5d1SDavid du Colombier {
646bd389b36SDavid du Colombier error++;
6473e12c5d1SDavid du Colombier errprint();
6483e12c5d1SDavid du Colombier exits("error");
6493e12c5d1SDavid du Colombier }
6503e12c5d1SDavid du Colombier /**/
6513e12c5d1SDavid du Colombier
6523e12c5d1SDavid du Colombier /*
6533e12c5d1SDavid du Colombier * print accumulated error reports
6543e12c5d1SDavid du Colombier */
6553e12c5d1SDavid du Colombier void
errprint(void)6563e12c5d1SDavid du Colombier errprint(void)
6573e12c5d1SDavid du Colombier {
6583e12c5d1SDavid du Colombier Bflush(&bout);
6593e12c5d1SDavid du Colombier for(; err != 0; err = err->e_nextp) {
6603e12c5d1SDavid du Colombier cerror(err->e_mess);
6613e12c5d1SDavid du Colombier fprint(2, "\n");
6623e12c5d1SDavid du Colombier }
6633e12c5d1SDavid du Colombier }
664