1*b873a79aSDavid du Colombier /*
2*b873a79aSDavid du Colombier permuted title index
3219b2ee8SDavid du Colombier ptx [-t] [-i ignore] [-o only] [-w num] [-r]
4219b2ee8SDavid du Colombier [-c commands] [-g gap] [-f] [input]
5*b873a79aSDavid du Colombier
6219b2ee8SDavid du Colombier Ptx reads the input file and permutes on words in it.
7219b2ee8SDavid du Colombier It excludes all words in the ignore file.
8219b2ee8SDavid du Colombier Alternately it includes words in the only file.
9219b2ee8SDavid du Colombier if neither is given it excludes the words in
10*b873a79aSDavid du Colombier /sys/lib/man/permind/ignore.
11219b2ee8SDavid du Colombier
12219b2ee8SDavid du Colombier The width of the output line (except for -r field)
13219b2ee8SDavid du Colombier can be changed to num,
14219b2ee8SDavid du Colombier which is a troff width measure, ens by default.
15219b2ee8SDavid du Colombier with no -w, num is 72n, or 100n under -t.
16219b2ee8SDavid du Colombier the -f flag tells the program to fold the output
17219b2ee8SDavid du Colombier the -t flag says the output is for troff
18219b2ee8SDavid du Colombier font specifier -F implies -t.
19219b2ee8SDavid du Colombier -g sets the gutter
20219b2ee8SDavid du Colombier -h sets the hole between wrapped segments
21219b2ee8SDavid du Colombier -r takes the first word on each line and makes it
22219b2ee8SDavid du Colombier into a fifth field.
23219b2ee8SDavid du Colombier -c inserts troff commands for font-setting etc at beginning
24219b2ee8SDavid du Colombier */
25219b2ee8SDavid du Colombier
26219b2ee8SDavid du Colombier #include <u.h>
27219b2ee8SDavid du Colombier #include <libc.h>
28219b2ee8SDavid du Colombier #include <stdio.h>
29219b2ee8SDavid du Colombier #include <ctype.h>
30*b873a79aSDavid du Colombier
31219b2ee8SDavid du Colombier #define DEFLTX "/sys/lib/man/permind/ignore"
32*b873a79aSDavid du Colombier #define TILDE 0177 /* actually RUBOUT, not ~ */
33219b2ee8SDavid du Colombier #define N 30
34219b2ee8SDavid du Colombier #define MAX N*BUFSIZ
35219b2ee8SDavid du Colombier #define LMAX 2048
36219b2ee8SDavid du Colombier #define MAXT 2048
37219b2ee8SDavid du Colombier #define MASK 03777
38219b2ee8SDavid du Colombier #define ON 1
39219b2ee8SDavid du Colombier
40219b2ee8SDavid du Colombier #define isabreak(c) (btable[c])
41219b2ee8SDavid du Colombier
42219b2ee8SDavid du Colombier char *getline(void);
43219b2ee8SDavid du Colombier void msg(char *, char *);
44219b2ee8SDavid du Colombier void extra(int);
45219b2ee8SDavid du Colombier void diag(char *, char *);
46219b2ee8SDavid du Colombier void cmpline(char *);
47219b2ee8SDavid du Colombier int cmpword(char *, char *, char *);
48219b2ee8SDavid du Colombier void putline(char *, char *);
49219b2ee8SDavid du Colombier void makek(void);
50219b2ee8SDavid du Colombier void getsort(void);
51219b2ee8SDavid du Colombier char *rtrim(char *, char *, int);
52219b2ee8SDavid du Colombier char *ltrim(char *, char *, int);
53219b2ee8SDavid du Colombier void putout(char *, char *);
54219b2ee8SDavid du Colombier void setlen(void);
55219b2ee8SDavid du Colombier void getlen(void);
56219b2ee8SDavid du Colombier int hash(char *, char *);
57219b2ee8SDavid du Colombier int storeh(int, char *);
58219b2ee8SDavid du Colombier
59219b2ee8SDavid du Colombier int status;
60219b2ee8SDavid du Colombier
61219b2ee8SDavid du Colombier char *hasht[MAXT];
62219b2ee8SDavid du Colombier char line[LMAX];
63219b2ee8SDavid du Colombier char mark[LMAX];
64219b2ee8SDavid du Colombier struct word {
65219b2ee8SDavid du Colombier char *p;
66219b2ee8SDavid du Colombier int w;
67219b2ee8SDavid du Colombier } word[LMAX/2];
68219b2ee8SDavid du Colombier char btable[256];
69219b2ee8SDavid du Colombier int ignore;
70219b2ee8SDavid du Colombier int only;
71219b2ee8SDavid du Colombier char *lenarg;
72219b2ee8SDavid du Colombier char *gutarg;
73219b2ee8SDavid du Colombier char *holarg;
74219b2ee8SDavid du Colombier int llen;
75219b2ee8SDavid du Colombier int spacesl;
76219b2ee8SDavid du Colombier int gutter;
77219b2ee8SDavid du Colombier int hole;
78219b2ee8SDavid du Colombier int mlen = LMAX;
79219b2ee8SDavid du Colombier int halflen;
80219b2ee8SDavid du Colombier int rflag;
81219b2ee8SDavid du Colombier char *strtbufp, *endbufp;
82219b2ee8SDavid du Colombier
83219b2ee8SDavid du Colombier
84219b2ee8SDavid du Colombier char *empty = "";
85219b2ee8SDavid du Colombier char *font = "R";
86219b2ee8SDavid du Colombier char *roff = "/bin/nroff";
87219b2ee8SDavid du Colombier char *troff = "/bin/troff";
88219b2ee8SDavid du Colombier
89219b2ee8SDavid du Colombier char *infile = "/fd/0";
90219b2ee8SDavid du Colombier FILE *inptr;
91219b2ee8SDavid du Colombier
92219b2ee8SDavid du Colombier FILE *outptr = stdout;
93219b2ee8SDavid du Colombier
94219b2ee8SDavid du Colombier char *sortfile = "ptxsort"; /* output of sort program */
95219b2ee8SDavid du Colombier char nofold[] = {'-', 'd', 't', TILDE, 0};
96219b2ee8SDavid du Colombier char fold[] = {'-', 'd', 'f', 't', TILDE, 0};
97219b2ee8SDavid du Colombier char *sortopt = nofold;
98219b2ee8SDavid du Colombier FILE *sortptr;
99219b2ee8SDavid du Colombier
100219b2ee8SDavid du Colombier char *kfile = "ptxmark"; /* ptxsort + troff goo for widths */
101219b2ee8SDavid du Colombier FILE *kptr;
102219b2ee8SDavid du Colombier
103219b2ee8SDavid du Colombier char *wfile = "ptxwidth"; /* widths of words in ptxsort */
104219b2ee8SDavid du Colombier FILE *wptr;
105219b2ee8SDavid du Colombier
106219b2ee8SDavid du Colombier char *bfile; /*contains user supplied break chars */
107219b2ee8SDavid du Colombier FILE *bptr;
108219b2ee8SDavid du Colombier
109219b2ee8SDavid du Colombier char *cmds;
110219b2ee8SDavid du Colombier
main(int argc,char ** argv)111219b2ee8SDavid du Colombier main(int argc, char **argv)
112219b2ee8SDavid du Colombier {
113219b2ee8SDavid du Colombier int c;
114219b2ee8SDavid du Colombier char *bufp;
115219b2ee8SDavid du Colombier char *pend;
116219b2ee8SDavid du Colombier char *xfile;
117219b2ee8SDavid du Colombier FILE *xptr;
1189a747e4fSDavid du Colombier Waitmsg *w;
119219b2ee8SDavid du Colombier
120219b2ee8SDavid du Colombier /* argument decoding */
121219b2ee8SDavid du Colombier xfile = DEFLTX;
122219b2ee8SDavid du Colombier ARGBEGIN {
123219b2ee8SDavid du Colombier case 'r':
124219b2ee8SDavid du Colombier rflag = 1;
125219b2ee8SDavid du Colombier break;
126219b2ee8SDavid du Colombier case 'f':
127219b2ee8SDavid du Colombier sortopt = fold;
128219b2ee8SDavid du Colombier break;
129219b2ee8SDavid du Colombier case 'w':
130219b2ee8SDavid du Colombier if(lenarg)
131219b2ee8SDavid du Colombier extra(ARGC());
132219b2ee8SDavid du Colombier lenarg = ARGF();
133219b2ee8SDavid du Colombier break;
134219b2ee8SDavid du Colombier case 'c':
135219b2ee8SDavid du Colombier if(cmds)
136219b2ee8SDavid du Colombier extra(ARGC());
137219b2ee8SDavid du Colombier cmds = ARGF();
138219b2ee8SDavid du Colombier case 't':
139219b2ee8SDavid du Colombier roff = troff;
140219b2ee8SDavid du Colombier break;
141219b2ee8SDavid du Colombier case 'g':
142219b2ee8SDavid du Colombier if(gutarg)
143219b2ee8SDavid du Colombier extra(ARGC());
144219b2ee8SDavid du Colombier gutarg = ARGF();
145219b2ee8SDavid du Colombier break;
146219b2ee8SDavid du Colombier case 'h':
147219b2ee8SDavid du Colombier if(holarg)
148219b2ee8SDavid du Colombier extra(ARGC());
149219b2ee8SDavid du Colombier holarg = ARGF();
150219b2ee8SDavid du Colombier break;
151219b2ee8SDavid du Colombier
152219b2ee8SDavid du Colombier case 'i':
153219b2ee8SDavid du Colombier if(only|ignore)
154219b2ee8SDavid du Colombier extra(ARGC());
155219b2ee8SDavid du Colombier ignore++;
156219b2ee8SDavid du Colombier xfile = ARGF();
157219b2ee8SDavid du Colombier break;
158219b2ee8SDavid du Colombier
159219b2ee8SDavid du Colombier case 'o':
160219b2ee8SDavid du Colombier if(only|ignore)
161219b2ee8SDavid du Colombier extra(ARGC());
162219b2ee8SDavid du Colombier only++;
163219b2ee8SDavid du Colombier xfile = ARGF();
164219b2ee8SDavid du Colombier break;
165219b2ee8SDavid du Colombier
166219b2ee8SDavid du Colombier case 'b':
167219b2ee8SDavid du Colombier if(bfile)
168219b2ee8SDavid du Colombier extra(ARGC());
169219b2ee8SDavid du Colombier bfile = ARGF();
170219b2ee8SDavid du Colombier break;
171219b2ee8SDavid du Colombier
172219b2ee8SDavid du Colombier default:
173219b2ee8SDavid du Colombier diag("Illegal argument:",*argv);
174219b2ee8SDavid du Colombier } ARGEND
175219b2ee8SDavid du Colombier
176219b2ee8SDavid du Colombier if(lenarg == 0)
177219b2ee8SDavid du Colombier lenarg = troff? "100n": "72n";
178219b2ee8SDavid du Colombier if(gutarg == 0)
179219b2ee8SDavid du Colombier gutarg = "3n";
180219b2ee8SDavid du Colombier if(holarg == 0)
181219b2ee8SDavid du Colombier holarg = gutarg;
182219b2ee8SDavid du Colombier
183219b2ee8SDavid du Colombier if(argc > 1)
184219b2ee8SDavid du Colombier diag("Too many filenames",empty);
185219b2ee8SDavid du Colombier if(argc == 1)
186219b2ee8SDavid du Colombier infile = *argv;
187219b2ee8SDavid du Colombier
188219b2ee8SDavid du Colombier /* Default breaks of blank, tab and newline */
189219b2ee8SDavid du Colombier btable[' '] = ON;
190219b2ee8SDavid du Colombier btable['\t'] = ON;
191219b2ee8SDavid du Colombier btable['\n'] = ON;
192219b2ee8SDavid du Colombier if(bfile) {
193219b2ee8SDavid du Colombier if((bptr = fopen(bfile,"r")) == NULL)
194219b2ee8SDavid du Colombier diag("Cannot open break char file",bfile);
195219b2ee8SDavid du Colombier
196219b2ee8SDavid du Colombier while((c = getc(bptr)) != EOF)
197219b2ee8SDavid du Colombier btable[c] = ON;
198219b2ee8SDavid du Colombier }
199219b2ee8SDavid du Colombier
200*b873a79aSDavid du Colombier /*
201*b873a79aSDavid du Colombier Allocate space for a buffer. If only or ignore file present
202219b2ee8SDavid du Colombier read it into buffer. Else read in default ignore file
203219b2ee8SDavid du Colombier and put resulting words in buffer.
204219b2ee8SDavid du Colombier */
205219b2ee8SDavid du Colombier
206219b2ee8SDavid du Colombier if((strtbufp = calloc(N,BUFSIZ)) == NULL)
207219b2ee8SDavid du Colombier diag("Out of memory space",empty);
208219b2ee8SDavid du Colombier bufp = strtbufp;
209219b2ee8SDavid du Colombier endbufp = strtbufp+MAX;
210219b2ee8SDavid du Colombier
211219b2ee8SDavid du Colombier if((xptr = fopen(xfile,"r")) == NULL)
212219b2ee8SDavid du Colombier diag("Cannot open file",xfile);
213219b2ee8SDavid du Colombier
214*b873a79aSDavid du Colombier while(bufp < endbufp && (c = getc(xptr)) != EOF)
215219b2ee8SDavid du Colombier if(isabreak(c)) {
216219b2ee8SDavid du Colombier if(storeh(hash(strtbufp,bufp),strtbufp))
217219b2ee8SDavid du Colombier diag("Too many words",xfile);
218219b2ee8SDavid du Colombier *bufp++ = '\0';
219219b2ee8SDavid du Colombier strtbufp = bufp;
220*b873a79aSDavid du Colombier } else
221219b2ee8SDavid du Colombier *bufp++ = (isupper(c)?tolower(c):c);
222219b2ee8SDavid du Colombier if (bufp >= endbufp)
223219b2ee8SDavid du Colombier diag("Too many words in file",xfile);
224219b2ee8SDavid du Colombier endbufp = --bufp;
225219b2ee8SDavid du Colombier
226219b2ee8SDavid du Colombier /* open output file for sorting */
227219b2ee8SDavid du Colombier
228219b2ee8SDavid du Colombier if((sortptr = fopen(sortfile, "w")) == NULL)
229219b2ee8SDavid du Colombier diag("Cannot open output for sorting:",sortfile);
230219b2ee8SDavid du Colombier
231*b873a79aSDavid du Colombier /*
232*b873a79aSDavid du Colombier get a line of data and compare each word for
233219b2ee8SDavid du Colombier inclusion or exclusion in the sort phase
234219b2ee8SDavid du Colombier */
235219b2ee8SDavid du Colombier if (infile!=0 && (inptr = fopen(infile,"r")) == NULL)
236219b2ee8SDavid du Colombier diag("Cannot open data: ",infile);
237*b873a79aSDavid du Colombier while((pend = getline()) != NULL)
238219b2ee8SDavid du Colombier cmpline(pend);
239219b2ee8SDavid du Colombier fclose(sortptr);
240219b2ee8SDavid du Colombier
241219b2ee8SDavid du Colombier if(fork()==0){
242219b2ee8SDavid du Colombier execl("/bin/sort", "sort", sortopt, "+0", "-1", "+1",
243219b2ee8SDavid du Colombier sortfile, "-o", sortfile, 0);
244219b2ee8SDavid du Colombier diag("Sort exec failed","");
245219b2ee8SDavid du Colombier }
246*b873a79aSDavid du Colombier if((w = wait()) == NULL || w->msg[0] != '\0')
247219b2ee8SDavid du Colombier diag("Sort failed","");
2489a747e4fSDavid du Colombier free(w);
249219b2ee8SDavid du Colombier
250219b2ee8SDavid du Colombier makek();
251219b2ee8SDavid du Colombier if(fork()==0){
252219b2ee8SDavid du Colombier if(dup(create(wfile,OWRITE|OTRUNC,0666),1) == -1)
253219b2ee8SDavid du Colombier diag("Cannot create width file:",wfile);
254219b2ee8SDavid du Colombier execl(roff, roff, "-a", kfile, 0);
255219b2ee8SDavid du Colombier diag("Sort exec failed","");
256219b2ee8SDavid du Colombier }
257*b873a79aSDavid du Colombier if((w = wait()) == NULL || w->msg[0] != '\0')
258219b2ee8SDavid du Colombier diag("Sort failed","");
2599a747e4fSDavid du Colombier free(w);
260219b2ee8SDavid du Colombier
261219b2ee8SDavid du Colombier getsort();
262*b873a79aSDavid du Colombier /*
263*b873a79aSDavid du Colombier remove(sortfile);
264*b873a79aSDavid du Colombier remove(kfile);
265*b873a79aSDavid du Colombier */
266219b2ee8SDavid du Colombier fflush(0);
267219b2ee8SDavid du Colombier _exits(0);
268219b2ee8SDavid du Colombier /* I don't know what's wrong with the atexit func... */
269219b2ee8SDavid du Colombier /* exits(0); */
270219b2ee8SDavid du Colombier }
271219b2ee8SDavid du Colombier
272219b2ee8SDavid du Colombier void
msg(char * s,char * arg)273219b2ee8SDavid du Colombier msg(char *s, char *arg)
274219b2ee8SDavid du Colombier {
275219b2ee8SDavid du Colombier fprintf(stderr,"ptx: %s %s\n",s,arg);
276219b2ee8SDavid du Colombier }
277219b2ee8SDavid du Colombier
278219b2ee8SDavid du Colombier void
extra(int c)279219b2ee8SDavid du Colombier extra(int c)
280219b2ee8SDavid du Colombier {
281219b2ee8SDavid du Colombier char s[] = "-x.";
282*b873a79aSDavid du Colombier
283219b2ee8SDavid du Colombier s[1] = c;
284219b2ee8SDavid du Colombier diag("Extra option", s);
285219b2ee8SDavid du Colombier }
286219b2ee8SDavid du Colombier
287219b2ee8SDavid du Colombier void
diag(char * s,char * arg)288219b2ee8SDavid du Colombier diag(char *s, char *arg)
289219b2ee8SDavid du Colombier {
290219b2ee8SDavid du Colombier msg(s,arg);
291219b2ee8SDavid du Colombier /*
292219b2ee8SDavid du Colombier remove(sortfile);
293219b2ee8SDavid du Colombier remove(kfile);
294219b2ee8SDavid du Colombier */
295219b2ee8SDavid du Colombier exits(s);
296219b2ee8SDavid du Colombier }
297219b2ee8SDavid du Colombier
298219b2ee8SDavid du Colombier
299219b2ee8SDavid du Colombier char*
getline(void)300219b2ee8SDavid du Colombier getline(void)
301219b2ee8SDavid du Colombier {
302219b2ee8SDavid du Colombier int c;
303219b2ee8SDavid du Colombier char *linep;
304219b2ee8SDavid du Colombier char *endlinep;
305219b2ee8SDavid du Colombier
306219b2ee8SDavid du Colombier endlinep= line + mlen;
307219b2ee8SDavid du Colombier linep = line;
308219b2ee8SDavid du Colombier /* Throw away leading white space */
309219b2ee8SDavid du Colombier
310219b2ee8SDavid du Colombier while(isspace(c = getc(inptr)))
311219b2ee8SDavid du Colombier ;
312219b2ee8SDavid du Colombier if(c==EOF)
313219b2ee8SDavid du Colombier return(0);
314219b2ee8SDavid du Colombier ungetc(c,inptr);
315*b873a79aSDavid du Colombier while((c = getc(inptr)) != EOF)
316219b2ee8SDavid du Colombier switch (c) {
317219b2ee8SDavid du Colombier case '\t':
318219b2ee8SDavid du Colombier if(linep<endlinep)
319219b2ee8SDavid du Colombier *linep++ = ' ';
320219b2ee8SDavid du Colombier break;
321219b2ee8SDavid du Colombier case '\n':
322*b873a79aSDavid du Colombier while(isspace(*--linep))
323*b873a79aSDavid du Colombier ;
324219b2ee8SDavid du Colombier *++linep = '\n';
325219b2ee8SDavid du Colombier return(linep);
326219b2ee8SDavid du Colombier default:
327219b2ee8SDavid du Colombier if(linep < endlinep)
328219b2ee8SDavid du Colombier *linep++ = c;
329*b873a79aSDavid du Colombier break;
330219b2ee8SDavid du Colombier }
331219b2ee8SDavid du Colombier return(0);
332219b2ee8SDavid du Colombier }
333219b2ee8SDavid du Colombier
334219b2ee8SDavid du Colombier void
cmpline(char * pend)335219b2ee8SDavid du Colombier cmpline(char *pend)
336219b2ee8SDavid du Colombier {
337219b2ee8SDavid du Colombier char *pstrt, *pchar, *cp;
338219b2ee8SDavid du Colombier char **hp;
339219b2ee8SDavid du Colombier int flag;
340219b2ee8SDavid du Colombier
341219b2ee8SDavid du Colombier pchar = line;
342219b2ee8SDavid du Colombier if(rflag)
343219b2ee8SDavid du Colombier while(pchar < pend && !isspace(*pchar))
344219b2ee8SDavid du Colombier pchar++;
345219b2ee8SDavid du Colombier while(pchar < pend){
346219b2ee8SDavid du Colombier /* eliminate white space */
347219b2ee8SDavid du Colombier if(isabreak(*pchar++))
348219b2ee8SDavid du Colombier continue;
349219b2ee8SDavid du Colombier pstrt = --pchar;
350219b2ee8SDavid du Colombier
351219b2ee8SDavid du Colombier flag = 1;
352219b2ee8SDavid du Colombier while(flag){
353219b2ee8SDavid du Colombier if(isabreak(*pchar)) {
354219b2ee8SDavid du Colombier hp = &hasht[hash(pstrt,pchar)];
355219b2ee8SDavid du Colombier pchar--;
356219b2ee8SDavid du Colombier while(cp = *hp++){
357219b2ee8SDavid du Colombier if(hp == &hasht[MAXT])
358219b2ee8SDavid du Colombier hp = hasht;
359219b2ee8SDavid du Colombier /* possible match */
360219b2ee8SDavid du Colombier if(cmpword(pstrt,pchar,cp)){
361219b2ee8SDavid du Colombier /* exact match */
362219b2ee8SDavid du Colombier if(!ignore && only)
363219b2ee8SDavid du Colombier putline(pstrt,pend);
364219b2ee8SDavid du Colombier flag = 0;
365219b2ee8SDavid du Colombier break;
366219b2ee8SDavid du Colombier }
367219b2ee8SDavid du Colombier }
368219b2ee8SDavid du Colombier /* no match */
369219b2ee8SDavid du Colombier if(flag){
370219b2ee8SDavid du Colombier if(ignore || !only)
371219b2ee8SDavid du Colombier putline(pstrt,pend);
372219b2ee8SDavid du Colombier flag = 0;
373219b2ee8SDavid du Colombier }
374219b2ee8SDavid du Colombier }
375219b2ee8SDavid du Colombier pchar++;
376219b2ee8SDavid du Colombier }
377219b2ee8SDavid du Colombier }
378219b2ee8SDavid du Colombier }
379219b2ee8SDavid du Colombier
380219b2ee8SDavid du Colombier int
cmpword(char * cpp,char * pend,char * hpp)381219b2ee8SDavid du Colombier cmpword(char *cpp, char *pend, char *hpp)
382219b2ee8SDavid du Colombier {
383219b2ee8SDavid du Colombier char c;
384219b2ee8SDavid du Colombier
385219b2ee8SDavid du Colombier while(*hpp != '\0'){
386219b2ee8SDavid du Colombier c = *cpp++;
387219b2ee8SDavid du Colombier if((isupper(c)?tolower(c):c) != *hpp++)
388219b2ee8SDavid du Colombier return(0);
389219b2ee8SDavid du Colombier }
390*b873a79aSDavid du Colombier if(--cpp == pend)
391*b873a79aSDavid du Colombier return(1);
392219b2ee8SDavid du Colombier return(0);
393219b2ee8SDavid du Colombier }
394219b2ee8SDavid du Colombier
395219b2ee8SDavid du Colombier void
putline(char * strt,char * end)396219b2ee8SDavid du Colombier putline(char *strt, char *end)
397219b2ee8SDavid du Colombier {
398219b2ee8SDavid du Colombier char *cp;
399219b2ee8SDavid du Colombier
400219b2ee8SDavid du Colombier for(cp=strt; cp<end; cp++)
401219b2ee8SDavid du Colombier putc(*cp, sortptr);
402*b873a79aSDavid du Colombier /* Add extra blank before TILDE to sort correctly with -fd option */
403219b2ee8SDavid du Colombier putc(' ',sortptr);
404219b2ee8SDavid du Colombier putc(TILDE,sortptr);
405219b2ee8SDavid du Colombier for (cp=line; cp<strt; cp++)
406219b2ee8SDavid du Colombier putc(*cp,sortptr);
407219b2ee8SDavid du Colombier putc('\n',sortptr);
408219b2ee8SDavid du Colombier }
409219b2ee8SDavid du Colombier
410219b2ee8SDavid du Colombier void
makek(void)411219b2ee8SDavid du Colombier makek(void)
412219b2ee8SDavid du Colombier {
413219b2ee8SDavid du Colombier int i, c;
414219b2ee8SDavid du Colombier int nr = 0;
415219b2ee8SDavid du Colombier
416219b2ee8SDavid du Colombier if((sortptr = fopen(sortfile,"r")) == NULL)
417219b2ee8SDavid du Colombier diag("Cannot open sorted data:",sortfile);
418219b2ee8SDavid du Colombier if((kptr = fopen(kfile,"w")) == NULL)
419219b2ee8SDavid du Colombier diag("Cannot create mark file:",kfile);
420219b2ee8SDavid du Colombier if(cmds)
421219b2ee8SDavid du Colombier fprintf(kptr,"%s\n",cmds);
422219b2ee8SDavid du Colombier fprintf(kptr,
423219b2ee8SDavid du Colombier ".nf\n"
424219b2ee8SDavid du Colombier ".pl 1\n"
425219b2ee8SDavid du Colombier ".tr %c\\&\n", TILDE);
426219b2ee8SDavid du Colombier setlen();
427219b2ee8SDavid du Colombier
428219b2ee8SDavid du Colombier while((c = getc(sortptr)) != EOF) {
429219b2ee8SDavid du Colombier if(nr == 0) {
430219b2ee8SDavid du Colombier fprintf(kptr,".di xx\n");
431219b2ee8SDavid du Colombier nr++;
432219b2ee8SDavid du Colombier }
433219b2ee8SDavid du Colombier if(c == '\n') {
434219b2ee8SDavid du Colombier fprintf(kptr,"\n.di\n");
435219b2ee8SDavid du Colombier for(i=1; i<nr; i++)
436219b2ee8SDavid du Colombier fprintf(kptr,"\\n(%.2d ",i);
437219b2ee8SDavid du Colombier fprintf(kptr,"\n");
438219b2ee8SDavid du Colombier nr = 0;
439219b2ee8SDavid du Colombier continue;
440219b2ee8SDavid du Colombier }
441219b2ee8SDavid du Colombier if(isspace(c))
442219b2ee8SDavid du Colombier fprintf(kptr,"\\k(%.2d",nr++);
443219b2ee8SDavid du Colombier putc(c,kptr);
444219b2ee8SDavid du Colombier }
445219b2ee8SDavid du Colombier fclose(sortptr);
446219b2ee8SDavid du Colombier fclose(kptr);
447219b2ee8SDavid du Colombier }
448219b2ee8SDavid du Colombier
449219b2ee8SDavid du Colombier void
getsort(void)450219b2ee8SDavid du Colombier getsort(void)
451219b2ee8SDavid du Colombier {
452219b2ee8SDavid du Colombier char *tilde, *linep, *markp;
453*b873a79aSDavid du Colombier int i0, i1, i2, i3, i4, i5, i6, i7, w0, w6;
454219b2ee8SDavid du Colombier
455219b2ee8SDavid du Colombier if((sortptr = fopen(sortfile, "r")) == NULL)
456219b2ee8SDavid du Colombier diag("Cannot open sorted data:", sortfile);
457219b2ee8SDavid du Colombier if((wptr = fopen(wfile, "r")) == NULL)
458219b2ee8SDavid du Colombier diag("Cannot open width file:", wfile);
459219b2ee8SDavid du Colombier getlen();
460219b2ee8SDavid du Colombier
461219b2ee8SDavid du Colombier halflen = (llen-gutter)/2;
462219b2ee8SDavid du Colombier
463*b873a79aSDavid du Colombier while(fgets(line, sizeof(line), sortptr) != NULL) {
464*b873a79aSDavid du Colombier if(fgets(mark, sizeof(mark), wptr) == NULL)
465*b873a79aSDavid du Colombier diag("Phase error 1: premature EOF on width file",
466*b873a79aSDavid du Colombier wfile);
467219b2ee8SDavid du Colombier linep = line;
468219b2ee8SDavid du Colombier markp = mark;
469219b2ee8SDavid du Colombier i3 = i7 = 0;
470219b2ee8SDavid du Colombier word[i7].p = linep;
471219b2ee8SDavid du Colombier word[i7].w = 0;
472219b2ee8SDavid du Colombier for(linep=line; *linep; linep++) {
473219b2ee8SDavid du Colombier if(*linep == TILDE)
474219b2ee8SDavid du Colombier i3 = i7;
475219b2ee8SDavid du Colombier else if(*linep == '\n')
476219b2ee8SDavid du Colombier break;
477219b2ee8SDavid du Colombier else if(isspace(*linep)) {
478219b2ee8SDavid du Colombier i7++;
479219b2ee8SDavid du Colombier word[i7].p = linep;
480*b873a79aSDavid du Colombier if(!markp)
481*b873a79aSDavid du Colombier diag("Phase error 2: no widths for summary",
482*b873a79aSDavid du Colombier line);
483219b2ee8SDavid du Colombier word[i7].w = atoi(markp);
484219b2ee8SDavid du Colombier markp = strchr(markp+1, ' ');
485219b2ee8SDavid du Colombier }
486219b2ee8SDavid du Colombier }
487219b2ee8SDavid du Colombier i0 = 0;
488219b2ee8SDavid du Colombier for(i1=i0; i1<i3; i1++)
489219b2ee8SDavid du Colombier if(word[i1+1].w - word[i0].w >= halflen - spacesl)
490219b2ee8SDavid du Colombier break;
491219b2ee8SDavid du Colombier w0 = word[i1].w - word[i0].w;
492219b2ee8SDavid du Colombier i4 = i3 + rflag;
493219b2ee8SDavid du Colombier for(i6 = i7; i6>i4; i6--)
494219b2ee8SDavid du Colombier if(word[i7].w - word[i6-1].w >= halflen)
495219b2ee8SDavid du Colombier break;
496219b2ee8SDavid du Colombier w6 = word[i7].w - word[i6].w - spacesl;
497219b2ee8SDavid du Colombier for(i2=i1 ; i2<i3; i2++)
498219b2ee8SDavid du Colombier if(word[i2+1].w - word[i1].w + w6 >= halflen-hole)
499219b2ee8SDavid du Colombier break;
500219b2ee8SDavid du Colombier for(i5=i6; i5>i4; i5--)
501219b2ee8SDavid du Colombier if(word[i6].w - word[i5-1].w + w0 >= halflen-hole)
502219b2ee8SDavid du Colombier break;
503219b2ee8SDavid du Colombier
504219b2ee8SDavid du Colombier printf(".xx \"");
505219b2ee8SDavid du Colombier putout(word[i1].p+1,word[i2].p);
506219b2ee8SDavid du Colombier if(i1<i2 && i2<i3) putchar('/');
507219b2ee8SDavid du Colombier printf("\" \"");
508219b2ee8SDavid du Colombier if(i5>i4 && i6==i5) putchar('/');
509219b2ee8SDavid du Colombier putout(word[i6].p+1+(i6==i3),word[i7].p);
510219b2ee8SDavid du Colombier printf("\" \"");
511219b2ee8SDavid du Colombier putout(word[i0].p,word[i1].p);
512219b2ee8SDavid du Colombier if(i2<i3 && i1==i2) putchar('/');
513219b2ee8SDavid du Colombier printf("\" \"");
514219b2ee8SDavid du Colombier if(i5>i4 && i6>i5) putchar('/');
515219b2ee8SDavid du Colombier putout(word[i5].p+1+(i5==i3),word[i6].p);
516219b2ee8SDavid du Colombier if(rflag) {
517219b2ee8SDavid du Colombier printf("\" \"");
518219b2ee8SDavid du Colombier putout(word[i3].p+2,word[i4].p);
519219b2ee8SDavid du Colombier }
520219b2ee8SDavid du Colombier printf("\"\n");
521219b2ee8SDavid du Colombier }
522219b2ee8SDavid du Colombier }
523219b2ee8SDavid du Colombier
524219b2ee8SDavid du Colombier void
putout(char * strt,char * end)525219b2ee8SDavid du Colombier putout(char *strt, char *end)
526219b2ee8SDavid du Colombier {
527219b2ee8SDavid du Colombier char *cp;
528219b2ee8SDavid du Colombier
529219b2ee8SDavid du Colombier for(cp=strt; cp<end; )
530219b2ee8SDavid du Colombier putc(*cp++,outptr);
531219b2ee8SDavid du Colombier }
532219b2ee8SDavid du Colombier
533219b2ee8SDavid du Colombier void
setlen(void)534219b2ee8SDavid du Colombier setlen(void)
535219b2ee8SDavid du Colombier {
536219b2ee8SDavid du Colombier fprintf(kptr,
537219b2ee8SDavid du Colombier "\\w'\\h'%s''\n"
538219b2ee8SDavid du Colombier "\\w' /'\n"
539219b2ee8SDavid du Colombier "\\w'\\h'%s''\n"
540219b2ee8SDavid du Colombier "\\w'\\h'%s''\n",lenarg,gutarg,holarg);
541219b2ee8SDavid du Colombier }
542219b2ee8SDavid du Colombier
543219b2ee8SDavid du Colombier void
getlen(void)544219b2ee8SDavid du Colombier getlen(void)
545219b2ee8SDavid du Colombier {
546*b873a79aSDavid du Colombier char s[128];
547*b873a79aSDavid du Colombier
548*b873a79aSDavid du Colombier s[0] = '\0';
549219b2ee8SDavid du Colombier fgets(s,sizeof(s),kptr);
550219b2ee8SDavid du Colombier llen = atoi(s);
551219b2ee8SDavid du Colombier
552219b2ee8SDavid du Colombier fgets(s,sizeof(s),kptr);
553219b2ee8SDavid du Colombier spacesl = atoi(s);
554219b2ee8SDavid du Colombier
555219b2ee8SDavid du Colombier fgets(s,sizeof(s),kptr);
556219b2ee8SDavid du Colombier gutter = atoi(s);
557219b2ee8SDavid du Colombier
558219b2ee8SDavid du Colombier fgets(s,sizeof(s),kptr);
559219b2ee8SDavid du Colombier hole = atoi(s);
560219b2ee8SDavid du Colombier if(hole < 2*spacesl)
561219b2ee8SDavid du Colombier hole = 2*spacesl;
562219b2ee8SDavid du Colombier }
563219b2ee8SDavid du Colombier
564219b2ee8SDavid du Colombier int
hash(char * strtp,char * endp)565219b2ee8SDavid du Colombier hash(char *strtp, char *endp)
566219b2ee8SDavid du Colombier {
567219b2ee8SDavid du Colombier char *cp, c;
568219b2ee8SDavid du Colombier int i, j, k;
569219b2ee8SDavid du Colombier
570219b2ee8SDavid du Colombier /* Return zero hash number for single letter words */
571219b2ee8SDavid du Colombier if((endp - strtp) == 1)
572219b2ee8SDavid du Colombier return(0);
573219b2ee8SDavid du Colombier
574219b2ee8SDavid du Colombier cp = strtp;
575219b2ee8SDavid du Colombier c = *cp++;
576219b2ee8SDavid du Colombier i = (isupper(c)?tolower(c):c);
577219b2ee8SDavid du Colombier c = *cp;
578219b2ee8SDavid du Colombier j = (isupper(c)?tolower(c):c);
579219b2ee8SDavid du Colombier i = i*j;
580219b2ee8SDavid du Colombier cp = --endp;
581219b2ee8SDavid du Colombier c = *cp--;
582219b2ee8SDavid du Colombier k = (isupper(c)?tolower(c):c);
583219b2ee8SDavid du Colombier c = *cp;
584219b2ee8SDavid du Colombier j = (isupper(c)?tolower(c):c);
585219b2ee8SDavid du Colombier j = k*j;
586*b873a79aSDavid du Colombier return (i ^ (j>>2)) & MASK;
587219b2ee8SDavid du Colombier }
588219b2ee8SDavid du Colombier
589219b2ee8SDavid du Colombier int
storeh(int num,char * strtp)590219b2ee8SDavid du Colombier storeh(int num, char *strtp)
591219b2ee8SDavid du Colombier {
592219b2ee8SDavid du Colombier int i;
593219b2ee8SDavid du Colombier
594*b873a79aSDavid du Colombier for(i=num; i<MAXT; i++)
595219b2ee8SDavid du Colombier if(hasht[i] == 0) {
596219b2ee8SDavid du Colombier hasht[i] = strtp;
597219b2ee8SDavid du Colombier return(0);
598219b2ee8SDavid du Colombier }
599*b873a79aSDavid du Colombier for(i=0; i<num; i++)
600219b2ee8SDavid du Colombier if(hasht[i] == 0) {
601219b2ee8SDavid du Colombier hasht[i] = strtp;
602219b2ee8SDavid du Colombier return(0);
603219b2ee8SDavid du Colombier }
604219b2ee8SDavid du Colombier return(1);
605219b2ee8SDavid du Colombier }
606