xref: /plan9/sys/lib/man/permind/ptx1.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier 
2*219b2ee8SDavid du Colombier /*	permuted title index
3*219b2ee8SDavid du Colombier 	ptx [-t] [-i ignore] [-o only] [-w num] [-r]
4*219b2ee8SDavid du Colombier 	    [-c commands] [-g gap] [-f] [input]
5*219b2ee8SDavid du Colombier 	Ptx reads the input file and permutes on words in it.
6*219b2ee8SDavid du Colombier 	It excludes all words in the ignore file.
7*219b2ee8SDavid du Colombier 	Alternately it includes words in the only file.
8*219b2ee8SDavid du Colombier 	if neither is given it excludes the words in
9*219b2ee8SDavid du Colombier 	/sys/man/man0/permind/ignore.
10*219b2ee8SDavid du Colombier 
11*219b2ee8SDavid du Colombier 	The width of the output line (except for -r field)
12*219b2ee8SDavid du Colombier 	can be changed to num,
13*219b2ee8SDavid du Colombier 	which is a troff width measure, ens by default.
14*219b2ee8SDavid du Colombier 	with no -w, num is 72n, or 100n under -t.
15*219b2ee8SDavid du Colombier 	the -f flag tells the program to fold the output
16*219b2ee8SDavid du Colombier 	the -t flag says the output is for troff
17*219b2ee8SDavid du Colombier 	font specifier -F implies -t.
18*219b2ee8SDavid du Colombier 	-g sets the gutter
19*219b2ee8SDavid du Colombier 	-h sets the hole between wrapped segments
20*219b2ee8SDavid du Colombier 	-r takes the first word on each line and makes it
21*219b2ee8SDavid du Colombier 	into a fifth field.
22*219b2ee8SDavid du Colombier 	-c inserts troff commands for font-setting etc at beginning
23*219b2ee8SDavid du Colombier 
24*219b2ee8SDavid du Colombier 	*/
25*219b2ee8SDavid du Colombier 
26*219b2ee8SDavid du Colombier #include <u.h>
27*219b2ee8SDavid du Colombier #include <libc.h>
28*219b2ee8SDavid du Colombier #include <stdio.h>
29*219b2ee8SDavid du Colombier #include <ctype.h>
30*219b2ee8SDavid du Colombier #define DEFLTX "/sys/lib/man/permind/ignore"
31*219b2ee8SDavid du Colombier #define TILDE 0177
32*219b2ee8SDavid du Colombier #define	N 30
33*219b2ee8SDavid du Colombier #define	MAX	N*BUFSIZ
34*219b2ee8SDavid du Colombier #define LMAX	2048
35*219b2ee8SDavid du Colombier #define MAXT	2048
36*219b2ee8SDavid du Colombier #define MASK	03777
37*219b2ee8SDavid du Colombier #define ON	1
38*219b2ee8SDavid du Colombier 
39*219b2ee8SDavid du Colombier #define isabreak(c) (btable[c])
40*219b2ee8SDavid du Colombier 
41*219b2ee8SDavid du Colombier char *getline(void);
42*219b2ee8SDavid du Colombier void msg(char *, char *);
43*219b2ee8SDavid du Colombier void extra(int);
44*219b2ee8SDavid du Colombier void diag(char *, char *);
45*219b2ee8SDavid du Colombier void cmpline(char *);
46*219b2ee8SDavid du Colombier int cmpword(char *, char *, char *);
47*219b2ee8SDavid du Colombier void putline(char *, char *);
48*219b2ee8SDavid du Colombier void makek(void);
49*219b2ee8SDavid du Colombier void getsort(void);
50*219b2ee8SDavid du Colombier char *rtrim(char *, char *, int);
51*219b2ee8SDavid du Colombier char *ltrim(char *, char *, int);
52*219b2ee8SDavid du Colombier void putout(char *, char *);
53*219b2ee8SDavid du Colombier void setlen(void);
54*219b2ee8SDavid du Colombier void getlen(void);
55*219b2ee8SDavid du Colombier int hash(char *, char *);
56*219b2ee8SDavid du Colombier int storeh(int, char *);
57*219b2ee8SDavid du Colombier 
58*219b2ee8SDavid du Colombier int status;
59*219b2ee8SDavid du Colombier 
60*219b2ee8SDavid du Colombier 
61*219b2ee8SDavid du Colombier char *hasht[MAXT];
62*219b2ee8SDavid du Colombier char line[LMAX];
63*219b2ee8SDavid du Colombier char mark[LMAX];
64*219b2ee8SDavid du Colombier struct word {
65*219b2ee8SDavid du Colombier 	char *p;
66*219b2ee8SDavid du Colombier 	int w;
67*219b2ee8SDavid du Colombier } word[LMAX/2];
68*219b2ee8SDavid du Colombier char btable[256];
69*219b2ee8SDavid du Colombier int ignore;
70*219b2ee8SDavid du Colombier int only;
71*219b2ee8SDavid du Colombier char *lenarg;
72*219b2ee8SDavid du Colombier char *gutarg;
73*219b2ee8SDavid du Colombier char *holarg;
74*219b2ee8SDavid du Colombier int llen;
75*219b2ee8SDavid du Colombier int spacesl;
76*219b2ee8SDavid du Colombier int gutter;
77*219b2ee8SDavid du Colombier int hole;
78*219b2ee8SDavid du Colombier int mlen = LMAX;
79*219b2ee8SDavid du Colombier int halflen;
80*219b2ee8SDavid du Colombier int rflag;
81*219b2ee8SDavid du Colombier char *strtbufp, *endbufp;
82*219b2ee8SDavid du Colombier 
83*219b2ee8SDavid du Colombier 
84*219b2ee8SDavid du Colombier char *empty = "";
85*219b2ee8SDavid du Colombier char *font = "R";
86*219b2ee8SDavid du Colombier char *roff = "/bin/nroff";
87*219b2ee8SDavid du Colombier char *troff = "/bin/troff";
88*219b2ee8SDavid du Colombier 
89*219b2ee8SDavid du Colombier char *infile = "/fd/0";
90*219b2ee8SDavid du Colombier FILE *inptr;
91*219b2ee8SDavid du Colombier 
92*219b2ee8SDavid du Colombier FILE *outptr = stdout;
93*219b2ee8SDavid du Colombier 
94*219b2ee8SDavid du Colombier char *sortfile = "ptxsort";	/* output of sort program */
95*219b2ee8SDavid du Colombier char nofold[] = {'-', 'd', 't', TILDE, 0};
96*219b2ee8SDavid du Colombier char fold[] = {'-', 'd', 'f', 't', TILDE, 0};
97*219b2ee8SDavid du Colombier char *sortopt = nofold;
98*219b2ee8SDavid du Colombier FILE *sortptr;
99*219b2ee8SDavid du Colombier 
100*219b2ee8SDavid du Colombier char *kfile = "ptxmark";	/* ptxsort + troff goo for widths */
101*219b2ee8SDavid du Colombier FILE *kptr;
102*219b2ee8SDavid du Colombier 
103*219b2ee8SDavid du Colombier char *wfile = "ptxwidth";	/* widths of words in ptxsort */
104*219b2ee8SDavid du Colombier FILE *wptr;
105*219b2ee8SDavid du Colombier 
106*219b2ee8SDavid du Colombier char *bfile;	/*contains user supplied break chars */
107*219b2ee8SDavid du Colombier FILE *bptr;
108*219b2ee8SDavid du Colombier 
109*219b2ee8SDavid du Colombier char *cmds;
110*219b2ee8SDavid du Colombier 
111*219b2ee8SDavid du Colombier main(int argc, char **argv)
112*219b2ee8SDavid du Colombier {
113*219b2ee8SDavid du Colombier 	int c;
114*219b2ee8SDavid du Colombier 	char *bufp;
115*219b2ee8SDavid du Colombier 	char *pend;
116*219b2ee8SDavid du Colombier 
117*219b2ee8SDavid du Colombier 	char *xfile;
118*219b2ee8SDavid du Colombier 	FILE *xptr;
119*219b2ee8SDavid du Colombier 	Waitmsg w;
120*219b2ee8SDavid du Colombier 
121*219b2ee8SDavid du Colombier 
122*219b2ee8SDavid du Colombier /*	argument decoding	*/
123*219b2ee8SDavid du Colombier 
124*219b2ee8SDavid du Colombier 	xfile = DEFLTX;
125*219b2ee8SDavid du Colombier 	ARGBEGIN {
126*219b2ee8SDavid du Colombier 	case 'r':
127*219b2ee8SDavid du Colombier 		rflag = 1;
128*219b2ee8SDavid du Colombier 		break;
129*219b2ee8SDavid du Colombier 	case 'f':
130*219b2ee8SDavid du Colombier 		sortopt = fold;
131*219b2ee8SDavid du Colombier 		break;
132*219b2ee8SDavid du Colombier 	case 'w':
133*219b2ee8SDavid du Colombier 		if(lenarg)
134*219b2ee8SDavid du Colombier 			extra(ARGC());
135*219b2ee8SDavid du Colombier 		lenarg = ARGF();
136*219b2ee8SDavid du Colombier 		break;
137*219b2ee8SDavid du Colombier 	case 'c':
138*219b2ee8SDavid du Colombier 		if(cmds)
139*219b2ee8SDavid du Colombier 			extra(ARGC());
140*219b2ee8SDavid du Colombier 		cmds = ARGF();
141*219b2ee8SDavid du Colombier 	case 't':
142*219b2ee8SDavid du Colombier 		roff = troff;
143*219b2ee8SDavid du Colombier 		break;
144*219b2ee8SDavid du Colombier 	case 'g':
145*219b2ee8SDavid du Colombier 		if(gutarg)
146*219b2ee8SDavid du Colombier 			extra(ARGC());
147*219b2ee8SDavid du Colombier 		gutarg =  ARGF();
148*219b2ee8SDavid du Colombier 		break;
149*219b2ee8SDavid du Colombier 	case 'h':
150*219b2ee8SDavid du Colombier 		if(holarg)
151*219b2ee8SDavid du Colombier 			extra(ARGC());
152*219b2ee8SDavid du Colombier 		holarg =  ARGF();
153*219b2ee8SDavid du Colombier 		break;
154*219b2ee8SDavid du Colombier 
155*219b2ee8SDavid du Colombier 	case 'i':
156*219b2ee8SDavid du Colombier 		if(only|ignore)
157*219b2ee8SDavid du Colombier 			extra(ARGC());
158*219b2ee8SDavid du Colombier 		ignore++;
159*219b2ee8SDavid du Colombier 		xfile = ARGF();
160*219b2ee8SDavid du Colombier 		break;
161*219b2ee8SDavid du Colombier 
162*219b2ee8SDavid du Colombier 	case 'o':
163*219b2ee8SDavid du Colombier 		if(only|ignore)
164*219b2ee8SDavid du Colombier 			extra(ARGC());
165*219b2ee8SDavid du Colombier 		only++;
166*219b2ee8SDavid du Colombier 		xfile = ARGF();
167*219b2ee8SDavid du Colombier 		break;
168*219b2ee8SDavid du Colombier 
169*219b2ee8SDavid du Colombier 	case 'b':
170*219b2ee8SDavid du Colombier 		if(bfile)
171*219b2ee8SDavid du Colombier 			extra(ARGC());
172*219b2ee8SDavid du Colombier 		bfile = ARGF();
173*219b2ee8SDavid du Colombier 		break;
174*219b2ee8SDavid du Colombier 
175*219b2ee8SDavid du Colombier 	default:
176*219b2ee8SDavid du Colombier 		diag("Illegal argument:",*argv);
177*219b2ee8SDavid du Colombier 	} ARGEND
178*219b2ee8SDavid du Colombier 
179*219b2ee8SDavid du Colombier 	if(lenarg == 0)
180*219b2ee8SDavid du Colombier 		lenarg = troff? "100n": "72n";
181*219b2ee8SDavid du Colombier 	if(gutarg == 0)
182*219b2ee8SDavid du Colombier 		gutarg = "3n";
183*219b2ee8SDavid du Colombier 	if(holarg == 0)
184*219b2ee8SDavid du Colombier 		holarg = gutarg;
185*219b2ee8SDavid du Colombier 
186*219b2ee8SDavid du Colombier 	if(argc > 1)
187*219b2ee8SDavid du Colombier 		diag("Too many filenames",empty);
188*219b2ee8SDavid du Colombier 	if(argc == 1)
189*219b2ee8SDavid du Colombier 		infile = *argv;
190*219b2ee8SDavid du Colombier 
191*219b2ee8SDavid du Colombier 
192*219b2ee8SDavid du Colombier 	/* Default breaks of blank, tab and newline */
193*219b2ee8SDavid du Colombier 	btable[' '] = ON;
194*219b2ee8SDavid du Colombier 	btable['\t'] = ON;
195*219b2ee8SDavid du Colombier 	btable['\n'] = ON;
196*219b2ee8SDavid du Colombier 	if(bfile) {
197*219b2ee8SDavid du Colombier 		if((bptr = fopen(bfile,"r")) == NULL)
198*219b2ee8SDavid du Colombier 			diag("Cannot open break char file",bfile);
199*219b2ee8SDavid du Colombier 
200*219b2ee8SDavid du Colombier 		while((c = getc(bptr)) != EOF)
201*219b2ee8SDavid du Colombier 			btable[c] = ON;
202*219b2ee8SDavid du Colombier 	}
203*219b2ee8SDavid du Colombier 
204*219b2ee8SDavid du Colombier /*	Allocate space for a buffer.  If only or ignore file present
205*219b2ee8SDavid du Colombier 	read it into buffer. Else read in default ignore file
206*219b2ee8SDavid du Colombier 	and put resulting words in buffer.
207*219b2ee8SDavid du Colombier 	*/
208*219b2ee8SDavid du Colombier 
209*219b2ee8SDavid du Colombier 
210*219b2ee8SDavid du Colombier 	if((strtbufp = calloc(N,BUFSIZ)) == NULL)
211*219b2ee8SDavid du Colombier 		diag("Out of memory space",empty);
212*219b2ee8SDavid du Colombier 	bufp = strtbufp;
213*219b2ee8SDavid du Colombier 	endbufp = strtbufp+MAX;
214*219b2ee8SDavid du Colombier 
215*219b2ee8SDavid du Colombier 	if((xptr = fopen(xfile,"r")) == NULL)
216*219b2ee8SDavid du Colombier 		diag("Cannot open  file",xfile);
217*219b2ee8SDavid du Colombier 
218*219b2ee8SDavid du Colombier 	while(bufp < endbufp && (c = getc(xptr)) != EOF) {
219*219b2ee8SDavid du Colombier 		if(isabreak(c)) {
220*219b2ee8SDavid du Colombier 			if(storeh(hash(strtbufp,bufp),strtbufp))
221*219b2ee8SDavid du Colombier 				diag("Too many words",xfile);
222*219b2ee8SDavid du Colombier 			*bufp++ = '\0';
223*219b2ee8SDavid du Colombier 			strtbufp = bufp;
224*219b2ee8SDavid du Colombier 		}
225*219b2ee8SDavid du Colombier 		else {
226*219b2ee8SDavid du Colombier 			*bufp++ = (isupper(c)?tolower(c):c);
227*219b2ee8SDavid du Colombier 		}
228*219b2ee8SDavid du Colombier 	}
229*219b2ee8SDavid du Colombier 	if (bufp >= endbufp)
230*219b2ee8SDavid du Colombier 		diag("Too many words in file",xfile);
231*219b2ee8SDavid du Colombier 	endbufp = --bufp;
232*219b2ee8SDavid du Colombier 
233*219b2ee8SDavid du Colombier 	/* open output file for sorting */
234*219b2ee8SDavid du Colombier 
235*219b2ee8SDavid du Colombier 	if((sortptr = fopen(sortfile, "w")) == NULL)
236*219b2ee8SDavid du Colombier 		diag("Cannot open output for sorting:",sortfile);
237*219b2ee8SDavid du Colombier 
238*219b2ee8SDavid du Colombier /*	get a line of data and compare each word for
239*219b2ee8SDavid du Colombier 	inclusion or exclusion in the sort phase
240*219b2ee8SDavid du Colombier */
241*219b2ee8SDavid du Colombier 	if (infile!=0 && (inptr = fopen(infile,"r")) == NULL)
242*219b2ee8SDavid du Colombier 		diag("Cannot open data: ",infile);
243*219b2ee8SDavid du Colombier 	while(pend=getline())
244*219b2ee8SDavid du Colombier 		cmpline(pend);
245*219b2ee8SDavid du Colombier 	fclose(sortptr);
246*219b2ee8SDavid du Colombier 
247*219b2ee8SDavid du Colombier 	if(fork()==0){
248*219b2ee8SDavid du Colombier 		execl("/bin/sort", "sort", sortopt, "+0", "-1", "+1",
249*219b2ee8SDavid du Colombier 			sortfile, "-o", sortfile, 0);
250*219b2ee8SDavid du Colombier 		diag("Sort exec failed","");
251*219b2ee8SDavid du Colombier 	}
252*219b2ee8SDavid du Colombier 	if(wait(&w)<0 || w.msg[0]!=0)
253*219b2ee8SDavid du Colombier 		diag("Sort failed","");
254*219b2ee8SDavid du Colombier 
255*219b2ee8SDavid du Colombier 	makek();
256*219b2ee8SDavid du Colombier 	if(fork()==0){
257*219b2ee8SDavid du Colombier 		if(dup(create(wfile,OWRITE|OTRUNC,0666),1) == -1)
258*219b2ee8SDavid du Colombier 			diag("Cannot create width file:",wfile);
259*219b2ee8SDavid du Colombier 		execl(roff, roff, "-a", kfile, 0);
260*219b2ee8SDavid du Colombier 		diag("Sort exec failed","");
261*219b2ee8SDavid du Colombier 	}
262*219b2ee8SDavid du Colombier 	if(wait(&w)<0 || w.msg[0]!=0)
263*219b2ee8SDavid du Colombier 		diag("Sort failed","");
264*219b2ee8SDavid du Colombier 
265*219b2ee8SDavid du Colombier 	getsort();
266*219b2ee8SDavid du Colombier /*	remove(sortfile);
267*219b2ee8SDavid du Colombier 	remove(kfile);*/
268*219b2ee8SDavid du Colombier fflush(0);
269*219b2ee8SDavid du Colombier _exits(0);
270*219b2ee8SDavid du Colombier /* I don't know what's wrong with the atexit func... */
271*219b2ee8SDavid du Colombier /*	exits(0);	*/
272*219b2ee8SDavid du Colombier }
273*219b2ee8SDavid du Colombier 
274*219b2ee8SDavid du Colombier void
275*219b2ee8SDavid du Colombier msg(char *s, char *arg)
276*219b2ee8SDavid du Colombier {
277*219b2ee8SDavid du Colombier 	fprintf(stderr,"ptx: %s %s\n",s,arg);
278*219b2ee8SDavid du Colombier 	return;
279*219b2ee8SDavid du Colombier }
280*219b2ee8SDavid du Colombier 
281*219b2ee8SDavid du Colombier void
282*219b2ee8SDavid du Colombier extra(int c)
283*219b2ee8SDavid du Colombier {
284*219b2ee8SDavid du Colombier 	char s[] = "-x.";
285*219b2ee8SDavid du Colombier 	s[1] = c;
286*219b2ee8SDavid du Colombier 	diag("Extra option", s);
287*219b2ee8SDavid du Colombier }
288*219b2ee8SDavid du Colombier 
289*219b2ee8SDavid du Colombier void
290*219b2ee8SDavid du Colombier diag(char *s, char *arg)
291*219b2ee8SDavid du Colombier {
292*219b2ee8SDavid du Colombier 
293*219b2ee8SDavid du Colombier 	msg(s,arg);
294*219b2ee8SDavid du Colombier /*
295*219b2ee8SDavid du Colombier 	remove(sortfile);
296*219b2ee8SDavid du Colombier 	remove(kfile);
297*219b2ee8SDavid du Colombier */
298*219b2ee8SDavid du Colombier 	exits(s);
299*219b2ee8SDavid du Colombier }
300*219b2ee8SDavid du Colombier 
301*219b2ee8SDavid du Colombier 
302*219b2ee8SDavid du Colombier char*
303*219b2ee8SDavid du Colombier getline(void)
304*219b2ee8SDavid du Colombier {
305*219b2ee8SDavid du Colombier 
306*219b2ee8SDavid du Colombier 	int c;
307*219b2ee8SDavid du Colombier 	char *linep;
308*219b2ee8SDavid du Colombier 	char *endlinep;
309*219b2ee8SDavid du Colombier 
310*219b2ee8SDavid du Colombier 
311*219b2ee8SDavid du Colombier 	endlinep= line + mlen;
312*219b2ee8SDavid du Colombier 	linep = line;
313*219b2ee8SDavid du Colombier 	/* Throw away leading white space */
314*219b2ee8SDavid du Colombier 
315*219b2ee8SDavid du Colombier 	while(isspace(c=getc(inptr)))
316*219b2ee8SDavid du Colombier 		;
317*219b2ee8SDavid du Colombier 	if(c==EOF)
318*219b2ee8SDavid du Colombier 		return(0);
319*219b2ee8SDavid du Colombier 	ungetc(c,inptr);
320*219b2ee8SDavid du Colombier 	while(( c=getc(inptr)) != EOF) {
321*219b2ee8SDavid du Colombier 		switch (c) {
322*219b2ee8SDavid du Colombier 
323*219b2ee8SDavid du Colombier 			case '\t':
324*219b2ee8SDavid du Colombier 				if(linep<endlinep)
325*219b2ee8SDavid du Colombier 					*linep++ = ' ';
326*219b2ee8SDavid du Colombier 				break;
327*219b2ee8SDavid du Colombier 			case '\n':
328*219b2ee8SDavid du Colombier 				while(isspace(*--linep));
329*219b2ee8SDavid du Colombier 				*++linep = '\n';
330*219b2ee8SDavid du Colombier 				return(linep);
331*219b2ee8SDavid du Colombier 			default:
332*219b2ee8SDavid du Colombier 				if(linep < endlinep)
333*219b2ee8SDavid du Colombier 					*linep++ = c;
334*219b2ee8SDavid du Colombier 		}
335*219b2ee8SDavid du Colombier 	}
336*219b2ee8SDavid du Colombier 	return(0);
337*219b2ee8SDavid du Colombier }
338*219b2ee8SDavid du Colombier 
339*219b2ee8SDavid du Colombier void
340*219b2ee8SDavid du Colombier cmpline(char *pend)
341*219b2ee8SDavid du Colombier {
342*219b2ee8SDavid du Colombier 
343*219b2ee8SDavid du Colombier 	char *pstrt, *pchar, *cp;
344*219b2ee8SDavid du Colombier 	char **hp;
345*219b2ee8SDavid du Colombier 	int flag;
346*219b2ee8SDavid du Colombier 
347*219b2ee8SDavid du Colombier 	pchar = line;
348*219b2ee8SDavid du Colombier 	if(rflag)
349*219b2ee8SDavid du Colombier 		while(pchar<pend&&!isspace(*pchar))
350*219b2ee8SDavid du Colombier 			pchar++;
351*219b2ee8SDavid du Colombier 	while(pchar<pend){
352*219b2ee8SDavid du Colombier 	/* eliminate white space */
353*219b2ee8SDavid du Colombier 		if(isabreak(*pchar++))
354*219b2ee8SDavid du Colombier 			continue;
355*219b2ee8SDavid du Colombier 		pstrt = --pchar;
356*219b2ee8SDavid du Colombier 
357*219b2ee8SDavid du Colombier 		flag = 1;
358*219b2ee8SDavid du Colombier 		while(flag){
359*219b2ee8SDavid du Colombier 			if(isabreak(*pchar)) {
360*219b2ee8SDavid du Colombier 				hp = &hasht[hash(pstrt,pchar)];
361*219b2ee8SDavid du Colombier 				pchar--;
362*219b2ee8SDavid du Colombier 				while(cp = *hp++){
363*219b2ee8SDavid du Colombier 					if(hp == &hasht[MAXT])
364*219b2ee8SDavid du Colombier 						hp = hasht;
365*219b2ee8SDavid du Colombier 	/* possible match */
366*219b2ee8SDavid du Colombier 					if(cmpword(pstrt,pchar,cp)){
367*219b2ee8SDavid du Colombier 	/* exact match */
368*219b2ee8SDavid du Colombier 						if(!ignore && only)
369*219b2ee8SDavid du Colombier 							putline(pstrt,pend);
370*219b2ee8SDavid du Colombier 						flag = 0;
371*219b2ee8SDavid du Colombier 						break;
372*219b2ee8SDavid du Colombier 					}
373*219b2ee8SDavid du Colombier 				}
374*219b2ee8SDavid du Colombier 	/* no match */
375*219b2ee8SDavid du Colombier 				if(flag){
376*219b2ee8SDavid du Colombier 					if(ignore || !only)
377*219b2ee8SDavid du Colombier 						putline(pstrt,pend);
378*219b2ee8SDavid du Colombier 					flag = 0;
379*219b2ee8SDavid du Colombier 				}
380*219b2ee8SDavid du Colombier 			}
381*219b2ee8SDavid du Colombier 		pchar++;
382*219b2ee8SDavid du Colombier 		}
383*219b2ee8SDavid du Colombier 	}
384*219b2ee8SDavid du Colombier }
385*219b2ee8SDavid du Colombier 
386*219b2ee8SDavid du Colombier int
387*219b2ee8SDavid du Colombier cmpword(char *cpp, char *pend, char *hpp)
388*219b2ee8SDavid du Colombier {
389*219b2ee8SDavid du Colombier 	char c;
390*219b2ee8SDavid du Colombier 
391*219b2ee8SDavid du Colombier 	while(*hpp != '\0'){
392*219b2ee8SDavid du Colombier 		c = *cpp++;
393*219b2ee8SDavid du Colombier 		if((isupper(c)?tolower(c):c) != *hpp++)
394*219b2ee8SDavid du Colombier 			return(0);
395*219b2ee8SDavid du Colombier 	}
396*219b2ee8SDavid du Colombier 	if(--cpp == pend) return(1);
397*219b2ee8SDavid du Colombier 	return(0);
398*219b2ee8SDavid du Colombier }
399*219b2ee8SDavid du Colombier 
400*219b2ee8SDavid du Colombier void
401*219b2ee8SDavid du Colombier putline(char *strt, char *end)
402*219b2ee8SDavid du Colombier {
403*219b2ee8SDavid du Colombier 	char *cp;
404*219b2ee8SDavid du Colombier 
405*219b2ee8SDavid du Colombier 	for(cp=strt; cp<end; cp++)
406*219b2ee8SDavid du Colombier 		putc(*cp, sortptr);
407*219b2ee8SDavid du Colombier 	/* Add extra blank before TILDE to sort correctly
408*219b2ee8SDavid du Colombier 	   with -fd option */
409*219b2ee8SDavid du Colombier 	putc(' ',sortptr);
410*219b2ee8SDavid du Colombier 	putc(TILDE,sortptr);
411*219b2ee8SDavid du Colombier 	for (cp=line; cp<strt; cp++)
412*219b2ee8SDavid du Colombier 		putc(*cp,sortptr);
413*219b2ee8SDavid du Colombier 	putc('\n',sortptr);
414*219b2ee8SDavid du Colombier }
415*219b2ee8SDavid du Colombier 
416*219b2ee8SDavid du Colombier void
417*219b2ee8SDavid du Colombier makek(void)
418*219b2ee8SDavid du Colombier {
419*219b2ee8SDavid du Colombier 	int i, c;
420*219b2ee8SDavid du Colombier 	int nr = 0;
421*219b2ee8SDavid du Colombier 
422*219b2ee8SDavid du Colombier 	if((sortptr = fopen(sortfile,"r")) == NULL)
423*219b2ee8SDavid du Colombier 		diag("Cannot open sorted data:",sortfile);
424*219b2ee8SDavid du Colombier 	if((kptr = fopen(kfile,"w")) == NULL)
425*219b2ee8SDavid du Colombier 		diag("Cannot create mark file:",kfile);
426*219b2ee8SDavid du Colombier 	if(cmds)
427*219b2ee8SDavid du Colombier 		fprintf(kptr,"%s\n",cmds);
428*219b2ee8SDavid du Colombier 	fprintf(kptr,
429*219b2ee8SDavid du Colombier 		".nf\n"
430*219b2ee8SDavid du Colombier 		".pl 1\n"
431*219b2ee8SDavid du Colombier 		".tr %c\\&\n", TILDE);
432*219b2ee8SDavid du Colombier 	setlen();
433*219b2ee8SDavid du Colombier 
434*219b2ee8SDavid du Colombier 	while((c = getc(sortptr)) != EOF) {
435*219b2ee8SDavid du Colombier 		if(nr == 0) {
436*219b2ee8SDavid du Colombier 			fprintf(kptr,".di xx\n");
437*219b2ee8SDavid du Colombier 			nr++;
438*219b2ee8SDavid du Colombier 		}
439*219b2ee8SDavid du Colombier 		if(c == '\n') {
440*219b2ee8SDavid du Colombier 			fprintf(kptr,"\n.di\n");
441*219b2ee8SDavid du Colombier 			for(i=1; i<nr; i++)
442*219b2ee8SDavid du Colombier 				fprintf(kptr,"\\n(%.2d ",i);
443*219b2ee8SDavid du Colombier 			fprintf(kptr,"\n");
444*219b2ee8SDavid du Colombier 			nr = 0;
445*219b2ee8SDavid du Colombier 			continue;
446*219b2ee8SDavid du Colombier 		}
447*219b2ee8SDavid du Colombier 		if(isspace(c))
448*219b2ee8SDavid du Colombier 			fprintf(kptr,"\\k(%.2d",nr++);
449*219b2ee8SDavid du Colombier 		putc(c,kptr);
450*219b2ee8SDavid du Colombier 	}
451*219b2ee8SDavid du Colombier 	fclose(sortptr);
452*219b2ee8SDavid du Colombier 	fclose(kptr);
453*219b2ee8SDavid du Colombier }
454*219b2ee8SDavid du Colombier 
455*219b2ee8SDavid du Colombier 
456*219b2ee8SDavid du Colombier 
457*219b2ee8SDavid du Colombier void
458*219b2ee8SDavid du Colombier getsort(void)
459*219b2ee8SDavid du Colombier {
460*219b2ee8SDavid du Colombier 	char *tilde, *linep, *markp;
461*219b2ee8SDavid du Colombier 	int i0, i1, i2, i3, i4, i5, i6, i7;
462*219b2ee8SDavid du Colombier 	int w0, w6;
463*219b2ee8SDavid du Colombier 
464*219b2ee8SDavid du Colombier 	if((sortptr = fopen(sortfile,"r")) == NULL)
465*219b2ee8SDavid du Colombier 		diag("Cannot open sorted data:",sortfile);
466*219b2ee8SDavid du Colombier 	if((wptr = fopen(wfile,"r")) == NULL)
467*219b2ee8SDavid du Colombier 		diag("Cannot open width file:",wfile);
468*219b2ee8SDavid du Colombier 	getlen();
469*219b2ee8SDavid du Colombier 
470*219b2ee8SDavid du Colombier 	halflen = (llen-gutter)/2;
471*219b2ee8SDavid du Colombier 
472*219b2ee8SDavid du Colombier 	while(fgets(line,sizeof(line),sortptr) != 0) {
473*219b2ee8SDavid du Colombier 		if(fgets(mark,sizeof(mark),wptr) == 0)
474*219b2ee8SDavid du Colombier 			diag("Phase error 1","");
475*219b2ee8SDavid du Colombier 		linep = line;
476*219b2ee8SDavid du Colombier 		markp = mark;
477*219b2ee8SDavid du Colombier 		i3 = i7 = 0;
478*219b2ee8SDavid du Colombier 		word[i7].p = linep;
479*219b2ee8SDavid du Colombier 		word[i7].w = 0;
480*219b2ee8SDavid du Colombier 		for(linep=line; *linep; linep++) {
481*219b2ee8SDavid du Colombier 			if(*linep == TILDE)
482*219b2ee8SDavid du Colombier 				i3 = i7;
483*219b2ee8SDavid du Colombier 			else if(*linep == '\n')
484*219b2ee8SDavid du Colombier 				break;
485*219b2ee8SDavid du Colombier 			else if(isspace(*linep)) {
486*219b2ee8SDavid du Colombier 				i7++;
487*219b2ee8SDavid du Colombier 				word[i7].p = linep;
488*219b2ee8SDavid du Colombier 				if(!markp) {
489*219b2ee8SDavid du Colombier 					diag("Phase error 2","");
490*219b2ee8SDavid du Colombier 				}
491*219b2ee8SDavid du Colombier 				word[i7].w = atoi(markp);
492*219b2ee8SDavid du Colombier 				markp = strchr(markp+1,' ');
493*219b2ee8SDavid du Colombier 			}
494*219b2ee8SDavid du Colombier 		}
495*219b2ee8SDavid du Colombier 		i0 = 0;
496*219b2ee8SDavid du Colombier 		for(i1=i0; i1<i3; i1++)
497*219b2ee8SDavid du Colombier 			if(word[i1+1].w - word[i0].w >= halflen - spacesl)
498*219b2ee8SDavid du Colombier 				break;
499*219b2ee8SDavid du Colombier 		w0 = word[i1].w - word[i0].w;
500*219b2ee8SDavid du Colombier 		i4 = i3 + rflag;
501*219b2ee8SDavid du Colombier 		for(i6 = i7; i6>i4; i6--)
502*219b2ee8SDavid du Colombier 			if(word[i7].w - word[i6-1].w >= halflen)
503*219b2ee8SDavid du Colombier 				break;
504*219b2ee8SDavid du Colombier 		w6 = word[i7].w - word[i6].w - spacesl;
505*219b2ee8SDavid du Colombier 		for(i2=i1 ; i2<i3; i2++)
506*219b2ee8SDavid du Colombier 			if(word[i2+1].w - word[i1].w + w6 >= halflen-hole)
507*219b2ee8SDavid du Colombier 				break;
508*219b2ee8SDavid du Colombier 		for(i5=i6; i5>i4; i5--)
509*219b2ee8SDavid du Colombier 			if(word[i6].w - word[i5-1].w + w0 >= halflen-hole)
510*219b2ee8SDavid du Colombier 				break;
511*219b2ee8SDavid du Colombier 
512*219b2ee8SDavid du Colombier 		printf(".xx \"");
513*219b2ee8SDavid du Colombier 		putout(word[i1].p+1,word[i2].p);
514*219b2ee8SDavid du Colombier 		if(i1<i2 && i2<i3) putchar('/');
515*219b2ee8SDavid du Colombier 		printf("\" \"");
516*219b2ee8SDavid du Colombier 		if(i5>i4 && i6==i5) putchar('/');
517*219b2ee8SDavid du Colombier 		putout(word[i6].p+1+(i6==i3),word[i7].p);
518*219b2ee8SDavid du Colombier 		printf("\" \"");
519*219b2ee8SDavid du Colombier 		putout(word[i0].p,word[i1].p);
520*219b2ee8SDavid du Colombier 		if(i2<i3 && i1==i2) putchar('/');
521*219b2ee8SDavid du Colombier 		printf("\" \"");
522*219b2ee8SDavid du Colombier 		if(i5>i4 && i6>i5) putchar('/');
523*219b2ee8SDavid du Colombier 		putout(word[i5].p+1+(i5==i3),word[i6].p);
524*219b2ee8SDavid du Colombier 		if(rflag) {
525*219b2ee8SDavid du Colombier 			printf("\" \"");
526*219b2ee8SDavid du Colombier 			putout(word[i3].p+2,word[i4].p);
527*219b2ee8SDavid du Colombier 		}
528*219b2ee8SDavid du Colombier 		printf("\"\n");
529*219b2ee8SDavid du Colombier 	}
530*219b2ee8SDavid du Colombier }
531*219b2ee8SDavid du Colombier 
532*219b2ee8SDavid du Colombier void
533*219b2ee8SDavid du Colombier putout(char *strt, char *end)
534*219b2ee8SDavid du Colombier {
535*219b2ee8SDavid du Colombier 	char *cp;
536*219b2ee8SDavid du Colombier 
537*219b2ee8SDavid du Colombier 	for(cp=strt; cp<end; )
538*219b2ee8SDavid du Colombier 			putc(*cp++,outptr);
539*219b2ee8SDavid du Colombier }
540*219b2ee8SDavid du Colombier 
541*219b2ee8SDavid du Colombier void
542*219b2ee8SDavid du Colombier setlen(void)
543*219b2ee8SDavid du Colombier {
544*219b2ee8SDavid du Colombier 	fprintf(kptr,
545*219b2ee8SDavid du Colombier 		"\\w'\\h'%s''\n"
546*219b2ee8SDavid du Colombier 		"\\w' /'\n"
547*219b2ee8SDavid du Colombier 		"\\w'\\h'%s''\n"
548*219b2ee8SDavid du Colombier 		"\\w'\\h'%s''\n",lenarg,gutarg,holarg);
549*219b2ee8SDavid du Colombier }
550*219b2ee8SDavid du Colombier 
551*219b2ee8SDavid du Colombier void
552*219b2ee8SDavid du Colombier getlen(void)
553*219b2ee8SDavid du Colombier {
554*219b2ee8SDavid du Colombier 	char s[20];
555*219b2ee8SDavid du Colombier 	fgets(s,sizeof(s),kptr);
556*219b2ee8SDavid du Colombier 	llen = atoi(s);
557*219b2ee8SDavid du Colombier 
558*219b2ee8SDavid du Colombier 	fgets(s,sizeof(s),kptr);
559*219b2ee8SDavid du Colombier 	spacesl = atoi(s);
560*219b2ee8SDavid du Colombier 
561*219b2ee8SDavid du Colombier 	fgets(s,sizeof(s),kptr);
562*219b2ee8SDavid du Colombier 	gutter = atoi(s);
563*219b2ee8SDavid du Colombier 
564*219b2ee8SDavid du Colombier 	fgets(s,sizeof(s),kptr);
565*219b2ee8SDavid du Colombier 	hole = atoi(s);
566*219b2ee8SDavid du Colombier 	if(hole < 2*spacesl)
567*219b2ee8SDavid du Colombier 		hole = 2*spacesl;
568*219b2ee8SDavid du Colombier }
569*219b2ee8SDavid du Colombier 
570*219b2ee8SDavid du Colombier int
571*219b2ee8SDavid du Colombier hash(char *strtp, char *endp)
572*219b2ee8SDavid du Colombier {
573*219b2ee8SDavid du Colombier 	char *cp, c;
574*219b2ee8SDavid du Colombier 	int i, j, k;
575*219b2ee8SDavid du Colombier 
576*219b2ee8SDavid du Colombier 	/* Return zero hash number for single letter words */
577*219b2ee8SDavid du Colombier 	if((endp - strtp) == 1)
578*219b2ee8SDavid du Colombier 		return(0);
579*219b2ee8SDavid du Colombier 
580*219b2ee8SDavid du Colombier 	cp = strtp;
581*219b2ee8SDavid du Colombier 	c = *cp++;
582*219b2ee8SDavid du Colombier 	i = (isupper(c)?tolower(c):c);
583*219b2ee8SDavid du Colombier 	c = *cp;
584*219b2ee8SDavid du Colombier 	j = (isupper(c)?tolower(c):c);
585*219b2ee8SDavid du Colombier 	i = i*j;
586*219b2ee8SDavid du Colombier 	cp = --endp;
587*219b2ee8SDavid du Colombier 	c = *cp--;
588*219b2ee8SDavid du Colombier 	k = (isupper(c)?tolower(c):c);
589*219b2ee8SDavid du Colombier 	c = *cp;
590*219b2ee8SDavid du Colombier 	j = (isupper(c)?tolower(c):c);
591*219b2ee8SDavid du Colombier 	j = k*j;
592*219b2ee8SDavid du Colombier 
593*219b2ee8SDavid du Colombier 	k = (i ^ (j>>2)) & MASK;
594*219b2ee8SDavid du Colombier 	return(k);
595*219b2ee8SDavid du Colombier }
596*219b2ee8SDavid du Colombier 
597*219b2ee8SDavid du Colombier int
598*219b2ee8SDavid du Colombier storeh(int num, char *strtp)
599*219b2ee8SDavid du Colombier {
600*219b2ee8SDavid du Colombier 	int i;
601*219b2ee8SDavid du Colombier 
602*219b2ee8SDavid du Colombier 	for(i=num; i<MAXT; i++) {
603*219b2ee8SDavid du Colombier 		if(hasht[i] == 0) {
604*219b2ee8SDavid du Colombier 			hasht[i] = strtp;
605*219b2ee8SDavid du Colombier 			return(0);
606*219b2ee8SDavid du Colombier 		}
607*219b2ee8SDavid du Colombier 	}
608*219b2ee8SDavid du Colombier 	for(i=0; i<num; i++) {
609*219b2ee8SDavid du Colombier 		if(hasht[i] == 0) {
610*219b2ee8SDavid du Colombier 			hasht[i] = strtp;
611*219b2ee8SDavid du Colombier 			return(0);
612*219b2ee8SDavid du Colombier 		}
613*219b2ee8SDavid du Colombier 	}
614*219b2ee8SDavid du Colombier 	return(1);
615*219b2ee8SDavid du Colombier }
616