xref: /netbsd-src/games/bcd/bcd.c (revision 9795f61a5af380f665d92198f5c50f2cfdc80167)
1 /*	$NetBSD: bcd.c,v 1.17 2009/08/12 05:21:28 dholland 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\
38  The Regents of the University of California.  All rights reserved.");
39 #endif /* not lint */
40 
41 #ifndef lint
42 #if 0
43 static char sccsid[] = "@(#)bcd.c	8.2 (Berkeley) 3/20/94";
44 #else
45 __RCSID("$NetBSD: bcd.c,v 1.17 2009/08/12 05:21:28 dholland 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 
87 static const 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 
127 static void printcard(char *);
128 
129 int
main(int argc,char ** argv)130 main(int argc, char **argv)
131 {
132 	char cardline[80];
133 
134 	/* revoke setgid privileges */
135 	setgid(getgid());
136 
137 	/*
138 	 * The original bcd prompts with a "%" when reading from stdin,
139 	 * but this seems kind of silly.  So this one doesn't.
140 	 */
141 
142 	if (argc > 1) {
143 		while (--argc)
144 			printcard(*++argv);
145 	} else
146 		while (fgets(cardline, sizeof(cardline), stdin))
147 			printcard(cardline);
148 	exit(0);
149 }
150 
151 #define	COLUMNS	48
152 
153 static void
printcard(char * str)154 printcard(char *str)
155 {
156 	static const char rowchars[] = "   123456789";
157 	int i, row;
158 	char *p;
159 
160 	/* ruthlessly remove newlines and truncate at 48 characters. */
161 	if ((p = strchr(str, '\n')))
162 		*p = '\0';
163 
164 	if (strlen(str) > COLUMNS)
165 		str[COLUMNS] = '\0';
166 
167 	/* make string upper case. */
168 	for (p = str; *p; ++p)
169 		if (isascii((unsigned char)*p) && islower((unsigned char)*p))
170 			*p = toupper((unsigned char) *p);
171 
172 	 /* top of card */
173 	putchar(' ');
174 	for (i = 1; i <= COLUMNS; ++i)
175 		putchar('_');
176 	putchar('\n');
177 
178 	/*
179 	 * line of text.  Leave a blank if the character doesn't have
180 	 * a hole pattern.
181 	 */
182 	p = str;
183 	putchar('/');
184 	for (i = 1; *p; i++, p++)
185 		if (holes[(unsigned char)*p])
186 			putchar(*p);
187 		else
188 			putchar(' ');
189 	while (i++ <= COLUMNS)
190 		putchar(' ');
191 	putchar('|');
192 	putchar('\n');
193 
194 	/*
195 	 * 12 rows of potential holes; output a ']', which looks kind of
196 	 * like a hole, if the appropriate bit is set in the holes[] table.
197 	 * The original bcd output a '[', a backspace, five control A's,
198 	 * and then a ']'.  This seems a little excessive.
199 	 */
200 	for (row = 0; row <= 11; ++row) {
201 		putchar('|');
202 		for (i = 0, p = str; *p; i++, p++) {
203 			if (bit(holes[(unsigned char)*p], 11 - row))
204 				putchar(']');
205 			else
206 				putchar(rowchars[row]);
207 		}
208 		while (i++ < COLUMNS)
209 			putchar(rowchars[row]);
210 		putchar('|');
211 		putchar('\n');
212 	}
213 
214 	/* bottom of card */
215 	putchar('|');
216 	for (i = 1; i <= COLUMNS; i++)
217 		putchar('_');
218 	putchar('|');
219 	putchar('\n');
220 }
221