1 /* Copyright (c) 1983 Regents of the University of California */ 2 3 #ifndef lint 4 static char sccsid[] = "@(#)lam.c 4.5 (Berkeley) 05/19/88"; 5 #endif not lint 6 7 /* 8 * lam - laminate files 9 * Author: John Kunze, UCB 10 */ 11 12 #include <stdio.h> 13 14 #define MAXOFILES 20 15 #define BIGBUFSIZ 5 * BUFSIZ 16 17 struct openfile { /* open file structure */ 18 FILE *fp; /* file pointer */ 19 short eof; /* eof flag */ 20 short pad; /* pad flag for missing columns */ 21 char eol; /* end of line character */ 22 char *sepstring; /* string to print before each line */ 23 char *format; /* printf(3) style string spec. */ 24 } input[MAXOFILES]; 25 26 int morefiles; /* set by getargs(), changed by gatherline() */ 27 int nofinalnl; /* normally append \n to each output line */ 28 char buf[BUFSIZ]; 29 char line[BIGBUFSIZ]; 30 char *linep; 31 32 main(argc, argv) 33 int argc; 34 char **argv; 35 { 36 register struct openfile *ip; 37 char *gatherline(); 38 39 setbuf(stdout, buf); 40 getargs(argv); 41 if (!morefiles) 42 error("lam - laminate files", ""); 43 for (;;) { 44 linep = line; 45 for (ip = input; ip->fp != NULL; ip++) 46 linep = gatherline(ip); 47 if (!morefiles) 48 exit(0); 49 fputs(line, stdout); 50 fputs(ip->sepstring, stdout); 51 if (!nofinalnl) 52 putchar('\n'); 53 } 54 } 55 56 getargs(av) 57 char **av; 58 { 59 register struct openfile *ip = input; 60 register char *p; 61 register char *c; 62 static char fmtbuf[BUFSIZ]; 63 char *fmtp = fmtbuf; 64 int P, S, F, T; 65 66 P = S = F = T = 0; /* capitalized options */ 67 while (p = *++av) { 68 if (*p != '-' || !p[1]) { 69 morefiles++; 70 if (*p == '-') 71 ip->fp = stdin; 72 else if ((ip->fp = fopen(p, "r")) == NULL) { 73 perror(p); 74 exit(1); 75 } 76 ip->pad = P; 77 if (!ip->sepstring) 78 ip->sepstring = (S ? (ip-1)->sepstring : ""); 79 if (!ip->format) 80 ip->format = ((P || F) ? (ip-1)->format : "%s"); 81 if (!ip->eol) 82 ip->eol = (T ? (ip-1)->eol : '\n'); 83 ip++; 84 continue; 85 } 86 switch (*(c = ++p) | 040) { 87 case 's': 88 if (*++p || (p = *++av)) 89 ip->sepstring = p; 90 else 91 error("Need string after -%s", c); 92 S = (*c == 'S' ? 1 : 0); 93 break; 94 case 't': 95 if (*++p || (p = *++av)) 96 ip->eol = *p; 97 else 98 error("Need character after -%s", c); 99 T = (*c == 'T' ? 1 : 0); 100 nofinalnl = 1; 101 break; 102 case 'p': 103 ip->pad = 1; 104 P = (*c == 'P' ? 1 : 0); 105 case 'f': 106 F = (*c == 'F' ? 1 : 0); 107 if (*++p || (p = *++av)) { 108 fmtp += strlen(fmtp) + 1; 109 if (fmtp > fmtbuf + BUFSIZ) 110 error("No more format space", ""); 111 sprintf(fmtp, "%%%ss", p); 112 ip->format = fmtp; 113 } 114 else 115 error("Need string after -%s", c); 116 break; 117 default: 118 error("What do you mean by -%s?", c); 119 break; 120 } 121 } 122 ip->fp = NULL; 123 if (!ip->sepstring) 124 ip->sepstring = ""; 125 } 126 127 char * 128 pad(ip) 129 struct openfile *ip; 130 { 131 register char *p = ip->sepstring; 132 register char *lp = linep; 133 134 while (*p) 135 *lp++ = *p++; 136 if (ip->pad) { 137 sprintf(lp, ip->format, ""); 138 lp += strlen(lp); 139 } 140 return(lp); 141 } 142 143 char * 144 gatherline(ip) 145 struct openfile *ip; 146 { 147 char s[BUFSIZ]; 148 register int c; 149 register char *p; 150 register char *lp = linep; 151 char *end = s + BUFSIZ; 152 153 if (ip->eof) 154 return(pad(ip)); 155 for (p = s; (c = fgetc(ip->fp)) != EOF && p < end; p++) 156 if ((*p = c) == ip->eol) 157 break; 158 *p = '\0'; 159 if (c == EOF) { 160 ip->eof = 1; 161 if (ip->fp == stdin) 162 fclose(stdin); 163 morefiles--; 164 return(pad(ip)); 165 } 166 p = ip->sepstring; 167 while (*p) 168 *lp++ = *p++; 169 sprintf(lp, ip->format, s); 170 lp += strlen(lp); 171 return(lp); 172 } 173 174 error(msg, s) 175 char *msg; 176 char *s; 177 { 178 char buf[BUFSIZ]; 179 180 setbuf(stderr, buf); 181 fprintf(stderr, "lam: "); 182 fprintf(stderr, msg, s); 183 fprintf(stderr, "\nUsage: lam [ -[fp] min.max ] [ -s sepstring ] [ -t c ] file ...\n"); 184 if (strncmp("lam - ", msg, 6) == 0) 185 fprintf(stderr, "Options:\n\t%s\t%s\t%s\t%s\t%s", 186 "-f min.max field widths for file fragments\n", 187 "-p min.max like -f, but pad missing fragments\n", 188 "-s sepstring fragment separator\n", 189 "-t c input line terminator is c, no \\n after output lines\n", 190 "Capitalized options affect more than one file.\n"); 191 exit(1); 192 } 193