char * xmemdup0 (void const *p, size_t s) { char *result = xcharalloc (s + 1); memcpy (result, p, s); result[s] = 0; return result; }
void set_word_regexp (const char *regexp) { const char *msg; struct re_pattern_buffer new_word_regexp; if (!*regexp || STREQ (regexp, DEFAULT_WORD_REGEXP)) { default_word_regexp = true; return; } /* Dry run to see whether the new expression is compilable. */ init_pattern_buffer (&new_word_regexp, NULL); msg = re_compile_pattern (regexp, strlen (regexp), &new_word_regexp); regfree (&new_word_regexp); if (msg != NULL) { M4ERROR ((warning_status, 0, "bad regular expression `%s': %s", regexp, msg)); return; } /* If compilation worked, retry using the word_regexp struct. We can't rely on struct assigns working, so redo the compilation. The fastmap can be reused between compilations, and will be freed by the final regfree. */ if (!word_regexp.fastmap) word_regexp.fastmap = xcharalloc (UCHAR_MAX + 1); msg = re_compile_pattern (regexp, strlen (regexp), &word_regexp); assert (!msg); re_set_registers (&word_regexp, ®s, regs.num_regs, regs.start, regs.end); if (re_compile_fastmap (&word_regexp)) assert (false); default_word_regexp = false; }
static void make_room_for (int length) { int wanted_size; m4_diversion *selected_diversion = NULL; /* Compute needed size for in-memory buffer. Diversions in-memory buffers start at 0 bytes, then 512, then keep doubling until it is decided to flush them to disk. */ output_diversion->used = output_diversion->size - output_unused; for (wanted_size = output_diversion->size; wanted_size < output_diversion->used + length; wanted_size = wanted_size == 0 ? INITIAL_BUFFER_SIZE : wanted_size * 2) ; /* Check if we are exceeding the maximum amount of buffer memory. */ if (total_buffer_size - output_diversion->size + wanted_size > MAXIMUM_TOTAL_SIZE) { int selected_used; char *selected_buffer; m4_diversion *diversion; int count; gl_oset_iterator_t iter; const void *elt; /* Find out the buffer having most data, in view of flushing it to disk. Fake the current buffer as having already received the projected data, while making the selection. So, if it is selected indeed, we will flush it smaller, before it grows. */ selected_diversion = output_diversion; selected_used = output_diversion->used + length; iter = gl_oset_iterator (diversion_table); while (gl_oset_iterator_next (&iter, &elt)) { diversion = (m4_diversion *) elt; if (diversion->used > selected_used) { selected_diversion = diversion; selected_used = diversion->used; } } gl_oset_iterator_free (&iter); /* Create a temporary file, write the in-memory buffer of the diversion to this file, then release the buffer. Zero the diversion before doing anything that can exit () (including m4_tmpfile), so that the atexit handler doesn't try to close a garbage pointer as a file. */ selected_buffer = selected_diversion->u.buffer; total_buffer_size -= selected_diversion->size; selected_diversion->size = 0; selected_diversion->u.file = NULL; selected_diversion->u.file = m4_tmpfile (selected_diversion->divnum); if (selected_diversion->used > 0) { count = fwrite (selected_buffer, (size_t) selected_diversion->used, 1, selected_diversion->u.file); if (count != 1) M4ERROR ((EXIT_FAILURE, errno, "ERROR: cannot flush diversion to temporary file")); } /* Reclaim the buffer space for other diversions. */ free (selected_buffer); selected_diversion->used = 1; } /* Reload output_file, just in case the flushed diversion was current. */ if (output_diversion == selected_diversion) { /* The flushed diversion was current indeed. */ output_file = output_diversion->u.file; output_cursor = NULL; output_unused = 0; } else { /* Close any selected file since it is not the current diversion. */ if (selected_diversion) { FILE *file = selected_diversion->u.file; selected_diversion->u.file = NULL; if (m4_tmpclose (file, selected_diversion->divnum) != 0) m4_error (0, errno, _("cannot close temporary file for diversion")); } /* The current buffer may be safely reallocated. */ { char *buffer = output_diversion->u.buffer; output_diversion->u.buffer = xcharalloc ((size_t) wanted_size); memcpy (output_diversion->u.buffer, buffer, output_diversion->used); free (buffer); } total_buffer_size += wanted_size - output_diversion->size; output_diversion->size = wanted_size; output_cursor = output_diversion->u.buffer + output_diversion->used; output_unused = wanted_size - output_diversion->used; } }