1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2008 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 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 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 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