void start_order_char(wchar_t wc) { collchar_t *cc; int32_t ref; start_order(T_CHAR); /* * If we last saw an ellipsis, then we need to close the range. * Handle that here. Note that we have to be careful because the * items *inside* the range are treated exclusiveley to the items * outside of the range. The ends of the range can have quite * different weights than the range members. */ if (lastorder == T_ELLIPSIS) { int i; if (wc < ellipsis_start) { errf(_("malformed range!")); return; } while (ellipsis_start < wc) { /* * pick all of the saved weights for the * ellipsis. note that -1 encodes for the * ellipsis itself, which means to take the * current relative priority. */ if ((cc = get_collchar(ellipsis_start, 1)) == NULL) { INTERR; return; } for (i = 0; i < NUM_WT; i++) { collpri_t *p; if (((ref = ellipsis_weights[i]) == -1) || ((p = get_pri(ref)) == NULL) || (p->pri == -1)) { set_pri(cc->ref[i], nextpri, RESOLVED); } else { set_pri(cc->ref[i], ref, REFER); } ellipsis_weights[i] = 0; } ellipsis_start++; nextpri++; } } currchar = get_collchar(wc, 1); }
static ERTS_INLINE int prepare_crash_dump(int secs) { #define NUFBUF (3) int i, max; char env[21]; /* enough to hold any 64-bit integer */ size_t envsz; /*DeclareTmpHeapNoproc(heap,NUFBUF);*/ /*Eterm *hp = heap;*/ /*Eterm list = NIL;*/ int has_heart = 0; UseTmpHeapNoproc(NUFBUF); if (ERTS_PREPARED_CRASH_DUMP) return 0; /* We have already been called */ /* Positive secs means an alarm must be set * 0 or negative means no alarm * * Set alarm before we try to write to a port * we don't want to hang on a port write with * no alarm. * */ #if 0 /*ose TBD!!!*/ if (secs >= 0) { alarm((unsigned int)secs); } #endif /* Make sure we unregister at epmd (unknown fd) and get at least one free filedescriptor (for erl_crash.dump) */ max = max_files; if (max < 1024) max = 1024; for (i = 3; i < max; i++) { close(i); } envsz = sizeof(env); i = erts_sys_getenv__("ERL_CRASH_DUMP_NICE", env, &envsz); if (i >= 0) { int nice_val; nice_val = i != 0 ? 0 : atoi(env); if (nice_val > 39) { nice_val = 39; } set_pri(nice_val); } UnUseTmpHeapNoproc(NUFBUF); #undef NUFBUF return has_heart; }
void end_order_collsym(collsym_t *sym) { start_order(T_COLLSYM); /* update the weight */ set_pri(sym->ref, nextpri, RESOLVED); nextpri++; }
void add_order_subst(void) { subst_t srch; subst_t *s; avl_index_t where; int i; (void) memset(&srch, 0, sizeof (srch)); for (i = 0; i < curr_subst; i++) { srch.ref[i] = subst_weights[i]; subst_weights[i] = 0; } s = avl_find(&substs_ref[curr_weight], &srch, &where); if (s == NULL) { if ((s = calloc(sizeof (*s), 1)) == NULL) { errf(_("out of memory")); return; } s->key = new_pri(); /* * We use a self reference for our key, but we set a * high bit to indicate that this is a substitution * reference. This will expedite table lookups later, * and prevent table lookups for situations that don't * require it. (In short, its a big win, because we * can skip a lot of binary searching.) */ set_pri(s->key, (nextsubst[curr_weight] | COLLATE_SUBST_PRIORITY), RESOLVED); nextsubst[curr_weight] += 1; for (i = 0; i < curr_subst; i++) { s->ref[i] = srch.ref[i]; } avl_insert(&substs_ref[curr_weight], s, where); if (avl_find(&substs[curr_weight], s, &where) != NULL) { INTERR; return; } avl_insert(&substs[curr_weight], s, where); } curr_subst = 0; /* * We are using the current (unique) priority as a search key * in the substitution table. */ add_order_pri(s->key); }
void init_collate(void) { int i; avl_create(&collsyms, collsym_compare, sizeof (collsym_t), offsetof(collsym_t, avl)); avl_create(&collundefs, collundef_compare, sizeof (collsym_t), offsetof(collundef_t, avl)); avl_create(&elem_by_symbol, element_compare_symbol, sizeof (collelem_t), offsetof(collelem_t, avl_bysymbol)); avl_create(&elem_by_expand, element_compare_expand, sizeof (collelem_t), offsetof(collelem_t, avl_byexpand)); avl_create(&collchars, collchar_compare, sizeof (collchar_t), offsetof(collchar_t, avl)); for (i = 0; i < COLL_WEIGHTS_MAX; i++) { avl_create(&substs[i], subst_compare, sizeof (subst_t), offsetof(subst_t, avl)); avl_create(&substs_ref[i], subst_compare_ref, sizeof (subst_t), offsetof(subst_t, avl_ref)); avl_create(&weights[i], weight_compare, sizeof (weight_t), offsetof(weight_t, avl)); nweight[i] = 1; } (void) memset(&collinfo, 0, sizeof (collinfo)); /* allocate some initial priorities */ pri_ignore = new_pri(); set_pri(pri_ignore, 0, RESOLVED); for (i = 0; i < COLL_WEIGHTS_MAX; i++) { pri_undefined[i] = new_pri(); /* we will override this later */ set_pri(pri_undefined[i], COLLATE_MAX_PRIORITY, UNKNOWN); } }
void end_order(void) { int i; int32_t pri; int32_t ref; collpri_t *p; /* advance the priority/weight */ pri = nextpri; switch (currorder) { case T_CHAR: for (i = 0; i < NUM_WT; i++) { if (((ref = order_weights[i]) < 0) || ((p = get_pri(ref)) == NULL) || (p->pri == -1)) { /* unspecified weight is a self reference */ set_pri(currchar->ref[i], pri, RESOLVED); } else { set_pri(currchar->ref[i], ref, REFER); } order_weights[i] = -1; } /* leave a cookie trail in case next symbol is ellipsis */ ellipsis_start = currchar->wc + 1; currchar = NULL; break; case T_ELLIPSIS: /* save off the weights were we can find them */ for (i = 0; i < NUM_WT; i++) { ellipsis_weights[i] = order_weights[i]; order_weights[i] = -1; } break; case T_COLLELEM: if (currelem == NULL) { INTERR; } else { for (i = 0; i < NUM_WT; i++) { if (((ref = order_weights[i]) < 0) || ((p = get_pri(ref)) == NULL) || (p->pri == -1)) { set_pri(currelem->ref[i], pri, RESOLVED); } else { set_pri(currelem->ref[i], ref, REFER); } order_weights[i] = -1; } } break; case T_UNDEFINED: for (i = 0; i < NUM_WT; i++) { if (((ref = order_weights[i]) < 0) || ((p = get_pri(ref)) == NULL) || (p->pri == -1)) { set_pri(pri_undefined[i], -1, RESOLVED); } else { set_pri(pri_undefined[i], ref, REFER); } order_weights[i] = -1; } break; case T_SYMBOL: for (i = 0; i < NUM_WT; i++) { if (((ref = order_weights[i]) < 0) || ((p = get_pri(ref)) == NULL) || (p->pri == -1)) { set_pri(currundef->ref[i], pri, RESOLVED); } else { set_pri(currundef->ref[i], ref, REFER); } order_weights[i] = -1; } break; default: INTERR; } nextpri++; }
void dump_collate(void) { FILE *f; int i, j, n; size_t sz; int32_t pri; collelem_t *ce; collchar_t *cc; subst_t *sb; char vers[COLLATE_STR_LEN]; collate_char_t chars[UCHAR_MAX + 1]; collate_large_t *large; collate_subst_t *subst[COLL_WEIGHTS_MAX]; collate_chain_t *chain; /* * We have to run throught a preliminary pass to identify all the * weights that we use for each sorting level. */ for (i = 0; i < NUM_WT; i++) { add_weight(pri_ignore, i); } for (i = 0; i < NUM_WT; i++) { for (sb = avl_first(&substs[i]); sb; sb = AVL_NEXT(&substs[i], sb)) { for (j = 0; sb->ref[j]; j++) { add_weight(sb->ref[j], i); } } } for (ce = avl_first(&elem_by_expand); ce != NULL; ce = AVL_NEXT(&elem_by_expand, ce)) { add_weights(ce->ref); } for (cc = avl_first(&collchars); cc; cc = AVL_NEXT(&collchars, cc)) { add_weights(cc->ref); } /* * Now we walk the entire set of weights, removing the gaps * in the weights. This gives us optimum usage. The walk * occurs in priority. */ for (i = 0; i < NUM_WT; i++) { weight_t *w; for (w = avl_first(&weights[i]); w; w = AVL_NEXT(&weights[i], w)) { w->opt = nweight[i]; nweight[i] += 1; } } (void) memset(&chars, 0, sizeof (chars)); (void) memset(vers, 0, COLLATE_STR_LEN); (void) strlcpy(vers, COLLATE_VERSION, sizeof (vers)); /* * We need to make sure we arrange for the UNDEFINED field * to show up. Also, set the total weight counts. */ for (i = 0; i < NUM_WT; i++) { if (resolve_pri(pri_undefined[i]) == -1) { set_pri(pri_undefined[i], -1, RESOLVED); /* they collate at the end of everything else */ collinfo.undef_pri[i] = COLLATE_MAX_PRIORITY; } collinfo.pri_count[i] = nweight[i]; } collinfo.pri_count[NUM_WT] = max_wide(); collinfo.undef_pri[NUM_WT] = COLLATE_MAX_PRIORITY; collinfo.directive[NUM_WT] = DIRECTIVE_UNDEFINED; /* * Ordinary character priorities */ for (i = 0; i <= UCHAR_MAX; i++) { if ((cc = get_collchar(i, 0)) != NULL) { for (j = 0; j < NUM_WT; j++) { chars[i].pri[j] = get_weight(cc->ref[j], j); } } else { for (j = 0; j < NUM_WT; j++) { chars[i].pri[j] = get_weight(pri_undefined[j], j); } /* * Per POSIX, for undefined characters, we * also have to add a last item, which is the * character code. */ chars[i].pri[NUM_WT] = i; } } /* * Substitution tables */ for (i = 0; i < NUM_WT; i++) { collate_subst_t *st = NULL; n = collinfo.subst_count[i] = avl_numnodes(&substs[i]); if ((st = calloc(sizeof (collate_subst_t) * n, 1)) == NULL) { errf(_("out of memory")); return; } n = 0; for (sb = avl_first(&substs[i]); sb; sb = AVL_NEXT(&substs[i], sb)) { if ((st[n].key = resolve_pri(sb->key)) < 0) { /* by definition these resolve! */ INTERR; } if (st[n].key != (n | COLLATE_SUBST_PRIORITY)) { INTERR; } for (j = 0; sb->ref[j]; j++) { st[n].pri[j] = get_weight(sb->ref[j], i); } n++; } if (n != collinfo.subst_count[i]) INTERR; subst[i] = st; } /* * Chains, i.e. collating elements */ collinfo.chain_count = avl_numnodes(&elem_by_expand); chain = calloc(sizeof (collate_chain_t), collinfo.chain_count); if (chain == NULL) { errf(_("out of memory")); return; } for (n = 0, ce = avl_first(&elem_by_expand); ce != NULL; ce = AVL_NEXT(&elem_by_expand, ce), n++) { (void) wsncpy(chain[n].str, ce->expand, COLLATE_STR_LEN); for (i = 0; i < NUM_WT; i++) { chain[n].pri[i] = get_weight(ce->ref[i], i); } } if (n != collinfo.chain_count) INTERR; /* * Large (> UCHAR_MAX) character priorities */ large = calloc(sizeof (collate_large_t) * avl_numnodes(&collchars), 1); if (large == NULL) { errf(_("out of memory")); return; } i = 0; for (cc = avl_first(&collchars); cc; cc = AVL_NEXT(&collchars, cc)) { int undef = 0; /* we already gathered those */ if (cc->wc <= UCHAR_MAX) continue; for (j = 0; j < NUM_WT; j++) { if ((pri = get_weight(cc->ref[j], j)) < 0) { undef = 1; } if (undef && (pri >= 0)) { /* if undefined, then all priorities are */ INTERR; } else { large[i].pri.pri[j] = pri; } } if (!undef) { large[i].val = cc->wc; collinfo.large_count = i++; } } if ((f = open_category()) == NULL) { return; } /* Time to write the entire data set out */ if ((wr_category(vers, COLLATE_STR_LEN, f) < 0) || (wr_category(&collinfo, sizeof (collinfo), f) < 0) || (wr_category(&chars, sizeof (chars), f) < 0)) { delete_category(f); return; } for (i = 0; i < NUM_WT; i++) { sz = sizeof (collate_subst_t) * collinfo.subst_count[i]; if (wr_category(subst[i], sz, f) < 0) { delete_category(f); return; } } sz = sizeof (collate_chain_t) * collinfo.chain_count; if (wr_category(chain, sz, f) < 0) { delete_category(f); return; } sz = sizeof (collate_large_t) * collinfo.large_count; if (wr_category(large, sz, f) < 0) { delete_category(f); return; } close_category(f); }