1*9795f61aSdholland /* $NetBSD: bcd.c,v 1.17 2009/08/12 05:21:28 dholland Exp $ */
2101657d1Scgd
361f28255Scgd /*
4101657d1Scgd * Copyright (c) 1989, 1993
5101657d1Scgd * The Regents of the University of California. All rights reserved.
661f28255Scgd *
761f28255Scgd * This code is derived from software contributed to Berkeley by
8101657d1Scgd * Steve Hayman of the Indiana University Computer Science Dept.
961f28255Scgd *
1061f28255Scgd * Redistribution and use in source and binary forms, with or without
1161f28255Scgd * modification, are permitted provided that the following conditions
1261f28255Scgd * are met:
1361f28255Scgd * 1. Redistributions of source code must retain the above copyright
1461f28255Scgd * notice, this list of conditions and the following disclaimer.
1561f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1661f28255Scgd * notice, this list of conditions and the following disclaimer in the
1761f28255Scgd * documentation and/or other materials provided with the distribution.
18e5aeb4eaSagc * 3. Neither the name of the University nor the names of its contributors
1961f28255Scgd * may be used to endorse or promote products derived from this software
2061f28255Scgd * without specific prior written permission.
2161f28255Scgd *
2261f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2361f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2461f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2561f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2661f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2761f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2861f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2961f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3061f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3161f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3261f28255Scgd * SUCH DAMAGE.
3361f28255Scgd */
3461f28255Scgd
35492d7c20Slukem #include <sys/cdefs.h>
3661f28255Scgd #ifndef lint
372fe2731dSlukem __COPYRIGHT("@(#) Copyright (c) 1989, 1993\
382fe2731dSlukem The Regents of the University of California. All rights reserved.");
3961f28255Scgd #endif /* not lint */
4061f28255Scgd
4161f28255Scgd #ifndef lint
42492d7c20Slukem #if 0
43101657d1Scgd static char sccsid[] = "@(#)bcd.c 8.2 (Berkeley) 3/20/94";
44492d7c20Slukem #else
45*9795f61aSdholland __RCSID("$NetBSD: bcd.c,v 1.17 2009/08/12 05:21:28 dholland Exp $");
46492d7c20Slukem #endif
4761f28255Scgd #endif /* not lint */
4861f28255Scgd
4961f28255Scgd /*
5061f28255Scgd * bcd --
5161f28255Scgd *
5261f28255Scgd * Read one line of standard input and produce something that looks like a
5361f28255Scgd * punch card. An attempt to reimplement /usr/games/bcd. All I looked at
5461f28255Scgd * was the man page.
5561f28255Scgd *
5661f28255Scgd * I couldn't find a BCD table handy so I wrote a shell script to deduce what
5761f28255Scgd * the patterns were that the old bcd was using for each possible 8-bit
5861f28255Scgd * character. These are the results -- the low order 12 bits represent the
5961f28255Scgd * holes. (A 1 bit is a hole.) These may be wrong, but they match the old
6061f28255Scgd * program!
6161f28255Scgd *
6261f28255Scgd * Steve Hayman
6361f28255Scgd * sahayman@iuvax.cs.indiana.edu
6461f28255Scgd * 1989 11 30
65101657d1Scgd *
66101657d1Scgd *
67101657d1Scgd * I found an error in the table. The same error is found in the SunOS 4.1.1
68101657d1Scgd * version of bcd. It has apparently been around a long time. The error caused
69101657d1Scgd * 'Q' and 'R' to have the same punch code. I only noticed the error due to
70101657d1Scgd * someone pointing it out to me when the program was used to print a cover
71101657d1Scgd * for an APA! The table was wrong in 4 places. The other error was masked
72101657d1Scgd * by the fact that the input is converted to upper case before lookup.
73101657d1Scgd *
74101657d1Scgd * Dyane Bruce
75101657d1Scgd * db@diana.ocunix.on.ca
76101657d1Scgd * Nov 5, 1993
7761f28255Scgd */
7861f28255Scgd
7961f28255Scgd #include <sys/types.h>
80101657d1Scgd
8161f28255Scgd #include <stdio.h>
8232330650Smatt #include <stdlib.h>
83c4816c32Scgd #include <string.h>
8461f28255Scgd #include <ctype.h>
8522c39e3bShubertf #include <unistd.h>
8661f28255Scgd
87*9795f61aSdholland static const u_short holes[256] = {
8861f28255Scgd 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
8961f28255Scgd 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
9061f28255Scgd 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
9161f28255Scgd 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
9261f28255Scgd 0x0, 0x206, 0x20a, 0x042, 0x442, 0x222, 0x800, 0x406,
9361f28255Scgd 0x812, 0x412, 0x422, 0xa00, 0x242, 0x400, 0x842, 0x300,
9461f28255Scgd 0x200, 0x100, 0x080, 0x040, 0x020, 0x010, 0x008, 0x004,
9561f28255Scgd 0x002, 0x001, 0x012, 0x40a, 0x80a, 0x212, 0x00a, 0x006,
9661f28255Scgd 0x022, 0x900, 0x880, 0x840, 0x820, 0x810, 0x808, 0x804,
9761f28255Scgd 0x802, 0x801, 0x500, 0x480, 0x440, 0x420, 0x410, 0x408,
98bf0bd946Sjtc 0x404, 0x402, 0x401, 0x280, 0x240, 0x220, 0x210, 0x208,
9961f28255Scgd 0x204, 0x202, 0x201, 0x082, 0x822, 0x600, 0x282, 0x30f,
10061f28255Scgd 0x900, 0x880, 0x840, 0x820, 0x810, 0x808, 0x804, 0x802,
10161f28255Scgd 0x801, 0x500, 0x480, 0x440, 0x420, 0x410, 0x408, 0x404,
102962bceaeSjtc 0x402, 0x401, 0x280, 0x240, 0x220, 0x210, 0x208, 0x204,
10361f28255Scgd 0x202, 0x201, 0x082, 0x806, 0x822, 0x600, 0x282, 0x0,
10461f28255Scgd 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
10561f28255Scgd 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
10661f28255Scgd 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
10761f28255Scgd 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
10861f28255Scgd 0x206, 0x20a, 0x042, 0x442, 0x222, 0x800, 0x406, 0x812,
10961f28255Scgd 0x412, 0x422, 0xa00, 0x242, 0x400, 0x842, 0x300, 0x200,
11061f28255Scgd 0x100, 0x080, 0x040, 0x020, 0x010, 0x008, 0x004, 0x002,
11161f28255Scgd 0x001, 0x012, 0x40a, 0x80a, 0x212, 0x00a, 0x006, 0x022,
11261f28255Scgd 0x900, 0x880, 0x840, 0x820, 0x810, 0x808, 0x804, 0x802,
11361f28255Scgd 0x801, 0x500, 0x480, 0x440, 0x420, 0x410, 0x408, 0x404,
114bf0bd946Sjtc 0x402, 0x401, 0x280, 0x240, 0x220, 0x210, 0x208, 0x204,
11561f28255Scgd 0x202, 0x201, 0x082, 0x806, 0x822, 0x600, 0x282, 0x30f,
11661f28255Scgd 0x900, 0x880, 0x840, 0x820, 0x810, 0x808, 0x804, 0x802,
11761f28255Scgd 0x801, 0x500, 0x480, 0x440, 0x420, 0x410, 0x408, 0x404,
118962bceaeSjtc 0x402, 0x401, 0x280, 0x240, 0x220, 0x210, 0x208, 0x204,
11961f28255Scgd 0x202, 0x201, 0x082, 0x806, 0x822, 0x600, 0x282, 0x0
12061f28255Scgd };
12161f28255Scgd
12261f28255Scgd /*
12361f28255Scgd * i'th bit of w.
12461f28255Scgd */
12561f28255Scgd #define bit(w,i) ((w)&(1<<(i)))
12661f28255Scgd
127*9795f61aSdholland static void printcard(char *);
128492d7c20Slukem
129101657d1Scgd int
main(int argc,char ** argv)130bd6068f4Sjmc main(int argc, char **argv)
13161f28255Scgd {
13261f28255Scgd char cardline[80];
13361f28255Scgd
13422c39e3bShubertf /* revoke setgid privileges */
135f9eca697Smycroft setgid(getgid());
13622c39e3bShubertf
13761f28255Scgd /*
13861f28255Scgd * The original bcd prompts with a "%" when reading from stdin,
13961f28255Scgd * but this seems kind of silly. So this one doesn't.
14061f28255Scgd */
14161f28255Scgd
14261f28255Scgd if (argc > 1) {
14361f28255Scgd while (--argc)
14461f28255Scgd printcard(*++argv);
14561f28255Scgd } else
14661f28255Scgd while (fgets(cardline, sizeof(cardline), stdin))
14761f28255Scgd printcard(cardline);
14861f28255Scgd exit(0);
14961f28255Scgd }
15061f28255Scgd
15161f28255Scgd #define COLUMNS 48
15261f28255Scgd
153*9795f61aSdholland static void
printcard(char * str)154bd6068f4Sjmc printcard(char *str)
15561f28255Scgd {
156062503c3Shubertf static const char rowchars[] = " 123456789";
157492d7c20Slukem int i, row;
158b740fff7Sdholland char *p;
15961f28255Scgd
16061f28255Scgd /* ruthlessly remove newlines and truncate at 48 characters. */
161492d7c20Slukem if ((p = strchr(str, '\n')))
16261f28255Scgd *p = '\0';
16361f28255Scgd
16461f28255Scgd if (strlen(str) > COLUMNS)
16561f28255Scgd str[COLUMNS] = '\0';
16661f28255Scgd
16761f28255Scgd /* make string upper case. */
16861f28255Scgd for (p = str; *p; ++p)
169b740fff7Sdholland if (isascii((unsigned char)*p) && islower((unsigned char)*p))
170b740fff7Sdholland *p = toupper((unsigned char) *p);
17161f28255Scgd
17261f28255Scgd /* top of card */
17361f28255Scgd putchar(' ');
17461f28255Scgd for (i = 1; i <= COLUMNS; ++i)
17561f28255Scgd putchar('_');
17661f28255Scgd putchar('\n');
17761f28255Scgd
17861f28255Scgd /*
17961f28255Scgd * line of text. Leave a blank if the character doesn't have
18061f28255Scgd * a hole pattern.
18161f28255Scgd */
18261f28255Scgd p = str;
18361f28255Scgd putchar('/');
18461f28255Scgd for (i = 1; *p; i++, p++)
185b740fff7Sdholland if (holes[(unsigned char)*p])
18661f28255Scgd putchar(*p);
18761f28255Scgd else
18861f28255Scgd putchar(' ');
18961f28255Scgd while (i++ <= COLUMNS)
19061f28255Scgd putchar(' ');
19161f28255Scgd putchar('|');
19261f28255Scgd putchar('\n');
19361f28255Scgd
19461f28255Scgd /*
19561f28255Scgd * 12 rows of potential holes; output a ']', which looks kind of
19661f28255Scgd * like a hole, if the appropriate bit is set in the holes[] table.
19761f28255Scgd * The original bcd output a '[', a backspace, five control A's,
19861f28255Scgd * and then a ']'. This seems a little excessive.
19961f28255Scgd */
20061f28255Scgd for (row = 0; row <= 11; ++row) {
20161f28255Scgd putchar('|');
20261f28255Scgd for (i = 0, p = str; *p; i++, p++) {
203b740fff7Sdholland if (bit(holes[(unsigned char)*p], 11 - row))
20461f28255Scgd putchar(']');
20561f28255Scgd else
20661f28255Scgd putchar(rowchars[row]);
20761f28255Scgd }
20861f28255Scgd while (i++ < COLUMNS)
20961f28255Scgd putchar(rowchars[row]);
21061f28255Scgd putchar('|');
21161f28255Scgd putchar('\n');
21261f28255Scgd }
21361f28255Scgd
21461f28255Scgd /* bottom of card */
21561f28255Scgd putchar('|');
21661f28255Scgd for (i = 1; i <= COLUMNS; i++)
21761f28255Scgd putchar('_');
21861f28255Scgd putchar('|');
21961f28255Scgd putchar('\n');
22061f28255Scgd }
221