summaryrefslogtreecommitdiff
path: root/libc/stdio/old_vfprintf.c
AgeCommit message (Collapse)Author
2004-02-11New stdio core. Should be more maintainable. Fixes a couple of bugs.Manuel Novoa III
Codepaths streamlined. Improved performance for nonthreaded apps when linked with a thread-enabled libc. Minor iconv bug and some locale/thread related startup issues fixed. These showed up in getting a gcj-compiled java helloworld app running. Removed some old extension functions... _stdio_fdout and _stdio_fsfopen.
2003-09-06Implement vsnprintf (old_vfprintf only) and vsnscanf when uClibc isManuel Novoa III
configured with non-buffered stdio and non-wchar mode. Fix a couple of bugs that showed up in minimalist configurations. Update old_vfprintf to handle size qualifiers on the integer and %n conversions. It now passed the glibc printf tests with the exception of a floating point rounding difference.
2003-09-05Oops... Forgot to convert this to the new floating point conversion func.Manuel Novoa III
2003-08-01Add a new *scanf implementation, includeing the *wscanf functions.Manuel Novoa III
Should be standards compliant and with several optional features, including support for hexadecimal float notation, locale awareness, glibc-like locale-specific digit grouping with the `'' flag, and positional arg support. I tested it pretty well (finding several bugs in glibc's scanf in the process), but it is brand new so be aware. The *wprintf functions now support floating point output. Also, a couple of bugs were squashed. Finally, %a/%A conversions are now implemented. Implement the glibc xlocale interface for thread-specific locale support. Also add the various *_l(args, locale_t loc_arg) funcs. NOTE!!! setlocale() is NOT threadsafe! NOTE!!! The strto{floating point} conversion functions are now locale aware. The also now support hexadecimal floating point notation. Add the wcsto{floating point} conversion functions. Fix a bug in mktime() related to dst. Note that unlike glibc's mktime, uClibc's version always normalizes the struct tm before attempting to determine the correct dst setting if tm_isdst == -1 on entry. Add a stub version of the libintl functions. (untested) Fixed a known memory leak in setlocale() related to the collation data. Add lots of new config options (which Erik agreed to sort out :-), including finally exposing some of the stripped down stdio configs. Be careful with those though, as they haven't been tested in a long time. (temporary) GOTCHAs... The ctype functions are currently incorrect for 8-bit locales. They will be fixed shortly. The ctype functions are now table-based, resulting in larger staticly linked binaries. I'll be adding an option to use the old approach in the stub locale configuration.
2003-07-14Yikes! This was doing another lock instead of unlocking the stream.Manuel Novoa III
2002-07-07Attempt to clean up the strerror_r situation.Manuel Novoa III
2002-07-03Enable WCHAR support for C/POSIX stub locales.Manuel Novoa III
Implemented unformatted wide i/o functions. (ungetwc still needs testing) Fix a few bugs in wchar.c. Modifications for bcc/elks support.
2002-06-18Fix perror() and printf("%m") to not call strerror(), as required by theManuel Novoa III
standards. Temporarily added a utility function to wrap Erik's strerror_r so that "Unknown error xxx" strings can be generated for errno's which cause strerror_r to fail. That utility function will eventually be merged in with the strerror/strerror_r functions when I change over to optionallly mmap'ing the system error strings to provide for lower mem comsumption on non-MMU platforms, as well as locale-specific system error messages.
2002-05-11Adjust preprocessor logic to initialize QUAL_CHARS correctly for Erik's alphaManuel Novoa III
port. Also, explicitly use the macro versions of isdigit and isspace in the printf and scanf code.
2002-03-12Swap in the new stdio code.Manuel Novoa III
de <features.h> #include <errno.h> #include <stdlib.h> #include <string.h> #include <unistd.h> libc_hidden_proto(memcpy) libc_hidden_proto(strchr) libc_hidden_proto(strlen) libc_hidden_proto(strncmp) libc_hidden_proto(strndup) libc_hidden_proto(unsetenv) #include <bits/uClibc_mutex.h> __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); /* If this variable is not a null pointer we allocated the current environment. */ static char **last_environ; /* This function is used by `setenv' and `putenv'. The difference between the two functions is that for the former must create a new string which is then placed in the environment, while the argument of `putenv' must be used directly. This is all complicated by the fact that we try to reuse values once generated for a `setenv' call since we can never free the strings. */ int __add_to_environ (const char *name, const char *value, const char *combined, int replace) attribute_hidden; int __add_to_environ (const char *name, const char *value, const char *combined, int replace) { register char **ep; register size_t size; const size_t namelen = strlen (name); const size_t vallen = value != NULL ? strlen (value) + 1 : 0; int rv = -1; __UCLIBC_MUTEX_LOCK(mylock); /* We have to get the pointer now that we have the lock and not earlier since another thread might have created a new environment. */ ep = __environ; size = 0; if (ep != NULL) { for (; *ep != NULL; ++ep) { if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') break; else ++size; } } if (ep == NULL || *ep == NULL) { char **new_environ; /* We allocated this space; we can extend it. */ new_environ = (char **) realloc (last_environ, (size + 2) * sizeof (char *)); if (new_environ == NULL) { goto DONE; } /* If the whole entry is given add it. */ if (combined != NULL) { /* We must not add the string to the search tree since it belongs to the user. */ new_environ[size] = (char *) combined; } else { /* See whether the value is already known. */ new_environ[size] = (char *) malloc (namelen + 1 + vallen); if (new_environ[size] == NULL) { __set_errno (ENOMEM); goto DONE; } memcpy (new_environ[size], name, namelen); new_environ[size][namelen] = '='; memcpy (&new_environ[size][namelen + 1], value, vallen); } if (__environ != last_environ) { memcpy ((char *) new_environ, (char *) __environ, size * sizeof (char *)); } new_environ[size + 1] = NULL; last_environ = __environ = new_environ; } else if (replace) { char *np; /* Use the user string if given. */ if (combined != NULL) { np = (char *) combined; } else { np = malloc (namelen + 1 + vallen); if (np == NULL) { goto DONE; } memcpy (np, name, namelen); np[namelen] = '='; memcpy (&np[namelen + 1], value, vallen); } *ep = np; } rv = 0; DONE: __UCLIBC_MUTEX_UNLOCK(mylock); return rv; } libc_hidden_proto(setenv) int setenv (const char *name, const char *value, int replace) { return __add_to_environ (name, value, NULL, replace); } libc_hidden_def(setenv) libc_hidden_proto(unsetenv) int unsetenv (const char *name) { size_t len; char **ep; if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) { __set_errno (EINVAL); return -1; } len = strlen (name); __UCLIBC_MUTEX_LOCK(mylock); ep = __environ; while (*ep != NULL) { if (!strncmp (*ep, name, len) && (*ep)[len] == '=') { /* Found it. Remove this pointer by moving later ones back. */ char **dp = ep; do { dp[0] = dp[1]; } while (*dp++); /* Continue the loop in case NAME appears again. */ } else { ++ep; } } __UCLIBC_MUTEX_UNLOCK(mylock); return 0; } libc_hidden_def(unsetenv) /* The `clearenv' was planned to be added to POSIX.1 but probably never made it. Nevertheless the POSIX.9 standard (POSIX bindings for Fortran 77) requires this function. */ int clearenv (void) { __UCLIBC_MUTEX_LOCK(mylock); if (__environ == last_environ && __environ != NULL) { /* We allocated this environment so we can free it. */ free (__environ); last_environ = NULL; } /* Clear the environment pointer removes the whole environment. */ __environ = NULL; __UCLIBC_MUTEX_UNLOCK(mylock); return 0; } /* Put STRING, which is of the form "NAME=VALUE", in the environment. */ int putenv (char *string) { int result; const char *const name_end = strchr (string, '='); if (name_end != NULL) { char *name = strndup(string, name_end - string); result = __add_to_environ (name, NULL, string, 1); free(name); return(result); } unsetenv (string); return 0; }