bcd.c revision 1.12
1/*	$NetBSD: bcd.c,v 1.12 2003/08/07 09:37:04 agc Exp $	*/
2
3/*
4 * Copyright (c) 1989, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Steve Hayman of the Indiana University Computer Science Dept.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/cdefs.h>
36#ifndef lint
37__COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
38	The Regents of the University of California.  All rights reserved.\n");
39#endif /* not lint */
40
41#ifndef lint
42#if 0
43static char sccsid[] = "@(#)bcd.c	8.2 (Berkeley) 3/20/94";
44#else
45__RCSID("$NetBSD: bcd.c,v 1.12 2003/08/07 09:37:04 agc Exp $");
46#endif
47#endif /* not lint */
48
49/*
50 * bcd --
51 *
52 * Read one line of standard input and produce something that looks like a
53 * punch card.  An attempt to reimplement /usr/games/bcd.  All I looked at
54 * was the man page.
55 *
56 * I couldn't find a BCD table handy so I wrote a shell script to deduce what
57 * the patterns were that the old bcd was using for each possible 8-bit
58 * character.  These are the results -- the low order 12 bits represent the
59 * holes.  (A 1 bit is a hole.)  These may be wrong, but they match the old
60 * program!
61 *
62 * Steve Hayman
63 * sahayman@iuvax.cs.indiana.edu
64 * 1989 11 30
65 *
66 *
67 * I found an error in the table. The same error is found in the SunOS 4.1.1
68 * version of bcd. It has apparently been around a long time. The error caused
69 * 'Q' and 'R' to have the same punch code. I only noticed the error due to
70 * someone pointing it out to me when the program was used to print a cover
71 * for an APA!  The table was wrong in 4 places. The other error was masked
72 * by the fact that the input is converted to upper case before lookup.
73 *
74 * Dyane Bruce
75 * db@diana.ocunix.on.ca
76 * Nov 5, 1993
77 */
78
79#include <sys/types.h>
80
81#include <stdio.h>
82#include <stdlib.h>
83#include <string.h>
84#include <ctype.h>
85#include <unistd.h>
86
87const u_short holes[256] = {
88    0x0,	 0x0,	  0x0,	   0x0,	    0x0,     0x0,     0x0,     0x0,
89    0x0,	 0x0,	  0x0,	   0x0,	    0x0,     0x0,     0x0,     0x0,
90    0x0,	 0x0,	  0x0,	   0x0,	    0x0,     0x0,     0x0,     0x0,
91    0x0,	 0x0,	  0x0,	   0x0,	    0x0,     0x0,     0x0,     0x0,
92    0x0,	 0x206,	  0x20a,   0x042,   0x442,   0x222,   0x800,   0x406,
93    0x812,	 0x412,	  0x422,   0xa00,   0x242,   0x400,   0x842,   0x300,
94    0x200,	 0x100,	  0x080,   0x040,   0x020,   0x010,   0x008,   0x004,
95    0x002,	 0x001,	  0x012,   0x40a,   0x80a,   0x212,   0x00a,   0x006,
96    0x022,	 0x900,	  0x880,   0x840,   0x820,   0x810,   0x808,   0x804,
97    0x802,	 0x801,	  0x500,   0x480,   0x440,   0x420,   0x410,   0x408,
98    0x404,	 0x402,	  0x401,   0x280,   0x240,   0x220,   0x210,   0x208,
99    0x204,	 0x202,	  0x201,   0x082,   0x822,   0x600,   0x282,   0x30f,
100    0x900,	 0x880,	  0x840,   0x820,   0x810,   0x808,   0x804,   0x802,
101    0x801,	 0x500,	  0x480,   0x440,   0x420,   0x410,   0x408,   0x404,
102    0x402,	 0x401,	  0x280,   0x240,   0x220,   0x210,   0x208,   0x204,
103    0x202,	 0x201,	  0x082,   0x806,   0x822,   0x600,   0x282,   0x0,
104    0x0,	 0x0,	  0x0,	   0x0,	    0x0,     0x0,     0x0,     0x0,
105    0x0,	 0x0,	  0x0,	   0x0,	    0x0,     0x0,     0x0,     0x0,
106    0x0,	 0x0,	  0x0,	   0x0,	    0x0,     0x0,     0x0,     0x0,
107    0x0,	 0x0,	  0x0,	   0x0,	    0x0,     0x0,     0x0,     0x0,
108    0x206,	 0x20a,	  0x042,   0x442,   0x222,   0x800,   0x406,   0x812,
109    0x412,	 0x422,	  0xa00,   0x242,   0x400,   0x842,   0x300,   0x200,
110    0x100,	 0x080,	  0x040,   0x020,   0x010,   0x008,   0x004,   0x002,
111    0x001,	 0x012,	  0x40a,   0x80a,   0x212,   0x00a,   0x006,   0x022,
112    0x900,	 0x880,	  0x840,   0x820,   0x810,   0x808,   0x804,   0x802,
113    0x801,	 0x500,	  0x480,   0x440,   0x420,   0x410,   0x408,   0x404,
114    0x402,	 0x401,	  0x280,   0x240,   0x220,   0x210,   0x208,   0x204,
115    0x202,	 0x201,	  0x082,   0x806,   0x822,   0x600,   0x282,   0x30f,
116    0x900,	 0x880,	  0x840,   0x820,   0x810,   0x808,   0x804,   0x802,
117    0x801,	 0x500,	  0x480,   0x440,   0x420,   0x410,   0x408,   0x404,
118    0x402,	 0x401,	  0x280,   0x240,   0x220,   0x210,   0x208,   0x204,
119    0x202,	 0x201,	  0x082,   0x806,   0x822,   0x600,   0x282,   0x0
120};
121
122/*
123 * i'th bit of w.
124 */
125#define	bit(w,i)	((w)&(1<<(i)))
126
127int	main __P((int, char *[]));
128void	printcard __P((char *));
129
130int
131main(argc, argv)
132	int argc;
133	char **argv;
134{
135	char cardline[80];
136
137	/* revoke setgid privileges */
138	setgid(getgid());
139
140	/*
141	 * The original bcd prompts with a "%" when reading from stdin,
142	 * but this seems kind of silly.  So this one doesn't.
143	 */
144
145	if (argc > 1) {
146		while (--argc)
147			printcard(*++argv);
148	} else
149		while (fgets(cardline, sizeof(cardline), stdin))
150			printcard(cardline);
151	exit(0);
152}
153
154#define	COLUMNS	48
155
156void
157printcard(str)
158	char *str;
159{
160	static const char rowchars[] = "   123456789";
161	int i, row;
162	unsigned char *p;
163
164	/* ruthlessly remove newlines and truncate at 48 characters. */
165	if ((p = strchr(str, '\n')))
166		*p = '\0';
167
168	if (strlen(str) > COLUMNS)
169		str[COLUMNS] = '\0';
170
171	/* make string upper case. */
172	for (p = str; *p; ++p)
173		if (isascii(*p) && islower(*p))
174			*p = toupper(*p);
175
176	 /* top of card */
177	putchar(' ');
178	for (i = 1; i <= COLUMNS; ++i)
179		putchar('_');
180	putchar('\n');
181
182	/*
183	 * line of text.  Leave a blank if the character doesn't have
184	 * a hole pattern.
185	 */
186	p = str;
187	putchar('/');
188	for (i = 1; *p; i++, p++)
189		if (holes[(int)*p])
190			putchar(*p);
191		else
192			putchar(' ');
193	while (i++ <= COLUMNS)
194		putchar(' ');
195	putchar('|');
196	putchar('\n');
197
198	/*
199	 * 12 rows of potential holes; output a ']', which looks kind of
200	 * like a hole, if the appropriate bit is set in the holes[] table.
201	 * The original bcd output a '[', a backspace, five control A's,
202	 * and then a ']'.  This seems a little excessive.
203	 */
204	for (row = 0; row <= 11; ++row) {
205		putchar('|');
206		for (i = 0, p = str; *p; i++, p++) {
207			if (bit(holes[(int)*p], 11 - row))
208				putchar(']');
209			else
210				putchar(rowchars[row]);
211		}
212		while (i++ < COLUMNS)
213			putchar(rowchars[row]);
214		putchar('|');
215		putchar('\n');
216	}
217
218	/* bottom of card */
219	putchar('|');
220	for (i = 1; i <= COLUMNS; i++)
221		putchar('_');
222	putchar('|');
223	putchar('\n');
224}
225