lam.c revision 72153
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3527497Scharnierstatic const char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1993\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 381590Srgrimes#endif /* not lint */ 391590Srgrimes 401590Srgrimes#ifndef lint 4127497Scharnier#if 0 421590Srgrimesstatic char sccsid[] = "@(#)lam.c 8.1 (Berkeley) 6/6/93"; 4327497Scharnier#endif 4427497Scharnierstatic const char rcsid[] = 4550477Speter "$FreeBSD: head/usr.bin/lam/lam.c 72153 2001-02-08 05:58:55Z mikeh $"; 461590Srgrimes#endif /* not lint */ 471590Srgrimes 481590Srgrimes/* 491590Srgrimes * lam - laminate files 501590Srgrimes * Author: John Kunze, UCB 511590Srgrimes */ 521590Srgrimes 5372152Smikeh#include <ctype.h> 5427497Scharnier#include <err.h> 551590Srgrimes#include <stdio.h> 561590Srgrimes#include <stdlib.h> 571590Srgrimes#include <string.h> 581590Srgrimes 591590Srgrimes#define MAXOFILES 20 601590Srgrimes#define BIGBUFSIZ 5 * BUFSIZ 611590Srgrimes 621590Srgrimesstruct openfile { /* open file structure */ 631590Srgrimes FILE *fp; /* file pointer */ 641590Srgrimes short eof; /* eof flag */ 651590Srgrimes short pad; /* pad flag for missing columns */ 661590Srgrimes char eol; /* end of line character */ 671590Srgrimes char *sepstring; /* string to print before each line */ 681590Srgrimes char *format; /* printf(3) style string spec. */ 691590Srgrimes} input[MAXOFILES]; 701590Srgrimes 711590Srgrimesint morefiles; /* set by getargs(), changed by gatherline() */ 721590Srgrimesint nofinalnl; /* normally append \n to each output line */ 731590Srgrimeschar line[BIGBUFSIZ]; 741590Srgrimeschar *linep; 751590Srgrimes 7672153Smikehchar *gatherline (struct openfile *); 7772153Smikehvoid getargs (char **); 7872153Smikehchar *pad (struct openfile *); 7972153Smikehstatic void usage (void); 801590Srgrimes 811590Srgrimesint 8272153Smikehmain(int argc, char **argv) 831590Srgrimes{ 8472152Smikeh struct openfile *ip; 851590Srgrimes 861590Srgrimes getargs(argv); 871590Srgrimes if (!morefiles) 8827497Scharnier usage(); 891590Srgrimes for (;;) { 901590Srgrimes linep = line; 911590Srgrimes for (ip = input; ip->fp != NULL; ip++) 921590Srgrimes linep = gatherline(ip); 931590Srgrimes if (!morefiles) 941590Srgrimes exit(0); 951590Srgrimes fputs(line, stdout); 961590Srgrimes fputs(ip->sepstring, stdout); 971590Srgrimes if (!nofinalnl) 981590Srgrimes putchar('\n'); 991590Srgrimes } 1001590Srgrimes} 1011590Srgrimes 1021590Srgrimesvoid 10372153Smikehgetargs(char **av) 1041590Srgrimes{ 10572152Smikeh struct openfile *ip = input; 10672152Smikeh char *p, *c; 1071590Srgrimes static char fmtbuf[BUFSIZ]; 1081590Srgrimes char *fmtp = fmtbuf; 1091590Srgrimes int P, S, F, T; 1101590Srgrimes 1111590Srgrimes P = S = F = T = 0; /* capitalized options */ 1121590Srgrimes while ((p = *++av) != NULL) { 1131590Srgrimes if (*p != '-' || !p[1]) { 11472152Smikeh if (++morefiles >= MAXOFILES) 11572152Smikeh errx(1, "too many input files"); 1161590Srgrimes if (*p == '-') 1171590Srgrimes ip->fp = stdin; 1181590Srgrimes else if ((ip->fp = fopen(p, "r")) == NULL) { 11962894Skris err(1, "%s", p); 1201590Srgrimes } 1211590Srgrimes ip->pad = P; 1221590Srgrimes if (!ip->sepstring) 1231590Srgrimes ip->sepstring = (S ? (ip-1)->sepstring : ""); 1241590Srgrimes if (!ip->format) 1251590Srgrimes ip->format = ((P || F) ? (ip-1)->format : "%s"); 1261590Srgrimes if (!ip->eol) 1271590Srgrimes ip->eol = (T ? (ip-1)->eol : '\n'); 1281590Srgrimes ip++; 1291590Srgrimes continue; 1301590Srgrimes } 13172152Smikeh c = ++p; 13272152Smikeh switch (tolower(*c)) { 1331590Srgrimes case 's': 1341590Srgrimes if (*++p || (p = *++av)) 1351590Srgrimes ip->sepstring = p; 1361590Srgrimes else 13727497Scharnier errx(1, "need string after -%s", c); 1381590Srgrimes S = (*c == 'S' ? 1 : 0); 1391590Srgrimes break; 1401590Srgrimes case 't': 1411590Srgrimes if (*++p || (p = *++av)) 1421590Srgrimes ip->eol = *p; 1431590Srgrimes else 14427497Scharnier errx(1, "need character after -%s", c); 1451590Srgrimes T = (*c == 'T' ? 1 : 0); 1461590Srgrimes nofinalnl = 1; 1471590Srgrimes break; 1481590Srgrimes case 'p': 1491590Srgrimes ip->pad = 1; 1501590Srgrimes P = (*c == 'P' ? 1 : 0); 15172152Smikeh /* FALLTHROUGH */ 1521590Srgrimes case 'f': 1531590Srgrimes F = (*c == 'F' ? 1 : 0); 1541590Srgrimes if (*++p || (p = *++av)) { 1551590Srgrimes fmtp += strlen(fmtp) + 1; 15672152Smikeh if (fmtp >= fmtbuf + sizeof(fmtbuf)) 15727497Scharnier errx(1, "no more format space"); 15872152Smikeh /* restrict format string to only valid width formatters */ 15972152Smikeh if (strspn(p, "-.0123456789") != strlen(p)) 16072152Smikeh errx(1, "invalid format string `%s'", p); 16172152Smikeh if (snprintf(fmtp, fmtbuf + sizeof(fmtbuf) - fmtp, "%%%ss", p) 16272152Smikeh >= fmtbuf + sizeof(fmtbuf) - fmtp) 16372152Smikeh errx(1, "no more format space"); 1641590Srgrimes ip->format = fmtp; 1651590Srgrimes } 1661590Srgrimes else 16727497Scharnier errx(1, "need string after -%s", c); 1681590Srgrimes break; 1691590Srgrimes default: 17027497Scharnier errx(1, "what do you mean by -%s?", c); 1711590Srgrimes break; 1721590Srgrimes } 1731590Srgrimes } 1741590Srgrimes ip->fp = NULL; 1751590Srgrimes if (!ip->sepstring) 1761590Srgrimes ip->sepstring = ""; 1771590Srgrimes} 1781590Srgrimes 1791590Srgrimeschar * 18072153Smikehpad(struct openfile *ip) 1811590Srgrimes{ 18272152Smikeh char *lp = linep; 1831590Srgrimes 18472152Smikeh strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); 18572152Smikeh lp += strlen(lp); 1861590Srgrimes if (ip->pad) { 18772152Smikeh snprintf(lp, line + sizeof(line) - lp, ip->format, ""); 1881590Srgrimes lp += strlen(lp); 1891590Srgrimes } 1901590Srgrimes return (lp); 1911590Srgrimes} 1921590Srgrimes 1931590Srgrimeschar * 19472153Smikehgatherline(struct openfile *ip) 1951590Srgrimes{ 1961590Srgrimes char s[BUFSIZ]; 19772152Smikeh int c; 19872152Smikeh char *p; 19972152Smikeh char *lp = linep; 20072152Smikeh char *end = s + sizeof(s) - 1; 2011590Srgrimes 2021590Srgrimes if (ip->eof) 2031590Srgrimes return (pad(ip)); 2041590Srgrimes for (p = s; (c = fgetc(ip->fp)) != EOF && p < end; p++) 2051590Srgrimes if ((*p = c) == ip->eol) 2061590Srgrimes break; 2071590Srgrimes *p = '\0'; 2081590Srgrimes if (c == EOF) { 2091590Srgrimes ip->eof = 1; 2101590Srgrimes if (ip->fp == stdin) 2111590Srgrimes fclose(stdin); 2121590Srgrimes morefiles--; 2131590Srgrimes return (pad(ip)); 2141590Srgrimes } 21572152Smikeh strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); 2161590Srgrimes lp += strlen(lp); 21772152Smikeh snprintf(lp, line + sizeof(line) - lp, ip->format, s); 21872152Smikeh lp += strlen(lp); 2191590Srgrimes return (lp); 2201590Srgrimes} 2211590Srgrimes 22227497Scharnierstatic void 22327497Scharnierusage() 2241590Srgrimes{ 22527497Scharnier fprintf(stderr, "%s\n%s\n", 22627497Scharnier"usage: lam [ -f min.max ] [ -s sepstring ] [ -t c ] file ...", 22727497Scharnier" lam [ -p min.max ] [ -s sepstring ] [ -t c ] file ..."); 2281590Srgrimes exit(1); 2291590Srgrimes} 230