Files
QNX/lib/c/stdio/xgetstr.c
2025-08-20 19:02:58 +08:00

193 lines
4.3 KiB
C

/*
* $QNXtpLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
/* _Getstr function */
#include <ctype.h>
#include <string.h>
#include "xwchar.h"
#include "xstdio.h"
_STD_BEGIN
static int ranmatch(const char *s, int c, size_t n)
{ /* look for c in [] with ranges */
const unsigned char uc = (unsigned char)c;
const unsigned char *su = (const unsigned char *)s;
while (3 <= n)
if (su[1] == '-')
if (su[0] <= uc && uc <= su[2])
return (1);
else
su += 3, n -= 3;
else if (su[0] == uc)
return (1);
else
++su, --n;
for (; 0 < n; ++su, --n)
if (su[0] == uc)
return (1);
return (0);
}
int _Getstr(_Sft *px, int sfl)
{ /* convert %[] (sfl < 0), %c (sfl == 0), else %s */
char comp, *s = NULL;
char range = 0;
char seen = 0;
const char *pset, *t = NULL;
int ch, nset = 0;
int wfl = px->qual == 'l';
wchar_t *p = NULL;
_Mbstinit(mbst);
if (sfl < 0)
{ /* parse [] in format */
comp = (char)(*++px->s == '^' ? *px->s++ : '\0');
t = strchr(*px->s == ']' ? px->s + 1 : px->s, ']');
if (t == 0)
return (0);
nset = t - px->s;
pset = px->s;
px->s = t;
if (3 <= nset && memchr(pset + 1, '-', nset - 2))
range = 1;
}
px->nget = 0 < px->width ? px->width :
sfl != 0 ? INT_MAX : 1;
if (px->noconv)
;
else if (wfl)
p = va_arg(px->ap, wchar_t *);
else
s = va_arg(px->ap, char *);
{ /* deliver characters */
int nc = 0;
while ((ch = GETN(px)) != EOF)
if (0 < sfl && isspace(ch) || sfl < 0
&& (!range && (!comp && !memchr(pset, ch, nset)
|| comp && memchr(pset, ch, nset))
|| range && (!comp && !ranmatch(pset, ch, nset)
|| comp && ranmatch(pset, ch, nset))))
break;
else if (!wfl)
{ /* deliver a single byte */
if (px->noconv)
;
else if (px->prec == 0)
{ /* no room to store character, fail */
seen = 1;
break;
}
else
{ /* enough room, store and count char */
*s++ = (char)ch;
px->stored = 1;
--px->prec;
}
seen = 2;
}
else
{ /* build a wchar_t */
char buf[MB_LEN_MAX];
int n;
wchar_t wc;
buf[nc++] = (char)ch;
switch (n = _Mbtowc(&wc, buf, nc, &mbst))
{ /* try to build a wchar_t */
case -2:
seen |= 1; /* partial wchar_t */
if (nc < sizeof (buf))
break; /* try again with more chars */
case -1:
for (; 0 < nc; )
{ /* stop on conversion error */
int ch2 = buf[--nc];
UNGETN(px, ch2);
}
return (seen ? 0 : EOF);
case 0:
if (wc == L'\0') /* may be null wide char */
n = strlen(buf) + 1;
/* fall through */
default:
if (n == -3)
n = 0;
for (; n < nc; ) /* got a wchar_t, count and deliver */
{ /* return unused chars */
int ch3 = buf[--nc];
UNGETN(px, ch3);
}
if (px->noconv)
;
else if (px->prec == 0)
{ /* no room to store character, fail */
seen = 1;
break;
}
else
{ /* enough room, store and count char */
*p++ = wc;
px->stored = 1;
--px->prec;
}
--px->width;
seen = 2; /* whole wchar_t */
nc = 0;
}
}
}
UNGETN(px, ch);
if (sfl != 0 && seen == 2)
; /* store terminating nul */
else if (seen == 2)
return (1); /* success, delivered a character */
else if ((seen & 1) != 0 || ch == EOF)
return (EOF); /* conversion or input failure */
else
return (0); /* matching failure */
if (px->noconv)
;
else if (px->prec == 0)
return (0); /* no room to store nul, fail */
else if (wfl)
*p = L'\0';
else
*s = '\0';
return (1);
}
_STD_END
/*
* Copyright (c) 1992-2006 by P.J. Plauger. ALL RIGHTS RESERVED.
* Consult your license regarding permissions and restrictions.
V5.00:1296 */
__SRCVERSION("xgetstr.c $Rev: 153052 $");