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", "backspace", "shift", "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_BACKSPACE
, TOK_SHIFT
, 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)
275 #define KEY_BACKSPACE (0x0800 | KEY_EXTEND)
276 #define KEY_SHIFT (0x1000 | KEY_EXTEND)
291 struct layout
*sublayout
;
295 #define LAY_LOWERCASE 0
296 #define LAY_UPPERCASE 1
297 #define LAY_LOWERCASE_NUM 2
298 #define LAY_UPPERCASE_NUM 3
299 #define LAY_SPECIAL 4
300 #define LAY_SPECIAL_LOWER 5
301 #define LAY_SPECIAL_UPPER 6
306 struct layout
*layouts
;
317 #define KBD_SPECIAL 1
329 static struct global
*new_global(void)
331 return e_malloc(sizeof(struct global
));
334 static void free_sizes(struct size
*size
)
345 static void free_slides(struct slide_key
*sl
)
347 struct slide_key
*next
;
357 static void free_keys(struct key
*key
)
364 free_slides(key
->u
.slides
);
372 static void free_rows(struct row
*row
)
378 free_keys(row
->keys
);
384 static void free_layouts(struct layout
*lay
)
390 free_rows(lay
->rows
);
391 free_layouts(lay
->sublayout
);
398 static void free_kbds(struct kbd
*kbd
)
404 free_layouts(kbd
->layouts
);
410 static void free_global(struct global
*glob
)
414 free_sizes(glob
->sizes
);
415 free_kbds(glob
->kbds
);
425 struct tokenizer
*tokenizer
;
426 struct global
*global
;
432 static void init_parser(struct parser
*parser
)
434 parser
->tokenizer
= e_malloc(sizeof(struct tokenizer
));
435 init_tokenizer(parser
->tokenizer
);
436 parser
->tstr
= e_malloc(BUF_SIZE
);
437 parser
->global
= new_global();
440 static void close_parser(struct parser
*parser
)
444 free_global(parser
->global
);
446 close_tokenizer(parser
->tokenizer
);
447 free(parser
->tokenizer
);
450 #define error(parser, msg) tok_error((parser)->tokenizer, msg)
451 #define warning(parser, msg) tok_warning((parser)->tokenizer, msg)
452 #define error_end(parser) error(parser, "} expected")
454 static void get_tok(struct parser
*parser
)
456 parser
->ttype
= read_tok(parser
->tokenizer
, parser
->tstr
, BUF_SIZE
, &parser
->tint
);
459 static void __get_raw(struct parser
*parser
)
461 if (read_raw(parser
->tokenizer
, parser
->tstr
, BUF_SIZE
, 0) < 0)
462 error(parser
, "Unexpected end of file");
465 static void push_tok(struct parser
*parser
)
467 unread_tok(parser
->tokenizer
, parser
->tstr
);
470 #define is_type(parser, t) ((parser)->ttype == (t))
471 #define is_keyword(parser, w) ((parser)->ttype == TT_KEYWORD && (parser)->tint == (w))
472 #define is_begin(parser) ((parser)->ttype == TT_BEGIN)
473 #define is_end(parser) ((parser)->ttype == TT_END)
474 #define is_eof(parser) ((parser)->ttype == TT_EOF)
476 static void get_tok_type(struct parser
*parser
, int tt
)
479 if (!is_type(parser
, tt
)) {
481 case TT_NUM
: error(parser
, "Number expected");
482 case TT_STRING
: error(parser
, "String expected");
483 case TT_BEGIN
: error(parser
, "{ expected");
484 case TT_END
: error(parser
, "} expected");
485 default: error(parser
, "Syntax error");
490 #define get_tok_num(parser) get_tok_type(parser, TT_NUM)
491 #define get_tok_string(parser) get_tok_type(parser, TT_STRING)
492 #define get_tok_begin(parser) get_tok_type(parser, TT_BEGIN)
493 #define get_tok_end(parser) get_tok_type(parser, TT_END)
495 static void parse_sizes(struct parser
*parser
, struct global
*glob
)
500 if (parser
->tint
!= glob
->sizes_cnt
)
501 error(parser
, "size number out of order");
502 size
= e_malloc(sizeof(struct size
));
507 struct size
*last
= glob
->sizes
;
512 get_tok_begin(parser
);
515 if (is_keyword(parser
, TOK_WIDTH
)) {
517 size
->dim
[0] = parser
->tint
;
518 } else if (is_keyword(parser
, TOK_HEIGHT
)) {
520 size
->dim
[1] = parser
->tint
;
521 } else if (is_keyword(parser
, TOK_TEXTPOS
)) {
523 size
->dim
[2] = parser
->tint
;
524 } else if (is_keyword(parser
, TOK_LEFT
)) {
526 size
->dim
[3] = parser
->tint
;
527 } else if (is_keyword(parser
, TOK_TOP
)) {
529 size
->dim
[4] = parser
->tint
;
530 } else if (is_end(parser
)) {
537 static void parse_header(struct parser
*parser
, struct global
*glob
)
539 get_tok_begin(parser
);
542 if (is_keyword(parser
, TOK_NAME
)) {
543 get_tok_string(parser
);
544 set_str(&glob
->name
, parser
->tstr
);
545 } else if (is_keyword(parser
, TOK_LANG
)) {
546 get_tok_string(parser
);
547 set_str(&glob
->lang
, parser
->tstr
);
548 } else if (is_keyword(parser
, TOK_WC
)) {
549 get_tok_string(parser
);
550 set_str(&glob
->wc
, parser
->tstr
);
551 } else if (is_keyword(parser
, TOK_SIZE
)) {
552 parse_sizes(parser
, glob
);
553 } else if (is_end(parser
)) {
560 static void parse_slide(struct parser
*parser
, struct key
*key
)
564 if (is_keyword(parser
, TOK_KEY
)) {
565 struct slide_key
*skey
= e_malloc(sizeof(struct slide_key
));
569 key
->u
.slides
= skey
;
571 struct slide_key
*last
= key
->u
.slides
;
577 set_str(&skey
->name
, parser
->tstr
);
578 } else if (is_end(parser
))
585 static void parse_key(struct parser
*parser
, struct row
*row
, int type
)
587 struct key
*key
= e_malloc(sizeof(struct key
));
594 struct key
*last
= row
->keys
;
599 if (type
== TOK_KEY
) {
601 set_str(&key
->u
.name
, parser
->tstr
);
602 } else if (type
== TOK_WHITE
) {
603 set_str(&key
->u
.name
, "");
604 key
->flags
|= KEY_WHITE
;
605 } else if (type
== TOK_TAB
) {
606 set_str(&key
->u
.name
, "");
607 key
->flags
|= KEY_TAB
;
608 } else if (type
== TOK_BACKSPACE
) {
609 set_str(&key
->u
.name
, "");
610 key
->flags
|= KEY_BACKSPACE
;
611 } else if (type
== TOK_SHIFT
) {
612 set_str(&key
->u
.name
, "");
613 key
->flags
|= KEY_SHIFT
;
617 if (is_keyword(parser
, TOK_ALPHA
))
618 key
->flags
|= KEY_ALPHA
;
619 else if (is_keyword(parser
, TOK_NUM
))
620 key
->flags
|= KEY_NUM
;
621 else if (is_keyword(parser
, TOK_HEXA
))
622 key
->flags
|= KEY_HEXA
;
623 else if (is_keyword(parser
, TOK_TELE
))
624 key
->flags
|= KEY_TELE
;
625 else if (is_keyword(parser
, TOK_SPECIAL
))
626 key
->flags
|= KEY_SPECIAL
;
627 else if (is_keyword(parser
, TOK_DEAD
))
628 key
->flags
|= KEY_DEAD
;
629 else if (is_keyword(parser
, TOK_SIZE
)) {
631 key
->size
= parser
->tint
;
632 } else if (is_begin(parser
) && type
== TOK_SLIDE
)
633 parse_slide(parser
, key
);
634 else if (is_keyword(parser
, TOK_KEY
) ||
635 is_keyword(parser
, TOK_WHITE
) ||
636 is_keyword(parser
, TOK_TAB
) ||
637 is_keyword(parser
, TOK_BACKSPACE
) ||
638 is_keyword(parser
, TOK_SHIFT
) ||
639 is_keyword(parser
, TOK_SLIDE
) ||
642 if (type
== TOK_SLIDE
&& !key
->slides_cnt
)
643 error(parser
, "{ expected");
650 static void parse_row(struct parser
*parser
, struct layout
*lay
)
652 struct row
*row
= e_malloc(sizeof(struct row
));
658 struct row
*last
= lay
->rows
;
663 get_tok_begin(parser
);
666 if (is_keyword(parser
, TOK_KEY
))
667 parse_key(parser
, row
, TOK_KEY
);
668 else if (is_keyword(parser
, TOK_WHITE
))
669 parse_key(parser
, row
, TOK_WHITE
);
670 else if (is_keyword(parser
, TOK_TAB
))
671 parse_key(parser
, row
, TOK_TAB
);
672 else if (is_keyword(parser
, TOK_BACKSPACE
))
673 parse_key(parser
, row
, TOK_BACKSPACE
);
674 else if (is_keyword(parser
, TOK_SHIFT
))
675 parse_key(parser
, row
, TOK_SHIFT
);
676 else if (is_keyword(parser
, TOK_SLIDE
))
677 parse_key(parser
, row
, TOK_SLIDE
);
678 else if (is_end(parser
))
685 static void parse_layout(struct parser
*parser
, struct kbd
*kbd
, int type
)
687 struct layout
*lay
= e_malloc(sizeof(struct layout
));
689 if (type
== LAY_LOWERCASE_NUM
|| type
== LAY_UPPERCASE_NUM
) {
690 /* numeric layout is a sublayout of a normal layout */
691 struct layout
*find
= kbd
->layouts
;
693 if (find
->type
== type
- 2) {
694 find
->sublayout
= lay
;
701 error(parser
, "lowercase_num/uppercase_num has to follow lowercase/uppercase definition");
704 struct layout
*last
= kbd
->layouts
;
714 if ((type
== LAY_UPPERCASE
&& (!last
|| last
->type
!= LAY_LOWERCASE
)) ||
715 (type
== LAY_SPECIAL_UPPER
&& (!last
|| last
->type
!= LAY_SPECIAL_LOWER
)))
716 error(parser
, "uppercase has to follow lowercase definition");
717 if (type
== LAY_SPECIAL_UPPER
&& last
->name
)
718 set_str(&lay
->name
, last
->name
);
721 get_tok_begin(parser
);
724 if (is_keyword(parser
, TOK_NAME
)) {
725 get_tok_string(parser
);
727 error(parser
, "name must not be specified for uppercase layout in kbd_special section");
728 set_str(&lay
->name
, parser
->tstr
);
729 } else if (is_keyword(parser
, TOK_MARGIN
)) {
731 for (i
= 0; i
< 4; i
++) {
733 lay
->margins
[i
] = parser
->tint
;
735 } else if (is_keyword(parser
, TOK_DEFAULT_SIZE
)) {
737 lay
->default_size
= parser
->tint
;
738 } else if (is_keyword(parser
, TOK_ROW
))
739 parse_row(parser
, lay
);
740 else if (is_end(parser
))
747 static void parse_kbd(struct parser
*parser
, struct global
*glob
, int type
)
749 struct kbd
*kbd
= e_malloc(sizeof(struct kbd
));
754 struct kbd
*last
= glob
->kbds
;
761 get_tok_begin(parser
);
764 if (is_keyword(parser
, TOK_LOWERCASE
))
765 parse_layout(parser
, kbd
, LAY_LOWERCASE
);
766 else if (is_keyword(parser
, TOK_UPPERCASE
))
767 parse_layout(parser
, kbd
, LAY_UPPERCASE
);
768 else if (is_keyword(parser
, TOK_SPEC_LOWERCASE
)) {
769 if (type
!= KBD_SPECIAL
)
770 error(parser
, "special_lowercase allowed only in kbd_special section");
771 parse_layout(parser
, kbd
, LAY_SPECIAL_LOWER
);
772 } else if (is_keyword(parser
, TOK_SPEC_UPPERCASE
)) {
773 if (type
!= KBD_SPECIAL
)
774 error(parser
, "special_uppercase allowed only in kbd_special section");
775 parse_layout(parser
, kbd
, LAY_SPECIAL_UPPER
);
776 } else if (is_keyword(parser
, TOK_LOWERCASE_NUM
)) {
777 if (type
!= KBD_NORMAL
)
778 error(parser
, "lowercase_num allowed only in kbd_normal section");
779 parse_layout(parser
, kbd
, LAY_LOWERCASE_NUM
);
780 } else if (is_keyword(parser
, TOK_UPPERCASE_NUM
)) {
781 if (type
!= KBD_NORMAL
)
782 error(parser
, "uppercase_num allowed only in kbd_normal section");
783 parse_layout(parser
, kbd
, LAY_UPPERCASE_NUM
);
784 } else if (is_keyword(parser
, TOK_SPECIAL
)) {
785 if (type
!= KBD_THUMB
&& type
!= KBD_SPECIAL
)
786 error(parser
, "special allowed only in kbd_thumb and kbd_special sections");
787 parse_layout(parser
, kbd
, LAY_SPECIAL
);
788 } else if (is_end(parser
)) {
789 if (!kbd
->layouts_cnt
)
790 error(parser
, "no keyboard layouts defined");
797 static void parse_global(struct parser
*parser
)
799 struct global
*glob
= parser
->global
;
803 if (is_keyword(parser
, TOK_HEADER
))
804 parse_header(parser
, glob
);
805 else if (is_keyword(parser
, TOK_KBD_NORMAL
))
806 parse_kbd(parser
, glob
, KBD_NORMAL
);
807 else if (is_keyword(parser
, TOK_KBD_THUMB
))
808 parse_kbd(parser
, glob
, KBD_THUMB
);
809 else if (is_keyword(parser
, TOK_KBD_SPECIAL
))
810 parse_kbd(parser
, glob
, KBD_SPECIAL
);
811 else if (is_eof(parser
)) {
813 error(parser
, "no keyboards defined");
816 error(parser
, "header, kbd_normal, kbd_thumb or kbd_special expected");
823 struct global
*global
;
828 static void werror(struct writer
*writer
)
834 static void init_writer(struct writer
*writer
, struct global
*global
)
836 writer
->global
= global
;
837 writer
->starts
= e_malloc(sizeof(int) * global
->kbds_cnt
);
840 static void close_writer(struct writer
*writer
)
844 free(writer
->starts
);
847 static void writer_byte(struct writer
*writer
, unsigned char b
)
849 if (cops
->write(cpriv
, &b
, 1))
853 static void writer_word(struct writer
*writer
, unsigned int w
)
858 a
[1] = (w
>> 8) & 0xff;
859 if (cops
->write(cpriv
, a
, 2))
863 static void writer_string(struct writer
*writer
, char *s
)
871 writer_byte(writer
, len
);
873 if (cops
->write(cpriv
, s
, len
))
878 static void writer_sizes(struct writer
*writer
, struct size
*sizes
)
883 for (i
= 0; i
< 5; i
++)
884 writer_byte(writer
, sizes
->dim
[i
]);
889 static void writer_keys(struct writer
*writer
, struct key
*key
, int default_size
)
891 struct slide_key
*skey
;
894 writer_byte(writer
, key
->slides_cnt
? 1 : 0);
895 writer_byte(writer
, key
->flags
& 0xff);
896 if (key
->flags
& KEY_EXTEND
)
897 writer_byte(writer
, (key
->flags
>> 8) & 0xff);
898 if (!key
->slides_cnt
)
899 writer_string(writer
, key
->u
.name
);
901 writer_byte(writer
, key
->slides_cnt
| 0x80);
902 skey
= key
->u
.slides
;
904 writer_string(writer
, skey
->name
);
908 writer_byte(writer
, key
->size
>= 0 ? key
->size
: default_size
);
913 static void writer_sublayout(struct writer
*writer
, struct layout
*lay
)
919 for (tmp
= lay
->rows
; tmp
; tmp
= tmp
->next
)
920 cnt
+= tmp
->keys_cnt
;
921 writer_byte(writer
, cnt
);
922 writer_byte(writer
, lay
->rows_cnt
);
923 writer_byte(writer
, lay
->margins
[3]);
924 writer_byte(writer
, lay
->margins
[0]);
925 writer_byte(writer
, lay
->margins
[2]);
926 writer_byte(writer
, lay
->margins
[1]);
927 for (tmp
= lay
->rows
; tmp
; tmp
= tmp
->next
)
928 writer_byte(writer
, tmp
->keys_cnt
);
929 for (tmp
= lay
->rows
; tmp
; tmp
= tmp
->next
)
930 writer_keys(writer
, tmp
->keys
, lay
->default_size
);
933 static void writer_layouts(struct writer
*writer
, struct layout
*lay
, int idx
)
950 case LAY_SPECIAL_LOWER
:
954 case LAY_SPECIAL_UPPER
:
961 writer_byte(writer
, type
);
962 writer_byte(writer
, other
);
963 writer_string(writer
, lay
->name
);
964 writer_byte(writer
, lay
->sublayout
? 2 : 1);
965 writer_sublayout(writer
, lay
);
967 writer_sublayout(writer
, lay
->sublayout
);
970 static void writer_kbd(struct writer
*writer
, struct kbd
*kbd
)
975 writer_byte(writer
, kbd
->type
);
976 writer_byte(writer
, kbd
->layouts_cnt
);
977 writer_byte(writer
, 0);
978 writer_byte(writer
, kbd
->layouts
->default_size
); /* use the default size of the first layout */
979 for (lay
= kbd
->layouts
, i
= 0; lay
; lay
= lay
->next
, i
++)
980 writer_layouts(writer
, lay
, i
);
983 static void writer_global(struct writer
*writer
)
985 struct global
*glob
= writer
->global
;
989 writer_byte(writer
, 1); /* version */
990 writer_byte(writer
, glob
->kbds_cnt
);
991 writer_string(writer
, glob
->name
);
992 writer_string(writer
, glob
->lang
);
993 writer_string(writer
, glob
->wc
);
994 writer_byte(writer
, 2); /* always use the default screen modes */
995 writer_byte(writer
, 0);
996 writer_byte(writer
, 1);
997 writer_byte(writer
, glob
->sizes_cnt
);
998 writer_sizes(writer
, glob
->sizes
);
999 writer
->start_table
= cops
->tell(cpriv
);
1000 for (i
= 0; i
< glob
->kbds_cnt
; i
++)
1001 writer_word(writer
, 0);
1002 for (i
= 0; i
< 20; i
++)
1003 writer_byte(writer
, 0);
1004 for (kbd
= glob
->kbds
, i
= 0; kbd
; kbd
= kbd
->next
, i
++) {
1005 writer
->starts
[i
] = cops
->tell(cpriv
);
1006 writer_kbd(writer
, kbd
);
1008 cops
->seek(cpriv
, writer
->start_table
);
1009 for (i
= 0; i
< glob
->kbds_cnt
; i
++)
1010 writer_word(writer
, writer
->starts
[i
]);
1015 int compile(struct compiler_ops
*ops
, void *priv
)
1017 struct parser
*parser
= NULL
;
1018 struct writer
*writer
= NULL
;
1026 parser
= e_malloc(sizeof(struct parser
));
1027 writer
= e_malloc(sizeof(struct writer
));
1028 init_parser(parser
);
1029 parse_global(parser
);
1030 init_writer(writer
, parser
->global
);
1031 writer_global(writer
);
1032 if (cops
->return_lang
)
1033 cops
->return_lang(cpriv
, parser
->global
->lang
);
1035 close_writer(writer
);
1036 close_parser(parser
);
1039 return res
? -1 : 0;