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