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