[Cgui-develop] cgui/tools dat2c.c, 1.4, 1.4.4.1 memory.c, 1.2, 1.2.4.1 readme.txt, 1.2, 1.2.4.1 t_a
Brought to you by:
chrisan,
rasmusmyklebust
Update of /cvsroot/cgui/cgui/tools In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv1847 Modified Files: Tag: Experimental_2-0-0 dat2c.c memory.c readme.txt t_arr.c t_arr.h t_block.c t_block.h t_header.c t_header.h t_ilang.c t_ilang.h t_imed.c t_imed.h t_isec.c t_isec.h t_istr.c t_istr.h t_itree.c t_itree.h t_label.c t_label.h t_lang.c t_lang.h t_mktext.c t_parser.c t_parser.h t_scan.c t_scan.h t_sec.c t_sec.h t_tree.c t_tree.h t_tree2.h Log Message: fixed files in tools Index: t_parser.c =================================================================== RCS file: /cvsroot/cgui/cgui/tools/t_parser.c,v retrieving revision 1.2 retrieving revision 1.2.4.1 diff -C2 -d -r1.2 -r1.2.4.1 *** t_parser.c 25 Sep 2005 18:02:56 -0000 1.2 --- t_parser.c 21 Apr 2007 21:15:33 -0000 1.2.4.1 *************** *** 1,155 **** ! /* Parsing a list of tokens from a text source-file. Uses k-lookahed, ! because I'm tolazy to make left-factoring. Generates a kind of "tree" ! representing the source-file. */ ! ! #include <stdio.h> ! #include "t_tree.h" ! #include "t_scan.h" ! #include "t_parser.h" ! #include "t_sec.h" ! ! static void get_array_end(struct t_tokenlist *tl, struct t_array *arr) ! { ! struct t_token *t; ! ! match(tl, LT); ! match(tl, END); ! match(tl, EQ); ! t = next_token(tl); ! match(tl, ID); ! match(tl, GT); ! add_array_end(token_name(t), arr, token_row(t)); ! } ! ! static void get_labels(struct t_tokenlist *tl, void *labelkeeper, ! struct t_label* (*insert)(char *m, char *s, void *d, int line, struct t_block *bl), ! struct t_block *bl) ! { ! struct t_token *t, *t1, *t2; ! struct t_label *label; ! ! for (t1 = next_token(tl); token_type(t1) == ID; t1 = next_token(tl)) { ! match(tl, ID); ! t2 = next_token(tl); ! match(tl, STRING); ! label = insert(token_name(t1), token_name(t2), labelkeeper, token_row(t1), bl); ! for (t = next_token(tl); token_type(t) == STRING; t = next_token(tl)) { ! concat_string(token_name(t), label); ! match(tl, STRING); ! } ! } ! } ! ! static struct t_array *get_array_name(struct t_tokenlist *tl, struct t_section *sec) ! { ! struct t_token *t; ! ! match(tl, LT); ! match(tl, START); ! match(tl, EQ); ! t = next_token(tl); ! match(tl, ID); ! match(tl, GT); ! return insert_array(token_name(t), sec, token_row(t)); ! } ! ! static void get_label_array(struct t_tokenlist *tl, struct t_section *sec, struct t_block *bl) ! { ! struct t_array *arr; ! ! arr = get_array_name(tl, sec); ! get_labels(tl, arr, insert_array_label, bl); ! get_array_end(tl, arr); ! } ! ! static void get_block(struct t_tokenlist *tl, struct t_section *sec, struct t_block *root) ! { ! struct t_token *t; ! struct t_block *bl; ! int end; ! ! match(tl, BLOCKSTART); ! bl = create_block(); ! insert_block_node(root, bl); ! for (t = next_token(tl), end = 0; !end; t = next_token(tl)) { ! switch (token_type(t)) { ! case LT: ! get_label_array(tl, sec, bl); ! break; ! case ID: ! get_labels(tl, sec, insert_sec_label, bl); ! break; ! case BLOCKSTART: ! get_block(tl, sec, bl); ! break; ! default: ! end = 1; ! break; ! } ! } ! match(tl, BLOCKEND); ! } ! ! static struct t_language *get_language(struct t_tokenlist *tl, struct t_node *tree) ! { ! struct t_token *t; ! ! match(tl, LT); ! match(tl, LANGUAGE); ! match(tl, EQ); ! t = next_token(tl); ! match(tl, ID); ! match(tl, GT); ! return insert_language(token_name(t), tree); ! } ! ! static struct t_section *get_section(struct t_tokenlist *tl, struct t_language *lang, char *fn) ! { ! struct t_token *t; ! ! match(tl, LB); ! t = next_token(tl); ! match(tl, ID); ! match(tl, RB); ! return insert_section(token_name(t), lang, fn); ! } ! ! extern int parse(struct t_tokenlist *tl, struct t_node *tree, char *fn) ! { ! struct t_language *lang = NULL; ! struct t_section *sec = NULL; ! struct t_token *t; ! int end_seq; ! ! for (t = first_token(tl); token_type(t) != DONE; t = next_token(tl)) { ! if (token_type(t) == LT || lang == NULL) ! lang = get_language(tl, tree); ! if (token_type(next_token(tl)) == LB || sec == NULL) ! sec = get_section(tl, lang, fn); ! for (t = next_token(tl), end_seq = 0; !end_seq; t = next_token(tl)) { ! switch (token_type(t)) { ! case LT: ! if (token_type(token_k(2, tl)) == LANGUAGE) ! end_seq = 1; ! else ! get_label_array(tl, sec, block_root(sec)); ! break; ! case ID: ! get_labels(tl, sec, insert_sec_label, block_root(sec)); ! break; ! case LB: ! case DONE: ! end_seq = 1; ! break; ! case BLOCKSTART: ! get_block(tl, sec, block_root(sec)); ! break; ! default: ! match(tl, ID); ! end_seq = 1; ! break; ! } ! } ! } ! return token_type(t) == DONE; ! } --- 1,155 ---- ! /* Parsing a list of tokens from a text source-file. Uses k-lookahed, ! because I'm tolazy to make left-factoring. Generates a kind of "tree" ! representing the source-file. */ ! ! #include <stdio.h> ! #include "t_tree.h" ! #include "t_scan.h" ! #include "t_parser.h" ! #include "t_sec.h" ! ! static void get_array_end(struct t_tokenlist *tl, struct t_array *arr) ! { ! struct t_token *t; ! ! match(tl, LT); ! match(tl, END); ! match(tl, EQ); ! t = next_token(tl); ! match(tl, ID); ! match(tl, GT); ! add_array_end(token_name(t), arr, token_row(t)); ! } ! ! static void get_labels(struct t_tokenlist *tl, void *labelkeeper, ! struct t_label* (*insert)(char *m, char *s, void *d, int line, struct t_block *bl), ! struct t_block *bl) ! { ! struct t_token *t, *t1, *t2; ! struct t_label *label; ! ! for (t1 = next_token(tl); token_type(t1) == ID; t1 = next_token(tl)) { ! match(tl, ID); ! t2 = next_token(tl); ! match(tl, STRING); ! label = insert(token_name(t1), token_name(t2), labelkeeper, token_row(t1), bl); ! for (t = next_token(tl); token_type(t) == STRING; t = next_token(tl)) { ! concat_string(token_name(t), label); ! match(tl, STRING); ! } ! } ! } ! ! static struct t_array *get_array_name(struct t_tokenlist *tl, struct t_section *sec) ! { ! struct t_token *t; ! ! match(tl, LT); ! match(tl, START); ! match(tl, EQ); ! t = next_token(tl); ! match(tl, ID); ! match(tl, GT); ! return insert_array(token_name(t), sec, token_row(t)); ! } ! ! static void get_label_array(struct t_tokenlist *tl, struct t_section *sec, struct t_block *bl) ! { ! struct t_array *arr; ! ! arr = get_array_name(tl, sec); ! get_labels(tl, arr, insert_array_label, bl); ! get_array_end(tl, arr); ! } ! ! static void get_block(struct t_tokenlist *tl, struct t_section *sec, struct t_block *root) ! { ! struct t_token *t; ! struct t_block *bl; ! int end; ! ! match(tl, BLOCKSTART); ! bl = create_block(); ! insert_block_node(root, bl); ! for (t = next_token(tl), end = 0; !end; t = next_token(tl)) { ! switch (token_type(t)) { ! case LT: ! get_label_array(tl, sec, bl); ! break; ! case ID: ! get_labels(tl, sec, insert_sec_label, bl); ! break; ! case BLOCKSTART: ! get_block(tl, sec, bl); ! break; ! default: ! end = 1; ! break; ! } ! } ! match(tl, BLOCKEND); ! } ! ! static struct t_language *get_language(struct t_tokenlist *tl, struct t_node *tree) ! { ! struct t_token *t; ! ! match(tl, LT); ! match(tl, LANGUAGE); ! match(tl, EQ); ! t = next_token(tl); ! match(tl, ID); ! match(tl, GT); ! return insert_language(token_name(t), tree); ! } ! ! static struct t_section *get_section(struct t_tokenlist *tl, struct t_language *lang, char *fn) ! { ! struct t_token *t; ! ! match(tl, LB); ! t = next_token(tl); ! match(tl, ID); ! match(tl, RB); ! return insert_section(token_name(t), lang, fn); ! } ! ! extern int parse(struct t_tokenlist *tl, struct t_node *tree, char *fn) ! { ! struct t_language *lang = NULL; ! struct t_section *sec = NULL; ! struct t_token *t; ! int end_seq; ! ! for (t = first_token(tl); token_type(t) != DONE; t = next_token(tl)) { ! if (token_type(t) == LT || lang == NULL) ! lang = get_language(tl, tree); ! if (token_type(next_token(tl)) == LB || sec == NULL) ! sec = get_section(tl, lang, fn); ! for (t = next_token(tl), end_seq = 0; !end_seq; t = next_token(tl)) { ! switch (token_type(t)) { ! case LT: ! if (token_type(token_k(2, tl)) == LANGUAGE) ! end_seq = 1; ! else ! get_label_array(tl, sec, block_root(sec)); ! break; ! case ID: ! get_labels(tl, sec, insert_sec_label, block_root(sec)); ! break; ! case LB: ! case DONE: ! end_seq = 1; ! break; ! case BLOCKSTART: ! get_block(tl, sec, block_root(sec)); ! break; ! default: ! match(tl, ID); ! end_seq = 1; ! break; ! } ! } ! } ! return token_type(t) == DONE; ! } Index: t_ilang.h =================================================================== RCS file: /cvsroot/cgui/cgui/tools/t_ilang.h,v retrieving revision 1.2 retrieving revision 1.2.4.1 diff -C2 -d -r1.2 -r1.2.4.1 *** t_ilang.h 26 Mar 2006 10:27:49 -0000 1.2 --- t_ilang.h 21 Apr 2007 21:15:33 -0000 1.2.4.1 *************** *** 1,17 **** ! #ifndef ILANG_H ! #define ILANG_H ! ! #include <stdio.h> ! ! struct t_ilang; ! struct t_inode; ! struct t_isec; ! ! extern void destroy_ilang(struct t_ilang *il); ! extern struct t_ilang *insert_ilang(struct t_inode *it, char *lang); ! extern int equal_ilang_name(struct t_ilang *il, char *lang); ! extern void hook_isec(struct t_ilang *il, struct t_isec *is); ! extern int ilang_eq(struct t_ilang *il, struct t_ilang *ref); ! extern void print_final_text_lang(FILE *f, const struct t_ilang *il); ! ! #endif --- 1,17 ---- ! #ifndef ILANG_H ! #define ILANG_H ! ! #include <stdio.h> ! ! struct t_ilang; ! struct t_inode; ! struct t_isec; ! ! extern void destroy_ilang(struct t_ilang *il); ! extern struct t_ilang *insert_ilang(struct t_inode *it, char *lang); ! extern int equal_ilang_name(struct t_ilang *il, char *lang); ! extern void hook_isec(struct t_ilang *il, struct t_isec *is); ! extern int ilang_eq(struct t_ilang *il, struct t_ilang *ref); ! extern void print_final_text_lang(FILE *f, const struct t_ilang *il); ! ! #endif Index: memory.c =================================================================== RCS file: /cvsroot/cgui/cgui/tools/memory.c,v retrieving revision 1.2 retrieving revision 1.2.4.1 diff -C2 -d -r1.2 -r1.2.4.1 *** memory.c 25 Sep 2005 18:02:56 -0000 1.2 --- memory.c 21 Apr 2007 21:15:33 -0000 1.2.4.1 *************** *** 1,147 **** ! /* Module MEMORY ! Contains interface-functions for memory handling */ ! ! #include <allegro.h> ! #include <string.h> ! ! #include "cgui/mem.h" ! ! #include "../src/memint.h" ! ! #ifdef FORTIFY ! #include "../include/fortify2.h" ! #endif ! ! #if ALLEGRO_SUB_VERSION == 0 ! #define textout_ex(bmp, f, s, x, y, col, bgcol) textout(bmp, f, s, x, y, col) ! #endif ! ! typedef struct t_deinit_chain { ! void (*DeInitFunc)(void*); ! void *data; ! } t_deinit_chain; ! ! static t_deinit_chain *deinit_chain = NULL; ! static int nr_deinits = 0; ! int cgui_started = 0; ! ! #ifndef FORTIFY ! static void MemErr(void) ! { ! clear_to_color(screen, makecol(255,255,255)); ! textout_ex(screen, font, "Fatal error:Out of memory. The program will terminate", SCREEN_W/2, SCREEN_H/2, makecol(0,0,0), -1); ! rest(2000); ! exit(0); ! } ! #endif ! ! extern void DeInitChain(void) ! { ! int i; ! static int ishere = 0; ! ! if (ishere) ! return; ! ishere = 1; ! if (deinit_chain) { ! for (i=nr_deinits-1; i>=0; i--) { ! deinit_chain[i].DeInitFunc(deinit_chain[i].data); ! } ! Release(deinit_chain); ! deinit_chain = NULL; ! nr_deinits = 0; ! } ! #ifdef FORTIFY ! fortify_exit(); ! #endif ! ishere = 0; ! } ! ! extern void HookCguiDeInit(void (*DeInitFunc)(void*), void *data) ! { ! deinit_chain = ResizeMem(t_deinit_chain, deinit_chain, ++nr_deinits); ! deinit_chain[nr_deinits-1].DeInitFunc = DeInitFunc; ! deinit_chain[nr_deinits-1].data = data; ! } ! ! extern void UnHookCguiDeInit(void (*DeInitFunc)(void*), void *data) ! { ! int i; ! static int deinit_in_progress = 0; ! if (!deinit_in_progress) { ! deinit_in_progress = 1; ! for (i=0; i<nr_deinits; i++) { ! if (deinit_chain[i].DeInitFunc==DeInitFunc && deinit_chain[i].data==data) { ! for (i++; i<nr_deinits; i++) ! deinit_chain[i-1] = deinit_chain[i]; ! nr_deinits--; ! } ! } ! deinit_in_progress = 0; ! } ! } ! ! extern void RegisterCleanupFunc(int (*atexit_ptr)(void (*func)(void))) ! { ! static int done = 0; ! ! #ifdef FORTIFY ! if (!cgui_started) ! fortify_init(); ! #endif ! if (!done) { ! atexit_ptr(DeInitChain); ! done = 1; ! } ! } ! ! #ifndef FORTIFY ! #include <malloc.h> ! ! extern char *MkString(const char *string) ! { ! char *ns = strdup(string); ! ! if (ns == NULL && string != NULL) ! MemErr(); ! return ns; ! } ! ! extern void *cgui_malloc(size_t size) ! { ! void *mem; ! ! mem = malloc(size); ! if (mem == NULL && size) ! MemErr(); ! return mem; ! } ! ! extern void *cgui_realloc(void *oldmem, size_t newsize) ! { ! oldmem = realloc(oldmem, newsize); ! if (oldmem == NULL && newsize != 0) ! MemErr(); ! return oldmem; ! } ! ! extern void *cgui_calloc(size_t size) ! { ! void *mem; ! ! mem = calloc(1, size); ! if (mem == NULL && size) ! MemErr(); ! return mem; ! } ! #endif ! ! extern void Release(void *data) ! { ! free(data); ! } ! ! extern void InitMemory(int (*atexit_ptr)(void (*func)(void))) ! { ! RegisterCleanupFunc(atexit_ptr); ! } --- 1,147 ---- ! /* Module MEMORY ! Contains interface-functions for memory handling */ ! ! #include <allegro.h> ! #include <string.h> ! ! #include "cgui/mem.h" ! ! #include "../src/memint.h" ! ! #ifdef FORTIFY ! #include "../include/fortify2.h" ! #endif ! ! #if ALLEGRO_SUB_VERSION == 0 ! #define textout_ex(bmp, f, s, x, y, col, bgcol) textout(bmp, f, s, x, y, col) ! #endif ! ! typedef struct t_deinit_chain { ! void (*DeInitFunc)(void*); ! void *data; ! } t_deinit_chain; ! ! static t_deinit_chain *deinit_chain = NULL; ! static int nr_deinits = 0; ! int cgui_started = 0; ! ! #ifndef FORTIFY ! static void MemErr(void) ! { ! clear_to_color(screen, makecol(255,255,255)); ! textout_ex(screen, font, "Fatal error:Out of memory. The program will terminate", SCREEN_W/2, SCREEN_H/2, makecol(0,0,0), -1); ! rest(2000); ! exit(0); ! } ! #endif ! ! extern void DeInitChain(void) ! { ! int i; ! static int ishere = 0; ! ! if (ishere) ! return; ! ishere = 1; ! if (deinit_chain) { ! for (i=nr_deinits-1; i>=0; i--) { ! deinit_chain[i].DeInitFunc(deinit_chain[i].data); ! } ! Release(deinit_chain); ! deinit_chain = NULL; ! nr_deinits = 0; ! } ! #ifdef FORTIFY ! fortify_exit(); ! #endif ! ishere = 0; ! } ! ! extern void HookCguiDeInit(void (*DeInitFunc)(void*), void *data) ! { ! deinit_chain = ResizeMem(t_deinit_chain, deinit_chain, ++nr_deinits); ! deinit_chain[nr_deinits-1].DeInitFunc = DeInitFunc; ! deinit_chain[nr_deinits-1].data = data; ! } ! ! extern void UnHookCguiDeInit(void (*DeInitFunc)(void*), void *data) ! { ! int i; ! static int deinit_in_progress = 0; ! if (!deinit_in_progress) { ! deinit_in_progress = 1; ! for (i=0; i<nr_deinits; i++) { ! if (deinit_chain[i].DeInitFunc==DeInitFunc && deinit_chain[i].data==data) { ! for (i++; i<nr_deinits; i++) ! deinit_chain[i-1] = deinit_chain[i]; ! nr_deinits--; ! } ! } ! deinit_in_progress = 0; ! } ! } ! ! extern void RegisterCleanupFunc(int (*atexit_ptr)(void (*func)(void))) ! { ! static int done = 0; ! ! #ifdef FORTIFY ! if (!cgui_started) ! fortify_init(); ! #endif ! if (!done) { ! atexit_ptr(DeInitChain); ! done = 1; ! } ! } ! ! #ifndef FORTIFY ! #include <malloc.h> ! ! extern char *MkString(const char *string) ! { ! char *ns = strdup(string); ! ! if (ns == NULL && string != NULL) ! MemErr(); ! return ns; ! } ! ! extern void *cgui_malloc(size_t size) ! { ! void *mem; ! ! mem = malloc(size); ! if (mem == NULL && size) ! MemErr(); ! return mem; ! } ! ! extern void *cgui_realloc(void *oldmem, size_t newsize) ! { ! oldmem = realloc(oldmem, newsize); ! if (oldmem == NULL && newsize != 0) ! MemErr(); ! return oldmem; ! } ! ! extern void *cgui_calloc(size_t size) ! { ! void *mem; ! ! mem = calloc(1, size); ! if (mem == NULL && size) ! MemErr(); ! return mem; ! } ! #endif ! ! extern void Release(void *data) ! { ! free(data); ! } ! ! extern void InitMemory(int (*atexit_ptr)(void (*func)(void))) ! { ! RegisterCleanupFunc(atexit_ptr); ! } Index: t_parser.h =================================================================== RCS file: /cvsroot/cgui/cgui/tools/t_parser.h,v retrieving revision 1.2 retrieving revision 1.2.4.1 diff -C2 -d -r1.2 -r1.2.4.1 *** t_parser.h 26 Mar 2006 10:27:49 -0000 1.2 --- t_parser.h 21 Apr 2007 21:15:33 -0000 1.2.4.1 *************** *** 1,9 **** ! #ifndef PARSER_H ! #define PARSER_H ! ! struct t_node; ! struct t_tokenlist; ! ! extern int parse(struct t_tokenlist *tl, struct t_node *tree, char *fn); ! ! #endif --- 1,9 ---- ! #ifndef PARSER_H ! #define PARSER_H ! ! struct t_node; ! struct t_tokenlist; ! ! extern int parse(struct t_tokenlist *tl, struct t_node *tree, char *fn); ! ! #endif Index: t_sec.h =================================================================== RCS file: /cvsroot/cgui/cgui/tools/t_sec.h,v retrieving revision 1.2 retrieving revision 1.2.4.1 diff -C2 -d -r1.2 -r1.2.4.1 *** t_sec.h 26 Mar 2006 10:27:49 -0000 1.2 --- t_sec.h 21 Apr 2007 21:15:33 -0000 1.2.4.1 *************** *** 1,17 **** ! #ifndef SEC_H ! #define SEC_H ! ! struct t_section; ! struct t_array; ! struct t_header; ! struct t_ifile; ! ! extern struct t_section *insert_section(char *name, struct t_language *lang, char *fn); ! extern void destroy_section(struct t_section *sec); ! extern void hook_array(struct t_array *a, struct t_section *sec); ! extern void build_section_header(struct t_header *hdr, struct t_section *sec); ! extern void build_section_intermediate(struct t_section *sec, struct t_ifile *imed); ! extern struct t_block *block_root(struct t_section *sec); ! extern int check_hot_keys_sec(struct t_section *sec); ! ! #endif --- 1,17 ---- ! #ifndef SEC_H ! #define SEC_H ! ! struct t_section; ! struct t_array; ! struct t_header; ! struct t_ifile; ! ! extern struct t_section *insert_section(char *name, struct t_language *lang, char *fn); ! extern void destroy_section(struct t_section *sec); ! extern void hook_array(struct t_array *a, struct t_section *sec); ! extern void build_section_header(struct t_header *hdr, struct t_section *sec); ! extern void build_section_intermediate(struct t_section *sec, struct t_ifile *imed); ! extern struct t_block *block_root(struct t_section *sec); ! extern int check_hot_keys_sec(struct t_section *sec); ! ! #endif Index: t_ilang.c =================================================================== RCS file: /cvsroot/cgui/cgui/tools/t_ilang.c,v retrieving revision 1.2 retrieving revision 1.2.4.1 diff -C2 -d -r1.2 -r1.2.4.1 *** t_ilang.c 25 Sep 2005 18:02:56 -0000 1.2 --- t_ilang.c 21 Apr 2007 21:15:33 -0000 1.2.4.1 *************** *** 1,98 **** ! /* Contains the operations needed for the language node in an ! intermediate file structure */ ! ! #include <string.h> ! #include <stdio.h> ! #include <allegro.h> ! #include "cgui/mem.h" ! ! #include "t_itree.h" ! #include "t_isec.h" ! #include "t_ilang.h" ! ! typedef struct t_ilang { ! char *id; ! int n; ! struct t_isec **is; ! } t_ilang; ! ! extern int equal_ilang_name(struct t_ilang *il, char *lang) ! { ! return strcmp(il->id, lang) == 0; ! } ! ! extern void destroy_ilang(struct t_ilang *il) ! { ! int i; ! ! for (i = 0; i < il->n; i++) ! destroy_isection(il->is[i]); ! free(il->is); ! free(il->id); ! free(il); ! } ! ! extern void hook_isec(t_ilang *il, struct t_isec *is) ! { ! il->n++; ! il->is = ResizeMem(struct t_isec*, il->is, il->n); ! il->is[il->n - 1] = is; ! } ! ! extern t_ilang *insert_ilang(struct t_inode *it, char *lang) ! { ! t_ilang *il; ! ! il = get_ilang_ref(it, lang); ! if (il == NULL) { ! il = GetMem0(t_ilang, 1); ! il->id = MkString(lang); ! hook_ilang(it, il); ! } ! return il; ! } ! ! extern int ilang_eq(struct t_ilang *il, struct t_ilang *ref) ! { ! int i, j, x, eq = 1; ! const char *name = ""; ! ! if (il == ref) ! return eq; ! for (i = 0; i < ref->n; i++) { ! name = isection_name(ref->is[i]); ! for (j = 0; j < il->n; j++) { ! if (equal_isection_name(il->is[j], name)) { ! x = isec_eq(il->is[j], ref->is[i]); ! if (!x) { ! allegro_message("... language %s compared to %s\n", ! il->id, ref->id); ! } ! eq &= x; ! break; ! } ! } ! if (j >= il->n) { ! allegro_message("Section %s in file %s in language %s\n" ! "does not exist in language %s\n", ! name, isec_file(ref->is[i]), ref->id, il->id); ! eq = 0; ! break; ! } ! } ! if (eq && il->n > ref->n) { ! eq = 0; ! ilang_eq(ref, il); ! } ! return eq; ! } ! ! extern void print_final_text_lang(FILE *f, const t_ilang *il) ! { ! int i; ! ! qsort(il->is, il->n, sizeof(struct t_isec *), sort_isec); ! fprintf(f, "%s\n", il->id); ! for (i = 0; i < il->n; i++) ! print_final_text_section(f, il->is[i]); ! } --- 1,98 ---- ! /* Contains the operations needed for the language node in an ! intermediate file structure */ ! ! #include <string.h> ! #include <stdio.h> ! #include <allegro.h> ! #include "cgui/mem.h" ! ! #include "t_itree.h" ! #include "t_isec.h" ! #include "t_ilang.h" ! ! typedef struct t_ilang { ! char *id; ! int n; ! struct t_isec **is; ! } t_ilang; ! ! extern int equal_ilang_name(struct t_ilang *il, char *lang) ! { ! return strcmp(il->id, lang) == 0; ! } ! ! extern void destroy_ilang(struct t_ilang *il) ! { ! int i; ! ! for (i = 0; i < il->n; i++) ! destroy_isection(il->is[i]); ! free(il->is); ! free(il->id); ! free(il); ! } ! ! extern void hook_isec(t_ilang *il, struct t_isec *is) ! { ! il->n++; ! il->is = ResizeMem(struct t_isec*, il->is, il->n); ! il->is[il->n - 1] = is; ! } ! ! extern t_ilang *insert_ilang(struct t_inode *it, char *lang) ! { ! t_ilang *il; ! ! il = get_ilang_ref(it, lang); ! if (il == NULL) { ! il = GetMem0(t_ilang, 1); ! il->id = MkString(lang); ! hook_ilang(it, il); ! } ! return il; ! } ! ! extern int ilang_eq(struct t_ilang *il, struct t_ilang *ref) ! { ! int i, j, x, eq = 1; ! const char *name = ""; ! ! if (il == ref) ! return eq; ! for (i = 0; i < ref->n; i++) { ! name = isection_name(ref->is[i]); ! for (j = 0; j < il->n; j++) { ! if (equal_isection_name(il->is[j], name)) { ! x = isec_eq(il->is[j], ref->is[i]); ! if (!x) { ! allegro_message("... language %s compared to %s\n", ! il->id, ref->id); ! } ! eq &= x; ! break; ! } ! } ! if (j >= il->n) { ! allegro_message("Section %s in file %s in language %s\n" ! "does not exist in language %s\n", ! name, isec_file(ref->is[i]), ref->id, il->id); ! eq = 0; ! break; ! } ! } ! if (eq && il->n > ref->n) { ! eq = 0; ! ilang_eq(ref, il); ! } ! return eq; ! } ! ! extern void print_final_text_lang(FILE *f, const t_ilang *il) ! { ! int i; ! ! qsort(il->is, il->n, sizeof(struct t_isec *), sort_isec); ! fprintf(f, "%s\n", il->id); ! for (i = 0; i < il->n; i++) ! print_final_text_section(f, il->is[i]); ! } Index: t_tree.c =================================================================== RCS file: /cvsroot/cgui/cgui/tools/t_tree.c,v retrieving revision 1.2 retrieving revision 1.2.4.1 diff -C2 -d -r1.2 -r1.2.4.1 *** t_tree.c 25 Sep 2005 18:02:56 -0000 1.2 --- t_tree.c 21 Apr 2007 21:15:33 -0000 1.2.4.1 *************** *** 1,75 **** ! /* Contains the operations needed for a source tree */ ! ! #include "cgui/mem.h" ! #include "t_tree.h" ! #include "t_tree2.h" ! #include "t_lang.h" ! ! typedef struct t_node { ! int n; ! struct t_language **lang; ! } t_node; ! ! extern void destroy_tree(t_node *t) ! { ! int i; ! ! for (i=0; i < t->n; i++) ! destroy_language(t->lang[i]); ! free(t->lang); ! free(t); ! } ! ! extern t_node *create_tree() ! { ! t_node *t; ! ! t = GetMem0(t_node, 1); ! return t; ! } ! ! extern void build_header(t_node *t, const char *fn) ! { ! int i; ! ! for (i = 0; i < t->n; i++) ! build_lang_header(t->lang[i], fn); ! } ! ! extern void build_intermediate(t_node *t, struct t_ifile *ifil) ! { ! int i; ! ! for (i=0; i < t->n; i++) ! build_lang_intermediate(t->lang[i], ifil); ! } ! ! extern int print_header_file(const char *fn, const struct t_node *t) ! { ! FILE *f; ! ! f = fopen(fn, "wt"); ! if (f) { ! if (t->n) ! output_lang_header(f, t->lang[0]); ! fclose(f); ! return 1; ! } ! return 0; ! } ! ! extern void hook_language(struct t_language *lang, struct t_node *t) ! { ! t->n++; ! t->lang = ResizeMem(struct t_language*, t->lang, t->n); ! t->lang[t->n - 1] = lang; ! } ! ! extern int check_hot_keys_in_file(t_node *t) ! { ! int i, ok = 1; ! ! for (i=0; i < t->n; i++) ! ok &= check_hot_keys_lang(t->lang[i]); ! return ok; ! } --- 1,75 ---- ! /* Contains the operations needed for a source tree */ ! ! #include "cgui/mem.h" ! #include "t_tree.h" ! #include "t_tree2.h" ! #include "t_lang.h" ! ! typedef struct t_node { ! int n; ! struct t_language **lang; ! } t_node; ! ! extern void destroy_tree(t_node *t) ! { ! int i; ! ! for (i=0; i < t->n; i++) ! destroy_language(t->lang[i]); ! free(t->lang); ! free(t); ! } ! ! extern t_node *create_tree() ! { ! t_node *t; ! ! t = GetMem0(t_node, 1); ! return t; ! } ! ! extern void build_header(t_node *t, const char *fn) ! { ! int i; ! ! for (i = 0; i < t->n; i++) ! build_lang_header(t->lang[i], fn); ! } ! ! extern void build_intermediate(t_node *t, struct t_ifile *ifil) ! { ! int i; ! ! for (i=0; i < t->n; i++) ! build_lang_intermediate(t->lang[i], ifil); ! } ! ! extern int print_header_file(const char *fn, const struct t_node *t) ! { ! FILE *f; ! ! f = fopen(fn, "wt"); ! if (f) { ! if (t->n) ! output_lang_header(f, t->lang[0]); ! fclose(f); ! return 1; ! } ! return 0; ! } ! ! extern void hook_language(struct t_language *lang, struct t_node *t) ! { ! t->n++; ! t->lang = ResizeMem(struct t_language*, t->lang, t->n); ! t->lang[t->n - 1] = lang; ! } ! ! extern int check_hot_keys_in_file(t_node *t) ! { ! int i, ok = 1; ! ! for (i=0; i < t->n; i++) ! ok &= check_hot_keys_lang(t->lang[i]); ! return ok; ! } Index: dat2c.c =================================================================== RCS file: /cvsroot/cgui/cgui/tools/dat2c.c,v retrieving revision 1.4 retrieving revision 1.4.4.1 diff -C2 -d -r1.4 -r1.4.4.1 *** dat2c.c 25 Sep 2005 18:02:56 -0000 1.4 --- dat2c.c 21 Apr 2007 21:15:33 -0000 1.4.4.1 *************** *** 1,1669 **** ! /* ______ ___ ___ ! * /\ _ \ /\_ \ /\_ \ ! * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ ! * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ ! * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ ! * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ ! * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ ! * /\____/ ! * \_/__/ ! * [...3309 lines suppressed...] ! dat2c->prefix ? dat2c->prefix : "", ! dat2c->prefix ? "_" : "", ! dat2c->datafile_name ? dat2c->datafile_name : "data"); ! ! if (dat2c->fname_h) ! write_header_start(dat2c); ! write_source_start(dat2c); ! ! result = write_datafile(dat2c, dat2c->dat, ! dat2c->prefix ? dat2c->prefix : "", ! prefixed_name); ! ! write_header_end(dat2c); ! write_source_end(dat2c, prefixed_name); ! ! free(prefixed_name); ! clear_c_identifiers(); ! ! return result; ! } Index: t_tree.h =================================================================== RCS file: /cvsroot/cgui/cgui/tools/t_tree.h,v retrieving revision 1.2 retrieving revision 1.2.4.1 diff -C2 -d -r1.2 -r1.2.4.1 *** t_tree.h 26 Mar 2006 10:27:49 -0000 1.2 --- t_tree.h 21 Apr 2007 21:15:33 -0000 1.2.4.1 *************** *** 1,30 **** ! #ifndef TREE_H ! #define TREE_H ! ! struct t_node; ! struct t_label; ! struct t_language; ! struct t_section; ! struct t_array; ! struct t_ifile; ! struct t_block; ! ! extern struct t_node *create_tree(void); ! extern void destroy_tree(struct t_node *t); ! extern struct t_language *insert_language(char *name, struct t_node *tree); ! extern struct t_label *insert_array_label(char *macro, char *string, void *data, int line, struct t_block *bl); ! extern struct t_array *insert_array(char *name, struct t_section *sec, int line); ! extern struct t_label *insert_sec_label(char *macro, char *string, void *data, int line, struct t_block *bl); ! extern void add_array_end(char *name, struct t_array *arr, int line); ! extern void concat_string(char *name, struct t_label *label); ! extern struct t_block *create_block(void); ! extern void insert_block_node(struct t_block *root, struct t_block *newnode); ! ! extern int print_header_file(const char *fn, const struct t_node *t); ! ! extern void build_header(struct t_node *tree, const char *fn); ! extern void build_intermediate(struct t_node *t, struct t_ifile *ifil); ! ! extern int check_hot_keys_in_file(struct t_node *t); ! ! #endif --- 1,30 ---- ! #ifndef TREE_H ! #define TREE_H ! ! struct t_node; ! struct t_label; ! struct t_language; ! struct t_section; ! struct t_array; ! struct t_ifile; ! struct t_block; ! ! extern struct t_node *create_tree(void); ! extern void destroy_tree(struct t_node *t); ! extern struct t_language *insert_language(char *name, struct t_node *tree); ! extern struct t_label *insert_array_label(char *macro, char *string, void *data, int line, struct t_block *bl); ! extern struct t_array *insert_array(char *name, struct t_section *sec, int line); ! extern struct t_label *insert_sec_label(char *macro, char *string, void *data, int line, struct t_block *bl); ! extern void add_array_end(char *name, struct t_array *arr, int line); ! extern void concat_string(char *name, struct t_label *label); ! extern struct t_block *create_block(void); ! extern void insert_block_node(struct t_block *root, struct t_block *newnode); ! ! extern int print_header_file(const char *fn, const struct t_node *t); ! ! extern void build_header(struct t_node *tree, const char *fn); ! extern void build_intermediate(struct t_node *t, struct t_ifile *ifil); ! ! extern int check_hot_keys_in_file(struct t_node *t); ! ! #endif Index: readme.txt =================================================================== RCS file: /cvsroot/cgui/cgui/tools/readme.txt,v retrieving revision 1.2 retrieving revision 1.2.4.1 diff -C2 -d -r1.2 -r1.2.4.1 *** readme.txt 26 Mar 2006 10:27:49 -0000 1.2 --- readme.txt 21 Apr 2007 21:15:33 -0000 1.2.4.1 *************** *** 1,288 **** ! `mktext' is a program with the purpose to give a tool so that you can ! keep a program free from language dependent textstrings. ! ! Very brief about simple usage: A source-file (`.t') containing rows, each ! of which consist of pairs which defines the text. Each pair consist of: ! - a C-identifier ! - a quoted string ! Each source file must first of all start with a language definition, ! followed by a section definition. Then the actual text specifications ! follows. ! Example (suppose the below is contained in a file `foo.t'): ! <language=en> /* specifies the name of the language to `en' */ ! [foo] /* specifies the name of the section to `foo' */ ! /* three text-definitions: */ ! LABEL_NAME "Name:" ! LABEL_POINTS "Points:" ! LABEL_SPEED "Speed:" ! LABEL_BEGINNER "Beginner" ! ! The file will be read and a C header-file (`foo.ht') will be generated. ! Also a data-file (plain text) containing the contents of the strings will ! be generated. The name of that file will be what you typed on the command ! line. ! ! Your C-file, say foo.c, must load a certain section from that data-file ! (in this case it will have only one section, "foo"). The function that ! loads the text is `LoadTexts' se CGUI-docs for details. It will detetect ! the current language and if this is english, the specified strings will ! be loaded. ! Example code for loading: ! const char *const*my_texts; ! int size; ! . . . ! my_texts = LoadTexts("foo.txt", "foo", &size); ! ! To know where in `my_texts' a cerain string is you must first ! include foo.ht, then use the macro to index the string-array like: ! ! #include "foo.ht" ! . . . ! AddCheck(TOPLEFT, my_texts[LABEL_BEGINNER], &beginner); ! ! ! You don't need to know what the generated files looks like, but in case ! you are interested; for the example above the current implementation ! generates something like: ! ! foo.ht: ! #ifndef FOO_HT ! #define FOO_HT ! #define LABEL_NAME 0 ! #define LABEL_POINTS 1 ! #define LABEL_SPEED 2 ! #define LABEL_BEGINNER 3 ! #endif ! ! foo.txt: ! <en> ! [foo ! "Name: ! "Points: ! "Speed: ! "Beginner ! ! If the the file `allegro.cfg' is not present or if `allegro.cfg' don't ! contain any language specification, then `LoadTexts' will try to load ! section "en". ! If the the file `allegro.cfg' is present, the item `lang = xx' in the ! section `cgui' will be selected. If not present the item `language = xx' ! in the `global section' will be selected by `LoadTexts'. ! ! If the language requested is not present in the data-file, ! then `LoadTexts' will try to load text from the language part `en'. ! If `LoadTexts' fails to load the language `en' and there exists some ! other language(s) in the textfile, the first one will be loaded. ! ! About the "specification language" that mktext understands: ! - The source-file may contain C- and C++ style comments. ! - The string may be partitioned over multiple rows (using the same ! notation as in C): ! NAME "The name " ! "of a " ! "person:" ! - The string may contain quotation marks (") if ! indicated by back-slash (like in C-strings). ! - The following are reserved words: start,end,language ! - mktext will check that any pair of corresponding strings from different ! languages contains identical conversions codes. If you want the '%' to be ! written and the string shall later be passed to some *printf function ! then you must type '%' twice in the string (according to the C spec.). ! This can be done also in strings processed by `mktext'. The problem is if ! you plan to pass the string as it is to some other function like `textout' ! and you want a % to be written. `mktext' will believe than the '%' is the ! beginning of a conversion code and will complain about it. To avoid this ! you must type the code "%&" (the '&'-character will not be transfered to ! the output file). ! - You may create "string arrays". The syntax for that is a start ! indiciation, a sequence of sub-elements and finally an end indication. ! Example: ! ! LEVEL "Level:" ! <start=LEVEL_ALT> ! LEVEL_BEGINNER "Beginner" ! LEVEL_MEDIUM "Medium" ! LEVEL_ADVANCED "Advanced" ! <end=NR_LEVEL_ALT> ! ! This is specially useful if you use the drop-down-box function ! `AddDropDownS' in Cgui. ! Example: ! ! const char *const*txt; ! int size; ! txt = LoadTexts("foo.txt", "foo", &size); ! . . . ! AddDropDownS(TOPLEFT, 0, txt[LEVEL], &level, txt + LEVEL_ALT, NR_LEVEL_ALT); ! ! Possibly you may somewhere in your code have a switch statement that refers ! to the user selection (i.e. `level') and the code may look like: ! ! switch (level) { ! case LEVEL_BEGINNER: ! . . . ! break; ! case LEVEL_MEDIUM: ! . . . ! break; ! case LEVEL_ADVANCED: ! . . . ! break; ! } ! ! The if `level' is the variable which value was modified by the drop-down ! box or a radio group, its value will be in the range 0..2, which is also ! the numbers assigned to "elements" in the string array (always starting ! at 0). ! ! If there is no need for the names of the "elements" in the string-array, ! you can optioally use a single underscore (_) to indicate "no macro ! generation". ! ! A source file may contain several languages and/or sections. However, it ! is assumed that you rather preferer to have one section and one language ! per file. Typically you may want N source-files for each C-file that uses ! some texts (where N is the number of languages supported). ! Probably you want to have only one file containing the texts, in ! your final program distribution. ! Therfore `mktext' has the capability to merge all texts into one single ! destination file. ! ! Simple calling of `mktext' (the textfile is put into current directory and ! the headerfile(s) will be put in the same directory as the source(s)): ! ! mktext destfile source [source2 ...] ! ! Maintaining a large program in a structured manner, also includes proper ! handling of the various texts. You will probably want to put all texts ! used in a certain C-file into a specific text-source-file, like `foo.c' ! has its texts in `foo.t' and includes `foo.ht'. The compiled texts you ! will have in `myprog.txt'. ! ! In a large program that uses texts extensively, you are also interested in ! avoiding to re-compile all (or most of) the C-files only because you made ! changes for one text (resulting in a new `.ht' file). ! ! To fulfill all this, and to make it possible to set up dependencies in ! a proper way in makefiles, the generation can be made in two separate ! passes, the first generating the header-file (optionally excluded) and ! an intermediate text-file. The second pass generates the final ! text-file (similar to the link-pass of a program build). ! ! During the second pass the macro-identifiers from the different languages ! will be checked for equality (using the `en'-langugae as reference). Also ! existing conversions specifications (like %d, %s etc) will be ! checked as well as the `Requester' codes ('|'). ! ! Calling the mktext program for "compiling": ! ! mktext -c [-pXXXX] [-iYYYY] [-nh] source [source2 ...] ! ! where ! -XXXX is the path of the header file(s) (by default it will be put into ! the same directory as the source-file(s)). ! -YYYY is the path of the intermediate file(s) (by default it will be put ! into the same directory as the source-file(s)). ! -nh means "create no header file". Any two headerfiles originating from ! different languages will of course be identical (provided that the sources ! are correct) so you only need to have them generated for one of the ! languages. ! The suffix of the intermediate files is `.it' ! ! calling the mktext program for "linking": ! ! mktext -l destfile intermediate-file [intermediate-file2 ...] ! ! Advanced topics: ! ! * About labels and "hot-keys": ! If you have assigned hotkeys manually in a couple of strings, and want them ! to be checked for uniqueness: Just put them within a block (a pair of {}). ! Blocks may also be nested in the source. This is necessary if you use ! tab-windows (because you want the hotkeys outside the tab-part to be ! unique when combined with any selection of tab). Tab-windows may be nested. ! In a future there may also be automatic generation of hot-keys. ! Hot-keys within a Requester-text will be checked against each other ! (each button-label within the text must have a unique label). This check ! is always done. Requester-text shall be outside any block, because you ! don't want them to be checked against each other. ! ! * About file handling: ! If you need a text that contains more than one conversion ! specification, this may be a problem when translating to different ! languages. When creating an expressive text in a language different from ! yours, it will be a limitation to keep the conversion specifications in ! a fix order - remember that other languages may use a different "word ! order" (just look at the Germans :-). mktext provides a special "floating ! position" conversion code which has the syntax: %<any text>. When such a ! string is used in the program you must first call the ! RegisterConversionHandler, and then use PrintFloatingConversion (which ! similar to sprintf formats the input string into a destination string). ! ! Normal C-conversions (like %d, %s etc) can not be combined in such a ! string, they will be ignored (the point whith this "floating position" ! conversion is to get rid of all such codes). ! ! The semantics of this is a textual reference to a function, and thus is ! safe. If you mix things up and incidently pass the string to some standard ! function (like sprintf) the conversions codes will be ignored. If you ! forget to register the formatting functions (or miss-spel the text) the ! name of the conversion will be printed instead. ! ! See the cgui-help for details about RegisterConversionHandler ! and PrintFloatingConversion. ! ! Example: ! ! foo.t ! <language=en> ! [person_dialogue] ! PERSON_DIALOGUE "Dialogue for entering persons" ! NAME "Name:" ! AREA "Area:" ! CANCEL "Cancel" ! OK "OK" ! REQ_WARNING_PERSON_EXISTS "The entered person %<name> has already been " ! "entered (from %<area>).|Canel|OK" ! <language=se> ! [person_dialogue] ! PERSON_DIALOGUE "Dialog för att skriva in personer" ! NAME "Namn:" ! AREA "Distrikt:" ! CANCEL "Avbryt" ! OK "OK" ! REQ_WARNING_PERSON_EXISTS "I distriktet %<area> finns det redan en person " ! "med namnet %<name>.|Avbryt|OK" ! ! And in foo.c: ! . . . ! RegisterConversionHandler("<name>", format_name, new_person); ! RegisterConversionHandler("<area>", format_area, clatch_person); ! PrintFloatingConversion(s, text[REQ_WARNING_PERSON_EXISTS]); ! if (Req(s)) ! /* enter person */ ! else ! /* return to dialogue */ ! ! . . . ! void format_name(char *s, void *data) ! { ! struct t_person *p = data; ! sprintf(s, "%s (%d)", p->name, p->number); ! } ! ! void format_area(char *s, void *data) ! { ! struct t_person *p = data; ! sprintf(s, "%s", p->area->name); ! } ! ! (For swedes: yes, in the above example the text would easyly have been ! re-written to keep the same order of the conversion specifications as ! in the english version - swedish and english are two very similar ! languages, but there are other...) ! ! The registration of conversion-handlers are permanent. In many cases ! this is not very useful since the data object may alter from time to time. ! A re-registration for each use (like in the example above) will however ! replace the previous one. --- 1,288 ---- ! `mktext' is a program with the purpose to give a tool so that you can ! keep a program free from language dependent textstrings. ! ! Very brief about simple usage: A source-file (`.t') containing rows, each ! of which consist of pairs which defines the text. Each pair consist of: ! - a C-identifier ! - a quoted string ! Each source file must first of all start with a language definition, ! followed by a section definition. Then the actual text specifications ! follows. ! Example (suppose the below is contained in a file `foo.t'): ! <language=en> /* specifies the name of the language to `en' */ ! [foo] /* specifies the name of the section to `foo' */ ! /* three text-definitions: */ ! LABEL_NAME "Name:" ! LABEL_POINTS "Points:" ! LABEL_SPEED "Speed:" ! LABEL_BEGINNER "Beginner" ! ! The file will be read and a C header-file (`foo.ht') will be generated. ! Also a data-file (plain text) containing the contents of the strings will ! be generated. The name of that file will be what you typed on the command ! line. ! ! Your C-file, say foo.c, must load a certain section from that data-file ! (in this case it will have only one section, "foo"). The function that ! loads the text is `LoadTexts' se CGUI-docs for details. It will detetect ! the current language and if this is english, the specified strings will ! be loaded. ! Example code for loading: ! const char *const*my_texts; ! int size; ! . . . ! my_texts = LoadTexts("foo.txt", "foo", &size); ! ! To know where in `my_texts' a cerain string is you must first ! include foo.ht, then use the macro to index the string-array like: ! ! #include "foo.ht" ! . . . ! AddCheck(TOPLEFT, my_texts[LABEL_BEGINNER], &beginner); ! ! ! You don't need to know what the generated files looks like, but in case ! you are interested; for the example above the current implementation ! generates something like: ! ! foo.ht: ! #ifndef FOO_HT ! #define FOO_HT ! #define LABEL_NAME 0 ! #define LABEL_POINTS 1 ! #define LABEL_SPEED 2 ! #define LABEL_BEGINNER 3 ! #endif ! ! foo.txt: ! <en> ! [foo ! "Name: ! "Points: ! "Speed: ! "Beginner ! ! If the the file `allegro.cfg' is not present or if `allegro.cfg' don't ! contain any language specification, then `LoadTexts' will try to load ! section "en". ! If the the file `allegro.cfg' is present, the item `lang = xx' in the ! section `cgui' will be selected. If not present the item `language = xx' ! in the `global section' will be selected by `LoadTexts'. ! ! If the language requested is not present in the data-file, ! then `LoadTexts' will try to load text from the language part `en'. ! If `LoadTexts' fails to load the language `en' and there exists some ! other language(s) in the textfile, the first one will be loaded. ! ! About the "specification language" that mktext understands: ! - The source-file may contain C- and C++ style comments. ! - The string may be partitioned over multiple rows (using the same ! notation as in C): ! NAME "The name " ! "of a " ! "person:" ! - The string may contain quotation marks (") if ! indicated by back-slash (like in C-strings). ! - The following are reserved words: start,end,language ! - mktext will check that any pair of corresponding strings from different ! languages contains identical conversions codes. If you want the '%' to be ! written and the string shall later be passed to some *printf function ! then you must type '%' twice in the string (according to the C spec.). ! This can be done also in strings processed by `mktext'. The problem is if ! you plan to pass the string as it is to some other function like `textout' ! and you want a % to be written. `mktext' will believe than the '%' is the ! beginning of a conversion code and will complain about it. To avoid this ! you must type the code "%&" (the '&'-character will not be transfered to ! the output file). ! - You may create "string arrays". The syntax for that is a start ! indiciation, a sequence of sub-elements and finally an end indication. ! Example: ! ! LEVEL "Level:" ! <start=LEVEL_ALT> ! LEVEL_BEGINNER "Beginner" ! LEVEL_MEDIUM "Medium" ! LEVEL_ADVANCED "Advanced" ! <end=NR_LEVEL_ALT> ! ! This is specially useful if you use the drop-down-box function ! `AddDropDownS' in Cgui. ! Example: ! ! const char *const*txt; ! int size; ! txt = LoadTexts("foo.txt", "foo", &size); ! . . . ! AddDropDownS(TOPLEFT, 0, txt[LEVEL], &level, txt + LEVEL_ALT, NR_LEVEL_ALT); ! ! Possibly you may somewhere in your code have a switch statement that refers ! to the user selection (i.e. `level') and the code may look like: ! ! switch (level) { ! case LEVEL_BEGINNER: ! . . . ! break; ! case LEVEL_MEDIUM: ! . . . ! break; ! case LEVEL_ADVANCED: ! . . . ! break; ! } ! ! The if `level' is the variable which value was modified by the drop-down ! box or a radio group, its value will be in the range 0..2, which is also ! the numbers assigned to "elements" in the string array (always starting ! at 0). ! ! If there is no need for the names of the "elements" in the string-array, ! you can optioally use a single underscore (_) to indicate "no macro ! generation". ! ! A source file may contain several languages and/or sections. However, it ! is assumed that you rather preferer to have one section and one language ! per file. Typically you may want N source-files for each C-file that uses ! some texts (where N is the number of languages supported). ! Probably you want to have only one file containing the texts, in ! your final program distribution. ! Therfore `mktext' has the capability to merge all texts into one single ! destination file. ! ! Simple calling of `mktext' (the textfile is put into current directory and ! the headerfile(s) will be put in the same directory as the source(s)): ! ! mktext destfile source [source2 ...] ! ! Maintaining a large program in a structured manner, also includes proper ! handling of the various texts. You will probably want to put all texts ! used in a certain C-file into a specific text-source-file, like `foo.c' ! has its texts in `foo.t' and includes `foo.ht'. The compiled texts you ! will have in `myprog.txt'. ! ! In a large program that uses texts extensively, you are also interested in ! avoiding to re-compile all (or most of) the C-files only because you made ! changes for one text (resulting in a new `.ht' file). ! ! To fulfill all this, and to make it possible to set up dependencies in ! a proper way in makefiles, the generation can be made in two separate ! passes, the first generating the header-file (optionally excluded) and ! an intermediate text-file. The second pass generates the final ! text-file (similar to the link-pass of a program build). ! ! During the second pass the macro-identifiers from the different languages ! will be checked for equality (using the `en'-langugae as reference). Also ! existing conversions specifications (like %d, %s etc) will be ! checked as well as the `Requester' codes ('|'). ! ! Calling the mktext program for "compiling": ! ! mktext -c [-pXXXX] [-iYYYY] [-nh] source [source2 ...] ! ! where ! -XXXX is the path of the header file(s) (by default it will be put into ! the same directory as the source-file(s)). ! -YYYY is the path of the intermediate file(s) (by default it will be put ! into the same directory as the source-file(s)). ! -nh means "create no header file". Any two headerfiles originating from ! different languages will of course be identical (provided that the sources ! are correct) so you only need to have them generated for one of the ! languages. ! The suffix of the intermediate files is `.it' ! ! calling the mktext program for "linking": ! ! mktext -l destfile intermediate-file [intermediate-file2 ...] ! ! Advanced topics: ! ! * About labels and "hot-keys": ! If you have assigned hotkeys manually in a couple of strings, and want them ! to be checked for uniqueness: Just put them within a block (a pair of {}). ! Blocks may also be nested in the source. This is necessary if you use ! tab-windows (because you want the hotkeys outside the tab-part to be ! unique when combined with any selection of tab). Tab-windows may be nested. ! In a future there may also be automatic generation of hot-keys. ! Hot-keys within a Requester-text will be checked against each other ! (each button-label within the text must have a unique label). This check ! is always done. Requester-text shall be outside any block, because you ! don't want them to be checked against each other. ! ! * About file handling: ! If you need a text that contains more than one conversion ! specification, this may be a problem when translating to different ! languages. When creating an expressive text in a language different from ! yours, it will be a limitation to keep the conversion specifications in ! a fix order - remember that other languages may use a different "word ! order" (just look at the Germans :-). mktext provides a special "floating ! position" conversion code which has the syntax: %<any text>. When such a ! string is used in the program you must first call the ! RegisterConversionHandler, and then use PrintFloatingConversion (which ! similar to sprintf formats the input string into a destination string). ! ! Normal C-conversions (like %d, %s etc) can not be combined in such a ! string, they will be ignored (the point whith this "floating position" ! conversion is to get rid of all such codes). ! ! The semantics of this is a textual reference to a function, and thus is ! safe. If you mix things up and incidently pass the string to some standard ! function (like sprintf) the conversions codes will be ignored. If you ! forget to register the formatting functions (or miss-spel the text) the ! name of the conversion will be printed instead. ! ! See the cgui-help for details about RegisterConversionHandler ! and PrintFloatingConversion. ! ! Example: ! ! foo.t ! <language=en> ! [person_dialogue] ! PERSON_DIALOGUE "Dialogue for entering persons" ! NAME "Name:" ! AREA "Area:" ! CANCEL "Cancel" ! OK "OK" ! REQ_WARNING_PERSON_EXISTS "The entered person %<name> has already been " ! "entered (from %<area>).|Canel|OK" ! <language=se> ! [person_dialogue] ! PERSON_DIALOGUE "Dialog för att skriva in personer" ! NAME "Namn:" ! AREA "Distrikt:" ! CANCEL "Avbryt" ! OK "OK" ! REQ_WARNING_PERSON_EXISTS "I distriktet %<area> finns det redan en person " ! "med namnet %<name>.|Avbryt|OK" ! ! And in foo.c: ! . . . ! RegisterConversionHandler("<name>", format_name, new_person); ! RegisterConversionHandler("<area>", format_area, clatch_person); ! PrintFloatingConversion(s, text[REQ_WARNING_PERSON_EXISTS]); ! if (Req(s)) ! /* enter person */ ! else ! /* return to dialogue */ ! ! . . . ! void format_name(char *s, void *data) ! { ! struct t_person *p = data; ! sprintf(s, "%s (%d)", p->name, p->number); ! } ! ! void format_area(char *s, void *data) ! { ! struct t_person *p = data; ! sprintf(s, "%s", p->area->name); ! } ! ! (For swedes: yes, in the above example the text would easyly have been ! re-written to keep the same order of the conversion specifications as ! in the english version - swedish and english are two very similar ! languages, but there are other...) ! ! The registration of conversion-handlers are permanent. In many cases ! this is not very useful since the data object may alter from time to time. ! A re-registration for each use (like in the example above) will however ! replace the previous one. Index: t_block.h =================================================================== RCS file: /cvsroot/cgui/cgui/tools/t_block.h,v retrieving revision 1.2 retrieving revision 1.2.4.1 diff -C2 -d -r1.2 -r1.2.4.1 *** t_block.h 26 Mar 2006 10:27:49 -0000 1.2 --- t_block.h 21 Apr 2007 21:15:33 -0000 1.2.4.1 *************** *** 1,13 **** ! #ifndef BLOCK_H ! #define BLOCK_H ! ! struct t_block; ! struct t_label; ! ! extern struct t_block *create_block(void); ! extern void destroy_block_tree(struct t_block *root); ! extern void insert_block_node(struct t_block *root, struct t_block *newnode); ! extern void insert_block_label(struct t_block *root, struct t_label *l, char *hotkey, int row); ! extern int check_hot_keys(struct t_block *root); ! ! #endif --- 1,13 ---- ! #ifndef BLOCK_H ! #define BLOCK_H ! ! struct t_block; ! struct t_label; ! ! extern struct t_block *create_block(void); ! extern void destroy_block_tree(struct t_block *root); ! extern void insert_block_node(struct t_block *root, struct t_block *newnode); ! extern void insert_block_label(struct t_block *root, struct t_label *l, char *hotkey, int row); ! extern int check_hot_keys(struct t_block *root); ! ! #endif Index: t_scan.c =================================================================== RCS file: /cvsroot/cgui/cgui/tools/t_scan.c,v retrieving revision 1.2 retrieving revision 1.2.4.1 diff -C2 -d -r1.2 -r1.2.4.1 *** t_scan.c 25 Sep 2005 18:02:56 -0000 1.2 --- t_scan.c 21 Apr 2007 21:15:33 -0000 1.2.4.1 *************** *** 1,232 **** ! /* Scans a text source file, generating a token list, as intermediate ! reprsentation of the source file */ ! ! #include <stdio.h> ! #include <allegro.h> ! #include "cgui/mem.h" ! #include <string.h> ! #include <ctype.h> ! ! #include "t_parser.h" ! #include "t_scan.h" ! ! typedef struct t_token { ! int type; ! char *name; ! int line_nr; ! } t_token; ! ! typedef struct t_tokenlist { ! int n; ! t_token *t; ! t_token *cur; ! const char *fn; ! } t_tokenlist; ! ! typedef struct t_lex { ! int tok; ! char *pat; ! } t_lex; ! ! #define NRLEXEMES 3 ! t_lex lex[NRLEXEMES] = {{LANGUAGE, "language"}, {START, "start"}, {END, "end"}}; ! ! extern t_tokenlist *create_token_list(void) ! { ! t_tokenlist *tl; ! ! tl = GetMem0(t_tokenlist, 1); ! return tl; ! } ! ! extern void destroy_token_list(t_tokenlist *tl) ! { ! int i; ! ! for (i = 0; i < tl->n; i++) ! if (tl->t[i].name) ! free(tl->t[i].name); ! free(tl->t); ! free(tl); ! } ! ! static char *revert_token(int type) ! { ! switch (type) { ! case DONE: ! return "end of file"; ! case START: ! return "start"; ! case END: ! return "end"; ! case ID: ! return "identifier"; ! case STRING: ! return "string"; ! case LANGUAGE: ! return "language"; ! case ERROR: ! return "unknown pattern"; ! case NUM: ! return "numeric value"; ! case LT: ! return "<"; ! case GT: ! return ">"; ! case EQ: ! return "="; ! case LB: ! return "["; ! case RB: ! return "]"; ! default: ! return "internal error!"; ! } ! } ! ! extern void match(t_tokenlist *tl, int type) ! { ! unsigned i; ! ! if (token_type(next_token(tl)) == type)... [truncated message content] |