1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2013 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <glenn.s.fowler@gmail.com> *
18 * David Korn <dgkorn@gmail.com> *
19 * Phong Vo <phongvo@gmail.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 int d;
93 Sfio_t* t;
94 Wide_t* w;
95 char buf[1024];
96
97 STDIO_INT(f, "vfwscanf", int, (Sfio_t*, const wchar_t*, va_list), (f, fmt, args))
98
99 FWIDE(f, WEOF);
100 n = wcstombs(NiL, fmt, 0);
101 if (w = newof(0, Wide_t, 1, n))
102 {
103 d = dup(0);
104 if (t = sfnew(NiL, buf, sizeof(buf), d, SF_READ))
105 {
106 w->sfdisc.exceptf = wideexcept;
107 w->sfdisc.readf = wideread;
108 w->f = f;
109 if (sfdisc(t, &w->sfdisc) == &w->sfdisc)
110 {
111 wcstombs(w->fmt, fmt, n + 1);
112 v = sfvscanf(t, w->fmt, args);
113 }
114 else
115 {
116 free(w);
117 v = -1;
118 }
119 sfsetfd(t, -1);
120 sfclose(t);
121 }
122 else
123 {
124 free(w);
125 v = -1;
126 }
127 close(d);
128 }
129 else
130 v = -1;
131 return v;
132 }
133