This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[asperl] added AS patch#2
[perl5.git] / win32 / ipstdio.c
1 /*
2
3         ipstdio.c
4         Interface for perl stdio functions
5
6 */
7
8 #include "ipstdiowin.h"
9 #include <stdio.h>
10
11 class CPerlStdIO : public IPerlStdIOWin
12 {
13 public:
14         CPerlStdIO()
15         {
16                 pPerl = NULL;
17                 pSock = NULL;
18                 w32_platform = -1;
19         };
20         virtual PerlIO* Stdin(void);
21         virtual PerlIO* Stdout(void);
22         virtual PerlIO* Stderr(void);
23         virtual PerlIO* Open(const char *, const char *, int &err);
24         virtual int Close(PerlIO*, int &err);
25         virtual int Eof(PerlIO*, int &err);
26         virtual int Error(PerlIO*, int &err);
27         virtual void Clearerr(PerlIO*, int &err);
28         virtual int Getc(PerlIO*, int &err);
29         virtual char* GetBase(PerlIO *, int &err);
30         virtual int GetBufsiz(PerlIO *, int &err);
31         virtual int GetCnt(PerlIO *, int &err);
32         virtual char* GetPtr(PerlIO *, int &err);
33         virtual int Putc(PerlIO*, int, int &err);
34         virtual int Puts(PerlIO*, const char *, int &err);
35         virtual int Flush(PerlIO*, int &err);
36         virtual int Ungetc(PerlIO*,int, int &err);
37         virtual int Fileno(PerlIO*, int &err);
38         virtual PerlIO* Fdopen(int, const char *, int &err);
39         virtual SSize_t Read(PerlIO*,void *,Size_t, int &err);
40         virtual SSize_t Write(PerlIO*,const void *,Size_t, int &err);
41         virtual void SetCnt(PerlIO *, int, int &err);
42         virtual void SetPtrCnt(PerlIO *, char *, int, int& err);
43         virtual void Setlinebuf(PerlIO*, int &err);
44         virtual int Printf(PerlIO*, int &err, const char *,...);
45         virtual int Vprintf(PerlIO*, int &err, const char *, va_list);
46         virtual long Tell(PerlIO*, int &err);
47         virtual int Seek(PerlIO*, off_t, int, int &err);
48         virtual void Rewind(PerlIO*, int &err);
49         virtual PerlIO* Tmpfile(int &err);
50         virtual int Getpos(PerlIO*, Fpos_t *, int &err);
51         virtual int Setpos(PerlIO*, const Fpos_t *, int &err);
52         virtual void Init(int &err);
53         virtual void InitOSExtras(void* p);
54         virtual int OpenOSfhandle(long osfhandle, int flags);
55         virtual int GetOSfhandle(int filenum);
56
57         void ShutDown(void);
58
59         inline void SetPerlObj(CPerlObj *p) { pPerl = p; };
60         inline void SetSockCtl(CPerlSock *p) { pSock = p; };
61 protected:
62         inline int IsWin95(void)
63         {
64                 return (os_id() == VER_PLATFORM_WIN32_WINDOWS);
65         };
66         inline int IsWinNT(void)
67         {
68                 return (os_id() == VER_PLATFORM_WIN32_NT);
69         };
70         inline void AddToSocketTable(int fh)
71         {
72                 if(fh < _NSTREAM_)
73                         bSocketTable[fh] = TRUE;
74         };
75         inline BOOL InSocketTable(int fh)
76         {
77                 if(fh < _NSTREAM_)
78                         return bSocketTable[fh];
79                 return FALSE;
80         };
81         inline void RemoveFromSocketTable(int fh)
82         {
83                 if(fh < _NSTREAM_)
84                         bSocketTable[fh] = FALSE;
85         };
86         DWORD os_id(void)
87         {
88                 if((-1) == w32_platform)
89                 {
90                         OSVERSIONINFO osver;
91
92                         memset(&osver, 0, sizeof(OSVERSIONINFO));
93                         osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
94                         GetVersionEx(&osver);
95                         w32_platform = osver.dwPlatformId;
96                 }
97                 return (w32_platform);
98         };
99
100
101         CPerlObj *pPerl;
102         CPerlSock *pSock;
103         DWORD w32_platform;
104         BOOL bSocketTable[_NSTREAM_];
105 };
106
107 void CPerlStdIO::ShutDown(void)
108 {
109         int i, err;
110         for(i = 0; i < _NSTREAM_; ++i)
111         {
112                 if(InSocketTable(i))
113                         pSock->CloseSocket(i, err);
114         }
115 };
116
117 #ifdef _X86_
118 extern "C" int __cdecl _alloc_osfhnd(void);
119 extern "C" int __cdecl _set_osfhnd(int fh, long value);
120 extern "C" void __cdecl _unlock(int);
121
122 #if (_MSC_VER >= 1000)
123 typedef struct
124 {
125         long osfhnd;    /* underlying OS file HANDLE */
126         char osfile;    /* attributes of file (e.g., open in text mode?) */
127         char pipech;    /* one char buffer for handles opened on pipes */
128 }       ioinfo;
129 extern "C" ioinfo * __pioinfo[];
130 #define IOINFO_L2E                      5
131 #define IOINFO_ARRAY_ELTS       (1 << IOINFO_L2E)
132 #define _pioinfo(i)     (__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1)))
133 #define _osfile(i)      (_pioinfo(i)->osfile)
134 #else
135 extern "C" extern char _osfile[];
136 #endif  // (_MSC_VER >= 1000)
137
138 #define FOPEN                   0x01    // file handle open
139 #define FAPPEND                 0x20    // file handle opened O_APPEND
140 #define FDEV                    0x40    // file handle refers to device
141 #define FTEXT                   0x80    // file handle is in text mode
142
143 #define _STREAM_LOCKS   26              // Table of stream locks
144 #define _LAST_STREAM_LOCK  (_STREAM_LOCKS+_NSTREAM_-1)  // Last stream lock
145 #define _FH_LOCKS          (_LAST_STREAM_LOCK+1)                // Table of fh locks
146 #endif  // _X86_
147
148 int CPerlStdIO::OpenOSfhandle(long osfhandle, int flags)
149 {
150         int fh;
151
152 #ifdef _X86_
153         if(IsWin95())
154         {
155                 // all this is here to handle Win95's GetFileType bug.
156                 char fileflags;         // _osfile flags 
157
158                 // copy relevant flags from second parameter 
159                 fileflags = FDEV;
160
161                 if(flags & _O_APPEND)
162                         fileflags |= FAPPEND;
163
164                 if(flags & _O_TEXT)
165                         fileflags |= FTEXT;
166
167                 // attempt to allocate a C Runtime file handle
168                 if((fh = _alloc_osfhnd()) == -1)
169                 {
170                         errno = EMFILE;         // too many open files 
171                         _doserrno = 0L;         // not an OS error
172                         return -1;                      // return error to caller
173                 }
174
175                 // the file is open. now, set the info in _osfhnd array
176                 _set_osfhnd(fh, osfhandle);
177
178                 fileflags |= FOPEN;                     // mark as open
179
180 #if (_MSC_VER >= 1000)
181                 _osfile(fh) = fileflags;        // set osfile entry
182 #else
183                 _osfile[fh] = fileflags;        // set osfile entry
184 #endif
185         }
186         else
187 #endif  // _X86_
188         fh = _open_osfhandle(osfhandle, flags);
189
190         if(fh >= 0)
191                 AddToSocketTable(fh);
192
193         return fh;                                      // return handle
194 }
195
196 int CPerlStdIO::GetOSfhandle(int filenum)
197 {
198         return _get_osfhandle(filenum);
199 }
200
201 PerlIO* CPerlStdIO::Stdin(void)
202 {
203     return (PerlIO*)(&_iob[0]);
204 }
205
206 PerlIO* CPerlStdIO::Stdout(void)
207 {
208     return (PerlIO*)(&_iob[1]);
209 }
210
211 PerlIO* CPerlStdIO::Stderr(void)
212 {
213     return (PerlIO*)(&_iob[2]);
214 }
215
216 PerlIO* CPerlStdIO::Open(const char *path, const char *mode, int &err)
217 {
218         PerlIO* ret = NULL;
219         if(*path != '\0')
220         {
221                 ret = (PerlIO*)fopen(path, mode);
222                 if(errno)
223                         err = errno;
224         }
225         else
226                 err = EINVAL;           
227         return ret;
228 }
229
230 extern "C" int _free_osfhnd(int fh);
231 int CPerlStdIO::Close(PerlIO* pf, int &err)
232 {
233         int ret = 0, fileNo = fileno((FILE*)pf);
234         if(InSocketTable(fileNo))
235         {
236                 RemoveFromSocketTable(fileNo);
237                 pSock->CloseSocket(fileNo, err);
238                 _free_osfhnd(fileNo);
239                 fclose((FILE*)pf);
240         }
241         else
242                 ret = fclose((FILE*)pf);
243
244         if(errno)
245                 err = errno;
246         return ret;
247 }
248
249 int CPerlStdIO::Eof(PerlIO* pf, int &err)
250 {
251         int ret = feof((FILE*)pf);
252         if(errno)
253                 err = errno;
254         return ret;
255 }
256
257 int CPerlStdIO::Error(PerlIO* pf, int &err)
258 {
259         int ret = ferror((FILE*)pf);
260         if(errno)
261                 err = errno;
262         return ret;
263 }
264
265 void CPerlStdIO::Clearerr(PerlIO* pf, int &err)
266 {
267         clearerr((FILE*)pf);
268         err = 0;
269 }
270
271 int CPerlStdIO::Getc(PerlIO* pf, int &err)
272 {
273         int ret = fgetc((FILE*)pf);
274         if(errno)
275                 err = errno;
276         return ret;
277 }
278
279 int CPerlStdIO::Putc(PerlIO* pf, int c, int &err)
280 {
281         int ret = fputc(c, (FILE*)pf);
282         if(errno)
283                 err = errno;
284         return ret;
285 }
286
287 int CPerlStdIO::Puts(PerlIO* pf, const char *s, int &err)
288 {
289         int ret = fputs(s, (FILE*)pf);
290         if(errno)
291                 err = errno;
292         return ret;
293 }
294
295 int CPerlStdIO::Flush(PerlIO* pf, int &err)
296 {
297         int ret = fflush((FILE*)pf);
298         if(errno)
299                 err = errno;
300         return ret;
301 }
302
303 int CPerlStdIO::Ungetc(PerlIO* pf,int c, int &err)
304 {
305         int ret = ungetc(c, (FILE*)pf);
306         if(errno)
307                 err = errno;
308         return ret;
309 }
310
311 int CPerlStdIO::Fileno(PerlIO* pf, int &err)
312 {
313         int ret = fileno((FILE*)pf);
314         if(errno)
315                 err = errno;
316         return ret;
317 }
318
319 PerlIO* CPerlStdIO::Fdopen(int fh, const char *mode, int &err)
320 {
321         PerlIO* ret = (PerlIO*)fdopen(fh, mode);
322         if(errno)
323                 err = errno;
324         return ret;
325 }
326
327 SSize_t CPerlStdIO::Read(PerlIO* pf, void * buffer, Size_t count, int &err)
328 {
329         size_t ret = fread(buffer, 1, count, (FILE*)pf);
330         if(errno)
331                 err = errno;
332         return ret;
333 }
334
335 SSize_t CPerlStdIO::Write(PerlIO* pf, const void * buffer, Size_t count, int &err)
336 {
337         size_t ret = fwrite(buffer, 1, count, (FILE*)pf);
338         if(errno)
339                 err = errno;
340         return ret;
341 }
342
343 void CPerlStdIO::Setlinebuf(PerlIO*, int &err)
344 {
345         croak("setlinebuf not implemented!\n");
346 }
347
348 int CPerlStdIO::Printf(PerlIO* pf, int &err, const char *format, ...)
349 {
350         va_list(arglist);
351         va_start(arglist, format);
352         int ret = Vprintf(pf, err, format, arglist);
353         if(errno)
354                 err = errno;
355         return ret;
356 }
357
358 int CPerlStdIO::Vprintf(PerlIO* pf, int &err, const char * format, va_list arg)
359 {
360         int ret = vfprintf((FILE*)pf, format, arg);
361         if(errno)
362                 err = errno;
363         return ret;
364 }
365
366 long CPerlStdIO::Tell(PerlIO* pf, int &err)
367 {
368         long ret = ftell((FILE*)pf);
369         if(errno)
370                 err = errno;
371         return ret;
372 }
373
374 int CPerlStdIO::Seek(PerlIO* pf, off_t offset, int origin, int &err)
375 {
376         int ret = fseek((FILE*)pf, offset, origin);
377         if(errno)
378                 err = errno;
379         return ret;
380 }
381
382 void CPerlStdIO::Rewind(PerlIO* pf, int &err)
383 {
384         rewind((FILE*)pf);
385 }
386
387 PerlIO* CPerlStdIO::Tmpfile(int &err)
388 {
389         return (PerlIO*)tmpfile();
390 }
391
392 int CPerlStdIO::Getpos(PerlIO* pf, Fpos_t *p, int &err)
393 {
394         int ret = fgetpos((FILE*)pf, (fpos_t*)p);
395         if(errno)
396                 err = errno;
397         return ret;
398 }
399
400 int CPerlStdIO::Setpos(PerlIO* pf, const Fpos_t *p, int &err)
401 {
402         int ret = fsetpos((FILE*)pf, (fpos_t*)p);
403         if(errno)
404                 err = errno;
405         return ret;
406 }
407
408 char* CPerlStdIO::GetBase(PerlIO *pf, int &err)
409 {
410         return ((FILE*)pf)->_base;
411 }
412
413 int CPerlStdIO::GetBufsiz(PerlIO *pf, int &err)
414 {
415         return ((FILE*)pf)->_bufsiz;
416 }
417
418 int CPerlStdIO::GetCnt(PerlIO *pf, int &err)
419 {
420         return ((FILE*)pf)->_cnt;
421 }
422
423 char* CPerlStdIO::GetPtr(PerlIO *pf, int &err)
424 {
425         return ((FILE*)pf)->_ptr;
426 }
427
428 void CPerlStdIO::SetCnt(PerlIO *pf, int n, int &err)
429 {
430         ((FILE*)pf)->_cnt = n;
431 }
432
433 void CPerlStdIO::SetPtrCnt(PerlIO *pf, char *ptr, int n, int& err)
434 {
435         ((FILE*)pf)->_ptr = ptr;
436         ((FILE*)pf)->_cnt = n;
437 }
438
439 void CPerlStdIO::Init(int &err)
440 {
441 }
442
443 void CPerlStdIO::InitOSExtras(void* p)
444 {
445 }
446
447