~alexandre-hardy/linuxjoymap/linuxjoymap

« back to all changes in this revision

Viewing changes to mapparser.c

  • Committer: Alexandre Hardy
  • Date: 2009-07-17 09:20:57 UTC
  • Revision ID: ah@zenwalk-20090717092057-oxa4o16isawqa7ue
Initial creation of project

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
#include <stdlib.h>
 
3
#include <stdarg.h>
 
4
#include <string.h>
 
5
#include <ctype.h>
 
6
#include "keys.h"
 
7
#include "program.h"
 
8
#include "parser.h"
 
9
#include "dictionary.h"
 
10
#include "validkeys.h"
 
11
 
 
12
static int error=0;
 
13
 
 
14
static struct reserved reserved[]={
 
15
        {"shift", SHIFT},
 
16
        {"button", BUTTON},
 
17
        {"axis", AXIS},
 
18
        {"code", CODE},
 
19
        {"script", SCRIPT},
 
20
        {"include", INCLUDE},
 
21
        {"joysticks", JOYSTICKS},
 
22
        {"joystick", JOYSTICK},
 
23
        {NULL, 0}
 
24
};
 
25
 
 
26
static char *known_keys[]={
 
27
        "id",
 
28
        "vendor",
 
29
        "product",
 
30
        "src", 
 
31
        "target",
 
32
        "axis",
 
33
        "plus",
 
34
        "minus",
 
35
        "device",
 
36
        "flags",
 
37
        "button",
 
38
        "axes",
 
39
        "buttons",
 
40
        NULL
 
41
};
 
42
 
 
43
FILE *pfile=NULL;
 
44
FILE *fmap=NULL;
 
45
int line=1;
 
46
int cpos=1;
 
47
static int nextchar=NONE;
 
48
 
 
49
static dictionary dict=NULL;
 
50
static struct program_button_remap map;
 
51
static struct program_axis_remap amap;
 
52
static struct scriptmap script;
 
53
struct program_code program;
 
54
struct program_button_remap buttons[MAX_ASSIGN];
 
55
struct program_axis_remap axes[MAX_ASSIGN];
 
56
struct scriptmap scriptassign[MAX_ASSIGN];
 
57
static int parse_err=0;
 
58
int nbuttons=0;
 
59
int naxes=0;
 
60
int nscript=0;
 
61
int njoysticks=0;
 
62
struct joystick joysticks[8];
 
63
 
 
64
static int base=0;
 
65
 
 
66
static char *id, *vendor, *product, *src, *target, *button, *device, *flags, *axis, *plus, *minus; 
 
67
static char compile[256]="";
 
68
 
 
69
static int ishex(char *s) {
 
70
        char c;
 
71
        if (*s!='0') return 0;
 
72
        s++;
 
73
        if (*s!='x') return 0;
 
74
        s++;
 
75
        while (*s!='\0') {
 
76
                c=*s;
 
77
                if ((('A'<=c)&&(c<='F'))||
 
78
                    (('a'<=c)&&(c<='f'))||
 
79
                    (('0'<=c)&&(c<='9'))) s++;
 
80
                else return 0;
 
81
        }
 
82
        return 1;
 
83
}
 
84
 
 
85
static int isnum(char *s) {
 
86
        char c;
 
87
        while (*s!='\0') {
 
88
                c=*s;
 
89
                if (('0'<=c)&&(c<='9')) s++;
 
90
                else return 0;
 
91
        }
 
92
        return 1;
 
93
}
 
94
 
 
95
int numeric(char *s) {
 
96
        int r=0;
 
97
        char msg[256];
 
98
        if (s==NULL) return 0;
 
99
        if (ishex(s)) {
 
100
                r=strtol(s, NULL, 16);
 
101
        } else if (isnum(s)) {
 
102
                r=strtol(s, NULL, 10);
 
103
        } else {
 
104
                sprintf(msg, "Expected a number, got %s instead", s);
 
105
                report(msg);
 
106
                return 0;
 
107
        }
 
108
        return r;
 
109
}
 
110
 
 
111
static int get_device(char *s) {
 
112
        char msg[256];
 
113
        if (s==NULL) report("Device expected!");
 
114
        if (strcmp(s, "joyaxis")==0) return DEVICE_JOYSTICK;
 
115
        if (strcmp(s, "joybtn")==0) return DEVICE_JOYSTICK;
 
116
        if (strcmp(s, "joystick")==0) return DEVICE_JOYSTICK;
 
117
        if (strcmp(s, "kbd")==0) return DEVICE_KBD;
 
118
        if (strcmp(s, "mouse")==0) return DEVICE_MOUSE;
 
119
        sprintf(msg, "Expecting a device type:joyaxis,joybtn,joystick,kbd,mouse. Found %s instead", s);
 
120
        report(msg);
 
121
        return 255;
 
122
}
 
123
 
 
124
static int get_type(char *s, dictionary d) {
 
125
        char *button, *axis;
 
126
        if (s==NULL) return 255;
 
127
        if (strcmp(s, "joyaxis")==0) return TYPE_AXIS;
 
128
        if (strcmp(s, "joybtn")==0) return TYPE_BUTTON;
 
129
        button=lookup_dictionary(d, "button");
 
130
        axis=lookup_dictionary(d, "axis");
 
131
        if ((button!=NULL)&&(axis!=NULL)) {
 
132
                report("Only one of the keys 'button' and 'axis' may be specified");
 
133
                return 255;
 
134
        }
 
135
        if (button!=NULL) return TYPE_BUTTON;
 
136
        if (axis!=NULL) return TYPE_AXIS;
 
137
        return 255;
 
138
}
 
139
 
 
140
static int parse_flags(char *s) {
 
141
        int flags=FLAG_NONE;
 
142
        char *p=s;
 
143
        int more=1;
 
144
        char msg[256];
 
145
        if (s==NULL) return flags;
 
146
        while (more) {
 
147
                while ((*p!='\0')&&(*p!=',')&&(*p!=';')) p++;
 
148
                if (*p=='\0') more=0;
 
149
                *p='\0';
 
150
                if (strcmp(s, "autorelease")==0) flags|=FLAG_AUTO_RELEASE;
 
151
                else if (strcmp(s, "release")==0) flags|=FLAG_RELEASE;
 
152
                else if (strcmp(s, "press")==0) flags|=FLAG_PRESS;
 
153
                else if (strcmp(s, "shift")==0) flags|=FLAG_SHIFT;
 
154
                else if (strcmp(s, "invert")==0) flags|=FLAG_INVERT;
 
155
                else {
 
156
                        sprintf(msg, "Unknown flag %s", s);
 
157
                        report(msg);
 
158
                }
 
159
                s=p+1;
 
160
        }
 
161
        return flags;
 
162
}
 
163
 
 
164
static void parse_sequence(__u16 *sequence, char *s, int base, int type) {
 
165
        char *p;
 
166
        int releaseflag=0;
 
167
        int value;
 
168
        int i;
 
169
        int n=0;
 
170
        char msg[256];
 
171
        if (s==NULL) return;
 
172
        if (isnum(s)) {
 
173
                if ((base==DEVICE_JOYSTICK)&&(type==TYPE_BUTTON)) {
 
174
                        base=BTN_JOYSTICK;
 
175
                } else if ((base==DEVICE_MOUSE)&&(type==TYPE_BUTTON)) {
 
176
                        base=BTN_MOUSE;
 
177
                } else base=0;
 
178
                sequence[0]=numeric(s)+base;
 
179
                sequence[1]=SEQUENCE_DONE;
 
180
        } else {
 
181
                p=s;
 
182
                while (*p!='\0') {
 
183
                        //skip whitespace
 
184
                        while ((*p!='\0')&&(isspace(*p))) p++;
 
185
                        s=p;
 
186
                        while ((*p!='\0')&&(!(isspace(*p)))) p++;
 
187
                        if (*p!='\0') {
 
188
                                *p='\0';
 
189
                                p++;
 
190
                        }
 
191
                        value=-1;
 
192
                        if (strcmp(s, "REL")==0) releaseflag=RELEASEMASK;
 
193
                        else {
 
194
                                i=0;
 
195
                                while (keymap[i].value!=-1) {
 
196
                                        if (strcmp(keymap[i].key, s)==0) 
 
197
                                                value=keymap[i].value;
 
198
                                        i++;
 
199
                                }
 
200
                                if (value==-1) {
 
201
                                        parse_err=1;
 
202
                                        sprintf(msg, "Unknown key %s", s);
 
203
                                        report(msg);
 
204
                                } else {
 
205
                                        sequence[n]=value|releaseflag;
 
206
                                        releaseflag=0;
 
207
                                        n++;
 
208
                                }
 
209
                        }
 
210
                        s=p;
 
211
                }
 
212
                sequence[n]=SEQUENCE_DONE;
 
213
        }
 
214
}
 
215
 
 
216
static void show_dictionary(dictionary dict) {
 
217
        dictionary d=dict;
 
218
        char *entry;
 
219
        entry=get_current(d);
 
220
        while (entry!=NULL) {
 
221
                printf("%s ", entry);
 
222
                d=next_entry(d);
 
223
                entry=get_current(d);
 
224
        }
 
225
}
 
226
 
 
227
static int has_required(dictionary dict, ...) {
 
228
        va_list ap;
 
229
        char *s;
 
230
        char *entry;
 
231
        char msg[256];
 
232
 
 
233
        va_start(ap, dict);
 
234
        s=va_arg(ap, char *);
 
235
        while (s!=NULL) {
 
236
                entry=lookup_dictionary(dict, s);
 
237
                if (entry==NULL) {
 
238
                        sprintf(msg, "Missing key:%s", s);
 
239
                        report(msg);
 
240
                        va_end(ap);
 
241
                        return 0;
 
242
                }
 
243
                s=va_arg(ap, char *);
 
244
        }
 
245
        va_end(ap);
 
246
        return 1;
 
247
}
 
248
 
 
249
void report(char *message) {
 
250
        error=1;
 
251
        fprintf(stderr, "%d:%d %s.\n", line, cpos, message);
 
252
}
 
253
 
 
254
void reportline(int line, int cpos, char *message) {
 
255
        error=1;
 
256
        fprintf(stderr, "%d:%d %s.\n", line, cpos, message);
 
257
}
 
258
 
 
259
int peekchar() {
 
260
        if (nextchar!=NONE) return nextchar;
 
261
        nextchar=fgetc(pfile);
 
262
        return nextchar;
 
263
}
 
264
 
 
265
void eatchar() {
 
266
        if (nextchar=='\n') {
 
267
                line++;
 
268
                cpos=1;
 
269
        } else cpos++;
 
270
        if (nextchar!=EOF)
 
271
                nextchar=NONE;
 
272
}
 
273
 
 
274
int readchar() {
 
275
        int c=peekchar();
 
276
        eatchar();
 
277
        return c;
 
278
}
 
279
 
 
280
static struct token newline() {
 
281
        struct token t;
 
282
        t.line=line;
 
283
        t.pos=cpos;
 
284
        t.type=NL;
 
285
        strcpy(t.value, "\n");
 
286
        eatchar();
 
287
        return t;
 
288
}
 
289
 
 
290
static struct token eof() {
 
291
        struct token t;
 
292
        t.line=line;
 
293
        t.pos=cpos;
 
294
        t.type=EOF;
 
295
        strcpy(t.value, "end of file");
 
296
        return t;
 
297
}
 
298
 
 
299
static void parse_comment() {
 
300
        //first character was #
 
301
        //read until newline
 
302
        int nc;
 
303
        nc=peekchar();
 
304
        while ((nc!='\n')&&(nc!=EOF)) {
 
305
                eatchar();
 
306
                nc=peekchar();
 
307
        }
 
308
}
 
309
 
 
310
static void skipwhite() {
 
311
        int nc=peekchar();
 
312
        while (isspace(nc)&&(nc!='\n')) {
 
313
                eatchar();
 
314
                nc=peekchar();
 
315
        }
 
316
}
 
317
 
 
318
static struct token parse_string() {
 
319
        //opening quote has been read
 
320
        //read until closing quote
 
321
        struct token t;
 
322
        int pos=0;
 
323
        int nc;
 
324
        t.line=line;
 
325
        t.pos=cpos;
 
326
        t.type=STRING;
 
327
 
 
328
        nc=readchar();
 
329
        nc=readchar();
 
330
        while (nc!='"') {
 
331
                if (nc==EOF) {
 
332
                        report("Unexpected end of file while parsing a string literal");
 
333
                        break;
 
334
                }
 
335
                t.value[pos++]=nc;
 
336
                nc=readchar();
 
337
        }
 
338
        t.value[pos]='\0';
 
339
        return t;
 
340
}
 
341
 
 
342
static struct token parse_value(struct token t, int pos) {
 
343
        int nc;
 
344
        t.type=VALUE;
 
345
        if (pos>=0) {
 
346
                nc=peekchar();
 
347
                while (isalnum(nc)||(nc==',')||(nc==';')) {
 
348
                        t.value[pos++]=nc;
 
349
                        eatchar();
 
350
                        nc=peekchar();
 
351
                }
 
352
                t.value[pos]='\0';
 
353
        }
 
354
        nc=0;
 
355
        while (reserved[nc].token!=NULL) {
 
356
                if (strcmp(reserved[nc].token, t.value)==0) {
 
357
                        t.type=reserved[nc].value;
 
358
                        break;
 
359
                }
 
360
                nc++;
 
361
        }
 
362
        return t;
 
363
}
 
364
 
 
365
static struct token parse_id(struct token t, int pos) {
 
366
        int nc;
 
367
        t.type=ID;
 
368
        nc=peekchar();
 
369
        while (isalnum(nc)||(nc=='_')) {
 
370
                t.value[pos++]=nc;
 
371
                eatchar();
 
372
                nc=peekchar();
 
373
        }
 
374
        t.value[pos]='\0';
 
375
        nc=peekchar();
 
376
        if (nc!='=') {
 
377
                report("Expected an \"=\"");
 
378
        } else eatchar();
 
379
        
 
380
        return t;
 
381
}
 
382
 
 
383
static struct token parse_id_or_value() {
 
384
        struct token t;
 
385
        int pos=0;
 
386
        int nc;
 
387
        char message[256];
 
388
        t.line=line;
 
389
        t.pos=cpos;
 
390
        nc=peekchar();
 
391
        while (nc!=EOF) {
 
392
                if (nc=='_') return parse_id(t, pos);
 
393
                if (nc=='=') return parse_id(t, pos);
 
394
                if (nc==',') return parse_value(t, pos);
 
395
                if (nc==';') return parse_value(t, pos);
 
396
                if (isspace(nc)) {
 
397
                        skipwhite();
 
398
                        nc=peekchar();
 
399
                        if (nc=='=') return parse_id(t, pos);
 
400
                        t.value[pos]='\0';
 
401
                        pos=-1;
 
402
                        return parse_value(t, pos);
 
403
                }
 
404
                if (isalnum(nc)) {
 
405
                        t.value[pos++]=nc;
 
406
                } else {
 
407
                        sprintf(message, "Unexpected character \"%c\".", nc);
 
408
                        report(message);
 
409
                        eatchar();
 
410
                        break;
 
411
                }
 
412
                t.value[pos]='\0';
 
413
                eatchar();
 
414
                nc=peekchar();
 
415
        }
 
416
        t.type=ID;
 
417
        report("Missing =");
 
418
        return t;
 
419
}
 
420
 
 
421
static struct token maptoken() {
 
422
        int skip=1;
 
423
        int nc;
 
424
        struct token t;
 
425
        char message[256];
 
426
        while (skip) {
 
427
                nc=peekchar();
 
428
                if (nc=='#') 
 
429
                        parse_comment();
 
430
                else if ((nc!='\n')&&isspace(nc)) 
 
431
                        skipwhite();
 
432
                else skip=0;
 
433
        }
 
434
        if (nc=='\n') return newline();
 
435
        if (nc==EOF) return eof();
 
436
        if (nc=='"') return parse_string();
 
437
        if (nc==',') return parse_value(t,0);
 
438
        if (nc==';') return parse_value(t,0);
 
439
        if (nc=='_') return parse_value(t,0);
 
440
        if (isdigit(nc)) return parse_value(t,0);
 
441
        if (isalnum(nc)) return parse_id_or_value();
 
442
        sprintf(message, "Unexpected character \"%c\".", nc);
 
443
        report(message);
 
444
        t.type=ERROR;
 
445
        t.line=line;
 
446
        t.pos=cpos;
 
447
        t.value[0]=nc;
 
448
        t.value[1]='\0';
 
449
        eatchar();
 
450
        return t;
 
451
}
 
452
 
 
453
struct token (*tokenizer)()=NULL;
 
454
static struct token nexttoken;
 
455
struct token peektoken() {
 
456
        if (nexttoken.type!=NONE) return nexttoken;
 
457
        nexttoken=tokenizer();
 
458
        return nexttoken;
 
459
}
 
460
 
 
461
void eattoken() {
 
462
        if (nexttoken.type!=EOF) nexttoken.type=NONE;
 
463
}
 
464
 
 
465
struct token readtoken() {
 
466
        struct token t;
 
467
        t=peektoken();
 
468
        eattoken();
 
469
        return t;
 
470
}
 
471
 
 
472
void init_tokenizer() {
 
473
        nextchar=NONE;
 
474
        nexttoken.type=NONE;
 
475
        line=1;
 
476
        cpos=1;
 
477
}
 
478
 
 
479
static int known_key(char *s) {
 
480
        int i;
 
481
        i=0;
 
482
        while (known_keys[i]!=NULL) {
 
483
                if (strcmp(known_keys[i], s)==0) return 1;
 
484
                i++;
 
485
        }
 
486
        return 0;
 
487
}
 
488
 
 
489
static void parse_valuepairs() {
 
490
        struct token key;
 
491
        struct token value;
 
492
        char message[256];
 
493
        key=readtoken();
 
494
        while ((key.type!=NL)||(key.type!=EOF)) {
 
495
                if (key.type==NL) break;
 
496
                if (key.type==EOF) break;
 
497
                if (key.type==ID) {
 
498
                        if (!known_key(key.value)) {
 
499
                                sprintf(message, "Unknown key \"%s\"", key.value);
 
500
                                reportline(key.line, key.pos, message);
 
501
                        }
 
502
                        value=readtoken();
 
503
                        if ((value.type==STRING)||(value.type==VALUE)) {
 
504
                                dict=add_entry(dict, key.value, value.value);
 
505
                        } else {
 
506
                                sprintf(message, "Unexpected token \"%s\"", value.value);
 
507
                                reportline(value.line, value.pos, message);
 
508
                        }
 
509
                } else {
 
510
                        sprintf(message, "Unexpected token \"%s\"", key.value);
 
511
                        reportline(key.line, key.pos, message);
 
512
                }
 
513
                key=readtoken();
 
514
        }
 
515
}
 
516
 
 
517
static void parse_shift() {
 
518
        struct token t;
 
519
        t=readtoken();
 
520
        parse_valuepairs();
 
521
        printf("shift ");
 
522
        show_dictionary(dict);
 
523
        printf("\n");
 
524
        id=lookup_dictionary(dict, "id");
 
525
        vendor=lookup_dictionary(dict, "vendor");
 
526
        product=lookup_dictionary(dict, "product");
 
527
        src=lookup_dictionary(dict, "src");
 
528
        if ((id==NULL)&&((vendor==NULL)||(product==NULL))) {
 
529
                reportline(t.line, t.pos, "Must have id, or vendor and product");
 
530
        } else {
 
531
                if (has_required(dict, "src", NULL)) {
 
532
                        map.program=PROGRAM_BUTTON_REMAP;
 
533
                        if (id!=NULL)
 
534
                                map.joystick=numeric(id);
 
535
                        else
 
536
                                map.joystick=255;
 
537
                        map.vendor=numeric(vendor);
 
538
                        map.product=numeric(product);
 
539
                        map.srcbutton=numeric(src);
 
540
                        map.type=TYPE_SHIFT;
 
541
                        map.flags=FLAG_NONE;
 
542
                        buttons[nbuttons]=map;
 
543
                        nbuttons++;
 
544
                }       
 
545
        }
 
546
        free_dictionary(dict);
 
547
        dict=NULL;
 
548
}
 
549
 
 
550
static void parse_script() {
 
551
        struct token t;
 
552
        t=readtoken();
 
553
        parse_valuepairs();
 
554
        printf("script ");
 
555
        show_dictionary(dict);
 
556
        printf("\n");
 
557
        id=lookup_dictionary(dict, "id");
 
558
        vendor=lookup_dictionary(dict, "vendor");
 
559
        product=lookup_dictionary(dict, "product");
 
560
        device=lookup_dictionary(dict, "device");
 
561
        if ((id==NULL)&&((vendor==NULL)||(product==NULL))) {
 
562
                reportline(t.line, t.pos, "Must have id, or vendor and product");
 
563
        } else {
 
564
                if (has_required(dict, "device", NULL)) {
 
565
                        if (id!=NULL)
 
566
                                script.id=numeric(id);
 
567
                        else
 
568
                                script.id=-1;   
 
569
                        script.vendor=numeric(vendor);
 
570
                        script.product=numeric(product);
 
571
                        script.device=numeric(device);
 
572
                        scriptassign[nscript]=script;
 
573
                        nscript++;
 
574
                }       
 
575
        }
 
576
        free_dictionary(dict);
 
577
        dict=NULL;
 
578
}
 
579
 
 
580
static void parse_button() {
 
581
        struct token t;
 
582
        int num;
 
583
        t=readtoken();
 
584
        parse_valuepairs();
 
585
        id=lookup_dictionary(dict, "id");
 
586
        vendor=lookup_dictionary(dict, "vendor");
 
587
        product=lookup_dictionary(dict, "product");
 
588
        src=lookup_dictionary(dict, "src");
 
589
        target=lookup_dictionary(dict, "target");
 
590
        button=lookup_dictionary(dict, "button");
 
591
        axis=lookup_dictionary(dict, "axis");
 
592
        device=lookup_dictionary(dict, "device");
 
593
        flags=lookup_dictionary(dict, "flags");
 
594
        if ((id==NULL)&&((vendor==NULL)||(product==NULL))) {
 
595
                reportline(t.line, t.pos, "Must have id, or vendor and product");
 
596
        } else {
 
597
                if (has_required(dict, "src", "target", NULL)) {
 
598
                        printf("button ");
 
599
                        show_dictionary(dict);
 
600
                        printf("\n");
 
601
                        map.program=PROGRAM_BUTTON_REMAP;
 
602
                        if (id!=NULL)
 
603
                                map.joystick=numeric(id);
 
604
                        else
 
605
                                map.joystick=255;
 
606
                        map.vendor=numeric(vendor);
 
607
                        map.product=numeric(product);
 
608
                        base=get_device(target);
 
609
                        map.device=base+(numeric(device)&0xF);
 
610
                        map.type=get_type(target,dict);
 
611
                        if  (base==DEVICE_JOYSTICK) {
 
612
                                num=numeric(device);
 
613
                                if (num>8) {
 
614
                                        report("Maximum of 8 joysticks allowed");
 
615
                                } else {
 
616
                                        if (num>=njoysticks) {
 
617
                                                njoysticks=num+1;
 
618
                                        }
 
619
                                        if (map.type==TYPE_AXIS) {
 
620
                                                if (joysticks[num].axes<=numeric(axis))
 
621
                                                        joysticks[num].axes=numeric(axis)+1;
 
622
                                        }
 
623
                                        if (map.type==TYPE_BUTTON) {
 
624
                                                if (joysticks[num].buttons<=numeric(button))
 
625
                                                        joysticks[num].buttons=numeric(button)+1;
 
626
                                        }
 
627
                                }
 
628
                        }
 
629
                        map.srcbutton=numeric(src)+BTN_JOYSTICK;
 
630
                        map.flags=parse_flags(flags);
 
631
                        if (button!=NULL)
 
632
                                parse_sequence(map.sequence, button, base, map.type);
 
633
                        else if (axis!=NULL)
 
634
                                parse_sequence(map.sequence, axis, base, map.type);
 
635
                        buttons[nbuttons]=map;
 
636
                        nbuttons++;
 
637
                        if (!((map.flags&FLAG_PRESS)||(map.flags&FLAG_RELEASE))&&
 
638
                                (map.sequence[1]==SEQUENCE_DONE)) {
 
639
                                if (map.sequence[0]&RELEASEMASK) {
 
640
                                        map.sequence[0]&=~RELEASEMASK;
 
641
                                } else {
 
642
                                        map.sequence[0]|=RELEASEMASK;
 
643
                                }
 
644
                                map.flags|=FLAG_RELEASE;
 
645
                                buttons[nbuttons]=map;
 
646
                                nbuttons++;
 
647
                        }
 
648
                }
 
649
        }
 
650
        free_dictionary(dict);
 
651
        dict=NULL;
 
652
}
 
653
 
 
654
static void parse_axis() {
 
655
        struct token t;
 
656
        int num;
 
657
        t=readtoken();
 
658
        parse_valuepairs();
 
659
        printf("axis ");
 
660
        show_dictionary(dict);
 
661
        printf("\n");
 
662
        id=lookup_dictionary(dict, "id");
 
663
        vendor=lookup_dictionary(dict, "vendor");
 
664
        product=lookup_dictionary(dict, "product");
 
665
        src=lookup_dictionary(dict, "src");
 
666
        target=lookup_dictionary(dict, "target");
 
667
        axis=lookup_dictionary(dict, "axis");
 
668
        plus=lookup_dictionary(dict, "plus");
 
669
        minus=lookup_dictionary(dict, "minus");
 
670
        device=lookup_dictionary(dict, "device");
 
671
        flags=lookup_dictionary(dict, "flags");
 
672
        if ((id==NULL)&&((vendor==NULL)||(product==NULL))) {
 
673
                reportline(t.line, t.pos, "Must have id, or vendor and product");
 
674
        } else {
 
675
                if (has_required(dict, "src", "target", NULL)) {
 
676
                        amap.program=PROGRAM_AXIS_REMAP;
 
677
                        if (id!=NULL)
 
678
                                amap.joystick=numeric(id);
 
679
                        else
 
680
                                amap.joystick=255;
 
681
                        amap.vendor=numeric(vendor);
 
682
                        amap.product=numeric(product);
 
683
                        amap.srcaxis=numeric(src);
 
684
                        base=get_device(target);
 
685
                        amap.device=base+(numeric(device)&0xF);
 
686
                        amap.type=get_type(target,dict);
 
687
                        if  (base==DEVICE_JOYSTICK) {
 
688
                                num=numeric(device);
 
689
                                if (num>8) {
 
690
                                        report("Maximum of 8 joysticks allowed");
 
691
                                } else {
 
692
                                        if (num>=njoysticks) {
 
693
                                                njoysticks=num+1;
 
694
                                        }
 
695
                                        if (amap.type==TYPE_AXIS) {
 
696
                                                if (joysticks[num].axes<=numeric(axis))
 
697
                                                        joysticks[num].axes=numeric(axis)+1;
 
698
                                        }
 
699
                                        if (amap.type==TYPE_BUTTON) {
 
700
                                                if (joysticks[num].buttons<=numeric(plus))
 
701
                                                        joysticks[num].buttons=numeric(plus)+1;
 
702
                                                if (joysticks[num].buttons<=numeric(minus))
 
703
                                                        joysticks[num].buttons=numeric(minus)+1;
 
704
                                        }
 
705
                                }
 
706
                        }
 
707
                        if ((base==DEVICE_JOYSTICK)&&(amap.type==TYPE_BUTTON)) {
 
708
                                base=BTN_JOYSTICK;
 
709
                        } else if ((base==DEVICE_MOUSE)&&(amap.type==TYPE_BUTTON)) {
 
710
                                base=BTN_MOUSE;
 
711
                        } else base=0;
 
712
                        amap.plus=numeric(plus)+base;
 
713
                        amap.minus=numeric(minus)+base;
 
714
                        amap.axis=numeric(axis);
 
715
                        amap.flags=parse_flags(flags);
 
716
                        axes[naxes]=amap;
 
717
                        naxes++;
 
718
                }
 
719
        }
 
720
        free_dictionary(dict);
 
721
        dict=NULL;
 
722
}
 
723
 
 
724
static void parse_joystick() {
 
725
        struct token t;
 
726
        char *axes; char *buttons;
 
727
        int num;
 
728
        t=readtoken();
 
729
        parse_valuepairs();
 
730
        axes=lookup_dictionary(dict, "axes");
 
731
        buttons=lookup_dictionary(dict, "buttons");
 
732
        device=lookup_dictionary(dict, "device");
 
733
        if (device==NULL) {
 
734
                reportline(t.line, t.pos, "Must have device");
 
735
        } else {
 
736
                num=numeric(device);
 
737
                if ((num<0)||(num>7)) reportline(t.line, t.pos, "Joystick must be 0-7");
 
738
                printf("joystick ");
 
739
                show_dictionary(dict);
 
740
                if (num>=njoysticks) njoysticks=num+1;
 
741
                printf("\n");
 
742
                if (axes!=NULL)
 
743
                        joysticks[num].axes=numeric(axes);
 
744
                else
 
745
                        joysticks[num].axes=0;
 
746
                if (buttons!=NULL)
 
747
                        joysticks[num].buttons=numeric(buttons);
 
748
                else
 
749
                        joysticks[num].buttons=0;
 
750
        }
 
751
        free_dictionary(dict);
 
752
        dict=NULL;
 
753
}
 
754
 
 
755
static void parse_code() {
 
756
        struct token t;
 
757
        t=readtoken();
 
758
        t=readtoken();
 
759
        printf("code ");
 
760
        if (t.type!=STRING) {
 
761
                reportline(t.line, t.pos, "String expected");
 
762
        } else strcpy(compile, t.value);
 
763
        t=readtoken();
 
764
        while ((t.type!=NL)&&(t.type!=EOF)) {
 
765
                reportline(t.line, t.pos, "No further token expected on this line");
 
766
        }
 
767
        printf("\"%s\"\n", compile);
 
768
}
 
769
 
 
770
static void parse_joysticks() {
 
771
        struct token t;
 
772
        int num;
 
773
        t=readtoken();
 
774
        t=readtoken();
 
775
        printf("joysticks ");
 
776
        if (t.type!=VALUE) {
 
777
                reportline(t.line, t.pos, "Value expected");
 
778
        } else num=numeric(t.value);
 
779
        t=readtoken();
 
780
        while ((t.type!=NL)&&(t.type!=EOF)) {
 
781
                reportline(t.line, t.pos, "No further token expected on this line");
 
782
        }
 
783
        if (num<0) reportline(t.line, t.pos, "Only positive numbers allowed");
 
784
        if (num>8) reportline(t.line, t.pos, "Maximum 8 joysticks allowed");
 
785
        njoysticks=num;
 
786
        printf("\"%d\"\n", num);
 
787
}
 
788
 
 
789
static void parse_lines();
 
790
static void parse_include() {
 
791
        struct token t;
 
792
        char include[256]="";
 
793
        FILE *backup;
 
794
        t=readtoken();
 
795
        t=readtoken();
 
796
        printf("include ");
 
797
        if (t.type!=STRING) {
 
798
                reportline(t.line, t.pos, "String expected");
 
799
        } else strcpy(include, t.value);
 
800
        t=readtoken();
 
801
        while ((t.type!=NL)&&(t.type!=EOF)) {
 
802
                reportline(t.line, t.pos, "No further token expected on this line");
 
803
        }
 
804
        printf("\"%s\"\n", include);
 
805
        backup=pfile;
 
806
        pfile=fopen(include, "r");
 
807
        if (pfile==NULL) reportline(t.line, t.pos, "Could not find specified file");
 
808
        else parse_lines();
 
809
        pfile=backup;
 
810
}
 
811
 
 
812
static void parse_lines() {
 
813
        struct token t;
 
814
        char message[256];
 
815
        t=peektoken();
 
816
        while (t.type!=EOF) {
 
817
                if (t.type==NL) {
 
818
                        t=readtoken();
 
819
                        //do nothing
 
820
                } else if (t.type==EOF) {
 
821
                        t=readtoken();
 
822
                        //do nothing
 
823
                } else if (t.type==CODE) {
 
824
                        parse_code();
 
825
                } else if (t.type==BUTTON) {
 
826
                        parse_button();
 
827
                } else if (t.type==AXIS) {
 
828
                        parse_axis();
 
829
                } else if (t.type==SHIFT) {
 
830
                        parse_shift();
 
831
                } else if (t.type==SCRIPT) {
 
832
                        parse_script();
 
833
                } else if (t.type==JOYSTICK) {
 
834
                        parse_joystick();
 
835
                } else if (t.type==JOYSTICKS) {
 
836
                        parse_joysticks();
 
837
                } else if (t.type==INCLUDE) {
 
838
                        parse_include();
 
839
                } else {
 
840
                        t=readtoken();
 
841
                        error=1;
 
842
                        if (t.type!=ERROR) {
 
843
                                sprintf(message, "Unexpected token \"%s\"", t.value);
 
844
                                reportline(t.line, t.pos, message);
 
845
                                while ((t.type!=EOF)&&(t.type!=NL)) {
 
846
                                        t=readtoken();
 
847
                                }
 
848
                        }
 
849
                }
 
850
                t=peektoken();
 
851
        }
 
852
}
 
853
 
 
854
int parse_map(void) {
 
855
        pfile=fmap;
 
856
        tokenizer=maptoken;
 
857
        init_tokenizer();
 
858
        parse_lines();
 
859
        free_dictionary(dict);
 
860
        dict=NULL;
 
861
        if (fmap!=stdin) fclose(fmap);
 
862
        if (strlen(compile)>0) {
 
863
                fprintf(stderr, "parsing program %s\n", compile);
 
864
                if (parse_program(compile, &program)!=0) error=1;
 
865
        }
 
866
        return error;
 
867
}
 
868