1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
|
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
*
* Copyright (C) 1997 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*/
#include "adio.h"
/* style: allow:sprintf:3 sig:0 */
/*
* Below are the "safe" versions of the various string and printf
* operations. They are directly taken from MPICH, with MPIU replaced by ADIOI.
*/
/*
* ADIOI_Strncpy - Copy at most n character. Stop once a null is reached.
*
* This is different from strncpy, which null pads so that exactly
* n characters are copied. The strncpy behavior is correct for many
* applications because it guarantees that the string has no uninitialized
* data.
*
* If n characters are copied without reaching a null, return an error.
* Otherwise, return 0.
*
*/
/*@ ADIOI_Strncpy - Copy a string with a maximum length
Input Parameters:
+ instr - String to copy
- maxlen - Maximum total length of 'outstr'
Output Parameters:
. outstr - String to copy into
Notes:
This routine is the routine that you wish 'strncpy' was. In copying
'instr' to 'outstr', it stops when either the end of 'outstr' (the
null character) is seen or the maximum length 'maxlen' is reached.
Unlike 'strncpy', it does not add enough nulls to 'outstr' after
copying 'instr' in order to move precisely 'maxlen' characters.
Thus, this routine may be used anywhere 'strcpy' is used, without any
performance cost related to large values of 'maxlen'.
Module:
Utility
@*/
int ADIOI_Strncpy( char *dest, const char *src, size_t n )
{
char * restrict d_ptr = dest;
const char * restrict s_ptr = src;
register int i;
i = (int)n;
while (*s_ptr && i-- > 0) {
*d_ptr++ = *s_ptr++;
}
if (i > 0) {
*d_ptr = 0;
return 0;
}
else
/* We may want to force an error message here, at least in the
debugging version */
return 1;
}
/* Append src to dest, but only allow dest to contain n characters (including
any null, which is always added to the end of the line */
/*@ ADIOI_Strnapp - Append to a string with a maximum length
Input Parameters:
+ instr - String to copy
- maxlen - Maximum total length of 'outstr'
Output Parameters:
. outstr - String to copy into
Notes:
This routine is similar to 'strncat' except that the 'maxlen' argument
is the maximum total length of 'outstr', rather than the maximum
number of characters to move from 'instr'. Thus, this routine is
easier to use when the declared size of 'instr' is known.
Module:
Utility
@*/
int ADIOI_Strnapp( char *dest, const char *src, size_t n )
{
char * restrict d_ptr = dest;
const char * restrict s_ptr = src;
register int i;
/* Get to the end of dest */
i = (int)n;
while (i-- > 0 && *d_ptr) d_ptr++;
if (i <= 0) return 1;
/* Append. d_ptr points at first null and i is remaining space. */
while (*s_ptr && i-- > 0) {
*d_ptr++ = *s_ptr++;
}
/* We allow i >= (not just >) here because the first while decrements
i by one more than there are characters, leaving room for the null */
if (i >= 0) {
*d_ptr = 0;
return 0;
}
else {
/* Force the null at the end */
*--d_ptr = 0;
/* We may want to force an error message here, at least in the
debugging version */
return 1;
}
}
/*@
ADIOI_Strdup - Duplicate a string
Synopsis:
.vb
char *ADIOI_Strdup( const char *str )
.ve
Input Parameters:
. str - null-terminated string to duplicate
Return value:
A pointer to a copy of the string, including the terminating null. A
null pointer is returned on error, such as out-of-memory.
Notes:
Like 'ADIOI_Malloc' and 'ADIOI_Free', this will often be implemented as a
macro but may use 'ADIOI_trstrdup' to provide a tracing version.
Module:
Utility
@*/
char *ADIOI_Strdup( const char *str )
{
char *p = ADIOI_Malloc( strlen(str) + 1 );
char *in_p = (char *)str;
char *save_p;
save_p = p;
if (p) {
while (*in_p) {
*p++ = *in_p++;
}
*p = '\0';
}
return save_p;
}
/*
* We need an snprintf replacement for systems without one
*/
#ifndef HAVE_SNPRINTF
#include <ctype.h>
/* FIXME: Really need a check for varargs.h vs stdarg.h */
#include <stdarg.h>
/*
* This is an approximate form which is suitable for most uses within
* the MPICH code
*/
int ADIOI_Snprintf( char *str, size_t size, const char *format, ... )
{
int n;
const char *p;
char *out_str = str;
va_list list;
va_start(list, format);
p = format;
while (*p && size > 0) {
char *nf;
nf = strchr(p, '%');
if (!nf) {
/* No more format characters */
while (size-- > 0 && *p) {
*out_str++ = *p++;
}
}
else {
int nc;
int width = -1;
/* Copy until nf */
while (p < nf && size-- > 0) {
*out_str++ = *p++;
}
/* p now points at nf */
/* Handle the format character */
nc = nf[1];
if (isdigit(nc)) {
/* Get the field width */
/* FIXME : Assumes ASCII */
width = nc - '0';
p = nf + 2;
while (*p && isdigit(*p)) {
width = 10 * width + (*p++ - '0');
}
/* When there is no longer a digit, get the format
character */
nc = *p++;
}
else {
/* Skip over the format string */
p += 2;
}
switch (nc) {
case '%':
*out_str++ = '%';
size--;
break;
case 'd':
{
int val;
char tmp[20];
char *t = tmp;
/* Get the argument, of integer type */
val = va_arg( list, int );
sprintf( tmp, "%d", val );
if (width > 0) {
int tmplen = strlen(tmp);
/* If a width was specified, pad with spaces on the
left (on the right if %-3d given; not implemented yet */
while (size-- > 0 && width-- > tmplen)
*out_str++ = ' ';
}
while (size-- > 0 && *t) {
*out_str++ = *t++;
}
}
break;
case 'x':
{
int val;
char tmp[20];
char *t = tmp;
/* Get the argument, of integer type */
val = va_arg( list, int );
sprintf( tmp, "%x", val );
if (width > 0) {
int tmplen = strlen(tmp);
/* If a width was specified, pad with spaces on the
left (on the right if %-3d given; not implemented yet */
while (size-- > 0 && width-- > tmplen)
*out_str++ = ' ';
}
while (size-- > 0 && *t) {
*out_str++ = *t++;
}
}
break;
case 'p':
{
void *val;
char tmp[20];
char *t = tmp;
val = va_arg( list, void * );
sprintf( tmp, "%p", val );
if (width > 0) {
int tmplen = strlen(tmp);
/* If a width was specified, pad with spaces on the
left (on the right if %-3d given; not implemented yet */
while (size-- > 0 && width-- > tmplen)
*out_str++ = ' ';
}
while (size-- > 0 && *t) {
*out_str++ = *t++;
}
}
break;
case 's':
{
char *s_arg;
/* Get the argument, of pointer to char type */
s_arg = va_arg( list, char * );
while (size-- > 0 && s_arg && *s_arg) {
*out_str++ = *s_arg++;
}
}
break;
default:
/* Error, unknown case */
return -1;
break;
}
}
}
va_end(list);
if (size-- > 0) *out_str++ = '\0';
n = (int)(out_str - str);
return n;
}
#endif
|