diff --git a/texk/web2c/luatexdir/lang/texlang.c b/texk/web2c/luatexdir/lang/texlang.c index ba7614ff..ccc0ec90 100644 --- a/texk/web2c/luatexdir/lang/texlang.c +++ b/texk/web2c/luatexdir/lang/texlang.c @@ -498,10 +498,20 @@ static char *hyphenation_exception(int exceptions, char *w) return ret; } +char *unsorted_buffer = NULL; +size_t *indexes = NULL; + +static int sort_func(const void *a, const void *b) { + size_t ia = *(size_t*)a; + size_t ib = *(size_t*)b; + return strcmp(&unsorted_buffer[ia], &unsorted_buffer[ib]); +} + char *exception_strings(struct tex_language *lang) { const char *value; size_t size = 0, current = 0; + size_t num_bytes = 0; size_t l = 0; char *ret = NULL; if (lang->exceptions == 0) @@ -509,19 +519,42 @@ char *exception_strings(struct tex_language *lang) lua_checkstack(Luas, 2); lua_rawgeti(Luas, LUA_REGISTRYINDEX, lang->exceptions); if (lua_istable(Luas, -1)) { - /*tex Iterate and join. */ + /*tex Determine required memory. */ lua_pushnil(Luas); while (lua_next(Luas, -2) != 0) { value = lua_tolstring(Luas, -1, &l); - if (current + 2 + l > size) { - ret = xrealloc(ret, (unsigned) ((size + size / 5) + current + l + 1024)); - size = (size + size / 5) + current + l + 1024; - } - *(ret + current) = ' '; - strcpy(ret + current + 1, value); + num_bytes += l + 1; + size++; + lua_pop(Luas, 1); + } + unsorted_buffer = xmalloc(num_bytes); + indexes = xmalloc(sizeof(size_t)*size); + + /*tex Fetch values. */ + current = 0; + size = 0; + lua_pushnil(Luas); + while (lua_next(Luas, -2) != 0) { + value = lua_tolstring(Luas, -1, &l); + strcpy(unsorted_buffer + current, value); + indexes[size++] = current; current += l + 1; lua_pop(Luas, 1); } + /*tex Sort and join. */ + qsort(indexes, size, sizeof(size_t), sort_func); + ret = xmalloc(num_bytes); + current = 0; + for (l = 0; l < size; l++) { + strcpy(ret + current, &unsorted_buffer[indexes[l]]); + current += strlen(&unsorted_buffer[indexes[l]]); + ret[current] = ' '; + current += 1; + } + ret[current - 1] = '\0'; + + free(unsorted_buffer); + free(indexes); } return ret; }