1 /* Copyright (c) 1983 Regents of the University of California */ 2 3 #ifndef lint 4 static char sccsid[] = "@(#)lam.c 4.3 (Berkeley) 07/28/84"; 5 #endif not lint 6 7 /* 8 * lam - laminate files 9 * Author: John Kunze, Office of Comp. Affairs, 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(buf, stdout); 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 = (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); 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 gatherline(ip) 129 struct openfile *ip; 130 { 131 char s[BUFSIZ]; 132 register int c; 133 register char *p; 134 register char *lp = linep; 135 char *end = s + BUFSIZ; 136 137 if (ip->eof) { 138 p = ip->sepstring; 139 while (*p) 140 *lp++ = *p++; 141 if (ip->pad) { 142 sprintf(lp, ip->format, ""); 143 lp += strlen(lp); 144 } 145 return(lp); 146 } 147 for (p = s; (c = fgetc(ip->fp)) != EOF && p < end; p++) 148 if ((*p = c) == ip->eol) 149 break; 150 *p = '\0'; 151 p = ip->sepstring; 152 while (*p) 153 *lp++ = *p++; 154 sprintf(lp, ip->format, s); 155 lp += strlen(lp); 156 if (c == EOF) { 157 ip->eof = 1; 158 if (ip->fp == stdin) 159 fclose(stdin); 160 morefiles--; 161 } 162 return(lp); 163 } 164 165 error(msg, s) 166 char *msg; 167 char *s; 168 { 169 char buf[BUFSIZ]; 170 171 setbuf(stderr, buf); 172 fprintf(stderr, "lam: "); 173 fprintf(stderr, msg, s); 174 fprintf(stderr, "\nUsage: lam [ -[fp] min.max ] [ -s sepstring ] [ -t c ] file ...\n"); 175 if (strncmp("lam - ", msg, 6) == 0) 176 fprintf(stderr, "Options:\n\t%s\t%s\t%s\t%s\t%s", 177 "-f min.max field widths for file fragments\n", 178 "-p min.max like -f, but pad missing fragments\n", 179 "-s sepstring fragment separator\n", 180 "-t c input line terminator is c, no \\n after output lines\n", 181 "Capitalized options affect more than one file.\n"); 182 exit(1); 183 } 184