4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give.
11 ********************************************************************************
12 ** This file implements various interfaces used for console and stream I/O
13 ** by the SQLite project command-line tools, as explained in console_io.h .
14 ** Functions prefixed by "SQLITE_INTERNAL_LINKAGE" behave as described there.
21 #ifndef SHELL_NO_SYSINC
29 #ifndef HAVE_CONSOLE_IO_H
30 # include "console_io.h"
33 # pragma warning(disable : 4204)
36 #ifndef SQLITE_CIO_NO_TRANSLATE
37 # if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
38 # ifndef SHELL_NO_SYSINC
41 # undef WIN32_LEAN_AND_MEAN
42 # define WIN32_LEAN_AND_MEAN
45 # define CIO_WIN_WC_XLATE 1 /* Use WCHAR Windows APIs for console I/O */
47 # ifndef SHELL_NO_SYSINC
50 # define CIO_WIN_WC_XLATE 0 /* Use plain C library stream I/O at console */
53 # define CIO_WIN_WC_XLATE 0 /* Not exposing translation routines at all */
57 static HANDLE
handleOfFile(FILE *pf
){
58 int fileDesc
= _fileno(pf
);
59 union { intptr_t osfh
; HANDLE fh
; } fid
= {
60 (fileDesc
>=0)? _get_osfhandle(fileDesc
) : (intptr_t)INVALID_HANDLE_VALUE
66 #ifndef SQLITE_CIO_NO_TRANSLATE
67 typedef struct PerStreamTags
{
78 /* Define NULL-like value for things which can validly be 0. */
79 # define SHELL_INVALID_FILE_PTR ((FILE *)~0)
81 # define SHELL_INVALID_CONS_MODE 0xFFFF0000
85 # define PST_INITIALIZER { INVALID_HANDLE_VALUE, SHELL_INVALID_CONS_MODE, \
86 {0,0,0,0}, SHELL_INVALID_FILE_PTR }
88 # define PST_INITIALIZER { 0, SHELL_INVALID_FILE_PTR }
91 /* Quickly say whether a known output is going to the console. */
93 static short pstReachesConsole(PerStreamTags
*ppst
){
94 return (ppst
->hx
!= INVALID_HANDLE_VALUE
);
97 # define pstReachesConsole(ppst) 0
100 # if CIO_WIN_WC_XLATE
101 static void restoreConsoleArb(PerStreamTags
*ppst
){
102 if( pstReachesConsole(ppst
) ) SetConsoleMode(ppst
->hx
, ppst
->consMode
);
105 # define restoreConsoleArb(ppst)
108 /* Say whether FILE* appears to be a console, collect associated info. */
109 static short streamOfConsole(FILE *pf
, /* out */ PerStreamTags
*ppst
){
110 # if CIO_WIN_WC_XLATE
112 DWORD dwCM
= SHELL_INVALID_CONS_MODE
;
113 HANDLE fh
= handleOfFile(pf
);
115 if( INVALID_HANDLE_VALUE
!= fh
){
116 rv
= (GetFileType(fh
) == FILE_TYPE_CHAR
&& GetConsoleMode(fh
,&dwCM
));
118 ppst
->hx
= (rv
)? fh
: INVALID_HANDLE_VALUE
;
119 ppst
->consMode
= dwCM
;
123 ppst
->reachesConsole
= ( (short)isatty(fileno(pf
)) );
124 return ppst
->reachesConsole
;
128 # ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
129 # define ENABLE_VIRTUAL_TERMINAL_PROCESSING (0x4)
132 # if CIO_WIN_WC_XLATE
133 /* Define console modes for use with the Windows Console API. */
134 # define SHELL_CONI_MODE \
135 (ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT | 0x80 \
136 | ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_PROCESSED_INPUT)
137 # define SHELL_CONO_MODE (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT \
138 | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
141 typedef struct ConsoleInfo
{
142 PerStreamTags pstSetup
[3];
143 PerStreamTags pstDesignated
[3];
144 StreamsAreConsole sacSetup
;
147 static short isValidStreamInfo(PerStreamTags
*ppst
){
148 return (ppst
->pf
!= SHELL_INVALID_FILE_PTR
);
151 static ConsoleInfo consoleInfo
= {
152 { /* pstSetup */ PST_INITIALIZER
, PST_INITIALIZER
, PST_INITIALIZER
},
153 { /* pstDesignated[] */ PST_INITIALIZER
, PST_INITIALIZER
, PST_INITIALIZER
},
154 SAC_NoConsole
/* sacSetup */
157 SQLITE_INTERNAL_LINKAGE
FILE* invalidFileStream
= (FILE *)~0;
159 # if CIO_WIN_WC_XLATE
160 static void maybeSetupAsConsole(PerStreamTags
*ppst
, short odir
){
161 if( pstReachesConsole(ppst
) ){
162 DWORD cm
= odir
? SHELL_CONO_MODE
: SHELL_CONI_MODE
;
163 SetConsoleMode(ppst
->hx
, cm
);
167 # define maybeSetupAsConsole(ppst,odir)
170 SQLITE_INTERNAL_LINKAGE
void consoleRenewSetup(void){
171 # if CIO_WIN_WC_XLATE
174 PerStreamTags
*ppst
= (ix
<3)?
175 &consoleInfo
.pstSetup
[ix
] : &consoleInfo
.pstDesignated
[ix
-3];
176 maybeSetupAsConsole(ppst
, (ix
% 3)>0);
182 SQLITE_INTERNAL_LINKAGE StreamsAreConsole
183 consoleClassifySetup( FILE *pfIn
, FILE *pfOut
, FILE *pfErr
){
184 StreamsAreConsole rv
= SAC_NoConsole
;
185 FILE* apf
[3] = { pfIn
, pfOut
, pfErr
};
187 for( ix
= 2; ix
>= 0; --ix
){
188 PerStreamTags
*ppst
= &consoleInfo
.pstSetup
[ix
];
189 if( streamOfConsole(apf
[ix
], ppst
) ){
190 rv
|= (SAC_InConsole
<<ix
);
192 consoleInfo
.pstDesignated
[ix
] = *ppst
;
193 if( ix
> 0 ) fflush(apf
[ix
]);
195 consoleInfo
.sacSetup
= rv
;
200 SQLITE_INTERNAL_LINKAGE
void SQLITE_CDECL
consoleRestore( void ){
201 # if CIO_WIN_WC_XLATE
202 static ConsoleInfo
*pci
= &consoleInfo
;
205 for( ix
=0; ix
<3; ++ix
){
206 if( pci
->sacSetup
& (SAC_InConsole
<<ix
) ){
207 PerStreamTags
*ppst
= &pci
->pstSetup
[ix
];
208 SetConsoleMode(ppst
->hx
, ppst
->consMode
);
214 #endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
216 #ifdef SQLITE_CIO_INPUT_REDIR
217 /* Say whether given FILE* is among those known, via either
218 ** consoleClassifySetup() or set{Output,Error}Stream, as
219 ** readable, and return an associated PerStreamTags pointer
220 ** if so. Otherwise, return 0.
222 static PerStreamTags
* isKnownReadable(FILE *pf
){
223 static PerStreamTags
*apst
[] = {
224 &consoleInfo
.pstDesignated
[0], &consoleInfo
.pstSetup
[0], 0
228 if( apst
[ix
]->pf
== pf
) break;
229 } while( apst
[++ix
] != 0 );
234 #ifndef SQLITE_CIO_NO_TRANSLATE
235 /* Say whether given FILE* is among those known, via either
236 ** consoleClassifySetup() or set{Output,Error}Stream, as
237 ** writable, and return an associated PerStreamTags pointer
238 ** if so. Otherwise, return 0.
240 static PerStreamTags
* isKnownWritable(FILE *pf
){
241 static PerStreamTags
*apst
[] = {
242 &consoleInfo
.pstDesignated
[1], &consoleInfo
.pstDesignated
[2],
243 &consoleInfo
.pstSetup
[1], &consoleInfo
.pstSetup
[2], 0
247 if( apst
[ix
]->pf
== pf
) break;
248 } while( apst
[++ix
] != 0 );
252 static FILE *designateEmitStream(FILE *pf
, unsigned chix
){
253 FILE *rv
= consoleInfo
.pstDesignated
[chix
].pf
;
254 if( pf
== invalidFileStream
) return rv
;
256 /* Setting a possibly new output stream. */
257 PerStreamTags
*ppst
= isKnownWritable(pf
);
259 PerStreamTags pst
= *ppst
;
260 consoleInfo
.pstDesignated
[chix
] = pst
;
261 }else streamOfConsole(pf
, &consoleInfo
.pstDesignated
[chix
]);
266 SQLITE_INTERNAL_LINKAGE
FILE *setOutputStream(FILE *pf
){
267 return designateEmitStream(pf
, 1);
269 # ifdef CONSIO_SET_ERROR_STREAM
270 SQLITE_INTERNAL_LINKAGE
FILE *setErrorStream(FILE *pf
){
271 return designateEmitStream(pf
, 2);
274 #endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
276 #ifndef SQLITE_CIO_NO_SETMODE
277 # if CIO_WIN_WC_XLATE
278 static void setModeFlushQ(FILE *pf
, short bFlush
, int mode
){
279 if( bFlush
) fflush(pf
);
280 _setmode(_fileno(pf
), mode
);
283 # define setModeFlushQ(f, b, m) if(b) fflush(f)
286 SQLITE_INTERNAL_LINKAGE
void setBinaryMode(FILE *pf
, short bFlush
){
287 setModeFlushQ(pf
, bFlush
, _O_BINARY
);
289 SQLITE_INTERNAL_LINKAGE
void setTextMode(FILE *pf
, short bFlush
){
290 setModeFlushQ(pf
, bFlush
, _O_TEXT
);
292 # undef setModeFlushQ
294 #else /* defined(SQLITE_CIO_NO_SETMODE) */
295 # define setBinaryMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
296 # define setTextMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
297 #endif /* defined(SQLITE_CIO_NO_SETMODE) */
299 #ifndef SQLITE_CIO_NO_TRANSLATE
300 # if CIO_WIN_WC_XLATE
301 /* Write buffer cBuf as output to stream known to reach console,
302 ** limited to ncTake char's. Return ncTake on success, else 0. */
303 static int conZstrEmit(PerStreamTags
*ppst
, const char *z
, int ncTake
){
306 int nwc
= MultiByteToWideChar(CP_UTF8
,0, z
,ncTake
, 0,0);
308 WCHAR
*zw
= sqlite3_malloc64(nwc
*sizeof(WCHAR
));
310 nwc
= MultiByteToWideChar(CP_UTF8
,0, z
,ncTake
, zw
,nwc
);
312 /* Translation from UTF-8 to UTF-16, then WCHARs out. */
313 if( WriteConsoleW(ppst
->hx
, zw
,nwc
, 0, NULL
) ){
324 /* For {f,o,e}PrintfUtf8() when stream is known to reach console. */
325 static int conioVmPrintf(PerStreamTags
*ppst
, const char *zFormat
, va_list ap
){
326 char *z
= sqlite3_vmprintf(zFormat
, ap
);
328 int rv
= conZstrEmit(ppst
, z
, (int)strlen(z
));
333 # endif /* CIO_WIN_WC_XLATE */
335 # ifdef CONSIO_GET_EMIT_STREAM
336 static PerStreamTags
* getDesignatedEmitStream(FILE *pf
, unsigned chix
,
337 PerStreamTags
*ppst
){
338 PerStreamTags
*rv
= isKnownWritable(pf
);
339 short isValid
= (rv
!=0)? isValidStreamInfo(rv
) : 0;
340 if( rv
!= 0 && isValid
) return rv
;
341 streamOfConsole(pf
, ppst
);
346 /* Get stream info, either for designated output or error stream when
347 ** chix equals 1 or 2, or for an arbitrary stream when chix == 0.
348 ** In either case, ppst references a caller-owned PerStreamTags
349 ** struct which may be filled in if none of the known writable
350 ** streams is being held by consoleInfo. The ppf parameter is a
351 ** byref output when chix!=0 and a byref input when chix==0.
353 static PerStreamTags
*
354 getEmitStreamInfo(unsigned chix
, PerStreamTags
*ppst
,
355 /* in/out */ FILE **ppf
){
356 PerStreamTags
*ppstTry
;
359 ppstTry
= &consoleInfo
.pstDesignated
[chix
];
360 if( !isValidStreamInfo(ppstTry
) ){
361 ppstTry
= &consoleInfo
.pstSetup
[chix
];
363 }else pfEmit
= ppstTry
->pf
;
364 if( !isValidStreamInfo(ppstTry
) ){
365 pfEmit
= (chix
> 1)? stderr
: stdout
;
367 streamOfConsole(pfEmit
, ppstTry
);
371 ppstTry
= isKnownWritable(*ppf
);
372 if( ppstTry
!= 0 ) return ppstTry
;
373 streamOfConsole(*ppf
, ppst
);
379 SQLITE_INTERNAL_LINKAGE
int oPrintfUtf8(const char *zFormat
, ...){
383 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
384 # if CIO_WIN_WC_XLATE
385 PerStreamTags
*ppst
= getEmitStreamInfo(1, &pst
, &pfOut
);
387 getEmitStreamInfo(1, &pst
, &pfOut
);
390 va_start(ap
, zFormat
);
391 # if CIO_WIN_WC_XLATE
392 if( pstReachesConsole(ppst
) ){
393 rv
= conioVmPrintf(ppst
, zFormat
, ap
);
396 rv
= vfprintf(pfOut
, zFormat
, ap
);
397 # if CIO_WIN_WC_XLATE
404 SQLITE_INTERNAL_LINKAGE
int ePrintfUtf8(const char *zFormat
, ...){
408 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
409 # if CIO_WIN_WC_XLATE
410 PerStreamTags
*ppst
= getEmitStreamInfo(2, &pst
, &pfErr
);
412 getEmitStreamInfo(2, &pst
, &pfErr
);
415 va_start(ap
, zFormat
);
416 # if CIO_WIN_WC_XLATE
417 if( pstReachesConsole(ppst
) ){
418 rv
= conioVmPrintf(ppst
, zFormat
, ap
);
421 rv
= vfprintf(pfErr
, zFormat
, ap
);
422 # if CIO_WIN_WC_XLATE
429 SQLITE_INTERNAL_LINKAGE
int fPrintfUtf8(FILE *pfO
, const char *zFormat
, ...){
432 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
433 # if CIO_WIN_WC_XLATE
434 PerStreamTags
*ppst
= getEmitStreamInfo(0, &pst
, &pfO
);
436 getEmitStreamInfo(0, &pst
, &pfO
);
439 va_start(ap
, zFormat
);
440 # if CIO_WIN_WC_XLATE
441 if( pstReachesConsole(ppst
) ){
442 maybeSetupAsConsole(ppst
, 1);
443 rv
= conioVmPrintf(ppst
, zFormat
, ap
);
444 if( 0 == isKnownWritable(ppst
->pf
) ) restoreConsoleArb(ppst
);
447 rv
= vfprintf(pfO
, zFormat
, ap
);
448 # if CIO_WIN_WC_XLATE
455 SQLITE_INTERNAL_LINKAGE
int fPutsUtf8(const char *z
, FILE *pfO
){
456 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
457 # if CIO_WIN_WC_XLATE
458 PerStreamTags
*ppst
= getEmitStreamInfo(0, &pst
, &pfO
);
460 getEmitStreamInfo(0, &pst
, &pfO
);
463 # if CIO_WIN_WC_XLATE
464 if( pstReachesConsole(ppst
) ){
466 maybeSetupAsConsole(ppst
, 1);
467 rv
= conZstrEmit(ppst
, z
, (int)strlen(z
));
468 if( 0 == isKnownWritable(ppst
->pf
) ) restoreConsoleArb(ppst
);
472 return (fputs(z
, pfO
)<0)? 0 : (int)strlen(z
);
473 # if CIO_WIN_WC_XLATE
478 SQLITE_INTERNAL_LINKAGE
int ePutsUtf8(const char *z
){
480 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
481 # if CIO_WIN_WC_XLATE
482 PerStreamTags
*ppst
= getEmitStreamInfo(2, &pst
, &pfErr
);
484 getEmitStreamInfo(2, &pst
, &pfErr
);
487 # if CIO_WIN_WC_XLATE
488 if( pstReachesConsole(ppst
) ) return conZstrEmit(ppst
, z
, (int)strlen(z
));
491 return (fputs(z
, pfErr
)<0)? 0 : (int)strlen(z
);
492 # if CIO_WIN_WC_XLATE
497 SQLITE_INTERNAL_LINKAGE
int oPutsUtf8(const char *z
){
499 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
500 # if CIO_WIN_WC_XLATE
501 PerStreamTags
*ppst
= getEmitStreamInfo(1, &pst
, &pfOut
);
503 getEmitStreamInfo(1, &pst
, &pfOut
);
506 # if CIO_WIN_WC_XLATE
507 if( pstReachesConsole(ppst
) ) return conZstrEmit(ppst
, z
, (int)strlen(z
));
510 return (fputs(z
, pfOut
)<0)? 0 : (int)strlen(z
);
511 # if CIO_WIN_WC_XLATE
516 #endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
518 #if !(defined(SQLITE_CIO_NO_UTF8SCAN) && defined(SQLITE_CIO_NO_TRANSLATE))
519 /* Skip over as much z[] input char sequence as is valid UTF-8,
520 ** limited per nAccept char's or whole characters and containing
521 ** no char cn such that ((1<<cn) & ccm)!=0. On return, the
522 ** sequence z:return (inclusive:exclusive) is validated UTF-8.
523 ** Limit: nAccept>=0 => char count, nAccept<0 => character
525 SQLITE_INTERNAL_LINKAGE
const char*
526 zSkipValidUtf8(const char *z
, int nAccept
, long ccm
){
527 int ng
= (nAccept
<0)? -nAccept
: 0;
528 const char *pcLimit
= (nAccept
>=0)? z
+nAccept
: 0;
530 while( (pcLimit
)? (z
<pcLimit
) : (ng
-- != 0) ){
532 if( (c
& 0x80) == 0 ){
533 if( ccm
!= 0L && c
< 0x20 && ((1L<<c
) & ccm
) != 0 ) return z
;
535 }else if( (c
& 0xC0) != 0xC0 ) return z
; /* not a lead byte */
537 const char *zt
= z
+1; /* Got lead byte, look at trail bytes.*/
539 if( pcLimit
&& zt
>= pcLimit
) return z
;
542 if( ct
==0 || (zt
-z
)>4 || (ct
& 0xC0)!=0x80 ){
543 /* Trailing bytes are too few, too many, or invalid. */
547 } while( ((c
<<= 1) & 0x40) == 0x40 ); /* Eat lead byte's count. */
553 #endif /*!(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))*/
555 #ifndef SQLITE_CIO_NO_TRANSLATE
557 SQLITE_INTERNAL_LINKAGE
int
558 fPutbUtf8(FILE *pfO
, const char *cBuf
, int nAccept
){
560 # if CIO_WIN_WC_XLATE
561 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
562 PerStreamTags
*ppst
= getEmitStreamInfo(0, &pst
, &pfO
);
563 if( pstReachesConsole(ppst
) ){
565 maybeSetupAsConsole(ppst
, 1);
566 rv
= conZstrEmit(ppst
, cBuf
, nAccept
);
567 if( 0 == isKnownWritable(ppst
->pf
) ) restoreConsoleArb(ppst
);
571 return (int)fwrite(cBuf
, 1, nAccept
, pfO
);
572 # if CIO_WIN_WC_XLATE
578 SQLITE_INTERNAL_LINKAGE
int
579 oPutbUtf8(const char *cBuf
, int nAccept
){
581 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
582 # if CIO_WIN_WC_XLATE
583 PerStreamTags
*ppst
= getEmitStreamInfo(1, &pst
, &pfOut
);
585 getEmitStreamInfo(1, &pst
, &pfOut
);
587 # if CIO_WIN_WC_XLATE
588 if( pstReachesConsole(ppst
) ){
589 return conZstrEmit(ppst
, cBuf
, nAccept
);
592 return (int)fwrite(cBuf
, 1, nAccept
, pfOut
);
593 # if CIO_WIN_WC_XLATE
599 SQLITE_INTERNAL_LINKAGE
int
600 ePutbUtf8(const char *cBuf
, int nAccept
){
602 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
603 PerStreamTags
*ppst
= getEmitStreamInfo(2, &pst
, &pfErr
);
604 # if CIO_WIN_WC_XLATE
605 if( pstReachesConsole(ppst
) ){
606 return conZstrEmit(ppst
, cBuf
, nAccept
);
609 return (int)fwrite(cBuf
, 1, nAccept
, pfErr
);
610 # if CIO_WIN_WC_XLATE
614 # endif /* defined(CONSIO_EPUTB) */
616 SQLITE_INTERNAL_LINKAGE
char* fGetsUtf8(char *cBuf
, int ncMax
, FILE *pfIn
){
617 if( pfIn
==0 ) pfIn
= stdin
;
618 # if CIO_WIN_WC_XLATE
619 if( pfIn
== consoleInfo
.pstSetup
[0].pf
620 && (consoleInfo
.sacSetup
& SAC_InConsole
)!=0 ){
621 # if CIO_WIN_WC_XLATE==1
622 # define SHELL_GULP 150 /* Count of WCHARS to be gulped at a time */
623 WCHAR wcBuf
[SHELL_GULP
+1];
624 int lend
= 0, noc
= 0;
625 if( ncMax
> 0 ) cBuf
[0] = 0;
626 while( noc
< ncMax
-8-1 && !lend
){
627 /* There is room for at least 2 more characters and a 0-terminator. */
628 int na
= (ncMax
> SHELL_GULP
*4+1 + noc
)? SHELL_GULP
: (ncMax
-1 - noc
)/4;
631 BOOL bRC
= ReadConsoleW(consoleInfo
.pstSetup
[0].hx
, wcBuf
, na
, &nbr
, 0);
632 if( bRC
&& nbr
>0 && (wcBuf
[nbr
-1]&0xF800)==0xD800 ){
633 /* Last WHAR read is first of a UTF-16 surrogate pair. Grab its mate. */
635 bRC
&= ReadConsoleW(consoleInfo
.pstSetup
[0].hx
, wcBuf
+nbr
, 1, &nbrx
, 0);
636 if( bRC
) nbr
+= nbrx
;
638 if( !bRC
|| (noc
==0 && nbr
==0) ) return 0;
640 int nmb
= WideCharToMultiByte(CP_UTF8
, 0, wcBuf
,nbr
,0,0,0,0);
641 if( nmb
!= 0 && noc
+nmb
<= ncMax
){
643 nmb
= WideCharToMultiByte(CP_UTF8
, 0, wcBuf
,nbr
,cBuf
+noc
,nmb
,0,0);
645 /* Fixup line-ends as coded by Windows for CR (or "Enter".)
646 ** This is done without regard for any setMode{Text,Binary}()
647 ** call that might have been done on the interactive input.
650 if( cBuf
[noc
-1]=='\n' ){
652 if( noc
> 1 && cBuf
[noc
-2]=='\r' ) cBuf
[--noc
-1] = '\n';
655 /* Check for ^Z (anywhere in line) too, to act as EOF. */
657 if( cBuf
[iseg
]=='\x1a' ){
658 noc
= iseg
; /* Chop ^Z and anything following. */
659 lend
= 1; /* Counts as end of line too. */
664 }else break; /* Drop apparent garbage in. (Could assert.) */
667 /* If got nothing, (after ^Z chop), must be at end-of-file. */
675 return fgets(cBuf
, ncMax
, pfIn
);
676 # if CIO_WIN_WC_XLATE
680 #endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
682 #if defined(_MSC_VER)
683 # pragma warning(default : 4204)
686 #undef SHELL_INVALID_FILE_PTR