示例#1
0
char *
xmemdup0 (void const *p, size_t s)
{
  char *result = xcharalloc (s + 1);
  memcpy (result, p, s);
  result[s] = 0;
  return result;
}
示例#2
0
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, &regs, regs.num_regs, regs.start, regs.end);
  if (re_compile_fastmap (&word_regexp))
    assert (false);

  default_word_regexp = false;
}
示例#3
0
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;
    }
}