+ worst_case = strlen(table->question_mark);
+
+ if (worst_case < strlen(table->star))
+ worst_case = strlen(table->star);
+
+ if (double_star && worst_case < strlen(table->double_star))
+ worst_case = strlen(table->double_star);
+
+ result = g_malloc(strlen(begin) + strlen(str) * worst_case + strlen(end) + 1);
+
+ /*
+ * Start by copying the beginning of the regex...
+ */
+
+ dst = g_stpcpy(result, begin);
+
+ /*
+ * ... Now to the meat of it.
+ */
+
+ for (src = str; *src; src++) {
+ c = *src;
+
+ /*
+ * First, check that we're in a character class: each and every
+ * character can be copied as is. We only need to be careful is the
+ * character is a closing bracket: it will end the character class IF
+ * AND ONLY IF it is not preceded by a backslash.
+ */
+
+ if (in_character_class) {
+ in_character_class = ((c != ']') || (*(src - 1) == '\\'));
+ goto straight_copy;
+ }
+
+ /*
+ * Are we in a quote? If yes, it is really simple: copy the current
+ * character, close the quote, the end.
+ */
+
+ if (in_quote) {
+ in_quote = FALSE;
+ goto straight_copy;
+ }
+
+ /*
+ * The only thing left to handle now is the "normal" case: we are not in
+ * a character class nor in a quote.
+ */
+
+ if (c == '\\') {
+ /*
+ * Backslash: append it, and open a new quote.
+ */
+ in_quote = TRUE;
+ goto straight_copy;
+ } else if (c == '[') {
+ /*
+ * Opening bracket: the beginning of a character class.
+ *
+ * Look ahead the next character: if it's an exclamation mark, then
+ * this is a complemented character class; append a caret to make
+ * the result string regex-friendly, and forward one character in
+ * advance.
+ */
+ *dst++ = c;
+ in_character_class = TRUE;
+ if (*(src + 1) == '!') {
+ *dst++ = '^';
+ src++;
+ }
+ } else if (IS_REGEX_META(c)) {
+ /*
+ * Regex metacharacter (except for ? and *, see below): append a
+ * backslash, and then the character itself.
+ */
+ *dst++ = '\\';
+ goto straight_copy;
+ } else if (c == '?')
+ /*
+ * Question mark: take the subsitution string out of our subst_table
+ * and append it to the string.
+ */
+ dst = g_stpcpy(dst, table->question_mark);
+ else if (c == '*') {
+ /*
+ * Star: append the subsitution string found in our subst_table.
+ * However, look forward the next character: if it's yet another
+ * star, then see if there is a substitution string for the double
+ * star and append this one instead.
+ *
+ * FIXME: this means that two consecutive stars in a glob string
+ * where there is no substition for double_star can lead to
+ * exponential regex execution time: consider [^/]*[^/]*.
+ */
+ const char *p = table->star;
+ if (double_star && *(src + 1) == '*') {
+ src++;
+ p = table->double_star;
+ }
+ dst = g_stpcpy(dst, p);
+ } else {
+ /*
+ * Any other character: append each time.
+ */
+straight_copy:
+ *dst++ = c;
+ }