1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)dohits.c	3.3 (Berkeley) 06/29/88";
20 #endif /* not lint */
21 
22 /*
23  * This program scans a file which describes a keyboard.  The output
24  * of the program is a series of 'C' declarations which describe a
25  * mapping between (scancode, shiftstate, altstate) and 3270 functions,
26  * characters, and AIDs.
27  *
28  * The format of the input file is as follows:
29  *
30  * keynumber [ scancode [ unshifted [ shifted [ alted [ shiftalted ] ] ] ] ]
31  *
32  * keynumber is in decimal, and starts in column 1.
33  * scancode is hexadecimal.
34  * unshifted, etc. - these are either a single ascii character,
35  *			or the name of a function or an AID-generating key.
36  *
37  * all fields are separated by a single space.
38  */
39 
40 #include <stdio.h>
41 #if	defined(unix)
42 #include <strings.h>
43 #else	/* defined(unix) */
44 #include <string.h>
45 #endif	/* defined(unix) */
46 #include <ctype.h>
47 #include "../general/general.h"
48 #include "../api/asc_ebc.h"
49 #include "../api/ebc_disp.h"
50 #include "../ctlr/function.h"
51 
52 #include "dohits.h"
53 
54 struct Hits Hits[256];		/* one for each of 0x00-0xff */
55 
56 struct thing *table[100];
57 
58 extern char *malloc();
59 
60 unsigned int
61 dohash(seed, string)
62 unsigned int seed;
63 char *string;
64 {
65     register unsigned int i = seed;
66     register unsigned char c;
67 
68     while (c = *string++) {
69 	if (c >= 0x60) {
70 	    c -= (0x60+0x20);
71 	} else {
72 	    c -= 0x20;
73 	}
74 	i = (i>>26) + (i<<6) + (c&0x3f);
75     }
76     return i;
77 }
78 
79 void
80 add(first, second, value)
81 char *first, *second;
82 int value;
83 {
84     struct thing **item, *this;
85 
86     item = &firstentry(second);
87     this = (struct thing *) malloc(sizeof *this);
88     this->next = *item;
89     *item = this;
90     this->value = value;
91     strcpy(this->name, first);
92     strcpy(this->name+strlen(this->name), second);
93 }
94 
95 void
96 scanwhite(file, prefix)
97 char *file,		/* Name of file to scan for whitespace prefix */
98      *prefix;		/* prefix of what should be picked up */
99 {
100     FILE *ourfile;
101     char compare[100];
102     char what[100], value[100];
103     char line[200];
104 
105     sprintf(compare, " %s%%[^,\t \n]", prefix);
106     if ((ourfile = fopen(file, "r")) == NULL) {
107 	perror("fopen");
108 	exit(1);
109     }
110     while (!feof(ourfile)) {
111 	if (fscanf(ourfile, compare,  what) == 1) {
112 	    add(prefix, what, 0);
113 	}
114 	do {
115 	    if (fgets(line, sizeof line, ourfile) == NULL) {
116 		if (!feof(ourfile)) {
117 		    perror("fgets");
118 		}
119 		break;
120 	    }
121 	} while (line[strlen(line)-1] != '\n');
122     }
123 }
124 
125 void
126 scandefine(file, prefix)
127 char *file,		/* Name of file to scan for #define prefix */
128      *prefix;		/* prefix of what should be picked up */
129 {
130     FILE *ourfile;
131     char compare[100];
132     char what[100], value[100];
133     char line[200];
134     int whatitis;
135 
136     sprintf(compare, "#define %s%%s %%s", prefix);
137     if ((ourfile = fopen(file, "r")) == NULL) {
138 	perror("fopen");
139 	exit(1);
140     }
141     while (!feof(ourfile)) {
142 	if (fscanf(ourfile, compare,  what, value) == 2) {
143 	    if (value[0] == '0') {
144 		if ((value[1] == 'x') || (value[1] == 'X')) {
145 		    sscanf(value, "0x%x", &whatitis);
146 		} else {
147 		    sscanf(value, "0%o", &whatitis);
148 		}
149 	    } else {
150 		sscanf(value, "%d", &whatitis);
151 	    }
152 	    add(prefix, what, whatitis);
153 	}
154 	do {
155 	    if (fgets(line, sizeof line, ourfile) == NULL) {
156 		if (!feof(ourfile)) {
157 		    perror("fgets");
158 		}
159 		break;
160 	    }
161 	} while (line[strlen(line)-1] != '\n');
162     }
163 }
164 
165 char *savechr(c)
166 unsigned char c;
167 {
168     char *foo;
169 
170     foo = malloc(sizeof c);
171     if (foo == 0) {
172 	fprintf(stderr, "No room for ascii characters!\n");
173 	exit(1);
174     }
175     *foo = c;
176     return foo;
177 }
178 
179 char *
180 doit(hit, type, hits)
181 struct hit *hit;
182 unsigned char *type;
183 struct Hits *hits;
184 {
185     struct thing *this;
186 
187     hit->ctlrfcn = FCN_NULL;
188     if (type[0] == 0) {
189 	return 0;
190     }
191     if (type[1] == 0) {		/* character */
192 	hit->ctlrfcn = FCN_CHARACTER;
193 	hit->code = ebc_disp[asc_ebc[type[0]]];
194 	return savechr(*type);		/* The character is the name */
195     } else {
196 	for (this = firstentry(type); this; this = this->next) {
197 	    if ((type[0] == this->name[4])
198 				&& (strcmp(type, this->name+4) == 0)) {
199 		this->hits = hits;
200 		if (this->name[0] == 'F') {
201 		    hit->ctlrfcn = FCN_NULL;	/* XXX */
202 		} else {
203 		    hit->ctlrfcn = FCN_AID;
204 		}
205 		return this->name;
206 	    }
207 	}
208 	fprintf(stderr, "Error: Unknown type %s.\n", type);
209 	return 0;
210     }
211 }
212 
213 
214 void
215 dohits(aidfile, fcnfile)
216 char	*aidfile, *fcnfile;
217 {
218     unsigned char plain[100], shifted[100], alted[100], shiftalted[100];
219     unsigned char line[200];
220     int keynumber, scancode;
221     int empty;
222     int i;
223     struct hit *hit;
224     struct hits *ph;
225     struct Hits *Ph;
226 
227     memset((char *)Hits, 0, sizeof Hits);
228 
229     /*
230      * First, we read "host3270.h" to find the names/values of
231      * various AID; then we read kbd3270.h to find the names/values
232      * of various FCNs.
233      */
234 
235     if (aidfile == 0) {
236 	aidfile = "../ctlr/hostctlr.h";
237     }
238     scandefine(aidfile, "AID_");
239     if (fcnfile == 0) {
240         fcnfile = "../ctlr/function.h";
241     }
242     scanwhite(fcnfile, "FCN_");
243 
244     while (gets(line) != NULL) {
245 	if (!isdigit(line[0])) {
246 	    continue;
247 	}
248 	plain[0] = shifted[0] = alted[0] = shiftalted[0] = 0;
249 	keynumber = -1;
250 	scancode = -1;
251 	(void) sscanf(line, "%d %x %s %s %s %s", &keynumber,
252 		    &scancode, plain, shifted, alted, shiftalted);
253 	if ((keynumber == -1) || (scancode == -1)
254 		|| ((plain[0] == 0)
255 		    && (shifted[0] == 0)
256 		    && (alted[0] == 0)
257 		    && (shiftalted[0] == 0))) {
258 	    continue;
259 	}
260 	if (scancode >= 256) {
261 	    fprintf(stderr,
262 		"Error: scancode 0x%02x for keynumber %d\n", scancode,
263 		    keynumber);
264 	    break;
265 	}
266 	if (Hits[scancode].hits.hit[0].ctlrfcn != undefined) {
267 	    fprintf(stderr,
268 		"Error: duplicate scancode 0x%02x for keynumber %d\n",
269 		    scancode, keynumber);
270 	    break;
271 	}
272 	hit = Hits[scancode].hits.hit;
273 	Hits[scancode].hits.keynumber = keynumber;
274 	Hits[scancode].name[0] = doit(hit, plain, &Hits[scancode]);
275 	Hits[scancode].name[1] = doit(hit+1, shifted, &Hits[scancode]);
276 	Hits[scancode].name[2] = doit(hit+2, alted, &Hits[scancode]);
277 	Hits[scancode].name[3] = doit(hit+3, shiftalted, &Hits[scancode]);
278     }
279 }
280