diff --git a/src/modules/_Charset/charsetmod.c b/src/modules/_Charset/charsetmod.c index 0352bb862b91137fbb9436273f7b0aeebfcfb8ee..745df96c914da645a05e0bac68309e682d09c15f 100644 --- a/src/modules/_Charset/charsetmod.c +++ b/src/modules/_Charset/charsetmod.c @@ -3,7 +3,7 @@ #endif /* HAVE_CONFIG_H */ #include "global.h" -RCSID("$Id: charsetmod.c,v 1.9 1999/02/10 21:51:16 hubbe Exp $"); +RCSID("$Id: charsetmod.c,v 1.10 1999/02/23 15:01:58 marcus Exp $"); #include "program.h" #include "interpret.h" #include "stralloc.h" @@ -1059,10 +1059,9 @@ void pike_module_init(void) { int i; struct svalue prog; - extern struct program *iso2022_init(); - struct program *iso2022_program = iso2022_init(); - if(iso2022_program != NULL) - add_program_constant("ISO2022", iso2022_program, ID_STATIC|ID_NOMASK); + extern void iso2022_init(); + + iso2022_init(); start_new_program(); ADD_STORAGE(struct std_cs_stor); diff --git a/src/modules/_Charset/iso2022.c b/src/modules/_Charset/iso2022.c index 5b21e7bf54cd56a587ee483a58bcec65ad8f41f2..fed8c1d290ecee70b41de9c4f69ff0719ce18496 100644 --- a/src/modules/_Charset/iso2022.c +++ b/src/modules/_Charset/iso2022.c @@ -3,7 +3,7 @@ #endif /* HAVE_CONFIG_H */ #include "global.h" -RCSID("$Id: iso2022.c,v 1.4 1999/02/10 21:51:17 hubbe Exp $"); +RCSID("$Id: iso2022.c,v 1.5 1999/02/23 15:01:59 marcus Exp $"); #include "program.h" #include "interpret.h" #include "stralloc.h" @@ -16,7 +16,8 @@ RCSID("$Id: iso2022.c,v 1.4 1999/02/10 21:51:17 hubbe Exp $"); #define PRGM_NAME "Locale.Charset.ISO2022" -static struct program *iso2022_program = NULL; +static struct program *iso2022dec_program = NULL; +static struct program *iso2022enc_program = NULL; struct gdesc { UNICHAR *transl; @@ -31,6 +32,12 @@ struct iso2022_stor { }; +struct iso2022enc_stor { + struct gdesc g[2]; + struct pike_string *replace; + struct string_builder strbuild; +}; + #define EMIT(X) string_builder_putchar(&s->strbuild,(X)) @@ -325,12 +332,158 @@ static void eat_string(struct pike_string *str, struct iso2022_stor *s) free_string(tmpstr); } +static void eat_enc_string(struct pike_string *str, struct iso2022enc_stor *s, + struct pike_string *rep) +{ + extern UNICHAR map_ANSI_X3_4_1968[]; + extern UNICHAR map_ISO_8859_1_1987[]; + INT32 l = str->len; + + switch(str->size_shift) { + case 0: + /* Simple case, just ASCII and latin1... */ + { + int asc, lat; + p_wchar0 c, *p = STR0(str); + if(s->g[0].mode == MODE_94 && s->g[0].index == 0x12) + asc = 1; + else + asc = 0; + if(s->g[1].mode == MODE_96 && s->g[1].index == 0x11) + lat = 1; + else + lat = 0; + while(l--) { + if((c=*p++)<0x80) { + if(c=='\r' || c=='\n') { + if(s->g[0].mode != MODE_94 || s->g[0].index != 0x12) { + s->g[0].transl = NULL; + s->g[0].index = 0; + } + s->g[1].transl = NULL; + s->g[1].index = 0; + lat = 0; + } else if(!asc && c>' ' && c<0x7f) { + string_builder_strcat(&s->strbuild, "\033(B"); + s->g[0].transl = map_ANSI_X3_4_1968; + s->g[0].mode = MODE_94; + s->g[0].index = 0x12; + asc = 1; + } + } else if(!lat) { + string_builder_strcat(&s->strbuild, "\033-A"); + s->g[1].transl = map_ISO_8859_1_1987; + s->g[1].mode = MODE_96; + s->g[1].index = 0x11; + lat = 1; + } + string_builder_putchar(&s->strbuild,c); + } + } + break; + case 1: + { + p_wchar1 c, *p = STR1(str); + while(l--) + if((c=*p++)<0x21 || c==0x7f) { + if(c=='\r' || c=='\n') { + if(s->g[0].mode != MODE_94 || s->g[0].index != 0x12) { + s->g[0].transl = NULL; + s->g[0].index = 0; + } + s->g[1].transl = NULL; + s->g[1].index = 0; + } + string_builder_putchar(&s->strbuild,c); + } else if(c<0x7f) { + if(s->g[0].mode != MODE_94 || s->g[0].index != 0x12) { + string_builder_strcat(&s->strbuild, "\033(B"); + s->g[0].transl = map_ANSI_X3_4_1968; + s->g[0].mode = MODE_94; + s->g[0].index = 0x12; + } + string_builder_putchar(&s->strbuild,c); + } else if(c<0x100) { + if(s->g[1].mode != MODE_96 || s->g[1].index != 0x11) { + string_builder_strcat(&s->strbuild, "\033-A"); + s->g[1].transl = map_ISO_8859_1_1987; + s->g[1].mode = MODE_96; + s->g[1].index = 0x11; + } + string_builder_putchar(&s->strbuild,c); + } else if(c==0xfffd) { + /* Substitution character... */ + if(rep != NULL) + eat_enc_string(rep, s, NULL); + else + error("Character unsupported by encoding.\n"); + } else if(c>=0x3000) { + /* CJK */ + error("Not implemented.\n"); + } else { + int mode, index, ch; + UNICHAR *ttab = NULL; + if(c<0x180) { + unsigned char map1[] = { + 0x02, 0x00, 0x15, 0x00, 0xa0, 0xa0, 0x02, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0x80, 0xc0, + 0x00, 0x08, 0xfc, 0x03, 0x30, 0x20, 0x00, 0x15, + 0x00, 0xf0, 0xff, 0x03, 0xf0, 0xff, 0x00, 0x00 }; + unsigned char map2[] = { 0x12, 0x13, 0x14, 0x20 }; + mode = MODE_96; + index = map2[(map1[(c-0x100)>>2]>>((c&3)<<1))&3]; + } else { + error("Not implemented.\n"); + } + if(index!=0 && (ttab = transltab[mode][index-0x10])!=NULL) { + switch(mode) { + case MODE_96: + for(ch=0; ch<96; ch++) + if(ttab[ch]==c) + break; + if(ch<96) { + if(s->g[1].mode != MODE_96 || s->g[1].index != index) { + string_builder_strcat(&s->strbuild, "\033-"); + string_builder_putchar(&s->strbuild,index+0x30); + s->g[1].transl = ttab; + s->g[1].mode = MODE_96; + s->g[1].index = index; + } + string_builder_putchar(&s->strbuild,ch+160); + } else + ttab = NULL; + break; + default: + ttab = NULL; + } + } + if(ttab == NULL) + if(rep != NULL) + eat_enc_string(rep, s, NULL); + else + error("Character unsupported by encoding.\n"); + } + } + break; + case 2: + { + /* Quick exit, no characters beyond 0xffe6 are supported anyway :) */ + if(rep == NULL) + error("Character unsupported by encoding.\n"); + + error("Not implemented.\n"); + } + break; + default: + fatal("Illegal shift size!\n"); + } +} static void f_feed(INT32 args) { struct pike_string *str; - get_all_args(PRGM_NAME"->feed()", args, "%S", &str); + get_all_args(PRGM_NAME"Dec->feed()", args, "%S", &str); eat_string(str, (struct iso2022_stor *)fp->current_storage); @@ -381,6 +534,67 @@ static void f_clear(INT32 args) push_object(this_object()); } + +static void f_enc_feed(INT32 args) +{ + struct pike_string *str; + + get_all_args(PRGM_NAME"Dec->feed()", args, "%W", &str); + + eat_enc_string(str, (struct iso2022enc_stor *)fp->current_storage, + ((struct iso2022enc_stor *)fp->current_storage)->replace); + + pop_n_elems(args); + push_object(this_object()); +} + +static void f_enc_drain(INT32 args) +{ + struct iso2022enc_stor *s = (struct iso2022enc_stor *)fp->current_storage; + + pop_n_elems(args); + push_string(finish_string_builder(&s->strbuild)); + init_string_builder(&s->strbuild, 0); +} + +static void f_enc_clear(INT32 args) +{ + extern UNICHAR map_ANSI_X3_4_1968[]; + struct iso2022enc_stor *s = (struct iso2022enc_stor *)fp->current_storage; + int i; + + pop_n_elems(args); + + for(i=0; i<2; i++) { + s->g[i].transl = NULL; + s->g[i].mode = MODE_96; + s->g[i].index = 0; + } + s->g[0].transl = map_ANSI_X3_4_1968; + s->g[0].mode = MODE_94; + s->g[0].index = 0x12; + + reset_string_builder(&s->strbuild); + + push_object(this_object()); +} + +static void f_create(INT32 args) +{ + struct iso2022enc_stor *s = (struct iso2022enc_stor *)fp->current_storage; + + check_all_args("create()", args, BIT_STRING|BIT_VOID|BIT_INT, 0); + + if(args>0 && sp[-args].type == T_STRING) { + if(s->replace != NULL) + free_string(s->replace); + add_ref(s->replace = sp[-args].u.string); + } + + pop_n_elems(args); + push_int(0); +} + static void init_stor(struct object *o) { struct iso2022_stor *s = (struct iso2022_stor *)fp->current_storage; @@ -406,7 +620,32 @@ static void exit_stor(struct object *o) free_string(finish_string_builder(&s->strbuild)); } -struct program *iso2022_init(void) +static void init_enc_stor(struct object *o) +{ + struct iso2022enc_stor *s = (struct iso2022enc_stor *)fp->current_storage; + + s->replace = NULL; + + init_string_builder(&s->strbuild,0); + + f_enc_clear(0); + pop_n_elems(1); +} + +static void exit_enc_stor(struct object *o) +{ + struct iso2022enc_stor *s = (struct iso2022enc_stor *)fp->current_storage; + + if(s->replace != NULL) { + free_string(s->replace); + s->replace = NULL; + } + + reset_string_builder(&s->strbuild); + free_string(finish_string_builder(&s->strbuild)); +} + +void iso2022_init(void) { start_new_program(); ADD_STORAGE(struct iso2022_stor); @@ -418,13 +657,33 @@ struct program *iso2022_init(void) ADD_FUNCTION("clear", f_clear,tFunc(,tObj), 0); set_init_callback(init_stor); set_exit_callback(exit_stor); - return iso2022_program = end_program(); + add_program_constant("ISO2022Dec", iso2022dec_program = end_program(), + ID_STATIC|ID_NOMASK); + + start_new_program(); + ADD_STORAGE(struct iso2022enc_stor); + /* function(string:object) */ + ADD_FUNCTION("feed", f_enc_feed,tFunc(tStr,tObj), 0); + /* function(:string) */ + ADD_FUNCTION("drain", f_enc_drain,tFunc(,tStr), 0); + /* function(:object) */ + ADD_FUNCTION("clear", f_enc_clear,tFunc(,tObj), 0); + /* function(string|void:void) */ + ADD_FUNCTION("create", f_create,tFunc(tOr(tStr,tVoid),tVoid), 0); + set_init_callback(init_enc_stor); + set_exit_callback(exit_enc_stor); + add_program_constant("ISO2022Enc", iso2022enc_program = end_program(), + ID_STATIC|ID_NOMASK); } void iso2022_exit(void) { - if(iso2022_program) { - free_program(iso2022_program); - iso2022_program = NULL; + if(iso2022dec_program) { + free_program(iso2022dec_program); + iso2022dec_program = NULL; + } + if(iso2022enc_program) { + free_program(iso2022enc_program); + iso2022enc_program = NULL; } } diff --git a/src/modules/_Charset/module.pmod.in b/src/modules/_Charset/module.pmod.in index 455f5d857cd90a722ebd0c30307656260595c7a3..c6c8d8f0669591e1c0e221c7bcd7035fb2b74f8d 100644 --- a/src/modules/_Charset/module.pmod.in +++ b/src/modules/_Charset/module.pmod.in @@ -29,7 +29,7 @@ object decoder(string name) }(); if(name[..7]=="iso-2022") - return ISO2022(); + return ISO2022Dec(); program p = ([ "utf-7": UTF7dec, @@ -90,6 +90,9 @@ object encoder(string name, string|void replacement) } }(replacement); + if(name[..7]=="iso-2022") + return ISO2022Enc(replacement); + program p = ([ "utf-7": UTF7enc, "utf-8": UTF8enc