File Coverage

win32console.c
Criterion Covered Total %
statement 4 4 100.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 4 4 100.0


line stmt bran cond sub pod time code
1             /*
2             * This file was generated automatically by ExtUtils::ParseXS version 3.57 from the
3             * contents of win32console.xs. Do not edit this file, edit win32console.xs instead.
4             *
5             * ANY CHANGES MADE HERE WILL BE LOST!
6             *
7             */
8              
9             #line 1 "win32console.xs"
10             #define PERL_NO_GET_CONTEXT
11             #include "EXTERN.h"
12             #include "perl.h"
13             #include "XSUB.h"
14             #include "perliol.h"
15             #include "ppport.h"
16              
17             #ifdef WIN32
18              
19             #define WORKBUF_SIZE 40
20              
21             #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
22             #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
23             #endif
24              
25             typedef struct {
26             struct _PerlIO base;
27              
28             /* the CRT handle, typically 1 or 2 */
29             int fd;
30              
31             /* the Win32 handle */
32             HANDLE h;
33              
34             /* mode of the handle*/
35             int imode;
36              
37             /* buffer containing incomplete utf8 characters
38             or possible escape sequences.
39             */
40             U8 workbuf[WORKBUF_SIZE];
41             size_t workbuf_used;
42              
43             /* used when translating utf-8 to utf-16 */
44             /* expanded as needed */
45             wchar_t *outbuf;
46             int outbuf_size;
47             } PerlIOW32Con;
48              
49             /* we largely ignore the flags at this point, but do propagate them
50             for dup.
51             This is PerlIOUnix_oflags() from perlio.c
52             */
53             int
54             PerlIOW32Con_oflags(const char *mode)
55             {
56             int oflags = -1;
57             if (*mode == IoTYPE_IMPLICIT || *mode == IoTYPE_NUMERIC)
58             mode++;
59             switch (*mode) {
60             case 'r':
61             oflags = O_RDONLY;
62             if (*++mode == '+') {
63             oflags = O_RDWR;
64             mode++;
65             }
66             break;
67              
68             case 'w':
69             oflags = O_CREAT | O_TRUNC;
70             if (*++mode == '+') {
71             oflags |= O_RDWR;
72             mode++;
73             }
74             else
75             oflags |= O_WRONLY;
76             break;
77              
78             case 'a':
79             oflags = O_CREAT | O_APPEND;
80             if (*++mode == '+') {
81             oflags |= O_RDWR;
82             mode++;
83             }
84             else
85             oflags |= O_WRONLY;
86             break;
87             }
88              
89             /* XXX TODO: PerlIO_open() test that exercises 'rb' and 'rt'. */
90              
91             /* Unless O_BINARY is different from O_TEXT, first bit-or:ing one
92             * of them in, and then bit-and-masking the other them away, won't
93             * have much of an effect. */
94             switch (*mode) {
95             case 'b':
96             #if O_TEXT != O_BINARY
97             oflags |= O_BINARY;
98             oflags &= ~O_TEXT;
99             #endif
100             mode++;
101             break;
102             case 't':
103             #if O_TEXT != O_BINARY
104             oflags |= O_TEXT;
105             oflags &= ~O_BINARY;
106             #endif
107             mode++;
108             break;
109             default:
110             #if O_BINARY != 0
111             /* bit-or:ing with zero O_BINARY would be useless. */
112             /*
113             * If neither "t" nor "b" was specified, open the file
114             * in O_BINARY mode.
115             *
116             * Note that if something else than the zero byte was seen
117             * here (e.g. bogus mode "rx"), just few lines later we will
118             * set the errno and invalidate the flags.
119             */
120             oflags |= O_BINARY;
121             #endif
122             break;
123             }
124             if (*mode || oflags == -1) {
125             SETERRNO(EINVAL, LIB_INVARG);
126             oflags = -1;
127             }
128             return oflags;
129             }
130              
131              
132             static IV
133             PerlIOW32Con_pushed(pTHX_ PerlIO* f, const char* mode, SV* arg,
134             PerlIO_funcs* tab) {
135             PERL_UNUSED_ARG(mode);
136             PERL_UNUSED_ARG(tab);
137              
138             /* FIXME: check mode? */
139             /* mode is NULL on binmode? */
140             if (SvOK(arg)) {
141             STRLEN len;
142             (void)SvPV(arg, len);
143             if (len) {
144             errno = EINVAL;
145             return -1;
146             }
147             }
148             PerlIOW32Con *con = PerlIOSelf(f, PerlIOW32Con);
149             PerlIO *next = PerlIONext(f);
150             if (next) {
151             /* FIXME: flush? */
152             /* otherwise it should come from open
153             as with :unix, we never call down
154             */
155             con->fd = PerlIO_fileno(next);
156             }
157             con->imode = mode ? PerlIOW32Con_oflags(mode) : 0;
158             con->h = (HANDLE)win32_get_osfhandle(con->fd);
159             con->outbuf = NULL;
160             con->outbuf_size = 0;
161            
162             DWORD cmode;
163             if (!GetConsoleMode(con->h, &cmode)) {
164             errno = ENOTTY;
165             return -1;
166             }
167              
168             cmode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
169             SetConsoleMode(con->h, cmode);
170             PerlIOBase(f)->flags |= PERLIO_F_UTF8 | PERLIO_F_OPEN;
171              
172             return 0;
173             }
174              
175             IV
176             PerlIOW32Con_popped(pTHX_ PerlIO *f)
177             {
178             PerlIOW32Con * const os = PerlIOSelf(f, PerlIOW32Con);
179             PERL_UNUSED_CONTEXT;
180            
181             if (os->outbuf) {
182             PerlMemShared_free(os->outbuf);
183             os->outbuf = NULL;
184             os->outbuf_size = 0;
185             }
186             return 0;
187             }
188              
189             static void
190             PerlIOW32Con_setfd(pTHX_ PerlIO *f, int fd) {
191             PerlIOSelf(f, PerlIOW32Con)->fd = fd;
192             }
193              
194             /* largely PerlIOUnix_open() */
195             static PerlIO *
196             PerlIOW32Con_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
197             IV n, const char *mode, int fd, int imode,
198             int perm, PerlIO *f, int narg, SV **args)
199             {
200             /* cloexec functions not visible */
201             /*bool known_cloexec = 0;*/
202             if (PerlIOValid(f)) {
203             if (PerlIOBase(f)->tab && PerlIOBase(f)->flags & PERLIO_F_OPEN)
204             (*PerlIOBase(f)->tab->Close)(aTHX_ f);
205             }
206             if (narg > 0) {
207             if (*mode == IoTYPE_NUMERIC)
208             mode++;
209             else {
210             imode = PerlIOW32Con_oflags(mode);
211             #ifdef VMS
212             perm = 0777; /* preserve RMS defaults, ACL inheritance, etc. */
213             #else
214             perm = 0666;
215             #endif
216             }
217             if (imode != -1) {
218             STRLEN len;
219             const char *path = SvPV_const(*args, len);
220             if (!IS_SAFE_PATHNAME(path, len, "open"))
221             return NULL;
222             fd = _open(path, imode, perm);
223             /*known_cloexec = 1;*/
224             }
225             }
226             if (fd >= 0) {
227             #if 0
228             /* these functions not exported or not win32? */
229             if (known_cloexec)
230             Perl_setfd_inhexec_for_sysfd(aTHX_ fd);
231             else
232             Perl_setfd_cloexec_or_inhexec_by_sysfdness(aTHX_ fd);
233             #endif
234             if (*mode == IoTYPE_IMPLICIT)
235             mode++;
236             if (!f) {
237             f = PerlIO_allocate(aTHX);
238             }
239             if (!PerlIOValid(f)) {
240             /* push sets the handle */
241             if (!(f = PerlIO_push(aTHX_ f, self, mode, PerlIOArg))) {
242             PerlLIO_close(fd);
243             return NULL;
244             }
245             }
246             PerlIOW32Con_setfd(aTHX_ f, fd);
247             PerlIOBase(f)->flags |= PERLIO_F_OPEN;
248             return f;
249             }
250             else {
251             if (f) {
252             NOOP;
253             /*
254             * FIXME: pop layers ???
255             */
256             }
257             return NULL;
258             }
259             }
260              
261             static IV
262             PerlIOW32Con_fileno(pTHX_ PerlIO *f)
263             {
264             PERL_UNUSED_CONTEXT;
265             return PerlIOSelf(f, PerlIOW32Con)->fd;
266             }
267              
268             static PerlIO *
269             PerlIOW32Con_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
270             {
271             const PerlIOW32Con * const os = PerlIOSelf(o, PerlIOW32Con);
272              
273             HANDLE h2 = NULL;
274             if (!DuplicateHandle(GetCurrentProcess(), os->h,
275             GetCurrentProcess(), &h2,
276             0, FALSE, DUPLICATE_SAME_ACCESS)) {
277             return NULL;
278             }
279             int fd = win32_open_osfhandle((intptr_t)h2, os->imode);
280             PerlIO *df = PerlIOBase_dup(aTHX_ f, o, param, flags);
281             if (!f) {
282             return NULL;
283             }
284             PerlIOW32Con_setfd(aTHX_ df, fd);
285              
286             return df;
287             }
288              
289             SSize_t
290             PerlIOW32Con_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
291             {
292             PERL_UNUSED_ARG(f);
293             PERL_UNUSED_ARG(vbuf);
294             PERL_UNUSED_ARG(count);
295            
296             /* not implemented */
297             errno = EINVAL;
298             return -1;
299             }
300              
301             SSize_t
302             PerlIOW32Con_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
303             {
304             /* FIXME: locks */
305             /* FIXME: put unconsumed bytes in workbuf and use them the next time around */
306             /* FIXME: handle/discard out of range UTF-8? */
307             /* TODO: escape codes - might be possible with SetConsoleMode(... ENABLE_VIRTUAL_TERMINAL_PROCESSING) */
308              
309             PerlIOW32Con * const os = PerlIOSelf(f, PerlIOW32Con);
310             LPCSTR in = vbuf;
311             int wcount = MultiByteToWideChar(CP_UTF8, 0, in, count, os->outbuf, os->outbuf_size);
312             if (wcount > os->outbuf_size) {
313             /* out of space, expand and try again */
314             int newsize = os->outbuf_size ? os->outbuf_size * 2 : WORKBUF_SIZE;
315             if (newsize < wcount)
316             newsize = wcount;
317             os->outbuf = PerlMemShared_realloc(os->outbuf, newsize * sizeof(wchar_t));
318             os->outbuf_size = newsize;
319              
320             wcount = MultiByteToWideChar(CP_UTF8, 0, in, count, os->outbuf, os->outbuf_size);
321             }
322             if (wcount > 0
323             && WriteConsoleW(os->h, os->outbuf, wcount, NULL, NULL)) {
324             /* assume we wrote all */
325             return count;
326             }
327             errno = EINVAL; /* FIXME: error code */
328             return -1;
329             }
330              
331             Off_t
332             PerlIOW32Con_tell(pTHX_ PerlIO *f)
333             {
334             PERL_UNUSED_ARG(f);
335             errno = ESPIPE;
336             return -1;
337             }
338              
339             IV
340             PerlIOW32Con_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
341             {
342             PERL_UNUSED_ARG(f);
343             PERL_UNUSED_ARG(offset);
344             PERL_UNUSED_ARG(whence);
345             errno = ESPIPE;
346             return -1;
347             }
348              
349             IV
350             PerlIOW32Con_close(pTHX_ PerlIO *f)
351             {
352             /* FIXME: flush? */
353             /* FIXME: error handling */
354             const int fd = PerlIOSelf(f, PerlIOW32Con)->fd;
355             _close(fd);
356              
357             return 0;
358             }
359              
360             PERLIO_FUNCS_DECL(PerlIO_win32console) = {
361             sizeof(PerlIO_funcs),
362             "win32console",
363             sizeof(PerlIOW32Con),
364             PERLIO_K_RAW,
365             PerlIOW32Con_pushed,
366             PerlIOW32Con_popped,
367             PerlIOW32Con_open,
368             PerlIOBase_binmode, /* binmode */
369             NULL,
370             PerlIOW32Con_fileno,
371             PerlIOW32Con_dup,
372             PerlIOW32Con_read,
373             PerlIOBase_unread,
374             PerlIOW32Con_write,
375             PerlIOW32Con_seek,
376             PerlIOW32Con_tell,
377             PerlIOW32Con_close,
378             PerlIOBase_noop_ok, /* flush */
379             PerlIOBase_noop_fail, /* fill */
380             PerlIOBase_eof,
381             PerlIOBase_error,
382             PerlIOBase_clearerr,
383             PerlIOBase_setlinebuf,
384             NULL, /* get_base */
385             NULL, /* get_bufsiz */
386             NULL, /* get_ptr */
387             NULL, /* get_cnt */
388             NULL, /* set_ptrcnt */
389             };
390              
391             #endif
392              
393             #line 394 "win32console.c"
394             #ifndef PERL_UNUSED_VAR
395             # define PERL_UNUSED_VAR(var) if (0) var = var
396             #endif
397              
398             #ifndef dVAR
399             # define dVAR dNOOP
400             #endif
401              
402              
403             /* This stuff is not part of the API! You have been warned. */
404             #ifndef PERL_VERSION_DECIMAL
405             # define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s)
406             #endif
407             #ifndef PERL_DECIMAL_VERSION
408             # define PERL_DECIMAL_VERSION \
409             PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION)
410             #endif
411             #ifndef PERL_VERSION_GE
412             # define PERL_VERSION_GE(r,v,s) \
413             (PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s))
414             #endif
415             #ifndef PERL_VERSION_LE
416             # define PERL_VERSION_LE(r,v,s) \
417             (PERL_DECIMAL_VERSION <= PERL_VERSION_DECIMAL(r,v,s))
418             #endif
419              
420             /* XS_INTERNAL is the explicit static-linkage variant of the default
421             * XS macro.
422             *
423             * XS_EXTERNAL is the same as XS_INTERNAL except it does not include
424             * "STATIC", ie. it exports XSUB symbols. You probably don't want that
425             * for anything but the BOOT XSUB.
426             *
427             * See XSUB.h in core!
428             */
429              
430              
431             /* TODO: This might be compatible further back than 5.10.0. */
432             #if PERL_VERSION_GE(5, 10, 0) && PERL_VERSION_LE(5, 15, 1)
433             # undef XS_EXTERNAL
434             # undef XS_INTERNAL
435             # if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING)
436             # define XS_EXTERNAL(name) __declspec(dllexport) XSPROTO(name)
437             # define XS_INTERNAL(name) STATIC XSPROTO(name)
438             # endif
439             # if defined(__SYMBIAN32__)
440             # define XS_EXTERNAL(name) EXPORT_C XSPROTO(name)
441             # define XS_INTERNAL(name) EXPORT_C STATIC XSPROTO(name)
442             # endif
443             # ifndef XS_EXTERNAL
444             # if defined(HASATTRIBUTE_UNUSED) && !defined(__cplusplus)
445             # define XS_EXTERNAL(name) void name(pTHX_ CV* cv __attribute__unused__)
446             # define XS_INTERNAL(name) STATIC void name(pTHX_ CV* cv __attribute__unused__)
447             # else
448             # ifdef __cplusplus
449             # define XS_EXTERNAL(name) extern "C" XSPROTO(name)
450             # define XS_INTERNAL(name) static XSPROTO(name)
451             # else
452             # define XS_EXTERNAL(name) XSPROTO(name)
453             # define XS_INTERNAL(name) STATIC XSPROTO(name)
454             # endif
455             # endif
456             # endif
457             #endif
458              
459             /* perl >= 5.10.0 && perl <= 5.15.1 */
460              
461              
462             /* The XS_EXTERNAL macro is used for functions that must not be static
463             * like the boot XSUB of a module. If perl didn't have an XS_EXTERNAL
464             * macro defined, the best we can do is assume XS is the same.
465             * Dito for XS_INTERNAL.
466             */
467             #ifndef XS_EXTERNAL
468             # define XS_EXTERNAL(name) XS(name)
469             #endif
470             #ifndef XS_INTERNAL
471             # define XS_INTERNAL(name) XS(name)
472             #endif
473              
474             /* Now, finally, after all this mess, we want an ExtUtils::ParseXS
475             * internal macro that we're free to redefine for varying linkage due
476             * to the EXPORT_XSUB_SYMBOLS XS keyword. This is internal, use
477             * XS_EXTERNAL(name) or XS_INTERNAL(name) in your code if you need to!
478             */
479              
480             #undef XS_EUPXS
481             #if defined(PERL_EUPXS_ALWAYS_EXPORT)
482             # define XS_EUPXS(name) XS_EXTERNAL(name)
483             #else
484             /* default to internal */
485             # define XS_EUPXS(name) XS_INTERNAL(name)
486             #endif
487              
488             #ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE
489             #define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params)
490              
491             /* prototype to pass -Wmissing-prototypes */
492             STATIC void
493             S_croak_xs_usage(const CV *const cv, const char *const params);
494              
495             STATIC void
496             S_croak_xs_usage(const CV *const cv, const char *const params)
497             {
498             const GV *const gv = CvGV(cv);
499              
500             PERL_ARGS_ASSERT_CROAK_XS_USAGE;
501              
502             if (gv) {
503             const char *const gvname = GvNAME(gv);
504             const HV *const stash = GvSTASH(gv);
505             const char *const hvname = stash ? HvNAME(stash) : NULL;
506              
507             if (hvname)
508             Perl_croak_nocontext("Usage: %s::%s(%s)", hvname, gvname, params);
509             else
510             Perl_croak_nocontext("Usage: %s(%s)", gvname, params);
511             } else {
512             /* Pants. I don't think that it should be possible to get here. */
513             Perl_croak_nocontext("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params);
514             }
515             }
516             #undef PERL_ARGS_ASSERT_CROAK_XS_USAGE
517              
518             #define croak_xs_usage S_croak_xs_usage
519              
520             #endif
521              
522             /* NOTE: the prototype of newXSproto() is different in versions of perls,
523             * so we define a portable version of newXSproto()
524             */
525             #ifdef newXS_flags
526             #define newXSproto_portable(name, c_impl, file, proto) newXS_flags(name, c_impl, file, proto, 0)
527             #else
528             #define newXSproto_portable(name, c_impl, file, proto) (PL_Sv=(SV*)newXS(name, c_impl, file), sv_setpv(PL_Sv, proto), (CV*)PL_Sv)
529             #endif /* !defined(newXS_flags) */
530              
531             #if PERL_VERSION_LE(5, 21, 5)
532             # define newXS_deffile(a,b) Perl_newXS(aTHX_ a,b,file)
533             #else
534             # define newXS_deffile(a,b) Perl_newXS_deffile(aTHX_ a,b)
535             #endif
536              
537             /* simple backcompat versions of the TARGx() macros with no optimisation */
538             #ifndef TARGi
539             # define TARGi(iv, do_taint) sv_setiv_mg(TARG, iv)
540             # define TARGu(uv, do_taint) sv_setuv_mg(TARG, uv)
541             # define TARGn(nv, do_taint) sv_setnv_mg(TARG, nv)
542             #endif
543              
544             #line 545 "win32console.c"
545             #ifdef __cplusplus
546             extern "C" {
547             #endif
548             XS_EXTERNAL(boot_PerlIO__win32console); /* prototype to pass -Wmissing-prototypes */
549 2           XS_EXTERNAL(boot_PerlIO__win32console)
550             {
551             #if PERL_VERSION_LE(5, 21, 5)
552             dVAR; dXSARGS;
553             #else
554 2           dVAR; dXSBOOTARGSXSAPIVERCHK;
555             #endif
556              
557             PERL_UNUSED_VAR(cv); /* -W */
558             PERL_UNUSED_VAR(items); /* -W */
559             #if PERL_VERSION_LE(5, 21, 5)
560             XS_VERSION_BOOTCHECK;
561             # ifdef XS_APIVERSION_BOOTCHECK
562             XS_APIVERSION_BOOTCHECK;
563             # endif
564             #endif
565              
566              
567             /* Initialisation Section */
568              
569             #line 387 "win32console.xs"
570             #ifdef WIN32
571             PerlIO_define_layer(aTHX_ (PerlIO_funcs*)&PerlIO_win32console);
572             #endif
573              
574             #line 575 "win32console.c"
575              
576             /* End of Initialisation Section */
577              
578             #if PERL_VERSION_LE(5, 21, 5)
579             # if PERL_VERSION_GE(5, 9, 0)
580             if (PL_unitcheckav)
581             call_list(PL_scopestack_ix, PL_unitcheckav);
582             # endif
583             XSRETURN_YES;
584             #else
585 2           Perl_xs_boot_epilog(aTHX_ ax);
586             #endif
587 2           }
588              
589             #ifdef __cplusplus
590             }
591             #endif