• Patch: Elm ME+ 2.5 PLalpha62 -> Elm ME+ 2.5 PLalpha63 [5/7] (3/7)

    From Kari Hurtta@21:1/5 to All on Wed Jan 3 13:52:43 2024
    [continued from previous message]

    + struct tagfilter_entities * enttyp;
    + struct string * entity_value;
    + uint16 unicode_value;
    + int lineno;
    + unsigned ne_match_flags;
    + enum change_mode merged_entity;
    + size_t * res_idx_p /* append mode */;
    + int * append_need_rewrite_p;
    + int * errors;
    + struct string * rest_S;
    + struct string * entity_type;
    + int set_old;
    + {
    + int r = 1;
    +
    + union sort_key key;
    + union sort_item_default def;
    + union sort_item res;
    +
    + struct string_sort * search_key = NULL;
    +
    + if (TAGFILTER_ENTITIES_CONF_magic != conf->magic)
    + mime_panic(__FILE__,__LINE__," set_tagfilter_entity",
    + "Bad magic number (tagfilter_entities_conf)");
    +
    +
    + /* Shares named_reference and increments refcount */
    + search_key = new_string_sort(named_reference);
    +
    + key.string_sort = search_key;
    + def.dummy = NULL;
    + res.dummy = NULL;
    +
    + /* Increments refcount, returns 1 if found or created */
    + if (search_sort_list_item(conf->root,
    + sort_list_insert_hint /* sequential append mode, + uses res_idx
    + */
    + /* sort_list_search_create <-- when random order */
    + ,key,def,
    + &res,res_idx_p,append_need_rewrite_p)) {
    +
    + DPRINT(Debug,14,(&Debug,
    + "set_tagfilter_entity: search_sort_list_item found or created item #%zu\n",
    + *res_idx_p));
    +
    + if (res.entity) {
    + struct entity_sort_item * entity_item = res.entity;
    + size_t newpos = 0;
    + int merged = 0;
    +
    + if (ENTITY_SORT_ITEM_magic != entity_item->magic)
    + mime_panic(__FILE__,__LINE__,"set_tagfilter_entity",
    + "Bad magic number (entity_sort_item)");
    +
    + if (entity_item->entities) {
    + size_t a;
    +
    + for (a = 0; a < entity_item->entities_count; a++) {
    +
    + if (enttyp == entity_item->entities[a].entity_type) {
    +
    + if (! entity_item->entities[a].result) {
    +
    + newpos = a;
    + goto found1;
    + }
    +
    + if (NAME_ENTITY_MATCH_magic !=
    + entity_item->entities[a].result->magic)
    + mime_panic(__FILE__,__LINE__,"set_tagfilter_entity",
    + "Bad magic number (name_entity_match)"); +
    + if (conf != entity_item->entities[a].result->conf)
    + mime_panic(__FILE__,__LINE__,"set_tagfilter_entities",
    + "Bad conf (name_entity_match)");
    +
    +
    + switch (merged_entity) {
    + case read_entities:
    + /* Is this merge */
    + if (entity_item->entities[a].need_on_disk) {
    +
    + newpos = a;
    + merged = 1;
    +
    + goto found1;
    + }
    + break;
    + case merge_entities:
    + newpos = a;
    + merged = 1;
    +
    + goto found1;
    + }
    +
    + if (rest_S && entity_type) {
    + if (tagfilter_is_printableln(filename,lineno,rest_S))
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeEntityDuplicate,
    + "%s: %d: Duplicate entity %S with type %S - already given on line %d: %S"),
    + filename,lineno,
    + named_reference,entity_type,
    + entity_item->entities[a].result->lineno,
    + rest_S);
    + }
    +
    + (*errors) ++;
    + goto fail2;
    +
    + }
    + }
    + }
    +
    + entity_item->entities =
    + safe_array_realloc(entity_item->entities,
    + entity_item->entities_count+1,
    + sizeof (entity_item->entities[0]));
    +
    + newpos = entity_item->entities_count++;
    +
    + /* bzero is defined on hdrs/defs.h */
    + bzero((void *)&(entity_item->entities[newpos]),
    + sizeof ((entity_item->entities[newpos])));
    +
    + entity_item->entities[newpos].entity_type = enttyp;
    + entity_item->entities[newpos].result = NULL;
    + entity_item->entities[newpos].old = set_old;
    +
    +
    + found1:
    +
    + if (newpos >= entity_item->entities_count)
    + mime_panic(__FILE__,__LINE__,"set_tagfilter_entity",
    + "Bad newpos");
    +
    + if (entity_item->entities[newpos].entity_type != enttyp)
    + mime_panic(__FILE__,__LINE__,"set_tagfilter_entity",
    + "Bad type on newpos");
    +
    + entity_item->entities[newpos].need_on_disk = 0;
    + entity_item->entities[newpos].delete = 0;
    +
    + if (entity_item->entities[newpos].result) {
    + if (NAME_ENTITY_MATCH_magic !=
    + entity_item->entities[newpos].result->magic)
    + mime_panic(__FILE__,__LINE__,"set_tagfilter_entity",
    + "Bad magic number (name_entity_match)");
    +
    + if (conf != entity_item->entities[newpos].result->conf)
    + mime_panic(__FILE__,__LINE__,"set_tagfilter_entity",
    + "Bad conf ((name_entity_match)");
    +
    + if (!merged) {
    + if (rest_S && entity_type) {
    + if (tagfilter_is_printableln(filename,lineno,rest_S))
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeEntityDuplicate,
    + "%s: %d: Duplicate entity %S with type %S - already given on line %d: %S"),
    + filename,lineno,
    + named_reference,entity_type,
    + entity_item->entities[newpos].result->lineno,
    + rest_S);
    + }
    + (*errors) ++;
    + }
    +
    + entity_item->entities[newpos].result->lineno = lineno;
    +
    + if (entity_item->entities[newpos].result->entity_value)
    + free_string(& (entity_item->entities[newpos].result->
    + entity_value));
    + if (entity_value)
    + entity_item->entities[newpos].result->entity_value =
    + dup_string(entity_value);
    +
    + entity_item->entities[newpos].result->unicode_value = unicode_value;
    + entity_item->entities[newpos].result->flags = ne_match_flags;
    +
    + } else
    + entity_item->entities[newpos].result =
    + malloc_name_entity_match(entity_value,unicode_value,
    + conf,lineno,ne_match_flags);
    +
    + if (conf->linked)
    + link_name_entity_match(entity_item->entities[newpos].result,
    + entity_item->entities[newpos].entity_type,
    + entity_item->reference_key,
    + errors);
    +
    + free_entity_sort_item(&res); /* Decrement refcount */
    + } else {
    + DPRINT(Debug,14,(&Debug,
    + "set_tagfilter_entity: search_sort_list_item did not set entity\n"));
    + r = 0;
    + }
    +
    + } else {
    + DPRINT(Debug,14,(&Debug,
    + "set_tagfilter_entity: search_sort_list_item failed to create entry\n"));
    +
    + r = 0;
    + }
    +
    + fail2:
    + if (search_key)
    + free_string_sort(&search_key);
    +
    +
    + return r;
    + }
    +
    +
    +
    +
    + int change_tagfilter_entities(conf,new,rc,filename,errors)
    + struct tagfilter_entities_conf **conf;
    + struct tagfilter_entities_conf * new;
    + enum record_mode rc /* SYSTEM_RC = 0,
    + LOCAL_RC = 1 */;
    + const char * filename;
    + int * errors;
    + {
    + int ret = 1;
    +
    + if (*conf) {
    +
    + if (TAGFILTER_ENTITIES_CONF_magic != (*conf)->magic)
    + mime_panic(__FILE__,__LINE__,"change_tagfilter_entities",
    + "Bad magic number (tagfilter_entities_conf, *conf)");
    +
    + }
    +
    + if (TAGFILTER_ENTITIES_CONF_magic != new->magic)
    + mime_panic(__FILE__,__LINE__,"change_tagfilter_entities",
    + "Bad magic number (tagfilter_entities_conf, new");
    +
    + if (new->root) {
    + size_t count = sort_list_len(new->root);
    + size_t i;
    + size_t new_idx = 0;
    + int append_need_rewrite = 0;
    +
    + if (!*conf) {
    +
    + DPRINT(Debug,14,(&Debug,
    + "change_tagfilter_entities: Creating config, count=%zu entities for %s\n",
    + count,filename));
    +
    + *conf = malloc_tagfilter_entities_conf(rc,filename,count);
    + } else {
    +
    + if ((*conf)->root) {
    + size_t old_count = sort_list_len((*conf)->root);
    +
    + DPRINT(Debug,14,(&Debug,
    + "change_tagfilter_entities: %zu entires already on %s\n",
    + old_count,(*conf)->filename));
    + } else {
    + (*conf)->root = alloc_sort_list(&entity_map_operation,count);
    + }
    +
    + (*conf)->rc = rc;
    + if ((*conf)->filename != filename) {
    + DPRINT(Debug,14,(&Debug,
    + "change_tagfilter_entities: filename %s => %s\n",
    + (*conf)->filename,filename));
    + (*conf)->filename = strmcpy((*conf)->filename,filename);
    + }
    + }
    +
    + /* merge request from elmtagfilterents */
    +
    + for (i = 0; i < count; i++) {
    +
    + union sort_item res;
    +
    + res.entity = NULL;
    +
    + /* Increments refcount */
    + get_sort_list_item(new->root,sort_list_get_normal,i,&res);
    +
    + if (res.entity) {
    + struct entity_sort_item * entity_item = res.entity;
    +
    + if (ENTITY_SORT_ITEM_magic != entity_item->magic)
    + mime_panic(__FILE__,__LINE__,"change_tagfilter_entities",
    + "Bad magic number (entity_sort_item)");
    +
    + DPRINT(Debug,14,(&Debug,"change_tagfilter_entities: entity %zu = \"%S\"\n",
    + i,entity_item->reference_key));
    +
    +
    + if (entity_item->entities) {
    + size_t j;
    +
    + for (j = 0; j < entity_item->entities_count; j++) {
    + const char * type = "???";
    +
    + if (! entity_item->entities[j].entity_type ||
    + ! entity_item->entities[j].result)
    + continue;
    +
    + if (TAGFILTER_ENTITIES_magic !=
    + entity_item->entities[j].entity_type->magic)
    + mime_panic(__FILE__,__LINE__,"change_tagfilter_entities",
    + "Bad magic number (tagfilter_entities)");
    + type = entity_item->entities[j].entity_type->type_tag; +
    + DPRINT(Debug,14,(&Debug," : %zu %s\n",
    + j,type));
    +
    + if (NAME_ENTITY_MATCH_magic != entity_item->entities[j].result->magic)
    + mime_panic(__FILE__,__LINE__,"change_tagfilter_entities",
    + "Bad magic number (name_entity_match)"); +
    +
    +
    +
    + if (set_tagfilter_entity(filename,*conf,entity_item->reference_key,
    + entity_item->entities[j].entity_type,
    + entity_item->entities[j].result->entity_value,
    + entity_item->entities[j].result->unicode_value,
    +
    + /* Not really correct */
    + entity_item->entities[j].result->lineno,
    +
    + entity_item->entities[j].result->flags,
    + merge_entities,
    + &new_idx,
    + &append_need_rewrite,
    + errors,NULL,NULL,0
    + )) {
    +
    + DPRINT(Debug,14,(&Debug," - %zu %s => %zu\n",
    + j,type,new_idx));
    +
    + } else {
    + DPRINT(Debug,14,(&Debug," - %zu %s => failed\n",
    + j,type));
    +
    + ret = 0;
    + }
    + }
    + }
    +
    + free_entity_sort_item(&res);
    + }
    + }
    + }
    +
    + return ret;
    + }
    +
    + int merge_tagfilter_entities(filename,f,conf,errors,fileset,propline,rc,need_rewrite)
    + const char * filename;
    + FILE * f;
    + struct tagfilter_entities_conf * conf;
    + int *errors;
    + charset_t *fileset;
    + struct editor_propline **propline;
    + enum record_mode rc /* SYSTEM_RC = 0,
    + LOCAL_RC = 1 */;
    + int *need_rewrite;
    + {
    + int r;
    +
    + r = read_tagfilter_entities(filename,f,&conf,errors,fileset,propline,
    + rc, need_rewrite);
    +
    + return r;
    + }
    +
    + static int read_tagfilter_entities(filename,f,conf,errors,fileset,propline,rc,need_rewrite)
    + const char * filename;
    + FILE * f;
    + struct tagfilter_entities_conf ** conf;
    + int * errors;
    + charset_t * fileset;
    + struct editor_propline ** propline;
    + enum record_mode rc /* SYSTEM_RC = 0,
    + LOCAL_RC = 1 */;
    + int * need_rewrite;
    + {
    + charset_t cs = system_charset;
    + const char * csn = get_charset_MIME_name(cs);
    +
    + size_t res_idx = 0; /* Append mode position */
    + char * buf = NULL;
    + int c;
    + size_t count = 0;
    + int last_c = '\n';
    + int lineno = 0;
    +
    + int append_need_rewrite = 0;
    +
    + int fail_it = 0;
    + size_t pos = 0;
    + enum syscall_status r;
    +
    + int ret_status = 0;
    + int set_old = 0;
    +
    + if (fileset && *fileset) {
    + csn = get_charset_MIME_name(*fileset);
    +
    + cs = *fileset;
    +
    + if (csn) {
    + DPRINT(Debug,2,(&Debug,
    + "read_tagfilter_entities: %s: default charset: %s\n",
    + filename,csn));
    + }
    + }
    +
    + /* Look for editor property line */
    +
    + if (propline) {
    + enum editor_propline_v propline_mode =
    + give_dt_enumerate_as_int(&editor_tfent_propline);
    +
    + /* Nothing detected yet */
    +
    + if (*propline)
    + free_editor_propline(propline);
    +
    + if (propline_mode != editor_propline_ignore) {
    + int i;
    +
    + for (i = 0; i < 3 && !*propline; i++) {
    + int l1;
    +
    + c = fgetc(f);
    +
    + if (EOF == c)
    + goto propline_failure;
    + if ('\n' == c)
    + continue;
    +
    + ungetc(c,f);
    +
    + if ('#' != c)
    + break;
    +
    + l1 = malloc_gets(&buf,LONG_STRING,f);
    + if (l1 > 1) {
    +
    + if ('#' != buf[0])
    + goto propline_failure;
    +
    + *propline =
    + detect_editor_propline(propline_mode,
    + buf,l1,filename,i,&cs);
    +
    + csn = get_charset_MIME_name(cs);
    +
    + } else { /* something wrong? */
    + propline_failure:
    +
    + rewind(f);
    + break;
    + }
    + }
    + }
    +
    + pos = ftell(f);
    + }
    +
    +
    + if (*conf) {
    +
    + if (TAGFILTER_ENTITIES_CONF_magic != (*conf)->magic)
    + mime_panic(__FILE__,__LINE__,"read_tagfilter_entities",
    + "Bad magic number (tagfilter_entities_conf)");
    +
    + if ((*conf)->root) {
    + size_t map_len = sort_list_len((*conf)->root);
    + size_t i;
    + size_t old_count = 0;
    +
    + DPRINT(Debug,14,(&Debug,
    + "read_tagfilter_entities: %zu items on tagfilter_entities_conf already\n",
    + map_len));
    +
    + for (i = 0; i < map_len; i++) {
    +
    + union sort_item res;
    +
    + res.entity = NULL;
    +
    + /* Increments refcount */
    + get_sort_list_item((*conf)->root,sort_list_get_normal,i,&res); +
    + if (res.entity) {
    + struct entity_sort_item * entity_item = res.entity;
    +
    + if (ENTITY_SORT_ITEM_magic != entity_item->magic)
    + mime_panic(__FILE__,__LINE__,"read_tagfilter_entities", + "Bad magic number (entity_sort_item)");
    +
    + DPRINT(Debug,14,(&Debug,"read_tagfilter_entities: entity %zu = \"%S\"\n",
    + i,entity_item->reference_key));
    +
    + if (entity_item->entities) {
    + size_t j;
    +
    + for (j = 0; j < entity_item->entities_count; j++) {
    + const char * type = "???";
    +
    + if (entity_item->entities[j].entity_type) {
    + if (TAGFILTER_ENTITIES_magic !=
    + entity_item->entities[j].entity_type->magic)
    + mime_panic(__FILE__,__LINE__,"read_tagfilter_entities",
    + "Bad magic number (tagfilter_entities)");
    + type = entity_item->entities[j].entity_type->type_tag;
    + }
    +
    + DPRINT(Debug,14,(&Debug," : %zu %s",
    + j,type));
    + if (entity_item->entities[j].delete) {
    + DPRINT(Debug,14,(&Debug,", marked for delete"));
    + } else if (entity_item->entities[j].old) {
    + entity_item->entities[j].need_on_disk = 1;
    + DPRINT(Debug,14,(&Debug,", old -- marked need_on_disk"));
    + old_count++;
    + } else if (entity_item->entities[j].need_on_disk) { + entity_item->entities[j].need_on_disk = 0;
    + DPRINT(Debug,14,(&Debug,", clearing need_on_disk"));
    + }
    + DPRINT(Debug,14,(&Debug,"\n"));
    +
    + }
    + }
    +
    + free_entity_sort_item(&res);
    + }
    +
    + if (old_count) {
    + DPRINT(Debug,14,(&Debug,
    + "read_tagfilter_entities: %zu old entities marked need_on_disk\n",
    + old_count));
    + }
    + }
    + }
    + } else {
    + set_old = 1; /* When later merged, need found from disk */
    + }
    +
    + if (!*conf || ! ((*conf)->root)) {
    +
    + DPRINT(Debug,14,(&Debug,
    + "read_tagfilter_entities: counting entity lines from offset %ld at %s\n",
    + pos,filename));
    +
    + while(EOF != (c = fgetc(f))) {
    + /* Rough guess about &entity lines */
    +
    + if (last_c == '\n' &&
    + c == '&')
    + count++;
    + last_c = c;
    + }
    +
    + r = fseek(f,pos,SEEK_SET);
    + switch (r) {
    + int err;
    + case syscall_success:
    + DPRINT(Debug,14,(&Debug,
    + "read_tagfilter_entities: Reading again from offset %ld at %s\n",
    + pos,filename));
    + break;
    + case syscall_error:
    + err = errno;
    + DPRINT(Debug,14,(&Debug,
    + "read_tagfilter_entities: Failed to seek to offset %ld at %s: %s\n",
    + pos,filename,strerror(err)));
    +
    + return 0;
    + }
    +
    +
    + if (!*conf) {
    +
    + DPRINT(Debug,14,(&Debug,
    + "read_tagfilter_entities: Creating config, count=%zu entity lines on %s\n",
    + count,filename));
    +
    + *conf = malloc_tagfilter_entities_conf(rc,filename,count);
    + } else if (! ((*conf)->root)) {
    + (*conf)->root = alloc_sort_list(&entity_map_operation,count);
    + }
    + }
    +
    + while(!feof(f) && !ferror(f) && !fail_it) {
    + int l1 = malloc_gets(&buf,LONG_STRING,f);
    + struct string * rest_S = NULL;
    + char * cx = buf;
    + int restlen = 0;
    + int ERRORS = 0;
    + int rs;
    + int L;
    +
    + if (-1 == l1) {
    + lib_error(CATGETS(elm_msg_cat, MeSet, MeTooLongLineNo,
    + "%s: %d: Too long line: %.30s..."),
    + filename,lineno+1,buf);
    + (*errors) ++;
    +
    + DPRINT(Debug,9,(&Debug,
    + "read_tagfilter_entities: %s: %d: failed to parse line, too long line\n",
    + filename,lineno+1));
    +
    +
    + break;
    + } else if (l1 < 0) {
    + DPRINT(Debug,9,(&Debug,
    + "read_tagfilter_entities: %s: %d: read error or EOF\n",
    + filename,lineno+1));
    + break;
    + }
    +
    + lineno++;
    +
    + if (l1 == 0)
    + continue;
    +
    + l1 = trim_whitespace_from_end(buf,l1);
    +
    + if (read_charset_tag(buf,l1,
    + filename,lineno,
    + errors,&cs,&csn))
    + continue;
    +
    + cx = buf;
    + while (*cx && whitespace (*cx)) /* skip leading whitespace */
    + cx++;
    + if ('#' == *cx)
    + continue;
    +
    + if (!*cx) {
    +
    + if (cx < buf + l1) {
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeNULcharacterOnLine,
    + "%s: %d: NUL character on line."),
    + filename,lineno);
    + (*errors) ++;
    +
    + DPRINT(Debug,9,(&Debug,
    + "read_tagfilter_entities: %s: %d: failed to parse line (NUL character)\n",
    + filename,lineno));
    +
    +
    + }
    +
    + }
    +
    + rest_S = new_string(cs);
    + restlen = (buf + l1) - cx;
    + rs = add_streambytes_to_string(rest_S,restlen,
    + cs2us(cx),&ERRORS);
    + if (rs < restlen) {
    + lib_error(CATGETS(elm_msg_cat, ElmSet, ElmFailedAsCharset,
    + "Failed to parse line %d as charset %s in \"%s\" file"),
    + lineno, csn ? csn : "<no MIME name>",filename);
    +
    + (*errors) ++;
    +
    + DPRINT(Debug,9,(&Debug,
    + "read_tagfilter_entities: %s: %d: failed to parse line\n",
    + filename,lineno));
    +
    + goto fail;
    + }
    +
    + if (ERRORS) {
    + lib_error(CATGETS(elm_msg_cat, ElmSet, ElmFileAsCharsetErrors,
    + "There is %d errors when parsing line %d as charset %s in \"%s\" file"),
    + ERRORS,lineno,
    + csn ? csn : "<no MIME name>",filename);
    +
    + (*errors) ++;
    +
    + DPRINT(Debug,9,(&Debug,
    + "read_tagfilter_entities: %s: %d: failed to parse line (%d character errors)\n",
    + filename,lineno, ERRORS));
    +
    +
    + goto fail;
    + }
    +
    + L = string_len(rest_S);
    + if (L > 0) {
    + uint16 code = give_unicode_from_string(rest_S,0);
    + struct string * named_reference = NULL;
    + struct string * entity_type = NULL;
    + struct string * entity_value = NULL;
    +
    + if (0x0026 /* & */ == code) {
    +
    + int x;
    + int seen_semicolon = 0;
    + int X = 0;
    + int rs;
    + uint16 found_delim = 0;
    +
    + enum value_mode {
    + null_value = 0,
    + quoted_string,
    + octal_value = 8,
    + decimal_value = 10,
    + hexdecimal_value = 16,
    +
    + } mode = null_value;
    + uint32 value = 0;
    +
    + int start_x = 0;
    + int end_x = 0;
    +
    + size_t y;
    +
    + struct tagfilter_entities * enttyp = NULL;
    + int ne_match_flags;
    +
    +
    +
    + for (x = 1; x < L; x++) {
    + code = give_unicode_from_string(rest_S,x);
    +
    +
    + if (0x003B /* ; */ == code) {
    + seen_semicolon = 1;
    + x++;
    + break;
    + } else if (0x0009 /* HT '\t' (horizontal tab) */ == code ||
    + 0x0020 /* SPACE */ == code) {
    + break;
    + } else if (tagfilter_entity_character(code,NULL)) {
    + /* OK */
    + } else {
    + goto badline;
    + }
    + }
    +
    + if (x < 2 || ( seen_semicolon && x < 3)) {
    + if (tagfilter_is_printableln(filename,lineno,rest_S))
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeEntityNotGiven,
    + "%s: %d: Entity name not given: %S"), + filename,lineno,rest_S);
    + (*errors) ++;
    + goto fail2;
    + }
    +
    + named_reference = clip_from_string(rest_S,&X,x);
    +
    + rs = get_word_from_string(rest_S,&entity_type,&X,
    + GWF_lowercase,cs2us(" \t"),
    + &found_delim);
    +
    + if (rs < 1 || !entity_type || string_len(entity_type) < 1) {
    + if (tagfilter_is_printableln(filename,lineno,rest_S))
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeEntityTypeNotGiven,
    + "%s: %d: Entity type not given: %S"), + filename,lineno,rest_S);
    + (*errors) ++;
    + goto fail2;
    + }
    +
    + for (x = X; x < L; x++) {
    + code = give_unicode_from_string(rest_S,x);
    +
    + if (0x0031 /* 1 */ <= code && code <= 0x0039 /* 9 */) {
    + mode = decimal_value;
    + break;
    + } else if (0x0078 /* x */ == code ||
    + 0x0058 /* X */ == code) {
    + x++;
    + mode = hexdecimal_value;
    + break;
    + } else if (0x0022 /* " */ == code) {
    + x++;
    + mode = quoted_string;
    + break;
    + } else if (0x0030 /* 0 */ == code) {
    + mode = octal_value;
    + break;
    + } else if (0x0009 /* HT '\t' (horizontal tab) */ == code ||
    + 0x0020 /* SPACE */ == code) {
    + /* Skip */
    + } else {
    + if (tagfilter_is_printableln(filename,lineno,rest_S))
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeEntityValNotOK,
    + "%s: %d: Entity value is not number or quoted string: %S"),
    + filename,lineno,rest_S);
    + (*errors) ++;
    + goto fail2;
    +
    + }
    + }
    +
    + switch (mode) {
    + case null_value: goto badline;
    + case quoted_string:
    + start_x = x;
    +
    + for (x = start_x; x < L; x++) {
    + code = give_unicode_from_string(rest_S,x);
    +
    + if (0x0022 /* " */ == code) {
    + end_x = x;
    + x++;
    + break;
    + } else if (0x005C /* \ */ == code) {
    + if (tagfilter_is_printableln(filename,lineno,rest_S))
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeEntityValNotBackSlash,
    + "%s: %d: Entity value does not allow backslash (\\): %S"),
    + filename,lineno,rest_S);
    + (*errors) ++;
    + goto fail2;
    + }
    + }
    +
    + if (end_x < start_x) {
    + if (tagfilter_is_printableln(filename,lineno,rest_S))
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeEntityValNotQuoteEnd,
    + "%s: %d: Entity value does not does not end with quote (\"): %S"),
    + filename,lineno,rest_S);
    + (*errors) ++;
    + goto fail2;
    + }
    +
    + X = start_x;
    + entity_value = clip_from_string(rest_S,&X,end_x-start_x);
    + X++;
    +
    + break;
    + case octal_value:
    + case decimal_value:
    + case hexdecimal_value:
    + start_x = x;
    +
    + for (x = start_x; x < L; x++) {
    + unsigned char v = 0;
    +
    + code = give_unicode_from_string(rest_S,x);
    +
    +
    +
    + if (0x0030 /* 0 */ <= code && code <= 0x0039 /* 9 */) { + v = code - 0x0030 /* 0 */;
    + } else if (0x0041 /* A */ <= code && code <= 0x005A /* Z */) {
    + v = code - 0x0041 /* A */ + 10;
    + } else if (0x0061 /* a */ <= code && code <= 0x007A /* z */) {
    + v = code - 0x0061 /* a */ + 10;
    +
    + } else if (0x0009 /* HT '\t' (horizontal tab) */ == code ||
    + 0x0020 /* SPACE */ == code) {
    +
    + break;
    +
    + } else {
    + if (tagfilter_is_printableln(filename,lineno,rest_S))
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeEntityValNotValidNumber,
    + "%s: %d: Entity value is not valid number: %S"),
    + filename,lineno,rest_S);
    + (*errors) ++;
    + goto fail2;
    + }
    +
    + if (v >= mode) {
    + if (tagfilter_is_printableln(filename,lineno,rest_S))
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeEntityValNotValidNumber,
    + "%s: %d: Entity value is not valid number: %S"),
    + filename,lineno,rest_S);
    + (*errors) ++;
    + goto fail2;
    + }
    +
    + value *= mode;
    + value += v;
    +
    + if (value > 0xFFFF) {
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeEntityValTooBig,
    + "%s: %d: Entity value is too big: %S"),
    + filename,lineno,rest_S);
    + (*errors) ++;
    + goto fail2;
    +
    + }
    + }
    +
    + X = x;
    + break;
    +
    + }
    +
    + for (x = X; x < L; x++) {
    + code = give_unicode_from_string(rest_S,x);
    +
    + if (0x0009 /* HT '\t' (horizontal tab) */ == code ||
    + 0x0020 /* SPACE */ == code) {
    +
    + /* OK */
    + } else if (0x0023 /* # */ == code) {
    + break;
    + } else {
    + if (tagfilter_is_printableln(filename,lineno,rest_S))
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeEntityValTarilinData,
    + "%s: %d: Entity value have trailing data: %S"),
    + filename,lineno,rest_S);
    + (*errors) ++;
    + goto fail2;
    +
    + }
    + }
    +
    + for (y = 0; y < entity_types_count; y++) {
    + if (TAGFILTER_ENTITIES_magic != entity_types[y]->magic)
    + mime_panic(__FILE__,__LINE__,"read_tagfilter_entities", + "Bad magic number (tagfilter_entities)");
    +
    + if (string_matches_ascii(entity_type,
    + cs2us(entity_types[y]->type_tag),0,
    + SMA_op_normal)) {
    + enttyp = entity_types[y];
    + break;
    + }
    + }
    +
    + if (!enttyp) {
    + if (tagfilter_is_printableln(filename,lineno,rest_S))
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeEntityTypeNotSup,
    + "%s: %d: Entity type %S not supported: %S"),
    + filename,lineno,entity_type,rest_S);
    + (*errors) ++;
    + goto fail2;
    + }
    +
    + if (mode < octal_value && !value)
    + value = UNICODE_BAD_CHAR; /* REPLACEMENT CHARACTER */
    +
    +
    + ne_match_flags =
    + seen_semicolon ? ne_match_SEMICOLON : 0;
    +
    + if (set_tagfilter_entity(filename,*conf,
    + named_reference,enttyp, entity_value, value,
    + lineno,ne_match_flags,read_entities,
    + &res_idx,&append_need_rewrite,
    + errors,rest_S,entity_type,set_old
    + )) {
    +
    + /* Nothing */
    +
    + } else {
    + DPRINT(Debug,14,(&Debug,
    + "read_tagfilter_entities: set_tagfilter_entity failed\n"));
    + fail_it = 1;
    + }
    +
    + if (append_need_rewrite && need_rewrite && !*need_rewrite) {
    + DPRINT(Debug,14,(&Debug,
    + "read_tagfilter_entities: Setting *need_rewrite\n"));
    + *need_rewrite = 1;
    + }
    +
    + } else {
    + badline:
    +
    +
    + if (tagfilter_is_printableln(filename,lineno,rest_S))
    + lib_error(CATGETS(elm_msg_cat, MeSet,
    + MeUnsupportedLineS,
    + "%s: %d: Unsupported line: %S"),
    + filename,lineno,rest_S);
    + (*errors) ++;
    +
    + DPRINT(Debug,9,(&Debug,
    + "read_tagfilter_entities: %s: %d: failed to parse line\n",
    + filename,lineno));
    + }
    +
    + fail2:
    +
    + if (entity_value)
    + free_string(&entity_value);
    + if (named_reference)
    + free_string(&named_reference);
    + if (entity_type)
    + free_string(&entity_type);
    + }
    +
    + fail:
    +
    + free_string(&rest_S);
    + }
    +
    + if (buf)
    + free(buf);
    +
    + if (fail_it)
    + ret_status = 0;
    + else if (feof(f) && (*conf)->root) {
    + size_t i;
    + size_t map_len = sort_list_len((*conf)->root);
    +
    +
    + for (i = 0; i < map_len; i++) {
    +
    + union sort_item res;
    +
    + res.entity = NULL;
    +
    + /* Increments refcount */
    + get_sort_list_item((*conf)->root,sort_list_get_normal,i,&res);
    +
    + if (res.entity) {
    + struct entity_sort_item * entity_item = res.entity;
    +
    + if (ENTITY_SORT_ITEM_magic != entity_item->magic)
    + mime_panic(__FILE__,__LINE__,"read_tagfilter_entities",
    + "Bad magic number (entity_sort_item)");
    +
    + DPRINT(Debug,14,(&Debug,"read_tagfilter_entities: entity %zu = \"%S\"\n",
    + i,res.entity->reference_key));
    +
    +
    + if (res.entity->entities) {
    + size_t j;
    +
    + for (j = 0; j < res.entity->entities_count; j++) {
    + const char * type = "???";
    +
    + if (res.entity->entities[j].entity_type) {
    + if (TAGFILTER_ENTITIES_magic !=
    + res.entity->entities[j].entity_type->magic)
    + mime_panic(__FILE__,__LINE__,"read_tagfilter_entities",
    + "Bad magic number (tagfilter_entities)");
    + type = res.entity->entities[j].entity_type->type_tag;
    + }
    +
    + DPRINT(Debug,14,(&Debug," : %zu %s",
    + j,type));
    +
    + if (res.entity->entities[j].old) {
    + DPRINT(Debug,14,(&Debug,", old"));
    + }
    +
    + if (res.entity->entities[j].delete) {
    + DPRINT(Debug,14,(&Debug,", marked for delete"));
    + }
    +
    + if (res.entity->entities[j].need_on_disk) {
    + DPRINT(Debug,14,(&Debug,", not seen on disk"));
    +
    + if (! res.entity->entities[j].need_on_disk) {
    + DPRINT(Debug,14,(&Debug," (marking for delete)"));
    +
    + res.entity->entities[j].delete = 1;
    + }
    + }
    +
    + DPRINT(Debug,14,(&Debug,"\n"));
    + }
    + }
    +
    + free_entity_sort_item(&res);
    + }
    + }
    +
    + ret_status = 1;
    + }
    +
    + return ret_status;
    + }
    +
    +
    + struct tagfilter_entities_conf * parse_tagfilter_entities(filename,errors,fileset,propline,rc,
    + need_rewrite
    + )
    + const char *filename;
    + int *errors;
    + charset_t *fileset;
    + struct editor_propline **propline;
    + enum record_mode rc /* SYSTEM_RC = 0,
    + LOCAL_RC = 1 */;
    + int *need_rewrite;
    + {
    + struct tagfilter_entities_conf * ret = NULL;
    +
    + int err = can_open(filename,"r");
    + FILE * f;
    +
    + if (err) {
    + DPRINT(Debug,2,(&Debug,
    + "parse_tagfilter_entities=NULL: %s: %s (can_open)\n",
    + filename,strerror(err)));
    + return NULL;
    + }
    +
    + f = fopen(filename,"r");
    + if (!f) {
    + err = errno;
    + DPRINT(Debug,2,(&Debug,
    + "parse_tagfilter_entities=NULL: %s: %s\n",
    + filename,strerror(err)));
    + return NULL;
    + }
    +
    + if (read_tagfilter_entities(filename,f,&ret,
    + errors,fileset,propline,rc,need_rewrite)) {
    + fclose(f);
    +
    + return ret;
    + }
    +
    + if (ret)
    + free_tagfilter_entities_conf(&ret);
    +
    + return ret;
    + }
    +
    + static struct tagfilter_entities_conf * malloc_tagfilter_entities_conf(rc,filename,
    + alloc_size)
    + enum record_mode rc;
    + const char * filename;
    + size_t alloc_size;
    + {
    + struct tagfilter_entities_conf * ret = safe_zero_alloc(sizeof(*ret));
    +
    + ret->magic = TAGFILTER_ENTITIES_CONF_magic;
    + ret->rc = rc;
    +
    + ret->filename = NULL;
    + if (filename)
    + ret->filename = safe_strdup(filename);
    +
    + ret->root = alloc_sort_list(&entity_map_operation,alloc_size);
    +
    + ret->linked = 0;
    +
    + return ret;
    + }
    +
    + void free_tagfilter_entities_conf(ptr)
    + struct tagfilter_entities_conf **ptr;
    + {
    + if (TAGFILTER_ENTITIES_CONF_magic != (*ptr)->magic)
    + mime_panic(__FILE__,__LINE__,"free_tagfilter_entities_conf",

    [continued in next message]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)