Merge remote-tracking branch 'origin/master' into wchar - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
(DIR) commit 3b42911841f616a37e3fa7bd5f4ad7177ce959cf
(DIR) parent b96ef460770e7d0bf335cbadbed7efd2db08199e
(HTM) Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 25 Mar 2025 10:52:47 +0100
Merge remote-tracking branch 'origin/master' into wchar
Diffstat:
M include/bits/darwin/sys/cdefs.h | 10 +---------
M include/bits/dragonfly/sys/cdefs.h | 9 +--------
M include/bits/freebsd/sys/cdefs.h | 9 +--------
M include/bits/linux/sys/cdefs.h | 9 +--------
M include/bits/netbsd/sys/cdefs.h | 9 +--------
M include/bits/openbsd/sys/cdefs.h | 9 +--------
M include/stdlib.h | 2 --
M include/wchar.h | 30 +++++++++++++++++++-----------
M src/cmd/scc-make/rules.c | 13 +++++++++----
M src/libc/arch/bsd/Makefile | 4 +---
D src/libc/arch/bsd/_mbsget.c | 9 ---------
D src/libc/arch/bsd/_mbsset.c | 9 ---------
M src/libc/arch/darwin/Makefile | 2 --
D src/libc/arch/darwin/_mbsget.c | 9 ---------
D src/libc/arch/darwin/_mbsset.c | 10 ----------
M src/libc/arch/linux/Makefile | 2 --
D src/libc/arch/linux/_mbsget.c | 9 ---------
D src/libc/arch/linux/_mbsset.c | 9 ---------
M src/libc/libc.h | 7 ++-----
M src/libc/objs/amd64-linux.mk | 2 --
M src/libc/objs/amd64-netbsd.mk | 2 --
M src/libc/objs/amd64-openbsd.mk | 2 --
M src/libc/objs/common-objs.mk | 4 ++++
M src/libc/stdlib/mblen.c | 9 ++++++++-
M src/libc/stdlib/mbstowcs.c | 4 +++-
M src/libc/stdlib/mbtowc.c | 10 +++++++++-
M src/libc/stdlib/wcstombs.c | 4 +++-
M src/libc/stdlib/wctomb.c | 4 +++-
M src/libc/string/strcmp.c | 2 +-
M src/libc/wchar/_validutf8.c | 2 +-
M src/libc/wchar/mbrlen.c | 4 ++++
M src/libc/wchar/mbrtowc.c | 92 +++++++++++++++++++++++--------
M src/libc/wchar/mbsinit.c | 4 +---
M src/libc/wchar/mbsrtowcs.c | 26 +++++++++++++++++++++-----
A src/libc/wchar/wcscmp.c | 15 +++++++++++++++
A src/libc/wchar/wcscoll.c | 9 +++++++++
A src/libc/wchar/wcscpy.c | 16 ++++++++++++++++
A src/libc/wchar/wcsncmp.c | 18 ++++++++++++++++++
M tests/libc/execute/.gitignore | 10 ++++++++++
A tests/libc/execute/0038-mbsinit.c | 29 +++++++++++++++++++++++++++++
A tests/libc/execute/0039-mbrtowc.c | 84 +++++++++++++++++++++++++++++++
A tests/libc/execute/0040-wcrtomb.c | 102 +++++++++++++++++++++++++++++++
A tests/libc/execute/0041-mbrlen.c | 75 +++++++++++++++++++++++++++++++
A tests/libc/execute/0042-mbsrtowcs.c | 126 +++++++++++++++++++++++++++++++
A tests/libc/execute/0044-wcslen.c | 28 ++++++++++++++++++++++++++++
A tests/libc/execute/0045-wcscmp.c | 36 +++++++++++++++++++++++++++++++
A tests/libc/execute/0046-wcsncmp.c | 30 ++++++++++++++++++++++++++++++
A tests/libc/execute/0047-wcscoll.c | 36 +++++++++++++++++++++++++++++++
A tests/libc/execute/0048-wcscpy.c | 32 +++++++++++++++++++++++++++++++
M tests/libc/execute/libc-tests.lst | 10 ++++++++++
A tests/libc/execute/mbtest.h | 44 +++++++++++++++++++++++++++++++
A tests/make/execute/0107-inference.… | 31 +++++++++++++++++++++++++++++++
52 files changed, 895 insertions(+), 177 deletions(-)
---
(DIR) diff --git a/include/bits/darwin/sys/cdefs.h b/include/bits/darwin/sys/cdefs.h
@@ -1,9 +1 @@
-#ifdef _NEED_MBSTATE_T
-#ifndef _MBSTATE_T
-typedef struct {
- unsigned char state[4];
- size_t count;
-} mbstate_t;
-#define _MBSTATE_T
-#endif
-#endif
+/* nothing fpr darwin */
(DIR) diff --git a/include/bits/dragonfly/sys/cdefs.h b/include/bits/dragonfly/sys/cdefs.h
@@ -1,8 +1 @@
-#ifdef _NEED_MBSTATE_T
-#ifndef _MBSTATE_T
-typedef union {
- char __mbstate8[128];
-} mbstate_t;
-#define _MBSTATE_T
-#endif
-#endif
+/* nothing for dragonfly */
(DIR) diff --git a/include/bits/freebsd/sys/cdefs.h b/include/bits/freebsd/sys/cdefs.h
@@ -1,8 +1 @@
-#ifdef _NEED_MBSTATE_T
-#ifndef _MBSTATE_T
-typedef union {
- char __mbstate8[128];
-} mbstate_t;
-#define _MBSTATE_T
-#endif
-#endif
+/* nothing for Openbsd */
(DIR) diff --git a/include/bits/linux/sys/cdefs.h b/include/bits/linux/sys/cdefs.h
@@ -1,8 +1 @@
-#ifdef _NEED_MBSTATE_T
-#ifndef _MBSTATE_T
-typedef struct __mbstate_t {
- unsigned __opaque1, __opaque2;
-} mbstate_t;
-#define _MBSTATE_T
-#endif
-#endif
+/* nothing for Linux */
(DIR) diff --git a/include/bits/netbsd/sys/cdefs.h b/include/bits/netbsd/sys/cdefs.h
@@ -1,8 +1 @@
-#ifdef _NEED_MBSTATE_T
-#ifndef _MBSTATE_T
-typedef union {
- char __mbstate8[128];
-} mbstate_t;
-#define _MBSTATE_T
-#endif
-#endif
+/* nothing for netbsd */
(DIR) diff --git a/include/bits/openbsd/sys/cdefs.h b/include/bits/openbsd/sys/cdefs.h
@@ -1,8 +1 @@
-#ifdef _NEED_MBSTATE_T
-#ifndef _MBSTATE_T
-typedef union {
- char __mbstate8[128];
-} mbstate_t;
-#define _MBSTATE_T
-#endif
-#endif
+/* nothing for Openbsd */
(DIR) diff --git a/include/stdlib.h b/include/stdlib.h
@@ -66,6 +66,4 @@ extern int wctomb(char *, wchar_t);
extern size_t mbstowcs(wchar_t *restrict, const char *restrict, size_t);
extern size_t wcstombs(char *restrict, const wchar_t *restrict, size_t);
-#define mblen(s,n) mbtowc(NULL, s, n)
-
#endif
(DIR) diff --git a/include/wchar.h b/include/wchar.h
@@ -8,10 +8,15 @@
#define _NEED_WCHARLIM
#define _NEED_WINT
#define _NEED_VA_LIST
-#define _NEED_MBSTATE_T
#include <arch/cdefs.h>
#include <sys/cdefs.h>
+typedef struct {
+ unsigned char oc;
+ unsigned char sh;
+ wchar_t wc;
+} mbstate_t;
+
struct tm;
struct _FILE;
@@ -30,8 +35,11 @@ extern wint_t fgetwc(struct _FILE *);
extern wint_t fputwc(wchar_t c, struct _FILE *);
extern wint_t getwc(struct _FILE *);
extern wint_t putwc(wchar_t, struct _FILE *);
-extern int fwide(struct _FILE *, int);
+extern wint_t getwchar(void);
+extern wint_t putwchar(wchar_t);
extern wint_t ungetwc(wint_t, struct _FILE *);
+
+extern int fwide(struct _FILE *, int);
extern wchar_t *fgetws(wchar_t *restrict, int, struct _FILE *restrict);
extern int fputws(const wchar_t *restrict, struct _FILE *restrict);
@@ -40,9 +48,6 @@ extern int swscanf(const wchar_t *restrict, const wchar_t *restrict, ...);
extern int wprintf(const wchar_t *restrict, ...);
extern int wscanf(const wchar_t *restrict, ...);
-extern wint_t getwchar(void);
-extern wint_t putwchar(wchar_t);
-
extern double wcstod(const wchar_t *restrict, wchar_t **restrict);
extern float wcstof(const wchar_t *restrict, wchar_t **restrict);
extern long double wcstold(const wchar_t *restrict, wchar_t **restrict);
@@ -57,13 +62,17 @@ extern wchar_t *wcsncpy(wchar_t *restrict, const wchar_t *restrict, size_t);
extern wchar_t *wmemcpy(wchar_t *restrict, const wchar_t *restrict, size_t);
extern wchar_t *wmemmove(wchar_t *, const wchar_t *, size_t);
+extern wchar_t *wmemset(wchar_t *, wchar_t, size_t);
+extern wchar_t *wmemchr(const wchar_t *, wchar_t, size_t);
+extern int wmemcmp(const wchar_t *, const wchar_t *, size_t);
+
+extern size_t wcslen(const wchar_t *);
+extern int wcscmp(const wchar_t *, const wchar_t *);
extern wchar_t *wcscat(wchar_t *restrict, const wchar_t *restrict);
extern wchar_t *wcsncat(wchar_t *restrict, const wchar_t *restrict, size_t);
-extern int wcscmp(const wchar_t *, const wchar_t *);
extern int wcscoll(const wchar_t *, const wchar_t *);
extern int wcsncmp(const wchar_t *, const wchar_t *, size_t);
extern size_t wcsxfrm(wchar_t *restrict, const wchar_t *restrict, size_t);
-extern int wmemcmp(const wchar_t *, const wchar_t *, size_t);
extern wchar_t *wcschr(const wchar_t *, wchar_t);
extern size_t wcscspn(const wchar_t *, const wchar_t *);
extern wchar_t *wcspbrk(const wchar_t *, const wchar_t *);
@@ -71,12 +80,11 @@ extern wchar_t *wcsrchr(const wchar_t *, wchar_t);
extern size_t wcsspn(const wchar_t *, const wchar_t *);
extern wchar_t *wcsstr(const wchar_t *, const wchar_t *);
extern wchar_t *wcstok(wchar_t *restrict, const wchar_t *restrict, wchar_t **restrict);
-extern wchar_t *wmemchr(const wchar_t *, wchar_t, size_t);
-extern size_t wcslen(const wchar_t *);
-extern wchar_t *wmemset(wchar_t *, wchar_t, size_t);
+
extern size_t wcsftime(wchar_t *restrict, size_t, const wchar_t *restrict, const struct tm *restrict);
extern wint_t btowc(int);
extern int wctob(wint_t);
+
extern int mbsinit(const mbstate_t *);
extern size_t mbrlen(const char *restrict, size_t, mbstate_t *restrict);
extern size_t mbrtowc(wchar_t *restrict, const char *restrict, size_t, mbstate_t *restrict);
@@ -85,7 +93,7 @@ extern size_t mbsrtowcs(wchar_t *restrict, const char **restrict, size_t, mbstat
extern size_t wcsrtombs(char *restrict, const wchar_t **restrict, size_t, mbstate_t *restrict);
extern int wcwidth(wchar_t);
-#define mbrlen(s, n, ps) mbrtowc(NULL, s, n, ps)
#define putwc(wc, fp) fputwc(wc, fp)
+#define getwc(fp) fgetwc(fp)
#endif
(DIR) diff --git a/src/cmd/scc-make/rules.c b/src/cmd/scc-make/rules.c
@@ -506,7 +506,7 @@ rebuild(Target *tp, int *buildp)
q = *p;
debug("checking dependency %s", q->name);
- if (q->actions)
+ if (strcmp(q->name, tp->name) == 0 && q->actions)
def = 1;
build = 0;
@@ -526,10 +526,14 @@ rebuild(Target *tp, int *buildp)
}
}
- if (tp->stamp == -1)
- need = 1;
- else if (!def && inference(tp, NOFORCE))
+ if (tp->stamp == -1) {
need = 1;
+ } else if (!def) {
+ debug("no action found for %s, looking a inference rule",
+ tp->name);
+ if (inference(tp, NOFORCE))
+ need = 1;
+ }
if (err) {
warning("target %s not remade because of errors", tp->name);
@@ -537,6 +541,7 @@ rebuild(Target *tp, int *buildp)
} else if (need) {
*buildp = 1;
+ debug("target %s needs updating", tp->name);
r = update(tp);
if (r == 0)
return 0;
(DIR) diff --git a/src/libc/arch/bsd/Makefile b/src/libc/arch/bsd/Makefile
@@ -4,8 +4,6 @@ include $(PROJECTDIR)/scripts/rules.mk
include ../../rules.mk
OBJS=\
- _mbsget.$O\
- _mbsset.$O\
- _waitpid.$O\
+ _waitpid.$O\
all: $(OBJS)
(DIR) diff --git a/src/libc/arch/bsd/_mbsget.c b/src/libc/arch/bsd/_mbsget.c
@@ -1,9 +0,0 @@
-#include <wchar.h>
-
-#include "../../libc.h"
-
-int
-_mbsget(mbstate_t *ps)
-{
- return ps->__mbstate8[0];
-}
(DIR) diff --git a/src/libc/arch/bsd/_mbsset.c b/src/libc/arch/bsd/_mbsset.c
@@ -1,9 +0,0 @@
-#include <wchar.h>
-
-#include "../../libc.h"
-
-int
-_mbsset(mbstate_t *ps, int ch)
-{
- return ps->__mbstate8[0] = ch;
-}
(DIR) diff --git a/src/libc/arch/darwin/Makefile b/src/libc/arch/darwin/Makefile
@@ -5,7 +5,5 @@ include ../../rules.mk
OBJS=\
_getheap.$O\
- _mbsget.$O\
- _mbsset.$O\
all: $(OBJS)
(DIR) diff --git a/src/libc/arch/darwin/_mbsget.c b/src/libc/arch/darwin/_mbsget.c
@@ -1,9 +0,0 @@
-#include <wchar.h>
-
-#include "../../libc.h"
-
-int
-_mbsget(mbstate_t *ps)
-{
- return ps->state[0];
-}
(DIR) diff --git a/src/libc/arch/darwin/_mbsset.c b/src/libc/arch/darwin/_mbsset.c
@@ -1,10 +0,0 @@
-#include <wchar.h>
-
-#include "../../libc.h"
-
-int
-_mbsset(mbstate_t *ps, int ch)
-{
- ps-count = 1;
- return ps->state[0] = ch;
-}
(DIR) diff --git a/src/libc/arch/linux/Makefile b/src/libc/arch/linux/Makefile
@@ -6,8 +6,6 @@ include ../../rules.mk
OBJS=\
_brk.$O\
_getheap.$O\
- _mbsget.$O\
- _mbsset.$O\
_sigaction.$O\
_waitpid.$O\
(DIR) diff --git a/src/libc/arch/linux/_mbsget.c b/src/libc/arch/linux/_mbsget.c
@@ -1,9 +0,0 @@
-#include <wchar.h>
-
-#include "../../libc.h"
-
-int
-_mbsget(mbstate_t *ps)
-{
- return ps->__opaque1;
-}
(DIR) diff --git a/src/libc/arch/linux/_mbsset.c b/src/libc/arch/linux/_mbsset.c
@@ -1,9 +0,0 @@
-#include <wchar.h>
-
-#include "../../libc.h"
-
-int
-_mbsset(mbstate_t *ps, int ch)
-{
- return ps->__opaque1 = ch;
-}
(DIR) diff --git a/src/libc/libc.h b/src/libc/libc.h
@@ -20,6 +20,7 @@ enum {
#define SECDAY (24 * SECHOUR) /* 86400 */
struct tm;
+struct _FILE;
struct tzone {
char *name;
@@ -61,9 +62,5 @@ extern void (*_atexithdl)(void);
#ifdef _WCHAR_H
extern int _validutf8(wchar_t, int *);
-extern int _mbsset(mbstate_t *, int);
-extern int _mbsget(mbstate_t *);
-#ifdef _STDIO_H
-extern wint_t _fputwc(wchar_t, FILE *, int *);
-#endif
+extern wint_t _fputwc(wchar_t, struct _FILE *, int *);
#endif
(DIR) diff --git a/src/libc/objs/amd64-linux.mk b/src/libc/objs/amd64-linux.mk
@@ -36,8 +36,6 @@ OBJS =\
arch/amd64/strcpy.$O\
arch/linux/_brk.$O\
arch/linux/_getheap.$O\
- arch/linux/_mbsget.$O\
- arch/linux/_mbsset.$O\
arch/linux/_sigaction.$O\
arch/linux/_waitpid.$O\
arch/posix/_open.$O\
(DIR) diff --git a/src/libc/objs/amd64-netbsd.mk b/src/libc/objs/amd64-netbsd.mk
@@ -28,8 +28,6 @@ OBJS =\
arch/amd64/strcmp.$O\
arch/amd64/strcpy.$O\
arch/bsd/_waitpid.$O\
- arch/bsd/_mbsget.$O\
- arch/bsd/_mbsset.$O\
arch/netbsd/_sigaction.$O\
arch/posix/_getheap.$O\
arch/posix/_open.$O\
(DIR) diff --git a/src/libc/objs/amd64-openbsd.mk b/src/libc/objs/amd64-openbsd.mk
@@ -33,8 +33,6 @@ OBJS =\
arch/amd64/strcmp.$O\
arch/amd64/strcpy.$O\
arch/bsd/_waitpid.$O\
- arch/bsd/_mbsget.$O\
- arch/bsd/_mbsset.$O\
arch/posix/_getheap.$O\
arch/posix/_open.$O\
arch/posix/_systime.$O\
(DIR) diff --git a/src/libc/objs/common-objs.mk b/src/libc/objs/common-objs.mk
@@ -127,6 +127,10 @@ COMMON_OBJS =\
wchar/mbsrtowcs.$O\
wchar/wcrtomb.$O\
wchar/wcslen.$O\
+ wchar/wcscmp.$O\
+ wchar/wcscoll.$O\
+ wchar/wcsncmp.$O\
+ wchar/wcscpy.$O\
wchar/wcsrtombs.$O\
wchar/wcwidth.$O\
wchar/putwc.$O\
(DIR) diff --git a/src/libc/stdlib/mblen.c b/src/libc/stdlib/mblen.c
@@ -1,9 +1,16 @@
#include <stdlib.h>
+#include <wchar.h>
#undef mblen
int
mblen(const char *s, size_t n)
{
- return mbtowc(NULL, s, n);
+ int ret;
+ static mbstate_t st;
+
+ ret = mbrtowc(NULL, s, n, &st);
+ if (ret < 0)
+ ret = -1;
+ return ret;
}
(DIR) diff --git a/src/libc/stdlib/mbstowcs.c b/src/libc/stdlib/mbstowcs.c
@@ -7,5 +7,7 @@
size_t
mbstowcs(wchar_t *restrict dest, const char *restrict src, size_t n)
{
- return mbsrtowcs(dest, (void *) &src, n, NULL);
+ static mbstate_t st;
+
+ return mbsrtowcs(dest, (void *) &src, n, &st);
}
(DIR) diff --git a/src/libc/stdlib/mbtowc.c b/src/libc/stdlib/mbtowc.c
@@ -1,4 +1,5 @@
#include <stdlib.h>
+#include <string.h>
#include <wchar.h>
#undef mbtowc
@@ -6,5 +7,12 @@
int
mbtowc(wchar_t *restrict pwc, const char *restrict s, size_t n)
{
- return mbrtowc(pwc, s, n, NULL);
+ static mbstate_t st;
+ int ret;
+
+ ret = mbrtowc(pwc, s, n, &st);
+ if (ret < 0)
+ ret = -1;
+
+ return ret;
}
(DIR) diff --git a/src/libc/stdlib/wcstombs.c b/src/libc/stdlib/wcstombs.c
@@ -6,5 +6,7 @@
size_t
wcstombs(char *restrict dest, const wchar_t *restrict src, size_t n)
{
- return wcsrtombs(dest, (void *) &src, n, NULL);
+ static mbstate_t st;
+
+ return wcsrtombs(dest, (void *) &src, n, &st);
}
(DIR) diff --git a/src/libc/stdlib/wctomb.c b/src/libc/stdlib/wctomb.c
@@ -6,5 +6,7 @@
int
wctomb(char *s, wchar_t wc)
{
- return wcrtomb(s, wc, NULL);
+ static mbstate_t st;
+
+ return wcrtomb(s, wc, &st);
}
(DIR) diff --git a/src/libc/string/strcmp.c b/src/libc/string/strcmp.c
@@ -5,7 +5,7 @@
int
strcmp(const char *s1, const char *s2)
{
- while (*s1 && *s2 && *s1 == *s2)
+ while (*s1 && *s1 == *s2)
++s1, ++s2;
return *(unsigned char *) s1 - *(unsigned char *) s2;
}
(DIR) diff --git a/src/libc/wchar/_validutf8.c b/src/libc/wchar/_validutf8.c
@@ -19,7 +19,7 @@ _validutf8(wchar_t wc, int *nbytes)
{0xD800, 0xDD00, 0, 3},
{0xDD00, 0x10000, 1, 3},
{0x10000, 0x110000, 1, 4},
- {0x11000, -1ul, 0, 0},
+ {0x110000, -1ul, 0, 0},
};
struct range *bp;
(DIR) diff --git a/src/libc/wchar/mbrlen.c b/src/libc/wchar/mbrlen.c
@@ -5,5 +5,9 @@
size_t
mbrlen(const char *restrict s, size_t n, mbstate_t *restrict ps)
{
+ static mbstate_t st;
+
+ if (!ps)
+ ps = &st;
return mbrtowc(NULL, s, n, ps);
}
(DIR) diff --git a/src/libc/wchar/mbrtowc.c b/src/libc/wchar/mbrtowc.c
@@ -1,5 +1,6 @@
#include <errno.h>
#include <stdlib.h>
+#include <string.h>
#include <wchar.h>
#include "../libc.h"
@@ -10,43 +11,88 @@ size_t
mbrtowc(wchar_t *restrict pwc, const char *restrict s, size_t n,
mbstate_t *restrict ps)
{
+ static mbstate_t state;
const unsigned char *t = (const unsigned char *) s;
+ wchar_t dummy;
unsigned long wc;
- unsigned c;
- int i, len, maxlen;
-
- if (t == NULL)
- return 0;
- if ((wc = *t) == 0)
- goto return_code;
-
- c = *t++;
- for (len = 0; n > 0 && c & 0x80; --n, ++len)
- c <<= 1;
- if (n == 0 && c & 0x80)
+ unsigned c, oc;
+ int sh, max;
+
+ if (!ps)
+ ps = &state;
+
+ if (t == NULL) {
+ if (ps->sh != 0)
+ goto return_error;
+ pwc = &dummy;
+ goto return_code_set;
+ }
+ if (n == 0)
return -2;
- if (len == 1 || len > MB_CUR_MAX)
- goto return_error;
- if (len == 0)
- goto return_code;
-
- wc = (c & 0xFF) >> len;
- for (i = 0; i < len-1; i++) {
- if (((c = *t++) & 0xC0) != 0x80)
+
+ oc = ps->oc;
+ wc = ps->wc;
+ sh = ps->sh;
+
+ /* initial state? */
+ if (sh == 0) {
+ /* NUL character? */
+ if ((c = wc = *t) == 0)
+ goto return_code;
+ t++;
+ n--;
+
+ /* fast track for ascii? */
+ if (c < 0x80)
+ goto return_code;
+
+ /* out of sequence multibyte? */
+ if ((c & 0xc0) != 0xc0)
goto return_error;
+
+ /* in sequence multibyte! */
+ oc = c << 1;
+ wc = 0;
+ sh = 1;
+ }
+
+ for ( ; n > 0; --n) {
+ if (sh > MB_CUR_MAX)
+ goto return_error;
+
+ c = *t++;
+ if ((c & 0xc0) != 0x80)
+ goto return_error;
+
wc <<= 6;
- wc |= c & 0x3F;
+ wc |= c & 0x3f;
+ oc <<= 1;
+ sh++;
+
+ if ((oc & 0x80) == 0) {
+ oc = (oc & 0xff) >> sh;
+ wc |= oc << (sh-1) * 6;
+
+ if (!_validutf8(wc, &max) || sh != max)
+ goto return_error;
+ goto return_code_set;
+ }
}
- if (!_validutf8(wc, &maxlen) || len != maxlen)
- goto return_error;
+ ps->sh = sh;
+ ps->oc = oc;
+ ps->wc = wc;
+ return -2;
+return_code_set:
+ memset(ps, 0, sizeof(*ps));
return_code:
if (pwc)
*pwc = wc;
return t - (unsigned char *) s;
return_error:
+ memset(ps, 0, sizeof(*ps));
errno = EILSEQ;
return -1;
}
(DIR) diff --git a/src/libc/wchar/mbsinit.c b/src/libc/wchar/mbsinit.c
@@ -1,7 +1,5 @@
#include <wchar.h>
-#include "../libc.h"
-
#undef mbsinit
int
@@ -9,5 +7,5 @@ mbsinit(const mbstate_t *ps)
{
if (!ps)
return 1;
- return _mbsget(ps) == 0;
+ return ps->oc == 0;
}
(DIR) diff --git a/src/libc/wchar/mbsrtowcs.c b/src/libc/wchar/mbsrtowcs.c
@@ -1,4 +1,5 @@
#include <limits.h>
+#include <string.h>
#include <wchar.h>
#undef mbsrtowcs
@@ -8,24 +9,39 @@ mbsrtowcs(wchar_t *restrict dest, const char **restrict src, size_t len,
mbstate_t *restrict ps)
{
wchar_t wc;
+ const char *s = *src;
size_t cnt, n;
+ static mbstate_t st;
+
+ if (!ps)
+ ps = &st;
for (n = 0; ; n++) {
- cnt = mbrtowc(&wc, *src, MB_LEN_MAX, ps);
+ cnt = mbrtowc(&wc, s, MB_LEN_MAX, ps);
+ if (cnt == (size_t) -2) {
+ s += MB_LEN_MAX;
+ continue;
+ }
if (cnt == (size_t) -1)
return -1;
if (dest) {
- if (n == len)
+ if (n == len) {
+ *src = s;
return n;
+ }
*dest++ = wc;
}
- *src += cnt;
+ s += cnt;
- if (wc == L'\0')
+ if (wc == 0)
break;
}
- *src = NULL;
+
+ if (dest) {
+ memset(ps, 0, sizeof(mbstate_t));
+ *src = NULL;
+ }
return n;
}
(DIR) diff --git a/src/libc/wchar/wcscmp.c b/src/libc/wchar/wcscmp.c
@@ -0,0 +1,15 @@
+#include <wchar.h>
+
+#undef wcscmp
+
+int
+wcscmp(const wchar_t *s1, const wchar_t *s2)
+{
+ unsigned long l1, l2;
+
+ while (*s1 && *s1 == *s2)
+ ++s1, ++s2;
+ l1 = *s1, l2 = *s2;
+
+ return l1 - l2;
+}
(DIR) diff --git a/src/libc/wchar/wcscoll.c b/src/libc/wchar/wcscoll.c
@@ -0,0 +1,9 @@
+#include <wchar.h>
+
+#undef wcscoll
+
+int
+wcscoll(const wchar_t *s1, const wchar_t *s2)
+{
+ return wcscmp(s1, s2);
+}
(DIR) diff --git a/src/libc/wchar/wcscpy.c b/src/libc/wchar/wcscpy.c
@@ -0,0 +1,16 @@
+#include <wchar.h>
+
+#undef wcscpy
+
+wchar_t *
+wcscpy(wchar_t * restrict s1, const wchar_t * restrict s2)
+{
+ wchar_t *ret = s1;
+
+ while ((*s1++ = *s2++) != '\0')
+ ;
+
+ return ret;
+
+}
+
(DIR) diff --git a/src/libc/wchar/wcsncmp.c b/src/libc/wchar/wcsncmp.c
@@ -0,0 +1,18 @@
+#include <wchar.h>
+
+#undef wcsncmp
+
+int
+wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n)
+{
+ unsigned long l1, l2;
+
+ for ( ; n > 0 && *s1 == *s2; --n)
+ ++s1, ++s2;
+
+ if (n == 0)
+ return 0;
+ l1 = *s1, l2 = *s2;
+
+ return l1 - l2;
+}
(DIR) diff --git a/tests/libc/execute/.gitignore b/tests/libc/execute/.gitignore
@@ -35,4 +35,14 @@
0035-setlocale
0036-localeconv
0037-malloc
+0038-mbsinit
+0039-mbrtowc
+0040-wcrtomb
+0041-mbrlen
+0042-mbsrtowcs
+0044-wcslen
+0045-wcscmp
+0046-wcsncmp
+0047-wcscoll
+0048-wcscpy
test.log
(DIR) diff --git a/tests/libc/execute/0038-mbsinit.c b/tests/libc/execute/0038-mbsinit.c
@@ -0,0 +1,29 @@
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+
+/*
+output:
+testing
+done
+end:
+*/
+
+void
+tests_mbsinit(void)
+{
+ mbstate_t s;
+
+ assert(mbsinit(NULL) != 0);
+ assert(mbsinit(memset(&s, 0, sizeof(s))) != 0);
+}
+
+int
+main()
+{
+ puts("testing");
+ tests_mbsinit();
+ puts("done");
+ return 0;
+}
(DIR) diff --git a/tests/libc/execute/0039-mbrtowc.c b/tests/libc/execute/0039-mbrtowc.c
@@ -0,0 +1,84 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "mbtest.h"
+
+/*
+output:
+testing
+testing mbrtowc1
+testing mbrtowc2
+testing mbtowc
+done
+end:
+*/
+
+#define NELEM(x) (sizeof(x)/sizeof(x[0]))
+
+void
+tests_mbrtowc(void)
+{
+ struct mbtest *tp;
+ int r;
+ mbstate_t s;
+
+ puts("testing mbrtowc1");
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ wc = -1;
+ errno = 0;
+ r = mbrtowc(tp->pwc, tp->s, tp->l, NULL);
+ assert(tp->r == r);
+ assert(tp->syserr == errno);
+ if (tp->r != -1)
+ assert(tp->wc == wc);
+ }
+
+ puts("testing mbrtowc2");
+ memset(&s, 0, sizeof(s));
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ wc = -1;
+ errno = 0;
+ r = mbrtowc(tp->pwc, tp->s, tp->l, &s);
+ assert(tp->r == r);
+ assert(tp->syserr == errno);
+ if (tp->r != -1)
+ assert(tp->wc == wc);
+ assert(mbsinit(&s) != 0 == tp->mbstate);
+ }
+}
+
+void
+tests_mbtowc(void)
+{
+ struct mbtest *tp;
+ int r, rt;
+
+ puts("testing mbtowc");
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ wc = -1;
+ errno = 0;
+ r = mbtowc(tp->pwc, tp->s, tp->l);
+ assert(tp->syserr == errno);
+ if (tp->r >= 0) {
+ rt = tp->r;
+ assert(tp->wc == wc);
+ } else {
+ rt = -1;
+ }
+ assert(rt == r);
+ }
+}
+
+int
+main()
+{
+ puts("testing");
+ tests_mbrtowc();
+ tests_mbtowc();
+ puts("done");
+ return 0;
+}
(DIR) diff --git a/tests/libc/execute/0040-wcrtomb.c b/tests/libc/execute/0040-wcrtomb.c
@@ -0,0 +1,102 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+/*
+output:
+testing
+testing wcrtomb1
+testing wcrtomb2
+testing wctomb
+done
+end:
+*/
+
+#define NELEM(x) (sizeof(x)/sizeof(x[0]))
+
+static char str[MB_CUR_MAX+1];
+
+static struct wctest {
+ wchar_t wc;
+ char *s;
+ char exp[MB_CUR_MAX+1];
+ int r;
+ int syserr;
+ int mbstate;
+} tests[] = {
+ {0, NULL, "", 1, 0, 1},
+ {0, str, "\0", 1, 0, 1},
+ {0x21, str, "\x21", 1, 0, 1},
+ {0x00A1, str, "\xc2\xa1", 2, 0, 1},
+ {0x2014, str, "\xe2\x80\x94", 3, 0, 1},
+ {0x01F4A9, str, "\xf0\x9f\x92\xa9", 4, 0, 1},
+
+ {0xd800, str, "", -1, EILSEQ, 1},
+ {0xDCFF, str, "", -1, EILSEQ, 1},
+ {0xDD00, str, "\xed\xb4\x80", 3, 0, 1},
+ {0x10ffff, str, "\xf4\x8f\xbf\xbf", 4, 0, 1},
+ {0x110000, str, "", -1, EILSEQ, 1},
+};
+
+void
+tests_wcrtomb(void)
+{
+ struct wctest *tp;
+ int r;
+ mbstate_t s;
+
+ puts("testing wcrtomb1");
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ memset(str, 0, MB_CUR_MAX+1);
+ errno = 0;
+ r = wcrtomb(tp->s, tp->wc, NULL);
+ assert(tp->r == r);
+ assert(tp->syserr == errno);
+ if (tp->s && tp->r != -1)
+ assert(!memcmp(tp->s, tp->exp, MB_CUR_MAX+1));
+ }
+
+ puts("testing wcrtomb2");
+ memset(&s, 0, sizeof(s));
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ memset(str, 0, MB_CUR_MAX+1);
+ errno = 0;
+ r = wcrtomb(tp->s, tp->wc, &s);
+ assert(tp->r == r);
+ assert(tp->syserr == errno);
+ if (tp->s && tp->r != -1)
+ assert(!memcmp(tp->s, tp->exp, MB_CUR_MAX+1));
+ assert(mbsinit(&s) != 0 == tp->mbstate);
+ }
+}
+
+void
+tests_wctomb(void)
+{
+ struct wctest *tp;
+ int r;
+
+ puts("testing wctomb");
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ memset(str, 0, MB_CUR_MAX+1);
+ errno = 0;
+ r = wctomb(tp->s, tp->wc);
+ assert(tp->r == r);
+ assert(tp->syserr == errno);
+ if (tp->s && tp->r != -1)
+ assert(!memcmp(tp->s, tp->exp, MB_CUR_MAX+1));
+ }
+}
+
+int
+main(void)
+{
+ puts("testing");
+ tests_wcrtomb();
+ tests_wctomb();
+ puts("done");
+ return 0;
+}
(DIR) diff --git a/tests/libc/execute/0041-mbrlen.c b/tests/libc/execute/0041-mbrlen.c
@@ -0,0 +1,75 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "mbtest.h"
+
+/*
+output:
+testing
+testing mbrlen1
+testing mbrlen2
+testing mblen
+done
+end:
+*/
+
+#define NELEM(x) (sizeof(x)/sizeof(x[0]))
+
+void
+tests_mbrlen(void)
+{
+ struct mbtest *tp;
+ int r;
+ mbstate_t s;
+
+ puts("testing mbrlen1");
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ wc = -1;
+ errno = 0;
+ r = mbrlen(tp->s, tp->l, NULL);
+ assert(tp->r == r);
+ assert(tp->syserr == errno);
+ }
+
+ puts("testing mbrlen2");
+ memset(&s, 0, sizeof(s));
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ wc = -1;
+ errno = 0;
+ r = mbrlen(tp->s, tp->l, &s);
+ assert(tp->r == r);
+ assert(tp->syserr == errno);
+ assert(mbsinit(&s) != 0 == tp->mbstate);
+ }
+}
+
+void
+tests_mblen(void)
+{
+ struct mbtest *tp;
+ int r, rt;
+
+ puts("testing mblen");
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ wc = -1;
+ errno = 0;
+ r = mblen(tp->s, tp->l);
+ assert(tp->syserr == errno);
+ rt = (tp->r >= 0) ? tp->r : -1;
+ assert(rt == r);
+ }
+}
+
+int
+main()
+{
+ puts("testing");
+ tests_mbrlen();
+ tests_mblen();
+ puts("done");
+ return 0;
+}
(DIR) diff --git a/tests/libc/execute/0042-mbsrtowcs.c b/tests/libc/execute/0042-mbsrtowcs.c
@@ -0,0 +1,126 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+/*
+output:
+testing
+testing mbsrtowcs1
+testing mbsrtowcs2
+testing mbstowcs
+done
+end:
+*/
+
+#define NELEM(x) (sizeof(x)/sizeof(x[0]))
+
+static char str[20];
+static wchar_t wcs[20];
+static struct mbstests {
+ char *s;
+ char *sexp;
+
+ wchar_t *wcs;
+ wchar_t *wcsexp;
+
+ size_t n;
+ int r;
+ int syserr;
+ int mbstate;
+} tests[] = {
+ /* s sexp wcs wcsexp n r syserr mbstate */
+ {"\0", NULL, wcs, (wchar_t[]) {0}, 1, 0, 0, 1},
+ {"\0", str, wcs, (wchar_t[]) {0}, 0, 0, 0, 1},
+ {"\0", str, NULL, (wchar_t[]) {0}, 1, 0, 0, 1},
+ {"\0", str, NULL, (wchar_t[]) {0}, 0, 0, 0, 1},
+
+ {"\x31", NULL, wcs, (wchar_t[]) {0x31, 0}, 2, 1, 0, 1},
+ {"\x31", str+1, wcs, (wchar_t[]) {0x31, 0}, 1, 1, 0, 1},
+ {"\x31", str, NULL, (wchar_t[]) {0x31, 0}, 1, 1, 0, 1},
+ {"\x31", str, NULL, (wchar_t[]) {0x31, 0}, 0, 1, 0, 1},
+
+ {"\x21\xc2\xa1\xe2\x80\x94\xf0\x9f\x92\xa9",
+ NULL, wcs,
+ (wchar_t[]) {0x21,0xa1,0x2014,0x1f4A9}, 20, 4, 0, 1},
+
+ {"\xf0\x9f",str, wcs, NULL, 20,-1, EILSEQ, 0},
+};
+
+void
+tests_mbsrtowcs(void)
+{
+ int r;
+ const char *s;
+ mbstate_t st;
+ struct mbstests *tp;
+
+ puts("testing mbsrtowcs1");
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ errno = 0;
+ if (tp->s != NULL)
+ s = strcpy(str, tp->s);
+ memset(wcs, -1, sizeof(wcs));
+
+ r = mbsrtowcs(tp->wcs, &s, tp->n, NULL);
+ assert(tp->r == r);
+ assert(tp->syserr == errno);
+ if (tp->r >= 0) {
+ assert(s == tp->sexp);
+ if (tp->wcs)
+ assert(!wcsncmp(tp->wcsexp, tp->wcs, tp->r));
+ }
+ }
+
+ puts("testing mbsrtowcs2");
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ errno = 0;
+ if (tp->s != NULL)
+ s = strcpy(str, tp->s);
+ memset(wcs, -1, sizeof(wcs));
+ memset(&st, 0, sizeof(st));
+
+ r = mbsrtowcs(tp->wcs, &s, tp->n, &st);
+ assert(tp->r == r);
+ assert(tp->syserr == errno);
+ if (tp->r >= 0) {
+ assert(s == tp->sexp);
+ if (tp->wcs)
+ assert(!wcsncmp(tp->wcsexp, tp->wcs, tp->r));
+ assert(mbsinit(&st) != 0 == tp->mbstate);
+ }
+ }
+}
+
+void
+tests_mbstowcs(void)
+{
+ int r;
+ struct mbstests *tp;
+
+ puts("testing mbstowcs");
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ errno = 0;
+ memset(wcs, -1, sizeof(wcs));
+
+ r = mbstowcs(tp->wcs, tp->s, tp->n);
+ assert(tp->r == r);
+ assert(tp->syserr == errno);
+ if (tp->r >= 0) {
+ if (tp->wcs)
+ assert(!wcsncmp(tp->wcsexp, tp->wcs, tp->r));
+ }
+ }
+}
+
+int
+main(void)
+{
+ puts("testing");
+ tests_mbsrtowcs();
+ tests_mbstowcs();
+ puts("done");
+ return 0;
+}
(DIR) diff --git a/tests/libc/execute/0044-wcslen.c b/tests/libc/execute/0044-wcslen.c
@@ -0,0 +1,28 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+output:
+testing
+done
+end:
+*/
+
+int
+main(void)
+{
+ wchar_t t1[] = {0, 0};
+ wchar_t t2[] = {0};
+ wchar_t t3[] = {0x31, 0};
+ wchar_t t4[] = {0x31, 0x32, 0, 0x33, 0};
+
+ puts("testing");
+ assert(wcslen(t1) == 0);
+ assert(wcslen(t2) == 0);
+ assert(wcslen(t3) == 1);
+ assert(wcslen(t4) == 2);
+ puts("done");
+
+ return 0;
+}
(DIR) diff --git a/tests/libc/execute/0045-wcscmp.c b/tests/libc/execute/0045-wcscmp.c
@@ -0,0 +1,36 @@
+#include <assert.h>
+#include <stdio.h>
+#include <wchar.h>
+
+/*
+output:
+testing
+done
+end:
+*/
+
+int
+main(void)
+{
+ wchar_t t1[] = {0};
+ wchar_t t2[] = {0};
+ wchar_t t3[] = {0x31, 0};
+ wchar_t t4[] = {0x31, 0};
+ wchar_t t5[] = {0x31, 0x32, 0};
+ wchar_t t6[] = {0, 0x31, 0};
+
+ puts("testing");
+ assert(wcscmp(t1, t1) == 0);
+ assert(wcscmp(t1, t2) == 0);
+ assert(wcscmp(t1, t3) < 0);
+ assert(wcscmp(t3, t1) > 0);
+ assert(wcscmp(t3, t3) == 0);
+ assert(wcscmp(t3, t4) == 0);
+ assert(wcscmp(t3, t5) < 0);
+ assert(wcscmp(t5, t3) > 0);
+ assert(wcscmp(t3, t6) > 0);
+ assert(wcscmp(t6, t3) < 0);
+ puts("done");
+
+ return 0;
+}
(DIR) diff --git a/tests/libc/execute/0046-wcsncmp.c b/tests/libc/execute/0046-wcsncmp.c
@@ -0,0 +1,30 @@
+#include <assert.h>
+#include <stdio.h>
+#include <wchar.h>
+
+/*
+output:
+testing
+done
+end:
+*/
+
+int
+main(void)
+{
+ wchar_t t1[] = {0};
+ wchar_t t2[] = {0};
+ wchar_t t3[] = {0x31, 0};
+ wchar_t t4[] = {0x31, 0};
+ wchar_t t5[] = {0x32, 0x33, 0};
+
+ puts("testing");
+ assert(wcsncmp(t1, t1, 0) == 0);
+ assert(wcsncmp(t1, t2, 0) == 0);
+ assert(wcsncmp(t3, t4, 1) == 0);
+ assert(wcsncmp(t3, t5, 1) < 0);
+ assert(wcsncmp(t5, t3, 1) > 0);
+ puts("done");
+
+ return 0;
+}
(DIR) diff --git a/tests/libc/execute/0047-wcscoll.c b/tests/libc/execute/0047-wcscoll.c
@@ -0,0 +1,36 @@
+#include <assert.h>
+#include <stdio.h>
+#include <wchar.h>
+
+/*
+output:
+testing
+done
+end:
+*/
+
+int
+main(void)
+{
+ wchar_t t1[] = {0};
+ wchar_t t2[] = {0};
+ wchar_t t3[] = {0x31, 0};
+ wchar_t t4[] = {0x31, 0};
+ wchar_t t5[] = {0x31, 0x32, 0};
+ wchar_t t6[] = {0, 0x31, 0};
+
+ puts("testing");
+ assert(wcscoll(t1, t1) == 0);
+ assert(wcscoll(t1, t2) == 0);
+ assert(wcscoll(t1, t3) < 0);
+ assert(wcscoll(t3, t1) > 0);
+ assert(wcscoll(t3, t3) == 0);
+ assert(wcscoll(t3, t4) == 0);
+ assert(wcscoll(t3, t5) < 0);
+ assert(wcscoll(t5, t3) > 0);
+ assert(wcscoll(t3, t6) > 0);
+ assert(wcscoll(t6, t3) < 0);
+ puts("done");
+
+ return 0;
+}
(DIR) diff --git a/tests/libc/execute/0048-wcscpy.c b/tests/libc/execute/0048-wcscpy.c
@@ -0,0 +1,31 @@
+#include <assert.h>
+#include <stdio.h>
+#include <wchar.h>
+
+/*
+output:
+testing
+done
+end:
+*/
+
+int
+main()
+{
+ wchar_t test[]= {'t', 'e', 's', 't', 0};
+ wchar_t *s, buf[40];
+
+ puts("testing");
+
+ s = wcscpy(buf, test);
+ assert(s == buf);
+ assert(!wcscmp(s, test));
+
+ s = wcscpy(buf, "");
+ assert(s == buf);
+ assert(!wcscmp(s, ""));
+
+ puts("done");
+
+ return 0;
+}
+\ No newline at end of file
(DIR) diff --git a/tests/libc/execute/libc-tests.lst b/tests/libc/execute/libc-tests.lst
@@ -34,3 +34,13 @@
0035-setlocale
0036-localeconv
0037-malloc [TODO]
+0038-mbsinit
+0039-mbrtowc
+0040-wcrtomb
+0041-mbrlen
+0042-mbsrtowcs
+0044-wcslen
+0045-wcscmp
+0046-wcsncmp
+0047-wcscoll
+0048-wcscpy
(DIR) diff --git a/tests/libc/execute/mbtest.h b/tests/libc/execute/mbtest.h
@@ -0,0 +1,44 @@
+static wchar_t wc;
+static struct mbtest {
+ char *s;
+ int l;
+ int r;
+ int mbstate;
+ int syserr;
+ wchar_t *pwc;
+ wchar_t wc;
+} tests[] = {
+ {"\0", 2, 0, 1, 0, &wc, 0},
+ {"\x21", 2, 1, 1, 0, &wc, 0x21},
+ {"\xc2\xa1", 3, 2, 1, 0, &wc, 0x00A1},
+ {"\xc2\xa1", 2, 2, 1, 0, &wc, 0x00A1},
+ {"\xe2\x80\x94", 4, 3, 1, 0, &wc, 0x2014},
+ {"\xf0\x9f\x92\xa9", 5, 4, 1, 0, &wc, 0x01F4A9},
+ {"\xf0\x9f\x92\xa9", 5, 4, 1, 0, NULL, -1},
+ {"\xf0\x9f\x92\xa9", -1, 4, 1, 0, &wc, 0x01F4A9},
+
+ {NULL, 4, 0, 1, 0, NULL, -1},
+ {"\xed\x9f\xbf", 4, 3, 1, 0, &wc, 0xd7ff},
+ {"\xed\xa0\x80", 4, -1, 1, EILSEQ, &wc, -1},
+ {"\xed\xb3\xbf", 4, -1, 1, EILSEQ, &wc, -1},
+ {"\xed\xb4\x80", 4, 3, 1, 0, &wc, 0xdd00},
+
+ {"\xf0\x9f\x92\xa9", 3, -2, 0, 0, &wc, -1},
+ {"\xa9", 2, 1, 1, 0, &wc, 0x01F4A9},
+ {"\xf0\x9f\x92\xa9", 3, -2, 0, 0, &wc, -1},
+ {NULL, 4, -1, 1, EILSEQ, &wc, -1},
+ {"\xa9", 2, -1, 1, EILSEQ, &wc, -1},
+ {"\xf0\x9f\x92\xa9", 3, -2, 0, 0, &wc, -1},
+ {NULL, 4, -1, 1, EILSEQ, &wc, -1},
+ {"\x21", 2, 1, 1, 0, &wc, 0x21},
+ {"\xf0\x9f\x92\xa9", 2, -2, 0, 0, &wc, -1},
+ {"\xf0\x9f\x92\xa9", 0, -2, 0, 0, &wc, -1},
+ {"\x92\xa9", 2, 2, 1, 0, &wc, 0x01F4A9},
+
+ {"\x80", 2, -1, 1, EILSEQ, &wc, -1},
+ {"\xc0\x80", 2, -1, 1, EILSEQ, &wc, -1},
+ {"\xc0\x00", 2, -1, 1, EILSEQ, &wc, -1},
+ {"\xc1\x81", 2, -1, 1, EILSEQ, &wc, -1},
+ {"\xf8\x81\x82\x83\x84\x85", -1, -1, 1, EILSEQ, &wc, -1},
+ {"\xfe\x81\x82\x83\x84\x85\x86", 8, -1, 1, EILSEQ, &wc, -1},
+};
(DIR) diff --git a/tests/make/execute/0107-inference.sh b/tests/make/execute/0107-inference.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+trap 'rm -f $tmp1 $tmp2 f f.?' EXIT INT TERM QUIT HUP
+
+tmp1=tmp1.$$
+tmp2=tmp2.$$
+
+cat >$tmp1 <<EOF
+c99 -O -o f f.c
+EOF
+
+cat >f.c <<'EOF'
+int
+main(void)
+{
+ return 0;
+}
+EOF
+
+touch -d '1970-01-01 00:00:01' f.h
+touch -d '1970-01-01 00:00:03' f
+touch -d '1970-01-01 00:00:04' f.c
+
+scc make -f- <<'EOF' > $tmp2 2>&1
+f: f.h
+
+f.h:
+ touch $@
+EOF
+
+diff $tmp1 $tmp2