1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
20 * *
21 ***********************************************************************/
22 #pragma prototyped
23
24 #include "stdhdr.h"
25
26 typedef struct
27 {
28 Sfdisc_t sfdisc; /* sfio discipline */
29 Sfio_t* f; /* original wide stream */
30 char fmt[1]; /* mb fmt */
31 } Wide_t;
32
33 /*
34 * wide exception handler
35 * free on close
36 */
37
38 static int
wideexcept(Sfio_t * f,int op,void * val,Sfdisc_t * dp)39 wideexcept(Sfio_t* f, int op, void* val, Sfdisc_t* dp)
40 {
41 if (sffileno(f) >= 0)
42 return -1;
43 switch (op)
44 {
45 case SF_ATEXIT:
46 sfdisc(f, SF_POPDISC);
47 break;
48 case SF_CLOSING:
49 case SF_DPOP:
50 case SF_FINAL:
51 if (op != SF_CLOSING)
52 free(dp);
53 break;
54 }
55 return 0;
56 }
57
58 /*
59 * sfio wide discipline read
60 * 1 wchar_t at a time
61 * go pure multibyte for best performance
62 */
63
64 static ssize_t
wideread(Sfio_t * f,Void_t * buf,size_t size,Sfdisc_t * dp)65 wideread(Sfio_t* f, Void_t* buf, size_t size, Sfdisc_t* dp)
66 {
67 register Wide_t* w = (Wide_t*)dp;
68 wchar_t wuf[2];
69
70 #if 0
71 if (sfread(w->f, wuf, sizeof(wuf[0])) != sizeof(wuf[0]))
72 return -1;
73 wuf[1] = 0;
74 return wcstombs(buf, wuf, size);
75 #else
76 ssize_t r;
77
78 r = sfread(w->f, wuf, sizeof(wuf[0]));
79 if (r != sizeof(wuf[0]))
80 return -1;
81 wuf[1] = 0;
82 r = wcstombs(buf, wuf, size);
83 return r;
84 #endif
85 }
86
87 int
vfwscanf(Sfio_t * f,const wchar_t * fmt,va_list args)88 vfwscanf(Sfio_t* f, const wchar_t* fmt, va_list args)
89 {
90 size_t n;
91 int v;
92 Sfio_t* t;
93 Wide_t* w;
94 char buf[1024];
95
96 STDIO_INT(f, "vfwscanf", int, (Sfio_t*, const wchar_t*, va_list), (f, fmt, args))
97
98 FWIDE(f, WEOF);
99 n = wcstombs(NiL, fmt, 0);
100 if (w = newof(0, Wide_t, 1, n))
101 {
102 if (t = sfnew(NiL, buf, sizeof(buf), OPEN_MAX+1, SF_READ))
103 {
104 w->sfdisc.exceptf = wideexcept;
105 w->sfdisc.readf = wideread;
106 w->f = f;
107 if (sfdisc(t, &w->sfdisc) == &w->sfdisc)
108 {
109 wcstombs(w->fmt, fmt, n + 1);
110 v = sfvscanf(t, w->fmt, args);
111 }
112 else
113 {
114 free(w);
115 v = -1;
116 }
117 sfsetfd(t, -1);
118 sfclose(t);
119 }
120 else
121 {
122 free(w);
123 v = -1;
124 }
125 }
126 else
127 v = -1;
128 return v;
129 }
130