1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1991 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)join.c 4.3 (Berkeley) 04/17/91"; 16 #endif /* not lint */ 17 18 /* join F1 F2 on stuff */ 19 20 #include <stdio.h> 21 #define F1 0 22 #define F2 1 23 #define NFLD 20 /* max field per line */ 24 #define comp() cmp(ppi[F1][j1],ppi[F2][j2]) 25 26 FILE *f[2]; 27 char buf[2][BUFSIZ]; /*input lines */ 28 char *ppi[2][NFLD]; /* pointers to fields in lines */ 29 char *s1,*s2; 30 int j1 = 1; /* join of this field of file 1 */ 31 int j2 = 1; /* join of this field of file 2 */ 32 int olist[2*NFLD]; /* output these fields */ 33 int olistf[2*NFLD]; /* from these files */ 34 int no; /* number of entries in olist */ 35 int sep1 = ' '; /* default field separator */ 36 int sep2 = '\t'; 37 char* null = ""; 38 int unpub1; 39 int unpub2; 40 int aflg; 41 42 main(argc, argv) 43 char *argv[]; 44 { 45 int i; 46 int n1, n2; 47 long top2, bot2; 48 long ftell(); 49 50 while (argc > 1 && argv[1][0] == '-') { 51 if (argv[1][1] == '\0') 52 break; 53 switch (argv[1][1]) { 54 case 'a': 55 switch(argv[1][2]) { 56 case '1': 57 aflg |= 1; 58 break; 59 case '2': 60 aflg |= 2; 61 break; 62 default: 63 aflg |= 3; 64 } 65 break; 66 case 'e': 67 null = argv[2]; 68 argv++; 69 argc--; 70 break; 71 case 't': 72 sep1 = sep2 = argv[1][2]; 73 break; 74 case 'o': 75 for (no = 0; no < 2*NFLD; no++) { 76 if (argv[2][0] == '1' && argv[2][1] == '.') { 77 olistf[no] = F1; 78 olist[no] = atoi(&argv[2][2]); 79 } else if (argv[2][0] == '2' && argv[2][1] == '.') { 80 olist[no] = atoi(&argv[2][2]); 81 olistf[no] = F2; 82 } else 83 break; 84 argc--; 85 argv++; 86 } 87 break; 88 case 'j': 89 if (argv[1][2] == '1') 90 j1 = atoi(argv[2]); 91 else if (argv[1][2] == '2') 92 j2 = atoi(argv[2]); 93 else 94 j1 = j2 = atoi(argv[2]); 95 argc--; 96 argv++; 97 break; 98 } 99 argc--; 100 argv++; 101 } 102 for (i = 0; i < no; i++) 103 olist[i]--; /* 0 origin */ 104 if (argc != 3) 105 error("usage: join [-an] [-estring] [-j1 x -j2 y] [-o list] [-tc] file1 file2"); 106 j1--; 107 j2--; /* everyone else believes in 0 origin */ 108 s1 = ppi[F1][j1]; 109 s2 = ppi[F2][j2]; 110 if (argv[1][0] == '-') 111 f[F1] = stdin; 112 else if ((f[F1] = fopen(argv[1], "r")) == NULL) 113 error("can't open %s", argv[1]); 114 if ((f[F2] = fopen(argv[2], "r")) == NULL) 115 error("can't open %s", argv[2]); 116 117 #define get1() n1=input(F1) 118 #define get2() n2=input(F2) 119 get1(); 120 bot2 = ftell(f[F2]); 121 get2(); 122 while(n1>0 && n2>0 || aflg!=0 && n1+n2>0) { 123 if(n1>0 && n2>0 && comp()>0 || n1==0) { 124 if(aflg&2) output(0, n2); 125 bot2 = ftell(f[F2]); 126 get2(); 127 } else if(n1>0 && n2>0 && comp()<0 || n2==0) { 128 if(aflg&1) output(n1, 0); 129 get1(); 130 } else /*(n1>0 && n2>0 && comp()==0)*/ { 131 while(n2>0 && comp()==0) { 132 output(n1, n2); 133 top2 = ftell(f[F2]); 134 get2(); 135 } 136 fseek(f[F2], bot2, 0); 137 get2(); 138 get1(); 139 for(;;) { 140 if(n1>0 && n2>0 && comp()==0) { 141 output(n1, n2); 142 get2(); 143 } else if(n1>0 && n2>0 && comp()<0 || n2==0) { 144 fseek(f[F2], bot2, 0); 145 get2(); 146 get1(); 147 } else /*(n1>0 && n2>0 && comp()>0 || n1==0)*/{ 148 fseek(f[F2], top2, 0); 149 bot2 = top2; 150 get2(); 151 break; 152 } 153 } 154 } 155 } 156 return(0); 157 } 158 159 input(n) /* get input line and split into fields */ 160 { 161 register int i, c; 162 char *bp; 163 char **pp; 164 165 bp = buf[n]; 166 pp = ppi[n]; 167 if (fgets(bp, BUFSIZ, f[n]) == NULL) 168 return(0); 169 for (i = 0; ; i++) { 170 if (sep1 == ' ') /* strip multiples */ 171 while ((c = *bp) == sep1 || c == sep2) 172 bp++; /* skip blanks */ 173 else 174 c = *bp; 175 if (c == '\n' || c == '\0') 176 break; 177 *pp++ = bp; /* record beginning */ 178 while ((c = *bp) != sep1 && c != '\n' && c != sep2 && c != '\0') 179 bp++; 180 *bp++ = '\0'; /* mark end by overwriting blank */ 181 /* fails badly if string doesn't have \n at end */ 182 } 183 *pp = 0; 184 return(i); 185 } 186 187 output(on1, on2) /* print items from olist */ 188 int on1, on2; 189 { 190 int i; 191 char *temp; 192 193 if (no <= 0) { /* default case */ 194 printf("%s", on1? ppi[F1][j1]: ppi[F2][j2]); 195 for (i = 0; i < on1; i++) 196 if (i != j1) 197 printf("%c%s", sep1, ppi[F1][i]); 198 for (i = 0; i < on2; i++) 199 if (i != j2) 200 printf("%c%s", sep1, ppi[F2][i]); 201 printf("\n"); 202 } else { 203 for (i = 0; i < no; i++) { 204 temp = ppi[olistf[i]][olist[i]]; 205 if(olistf[i]==F1 && on1<=olist[i] || 206 olistf[i]==F2 && on2<=olist[i] || 207 *temp==0) 208 temp = null; 209 printf("%s", temp); 210 if (i == no - 1) 211 printf("\n"); 212 else 213 printf("%c", sep1); 214 } 215 } 216 } 217 218 error(s1, s2, s3, s4, s5) 219 char *s1; 220 { 221 fprintf(stderr, "join: "); 222 fprintf(stderr, s1, s2, s3, s4, s5); 223 fprintf(stderr, "\n"); 224 exit(1); 225 } 226 227 cmp(s1, s2) 228 char *s1, *s2; 229 { 230 return(strcmp(s1, s2)); 231 } 232