Files
mercury/runtime/mercury_string.c
Peter Ross c848ef1e93 Reimplement string__format so that it uses less memory and it's
Estimated hours taken: 24

Reimplement string__format so that it uses less memory and it's
behaviour is closer to the C standard.

library/string.m:
    Reimplement string__format.  The new implementation parses the
    format string building a control structure.  The control structure
    is then traversed to generate the output.
    Implement string__to_char_list in C.
    Implement string__append_list in C as this results in no garbage
    being generated due to the creation of the intermediate strings,
    which can be quite a significant saving.
    Remove the string__append_list(out, in) mode as it generates an
    infinite number of solutions.
    Use MR_allocate_aligned_string_msg for all memory allocations.

runtime/mercury_string.h:
    Add a new macro MR_allocate_aligned_string_msg which allocates
    word aligned space for storage of a string in.

runtime/mercury_string.c:
    Define a new function MR_make_string which provides sprintf like
    functionality for creating MR_Strings.  This function is safe from
    buffer overflows providing the vsnprintf function is available.

runtime/Mmakefile:
    Add mercury_string.c

configure.in:
    Check for the vsnprintf function.

runtime/mercury_conf.h.in:
    Define HAVE_VSNPRINTF.
2000-08-10 09:01:17 +00:00

65 lines
1.3 KiB
C

/*
** Copyright (C) 2000 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/
/* mercury_string.c - string handling */
#include "mercury_imp.h"
#include "mercury_string.h"
MR_String
MR_make_string(MR_Code *proclabel, const char *fmt, ...) {
va_list ap;
MR_String result;
int n;
#ifdef HAVE_VSNPRINTF
/* Guess that 100 bytes should be sufficient */
int size = 100;
char *p;
p = MR_NEW_ARRAY(char, size);
while (1) {
/* Try to print in the allocated space. */
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
/* If that worked, return the string. */
if (n > -1 && n < size) {
break;
}
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
/* precisely what is needed */
size = n + 1;
else /* glibc 2.0 */
size *= 2; /* twice the old size */
MR_RESIZE_ARRAY(p, char, size);
}
#else
/* It is possible for this buffer to overflow */
/* and then bad things may happen */
char p[40960];
va_start(ap, fmt);
n = vsprintf(p, fmt, ap);
va_end(ap);
#endif
MR_allocate_aligned_string_msg(result, strlen(p),
proclabel);
strcpy((char *) result, p);
#ifdef HAVE_VFPRINTF
MR_free(p);
#endif
return result;
}