Annotation of 43BSD/contrib/X/keycomp/keycomp.c, revision 1.1.1.1

1.1       root        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:     }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.