2 * Copyright (c) 2007-2008 Jiri Benc <jbenc@upir.cz>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "vkb_compiler.h"
23 static struct compiler_ops *cops;
37 static char keywords[][32] = {
38 "header", "name", "lang", "wc", "size", "width", "height",
39 "textpos", "left", "top", "kbd_normal", "kbd_thumb", "kbd_special",
40 "lowercase", "lowercase_num", "uppercase", "uppercase_num",
41 "special_lowercase", "special_uppercase",
42 "special", "margin", "default_size", "row", "key", "slide",
43 "white", "tab", "alpha", "num", "hexa", "tele", "dead"
46 TOK_HEADER, TOK_NAME, TOK_LANG, TOK_WC, TOK_SIZE, TOK_WIDTH, TOK_HEIGHT,
47 TOK_TEXTPOS, TOK_LEFT, TOK_TOP, TOK_KBD_NORMAL, TOK_KBD_THUMB, TOK_KBD_SPECIAL,
48 TOK_LOWERCASE, TOK_LOWERCASE_NUM, TOK_UPPERCASE, TOK_UPPERCASE_NUM,
49 TOK_SPEC_LOWERCASE, TOK_SPEC_UPPERCASE,
50 TOK_SPECIAL, TOK_MARGIN, TOK_DEFAULT_SIZE, TOK_ROW, TOK_KEY, TOK_SLIDE,
51 TOK_WHITE, TOK_TAB, TOK_ALPHA, TOK_NUM, TOK_HEXA, TOK_TELE, TOK_DEAD
55 TT_KEYWORD, TT_NUM, TT_STRING, TT_BEGIN, TT_END, TT_EOF
58 static void tok_error(struct tokenizer *tokenizer, char *msg)
60 cops->error(cpriv, tokenizer->line, msg);
64 static void tok_warning(struct tokenizer *tokenizer, char *msg)
66 if (cops->warning(cpriv, tokenizer->line, msg))
70 static void *e_malloc(size_t size)
72 void *p = calloc(1, size);
74 cops->error(cpriv, -1, "Out of memory");
80 static void set_str(char **str, char *val)
88 *str = e_malloc(strlen(val) + 1);
92 static char *ltrim(char *buf)
94 while (buf && (*buf == ' ' || *buf == '\t' || *buf == '\n' || *buf == '\r'))
99 static char *find_white(char *buf)
101 while (buf && *buf && *buf != ' ' && *buf != '\t' && *buf != '\n' && *buf != '\r')
106 static int read_raw(struct tokenizer *tokenizer, char *dest, size_t size, int no_ltrim)
113 tokenizer->pos = ltrim(tokenizer->pos);
114 if (!*tokenizer->pos) {
116 tokenizer->pos = tokenizer->buf;
117 if (cops->get_line(cpriv, tokenizer->buf, BUF_SIZE))
122 s = find_white(tokenizer->pos + 1);
126 strncpy(dest, tokenizer->pos, size - 1);
127 dest[size - 1] = '\0';
134 static void finish_read_string(struct tokenizer *tokenizer, char *dest, size_t size)
155 tok_warning(tokenizer, "Ignored extra characters after the string");
160 if (read_raw(tokenizer, s, size - (s - dest), 1) < 0)
161 tok_error(tokenizer, "Unterminated (or too long) string");
165 static void skip_comment(struct tokenizer *tokenizer)
167 while (*tokenizer->pos)
171 static int find_keyword(char *s)
174 int max = (sizeof(keywords) / sizeof(*keywords));
176 for (i = 0; i < max; i++) {
177 if (!strcmp(s, keywords[i]))
183 static void unread_tok(struct tokenizer *tokenizer, char *tok)
185 strncpy(tokenizer->pushed, tok, BUF_SIZE - 1);
186 tokenizer->pushed[BUF_SIZE - 1] = '\0';
189 static enum tok_type read_tok(struct tokenizer *tokenizer, char *dest, size_t size, int *parsed_int)
194 if (*tokenizer->pushed) {
195 strncpy(dest, tokenizer->pushed, size - 1);
196 dest[size - 1] = '\0';
197 *tokenizer->pushed = '\0';
199 res = read_raw(tokenizer, dest, size, 0);
204 skip_comment(tokenizer);
208 if ((dest[0] >= '0' && dest[0] <= '9') || dest[0] == '-') {
209 *parsed_int = atoi(dest);
212 if (dest[0] == '"') {
213 finish_read_string(tokenizer, dest, size);
216 if (dest[0] == '{') {
218 tok_error(tokenizer, "Whitespace required after {");
221 if (dest[0] == '}') {
223 tok_error(tokenizer, "Whitespace required after }");
226 res = find_keyword(dest);
228 tok_error(tokenizer, "Uknown keyword");
233 static void init_tokenizer(struct tokenizer *tokenizer)
235 tokenizer->pos = tokenizer->buf = e_malloc(BUF_SIZE);
236 tokenizer->pushed = e_malloc(BUF_SIZE);
239 static void close_tokenizer(struct tokenizer *tokenizer)
243 free(tokenizer->buf);
244 free(tokenizer->pushed);
247 /*** parser structures ***/
251 struct slide_key *next;
258 struct slide_key *slides;
265 #define KEY_ALPHA 0x01
267 #define KEY_HEXA 0x04
268 #define KEY_TELE 0x08
269 #define KEY_SPECIAL 0x10
270 #define KEY_DEAD 0x20
271 #define KEY_WHITE 0x40
272 #define KEY_EXTEND 0x80
274 #define KEY_TAB (0x0400 | KEY_EXTEND)
289 struct layout *sublayout;
293 #define LAY_LOWERCASE 0
294 #define LAY_UPPERCASE 1
295 #define LAY_LOWERCASE_NUM 2
296 #define LAY_UPPERCASE_NUM 3
297 #define LAY_SPECIAL 4
298 #define LAY_SPECIAL_LOWER 5
299 #define LAY_SPECIAL_UPPER 6
304 struct layout *layouts;
315 #define KBD_SPECIAL 1
327 static struct global *new_global(void)
329 return e_malloc(sizeof(struct global));
332 static void free_sizes(struct size *size)
343 static void free_slides(struct slide_key *sl)
345 struct slide_key *next;
355 static void free_keys(struct key *key)
362 free_slides(key->u.slides);
370 static void free_rows(struct row *row)
376 free_keys(row->keys);
382 static void free_layouts(struct layout *lay)
388 free_rows(lay->rows);
389 free_layouts(lay->sublayout);
396 static void free_kbds(struct kbd *kbd)
402 free_layouts(kbd->layouts);
408 static void free_global(struct global *glob)
412 free_sizes(glob->sizes);
413 free_kbds(glob->kbds);
423 struct tokenizer *tokenizer;
424 struct global *global;
430 static void init_parser(struct parser *parser)
432 parser->tokenizer = e_malloc(sizeof(struct tokenizer));
433 init_tokenizer(parser->tokenizer);
434 parser->tstr = e_malloc(BUF_SIZE);
435 parser->global = new_global();
438 static void close_parser(struct parser *parser)
442 free_global(parser->global);
444 close_tokenizer(parser->tokenizer);
445 free(parser->tokenizer);
448 #define error(parser, msg) tok_error((parser)->tokenizer, msg)
449 #define warning(parser, msg) tok_warning((parser)->tokenizer, msg)
450 #define error_end(parser) error(parser, "} expected")
452 static void get_tok(struct parser *parser)
454 parser->ttype = read_tok(parser->tokenizer, parser->tstr, BUF_SIZE, &parser->tint);
457 static void __get_raw(struct parser *parser)
459 if (read_raw(parser->tokenizer, parser->tstr, BUF_SIZE, 0) < 0)
460 error(parser, "Unexpected end of file");
463 static void push_tok(struct parser *parser)
465 unread_tok(parser->tokenizer, parser->tstr);
468 #define is_type(parser, t) ((parser)->ttype == (t))
469 #define is_keyword(parser, w) ((parser)->ttype == TT_KEYWORD && (parser)->tint == (w))
470 #define is_begin(parser) ((parser)->ttype == TT_BEGIN)
471 #define is_end(parser) ((parser)->ttype == TT_END)
472 #define is_eof(parser) ((parser)->ttype == TT_EOF)
474 static void get_tok_type(struct parser *parser, int tt)
477 if (!is_type(parser, tt)) {
479 case TT_NUM: error(parser, "Number expected");
480 case TT_STRING: error(parser, "String expected");
481 case TT_BEGIN: error(parser, "{ expected");
482 case TT_END: error(parser, "} expected");
483 default: error(parser, "Syntax error");
488 #define get_tok_num(parser) get_tok_type(parser, TT_NUM)
489 #define get_tok_string(parser) get_tok_type(parser, TT_STRING)
490 #define get_tok_begin(parser) get_tok_type(parser, TT_BEGIN)
491 #define get_tok_end(parser) get_tok_type(parser, TT_END)
493 static void parse_sizes(struct parser *parser, struct global *glob)
498 if (parser->tint != glob->sizes_cnt)
499 error(parser, "size number out of order");
500 size = e_malloc(sizeof(struct size));
505 struct size *last = glob->sizes;
510 get_tok_begin(parser);
513 if (is_keyword(parser, TOK_WIDTH)) {
515 size->dim[0] = parser->tint;
516 } else if (is_keyword(parser, TOK_HEIGHT)) {
518 size->dim[1] = parser->tint;
519 } else if (is_keyword(parser, TOK_TEXTPOS)) {
521 size->dim[2] = parser->tint;
522 } else if (is_keyword(parser, TOK_LEFT)) {
524 size->dim[3] = parser->tint;
525 } else if (is_keyword(parser, TOK_TOP)) {
527 size->dim[4] = parser->tint;
528 } else if (is_end(parser)) {
535 static void parse_header(struct parser *parser, struct global *glob)
537 get_tok_begin(parser);
540 if (is_keyword(parser, TOK_NAME)) {
541 get_tok_string(parser);
542 set_str(&glob->name, parser->tstr);
543 } else if (is_keyword(parser, TOK_LANG)) {
544 get_tok_string(parser);
545 set_str(&glob->lang, parser->tstr);
546 } else if (is_keyword(parser, TOK_WC)) {
547 get_tok_string(parser);
548 set_str(&glob->wc, parser->tstr);
549 } else if (is_keyword(parser, TOK_SIZE)) {
550 parse_sizes(parser, glob);
551 } else if (is_end(parser)) {
558 static void parse_slide(struct parser *parser, struct key *key)
562 if (is_keyword(parser, TOK_KEY)) {
563 struct slide_key *skey = e_malloc(sizeof(struct slide_key));
567 key->u.slides = skey;
569 struct slide_key *last = key->u.slides;
575 set_str(&skey->name, parser->tstr);
576 } else if (is_end(parser))
583 static void parse_key(struct parser *parser, struct row *row, int type)
585 struct key *key = e_malloc(sizeof(struct key));
592 struct key *last = row->keys;
597 if (type == TOK_KEY) {
599 set_str(&key->u.name, parser->tstr);
600 } else if (type == TOK_WHITE) {
601 set_str(&key->u.name, "");
602 key->flags |= KEY_WHITE;
603 } else if (type == TOK_TAB) {
604 set_str(&key->u.name, "");
605 key->flags |= KEY_TAB;
609 if (is_keyword(parser, TOK_ALPHA))
610 key->flags |= KEY_ALPHA;
611 else if (is_keyword(parser, TOK_NUM))
612 key->flags |= KEY_NUM;
613 else if (is_keyword(parser, TOK_HEXA))
614 key->flags |= KEY_HEXA;
615 else if (is_keyword(parser, TOK_TELE))
616 key->flags |= KEY_TELE;
617 else if (is_keyword(parser, TOK_SPECIAL))
618 key->flags |= KEY_SPECIAL;
619 else if (is_keyword(parser, TOK_DEAD))
620 key->flags |= KEY_DEAD;
621 else if (is_keyword(parser, TOK_SIZE)) {
623 key->size = parser->tint;
624 } else if (is_begin(parser) && type == TOK_SLIDE)
625 parse_slide(parser, key);
626 else if (is_keyword(parser, TOK_KEY) ||
627 is_keyword(parser, TOK_WHITE) ||
628 is_keyword(parser, TOK_TAB) ||
629 is_keyword(parser, TOK_SLIDE) ||
632 if (type == TOK_SLIDE && !key->slides_cnt)
633 error(parser, "{ expected");
640 static void parse_row(struct parser *parser, struct layout *lay)
642 struct row *row = e_malloc(sizeof(struct row));
648 struct row *last = lay->rows;
653 get_tok_begin(parser);
656 if (is_keyword(parser, TOK_KEY))
657 parse_key(parser, row, TOK_KEY);
658 else if (is_keyword(parser, TOK_WHITE))
659 parse_key(parser, row, TOK_WHITE);
660 else if (is_keyword(parser, TOK_TAB))
661 parse_key(parser, row, TOK_TAB);
662 else if (is_keyword(parser, TOK_SLIDE))
663 parse_key(parser, row, TOK_SLIDE);
664 else if (is_end(parser))
671 static void parse_layout(struct parser *parser, struct kbd *kbd, int type)
673 struct layout *lay = e_malloc(sizeof(struct layout));
675 if (type == LAY_LOWERCASE_NUM || type == LAY_UPPERCASE_NUM) {
676 /* numeric layout is a sublayout of a normal layout */
677 struct layout *find = kbd->layouts;
679 if (find->type == type - 2) {
680 find->sublayout = lay;
687 error(parser, "lowercase_num/uppercase_num has to follow lowercase/uppercase definition");
690 struct layout *last = kbd->layouts;
700 if ((type == LAY_UPPERCASE && (!last || last->type != LAY_LOWERCASE)) ||
701 (type == LAY_SPECIAL_UPPER && (!last || last->type != LAY_SPECIAL_LOWER)))
702 error(parser, "uppercase has to follow lowercase definition");
703 if (type == LAY_SPECIAL_UPPER && last->name)
704 set_str(&lay->name, last->name);
707 get_tok_begin(parser);
710 if (is_keyword(parser, TOK_NAME)) {
711 get_tok_string(parser);
713 error(parser, "name must not be specified for uppercase layout in kbd_special section");
714 set_str(&lay->name, parser->tstr);
715 } else if (is_keyword(parser, TOK_MARGIN)) {
717 for (i = 0; i < 4; i++) {
719 lay->margins[i] = parser->tint;
721 } else if (is_keyword(parser, TOK_DEFAULT_SIZE)) {
723 lay->default_size = parser->tint;
724 } else if (is_keyword(parser, TOK_ROW))
725 parse_row(parser, lay);
726 else if (is_end(parser))
733 static void parse_kbd(struct parser *parser, struct global *glob, int type)
735 struct kbd *kbd = e_malloc(sizeof(struct kbd));
740 struct kbd *last = glob->kbds;
747 get_tok_begin(parser);
750 if (is_keyword(parser, TOK_LOWERCASE))
751 parse_layout(parser, kbd, LAY_LOWERCASE);
752 else if (is_keyword(parser, TOK_UPPERCASE))
753 parse_layout(parser, kbd, LAY_UPPERCASE);
754 else if (is_keyword(parser, TOK_SPEC_LOWERCASE)) {
755 if (type != KBD_SPECIAL)
756 error(parser, "special_lowercase allowed only in kbd_special section");
757 parse_layout(parser, kbd, LAY_SPECIAL_LOWER);
758 } else if (is_keyword(parser, TOK_SPEC_UPPERCASE)) {
759 if (type != KBD_SPECIAL)
760 error(parser, "special_uppercase allowed only in kbd_special section");
761 parse_layout(parser, kbd, LAY_SPECIAL_UPPER);
762 } else if (is_keyword(parser, TOK_LOWERCASE_NUM)) {
763 if (type != KBD_NORMAL)
764 error(parser, "lowercase_num allowed only in kbd_normal section");
765 parse_layout(parser, kbd, LAY_LOWERCASE_NUM);
766 } else if (is_keyword(parser, TOK_UPPERCASE_NUM)) {
767 if (type != KBD_NORMAL)
768 error(parser, "uppercase_num allowed only in kbd_normal section");
769 parse_layout(parser, kbd, LAY_UPPERCASE_NUM);
770 } else if (is_keyword(parser, TOK_SPECIAL)) {
771 if (type != KBD_THUMB && type != KBD_SPECIAL)
772 error(parser, "special allowed only in kbd_thumb and kbd_special sections");
773 parse_layout(parser, kbd, LAY_SPECIAL);
774 } else if (is_end(parser)) {
775 if (!kbd->layouts_cnt)
776 error(parser, "no keyboard layouts defined");
783 static void parse_global(struct parser *parser)
785 struct global *glob = parser->global;
789 if (is_keyword(parser, TOK_HEADER))
790 parse_header(parser, glob);
791 else if (is_keyword(parser, TOK_KBD_NORMAL))
792 parse_kbd(parser, glob, KBD_NORMAL);
793 else if (is_keyword(parser, TOK_KBD_THUMB))
794 parse_kbd(parser, glob, KBD_THUMB);
795 else if (is_keyword(parser, TOK_KBD_SPECIAL))
796 parse_kbd(parser, glob, KBD_SPECIAL);
797 else if (is_eof(parser)) {
799 error(parser, "no keyboards defined");
802 error(parser, "header, kbd_normal, kbd_thumb or kbd_special expected");
809 struct global *global;
814 static void werror(struct writer *writer)
820 static void init_writer(struct writer *writer, struct global *global)
822 writer->global = global;
823 writer->starts = e_malloc(sizeof(int) * global->kbds_cnt);
826 static void close_writer(struct writer *writer)
830 free(writer->starts);
833 static void writer_byte(struct writer *writer, unsigned char b)
835 if (cops->write(cpriv, &b, 1))
839 static void writer_word(struct writer *writer, unsigned int w)
844 a[1] = (w >> 8) & 0xff;
845 if (cops->write(cpriv, a, 2))
849 static void writer_string(struct writer *writer, char *s)
857 writer_byte(writer, len);
859 if (cops->write(cpriv, s, len))
864 static void writer_sizes(struct writer *writer, struct size *sizes)
869 for (i = 0; i < 5; i++)
870 writer_byte(writer, sizes->dim[i]);
875 static void writer_keys(struct writer *writer, struct key *key, int default_size)
877 struct slide_key *skey;
880 writer_byte(writer, key->slides_cnt ? 1 : 0);
881 writer_byte(writer, key->flags & 0xff);
882 if (key->flags & KEY_EXTEND)
883 writer_byte(writer, (key->flags >> 8) & 0xff);
884 if (!key->slides_cnt)
885 writer_string(writer, key->u.name);
887 writer_byte(writer, key->slides_cnt | 0x80);
888 skey = key->u.slides;
890 writer_string(writer, skey->name);
894 writer_byte(writer, key->size >= 0 ? key->size : default_size);
899 static void writer_sublayout(struct writer *writer, struct layout *lay)
905 for (tmp = lay->rows; tmp; tmp = tmp->next)
906 cnt += tmp->keys_cnt;
907 writer_byte(writer, cnt);
908 writer_byte(writer, lay->rows_cnt);
909 writer_byte(writer, lay->margins[3]);
910 writer_byte(writer, lay->margins[0]);
911 writer_byte(writer, lay->margins[2]);
912 writer_byte(writer, lay->margins[1]);
913 for (tmp = lay->rows; tmp; tmp = tmp->next)
914 writer_byte(writer, tmp->keys_cnt);
915 for (tmp = lay->rows; tmp; tmp = tmp->next)
916 writer_keys(writer, tmp->keys, lay->default_size);
919 static void writer_layouts(struct writer *writer, struct layout *lay, int idx)
936 case LAY_SPECIAL_LOWER:
940 case LAY_SPECIAL_UPPER:
947 writer_byte(writer, type);
948 writer_byte(writer, other);
949 writer_string(writer, lay->name);
950 writer_byte(writer, lay->sublayout ? 2 : 1);
951 writer_sublayout(writer, lay);
953 writer_sublayout(writer, lay->sublayout);
956 static void writer_kbd(struct writer *writer, struct kbd *kbd)
961 writer_byte(writer, kbd->type);
962 writer_byte(writer, kbd->layouts_cnt);
963 writer_byte(writer, 0);
964 writer_byte(writer, kbd->layouts->default_size); /* use the default size of the first layout */
965 for (lay = kbd->layouts, i = 0; lay; lay = lay->next, i++)
966 writer_layouts(writer, lay, i);
969 static void writer_global(struct writer *writer)
971 struct global *glob = writer->global;
975 writer_byte(writer, 1); /* version */
976 writer_byte(writer, glob->kbds_cnt);
977 writer_string(writer, glob->name);
978 writer_string(writer, glob->lang);
979 writer_string(writer, glob->wc);
980 writer_byte(writer, 2); /* always use the default screen modes */
981 writer_byte(writer, 0);
982 writer_byte(writer, 1);
983 writer_byte(writer, glob->sizes_cnt);
984 writer_sizes(writer, glob->sizes);
985 writer->start_table = cops->tell(cpriv);
986 for (i = 0; i < glob->kbds_cnt; i++)
987 writer_word(writer, 0);
988 for (i = 0; i < 20; i++)
989 writer_byte(writer, 0);
990 for (kbd = glob->kbds, i = 0; kbd; kbd = kbd->next, i++) {
991 writer->starts[i] = cops->tell(cpriv);
992 writer_kbd(writer, kbd);
994 cops->seek(cpriv, writer->start_table);
995 for (i = 0; i < glob->kbds_cnt; i++)
996 writer_word(writer, writer->starts[i]);
1001 int compile(struct compiler_ops *ops, void *priv)
1003 struct parser *parser = NULL;
1004 struct writer *writer = NULL;
1012 parser = e_malloc(sizeof(struct parser));
1013 writer = e_malloc(sizeof(struct writer));
1014 init_parser(parser);
1015 parse_global(parser);
1016 init_writer(writer, parser->global);
1017 writer_global(writer);
1018 if (cops->return_lang)
1019 cops->return_lang(cpriv, parser->global->lang);
1021 close_writer(writer);
1022 close_parser(parser);
1025 return res ? -1 : 0;