1: #include <X/mit-copyright.h>
   2: 
   3: /* Copyright 1985, Massachusetts Institute of Technology */
   4: 
   5: #ifndef lint
   6: static char *rcsid_keycomp_c = "$Header: keycomp.c,v 10.4 86/02/01 15:45:26 tony Rel $";
   7: #endif
   8: 
   9: #include <stdio.h>
  10: #include <X/X.h>
  11: #include "Xkeymap.h"
  12: 
  13: #define isnum(c) (((c) >= '0') && ((c) <= '9'))
  14: #define isoctal(c) (((c) >= '0') && ((c) <= '7'))
  15: #define whitespace(c) (((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\0'))
  16: 
  17: #define bool int
  18: #define TRUE 1
  19: #define FALSE 0
  20: 
  21: #define MAXLENGTH 80
  22: 
  23: typedef struct _EscMapEntry {
  24:     char from, to;} EscMapEntry;
  25: 
  26: typedef enum _ParseError {
  27:     e_NoError,
  28:     e_NoKeycode,
  29:     e_KeycodeTooBig,
  30:     e_Not1Or16Items,
  31:     e_NotNumber,
  32:     e_NumberTooBig,
  33:     e_SingleQuoteNotClosed,
  34:     e_StringTooLong,
  35:     e_DoubleQuoteNotClosed,
  36:     e_TooManyCharsBetweenQuotes,
  37:     e_Unrecognized
  38:     } ParseError;
  39: 
  40: #define CT_ESC_ENTRIES 5
  41: static EscMapEntry EscMap [CT_ESC_ENTRIES] = {
  42:     {'n', '\n'},
  43:     {'t', '\t'},
  44:     {'b', '\b'},
  45:     {'r', '\r'},
  46:     {'f', '\f'}} ;
  47: 
  48: static KeyMapElt keymap [256];
  49: 
  50: static int column_map[16] =
  51:     {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
  52: 
  53: /*  the following variables are global to facilitate error-handling */
  54: static int line_no = 0, item_no = 0;
  55: 
  56: /* the following variables are global to simplify initialization */
  57: char string_array [16][BUFSIZ];
  58: char *strings[16];
  59: 
  60: main ()
  61:     {
  62:     char s[BUFSIZ];
  63:     int i, j;
  64:     char magic = X_KEYMAP_MAGIC;
  65:     /* seek past end of keymap (to beginning of extension) */
  66:     if (isatty(fileno(stdout))
  67:       || (fseek (stdout, sizeof (keymap)+1, 0) == -1)) {
  68:     /* "+1" above is because magic number is first byte in file */
  69:     fprintf (stderr, "Couldn't fseek output file\n");
  70:     exit (-1);
  71:     }
  72:     for (i=0;i<256;i++)
  73:         for (j=0;j<16;j++)
  74:         keymap[i][j] = UNBOUND;
  75:     for (i=0;i<16;i++)
  76:         strings[i] = string_array[i];
  77:     while (gets(s)) {
  78:         ProcessLine(s);
  79:     line_no++;
  80:     }
  81:     fseek (stdout, 0, 0);
  82:     if (!fwrite (&magic, 1, 1, stdout)
  83:         || !fwrite (keymap, sizeof(keymap), 1, stdout)) {
  84:     fprintf (stderr, "Error writing beginning of output file\n");
  85:     exit (-1);
  86:     }
  87:     exit(0);
  88:     }
  89: 
  90: ProcessLine (line)
  91:     char *line;
  92:     {
  93:     int lengths [MAXLENGTH];
  94:     int i=0, items, keycode;
  95:     char c;
  96:     if (line[0] == '#' || line[0] == '\0')
  97:         /* ignore comment lines (starting with '#') and blank lines */
  98:         return;
  99:     if (!isnum(line[0]))
 100:         Error(e_NoKeycode);  /* line must start with key code */
 101:     i++;
 102:     while (isnum(line[i]))
 103:         i++;
 104:     c = line[i];
 105:     line[i] = '\0';
 106:     sscanf (line, (line[0] == '0') ? "%o" : "%d", &keycode);
 107:     if (keycode > 255)
 108:         Error(e_KeycodeTooBig);
 109:     line[i] = c;
 110:     items = ScanForItems (&line[i], strings, lengths);
 111:     if (items == 1) {
 112:     unsigned char value;
 113:     int j;
 114:     if (lengths[0] == 0)
 115:         value = UNBOUND;
 116:         else if (lengths[0] > 1 || !SingleCharBound (strings[0][0])) {
 117:         value = EXTENSION_BOUND;
 118:         AddToExtension (keycode, DontCareMetaBits, strings[0], lengths[0]);
 119:         }
 120:     else
 121:         value = strings[0][0];
 122:     for (j=0;j<16;j++)
 123:         keymap[keycode][j] = value;
 124:     }
 125:     else if (items == 16) {
 126:     int j;
 127:     for (j=0;j<16;j++) {
 128:         unsigned char value;
 129:         if (lengths[j] == 0)
 130:             value = UNBOUND;
 131:         else if (lengths[j] > 1 || !SingleCharBound (strings[j][0])) {
 132:         value = EXTENSION_BOUND;
 133:         AddToExtension (keycode, column_map[j], strings[j], lengths[j]);
 134:         }
 135:         else
 136:             value = strings[j][0];
 137:         keymap [keycode] [column_map[j]] = value;
 138:         }
 139:     }
 140:     else Error(e_Not1Or16Items);
 141:     }
 142: 
 143: AddToExtension (keycode, metabits, string, length)
 144:     unsigned int keycode, metabits;
 145:     char *string;
 146:     int length;
 147:     {
 148:     ExtensionHeader header;
 149:     header.keycode = keycode;
 150:     header.metabits = metabits;
 151:     header.length = length;
 152:     if (!fwrite (&header, ExtensionHeaderSize, 1, stdout) ||
 153:         !fwrite (string, length, 1, stdout)) {
 154:         fprintf (stderr, "Error writing extension to output file\n");
 155:         exit (-3);
 156:         }
 157:     }
 158: 
 159: int ScanForItems (line, items, lengths)
 160:     char *line;
 161:     char *items[16];
 162:     int lengths[16];
 163:     {
 164:     int i = 0;
 165:     item_no = 0;
 166:     while (1) {
 167: 
 168:     /* skip over leading white space */
 169:     while (whitespace(line[i])) {
 170:         if (line[i] == '\0')
 171:             return (item_no);
 172:         i++;
 173:         }
 174: 
 175:     if (isnum(line[i])) {
 176:         char *begin_num = &line[i];
 177:         char c;
 178: 
 179:         /* find end of number string */
 180:         while (c = line[++i], isnum (c))
 181:             /* this CANNOT be written isnum(line[++i]) because of side
 182: 	    	 * effect in expression passed to macro */
 183:             ;
 184: 
 185:         /* temporarily put null character at end of number string */
 186:         c = line[i];
 187:         line[i] = '\0';
 188:         lengths [item_no] = TranslateNumber (begin_num, items[item_no]);
 189:         line[i] = c;
 190:         }
 191: 
 192:     else switch (line[i]) {
 193:         case '#':
 194:             return(item_no);  /* rest of line is comment -- ignore it */
 195: 
 196:         case 'U':   /* "U" means "unbound" */
 197:             lengths [item_no] = 0;
 198:         i++;  /* increment past the "U" character */
 199:         break;
 200: 
 201:         case '\'':
 202:         case '"': /* something between quotes */ {
 203:             char c;
 204:         char *begin_quote = &line[i++];
 205:         bool backslash = FALSE;
 206:         while (1)
 207:             switch (c = line[i++]) {
 208:             case '\0':
 209:                 Error ((*begin_quote == '\'')
 210:                     ? e_SingleQuoteNotClosed
 211:                 : e_DoubleQuoteNotClosed);
 212:                 break;
 213:             case '\\':
 214:                 backslash = !backslash;
 215:                 break;
 216:             default:
 217:                 if (c == *begin_quote && !backslash)
 218:                     goto out1;
 219:                 backslash = FALSE;
 220:                 break;
 221:                 }
 222:           out1:
 223:         c = line [i];
 224:         line[i] = '\0';
 225:         lengths[item_no] = TranslateQuote (begin_quote, items[item_no]);
 226:         if ((lengths[item_no] > 1) && (*begin_quote == '\''))
 227:             Error (e_TooManyCharsBetweenQuotes);
 228:         line[i] = c;
 229:         break;
 230:         }
 231: 
 232:         default:
 233:             Error(e_Unrecognized);
 234:         break;
 235: 
 236:         }
 237: 
 238:     if (line[i] == ',')
 239:         i++;  /* ignore terminating comma */
 240:     if (!whitespace (line[i]))
 241:         Error(e_Unrecognized);
 242:     item_no++;
 243:     if (item_no == 16)
 244:         return (item_no);   /* ignore anything on line after 16th char */
 245:     }
 246: 
 247:     }
 248: 
 249: int TranslateNumber (from, to)
 250:     char *from, *to;
 251:     {
 252:     int value;
 253:     sscanf (from, (from[0] == '0') ? "%o" : "%d", &value);
 254:     if (value > 255)
 255:         Error(e_NumberTooBig);
 256:     to[0] = value;
 257:     return (1);  /* length */
 258:     }
 259: 
 260: 
 261: int TranslateQuote (from, to)
 262:     char *from, *to;
 263:     {
 264:     int from_length = strlen (from);
 265:     int i, to_length = 0;
 266:     for (i=1;i<from_length-1;i++) {
 267:     if (to_length >= MAXLENGTH)
 268:         Error(e_StringTooLong);
 269:     if (from[i] == '\\') {
 270:         if (isoctal (from[i+1])) {
 271:         /* backslash followed by octal digits */
 272:         int digits = 1; /* how many successive digits (max 3) */
 273:         int value;
 274:         if (isoctal (from[i+2]))
 275:             digits += (1 + isoctal (from[i+3]));
 276:         sscanf (from+i+1, "%3o", &value);
 277:         if (value > 255)
 278:             Error(e_NumberTooBig);
 279:         to[to_length++] = value;
 280:         i += digits;
 281:         }
 282:         else {
 283:         /* backslash followed by non-number */
 284:         int j;
 285:         for (j=0;j<CT_ESC_ENTRIES;j++)
 286:             if (EscMap[j].from == from[i+1]) {
 287:             to[to_length++] = EscMap[j].to;
 288:             goto out;
 289:             }
 290:         to[to_length++] = from[i+1];
 291:           out:
 292:         i++;
 293:         }
 294:         }
 295:     else
 296:         /* not a backslash, just an ordinary character */
 297:         to[to_length++] = from[i];
 298:     }
 299:     return (to_length);
 300:     }
 301: 
 302: Error (type)
 303:     ParseError type;
 304:     {
 305:     char *s;
 306:     switch (type) {
 307:     case e_NoKeycode:
 308:         s = "Line doesn't begin with keycode"; break;
 309:     case e_KeycodeTooBig:
 310:         s = "Keycode is too big"; break;
 311:     case e_Not1Or16Items:
 312:         s = "Line doesn't have 1 or 16 entries"; break;
 313:     case e_NotNumber:
 314:         s = "Non-number found after backslash in char constant"; break;
 315:     case e_NumberTooBig:
 316:         s = "Number after backslash is too big for a char constant"; break;
 317:     case e_SingleQuoteNotClosed:
 318:         s = "Closing single quote not found"; break;
 319:     case e_StringTooLong:
 320:         s = "String is too long"; break;
 321:     case e_DoubleQuoteNotClosed:
 322:         s = "Closing double quote not found"; break;
 323:     case e_TooManyCharsBetweenQuotes:
 324:         s = "Too many characters for single character constant"; break;
 325:     case e_Unrecognized:
 326:         s = "Not a U, number, single- or double-quoted string"; break;
 327:     default:
 328:         s = "Unknown error";  break;
 329:     }
 330:     fprintf (stderr, "Parse error at item %d on line %d:\n\t %s\n",
 331:         item_no+1, line_no+1, s);
 332:     exit (type);
 333:     }

Defined functions

AddToExtension defined in line 143; used 2 times
Error defined in line 302; used 10 times
ProcessLine defined in line 90; used 1 times
  • in line 78
ScanForItems defined in line 159; used 1 times
TranslateNumber defined in line 249; used 1 times
TranslateQuote defined in line 261; used 1 times
main defined in line 60; never used

Defined variables

EscMap defined in line 41; used 2 times
column_map defined in line 50; used 2 times
keymap defined in line 48; used 6 times
line_no defined in line 54; used 2 times
rcsid_keycomp_c defined in line 6; never used
string_array defined in line 57; used 1 times
  • in line 76
strings defined in line 58; used 8 times

Defined struct's

_EscMapEntry defined in line 23; never used

Defined enum's

_ParseError defined in line 26; never used

Defined typedef's

EscMapEntry defined in line 24; used 1 times
  • in line 41
ParseError defined in line 38; used 1 times

Defined macros

CT_ESC_ENTRIES defined in line 40; used 2 times
FALSE defined in line 19; used 2 times
MAXLENGTH defined in line 21; used 2 times
TRUE defined in line 18; never used
bool defined in line 17; used 1 times
isnum defined in line 13; used 4 times
isoctal defined in line 14; used 3 times
whitespace defined in line 15; used 2 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2009
Valid CSS Valid XHTML 1.0 Strict