Annotation of 43BSD/contrib/X/keycomp/keycomp.c, revision 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.