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 /* Character used to represent a known-incomplete UTF-8 char group (�) */
58 static WCHAR cBadGroup
= 0xfffd;
62 static HANDLE
handleOfFile(FILE *pf
){
63 int fileDesc
= _fileno(pf
);
64 union { intptr_t osfh
; HANDLE fh
; } fid
= {
65 (fileDesc
>=0)? _get_osfhandle(fileDesc
) : (intptr_t)INVALID_HANDLE_VALUE
71 #ifndef SQLITE_CIO_NO_TRANSLATE
72 typedef struct PerStreamTags
{
83 /* Define NULL-like value for things which can validly be 0. */
84 # define SHELL_INVALID_FILE_PTR ((FILE *)~0)
86 # define SHELL_INVALID_CONS_MODE 0xFFFF0000
90 # define PST_INITIALIZER { INVALID_HANDLE_VALUE, SHELL_INVALID_CONS_MODE, \
91 {0,0,0,0}, SHELL_INVALID_FILE_PTR }
93 # define PST_INITIALIZER { 0, SHELL_INVALID_FILE_PTR }
96 /* Quickly say whether a known output is going to the console. */
98 static short pstReachesConsole(PerStreamTags
*ppst
){
99 return (ppst
->hx
!= INVALID_HANDLE_VALUE
);
102 # define pstReachesConsole(ppst) 0
105 # if CIO_WIN_WC_XLATE
106 static void restoreConsoleArb(PerStreamTags
*ppst
){
107 if( pstReachesConsole(ppst
) ) SetConsoleMode(ppst
->hx
, ppst
->consMode
);
110 # define restoreConsoleArb(ppst)
113 /* Say whether FILE* appears to be a console, collect associated info. */
114 static short streamOfConsole(FILE *pf
, /* out */ PerStreamTags
*ppst
){
115 # if CIO_WIN_WC_XLATE
117 DWORD dwCM
= SHELL_INVALID_CONS_MODE
;
118 HANDLE fh
= handleOfFile(pf
);
120 if( INVALID_HANDLE_VALUE
!= fh
){
121 rv
= (GetFileType(fh
) == FILE_TYPE_CHAR
&& GetConsoleMode(fh
,&dwCM
));
123 ppst
->hx
= (rv
)? fh
: INVALID_HANDLE_VALUE
;
124 ppst
->consMode
= dwCM
;
128 ppst
->reachesConsole
= ( (short)isatty(fileno(pf
)) );
129 return ppst
->reachesConsole
;
133 # ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
134 # define ENABLE_VIRTUAL_TERMINAL_PROCESSING (0x4)
137 # if CIO_WIN_WC_XLATE
138 /* Define console modes for use with the Windows Console API. */
139 # define SHELL_CONI_MODE \
140 (ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT | 0x80 \
141 | ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_PROCESSED_INPUT)
142 # define SHELL_CONO_MODE (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT \
143 | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
146 typedef struct ConsoleInfo
{
147 PerStreamTags pstSetup
[3];
148 PerStreamTags pstDesignated
[3];
149 StreamsAreConsole sacSetup
;
152 static short isValidStreamInfo(PerStreamTags
*ppst
){
153 return (ppst
->pf
!= SHELL_INVALID_FILE_PTR
);
156 static ConsoleInfo consoleInfo
= {
157 { /* pstSetup */ PST_INITIALIZER
, PST_INITIALIZER
, PST_INITIALIZER
},
158 { /* pstDesignated[] */ PST_INITIALIZER
, PST_INITIALIZER
, PST_INITIALIZER
},
159 SAC_NoConsole
/* sacSetup */
162 SQLITE_INTERNAL_LINKAGE
FILE* invalidFileStream
= (FILE *)~0;
164 # if CIO_WIN_WC_XLATE
165 static void maybeSetupAsConsole(PerStreamTags
*ppst
, short odir
){
166 if( pstReachesConsole(ppst
) ){
167 DWORD cm
= odir
? SHELL_CONO_MODE
: SHELL_CONI_MODE
;
168 SetConsoleMode(ppst
->hx
, cm
);
172 # define maybeSetupAsConsole(ppst,odir)
175 SQLITE_INTERNAL_LINKAGE
void consoleRenewSetup(void){
176 # if CIO_WIN_WC_XLATE
179 PerStreamTags
*ppst
= (ix
<3)?
180 &consoleInfo
.pstSetup
[ix
] : &consoleInfo
.pstDesignated
[ix
-3];
181 maybeSetupAsConsole(ppst
, (ix
% 3)>0);
187 SQLITE_INTERNAL_LINKAGE StreamsAreConsole
188 consoleClassifySetup( FILE *pfIn
, FILE *pfOut
, FILE *pfErr
){
189 StreamsAreConsole rv
= SAC_NoConsole
;
190 FILE* apf
[3] = { pfIn
, pfOut
, pfErr
};
192 for( ix
= 2; ix
>= 0; --ix
){
193 PerStreamTags
*ppst
= &consoleInfo
.pstSetup
[ix
];
194 if( streamOfConsole(apf
[ix
], ppst
) ){
195 rv
|= (SAC_InConsole
<<ix
);
197 consoleInfo
.pstDesignated
[ix
] = *ppst
;
198 if( ix
> 0 ) fflush(apf
[ix
]);
200 consoleInfo
.sacSetup
= rv
;
205 SQLITE_INTERNAL_LINKAGE
void SQLITE_CDECL
consoleRestore( void ){
206 # if CIO_WIN_WC_XLATE
207 static ConsoleInfo
*pci
= &consoleInfo
;
210 for( ix
=0; ix
<3; ++ix
){
211 if( pci
->sacSetup
& (SAC_InConsole
<<ix
) ){
212 PerStreamTags
*ppst
= &pci
->pstSetup
[ix
];
213 SetConsoleMode(ppst
->hx
, ppst
->consMode
);
219 #endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
221 #ifdef SQLITE_CIO_INPUT_REDIR
222 /* Say whether given FILE* is among those known, via either
223 ** consoleClassifySetup() or set{Output,Error}Stream, as
224 ** readable, and return an associated PerStreamTags pointer
225 ** if so. Otherwise, return 0.
227 static PerStreamTags
* isKnownReadable(FILE *pf
){
228 static PerStreamTags
*apst
[] = {
229 &consoleInfo
.pstDesignated
[0], &consoleInfo
.pstSetup
[0], 0
233 if( apst
[ix
]->pf
== pf
) break;
234 } while( apst
[++ix
] != 0 );
239 #ifndef SQLITE_CIO_NO_TRANSLATE
240 /* Say whether given FILE* is among those known, via either
241 ** consoleClassifySetup() or set{Output,Error}Stream, as
242 ** writable, and return an associated PerStreamTags pointer
243 ** if so. Otherwise, return 0.
245 static PerStreamTags
* isKnownWritable(FILE *pf
){
246 static PerStreamTags
*apst
[] = {
247 &consoleInfo
.pstDesignated
[1], &consoleInfo
.pstDesignated
[2],
248 &consoleInfo
.pstSetup
[1], &consoleInfo
.pstSetup
[2], 0
252 if( apst
[ix
]->pf
== pf
) break;
253 } while( apst
[++ix
] != 0 );
257 static FILE *designateEmitStream(FILE *pf
, unsigned chix
){
258 FILE *rv
= consoleInfo
.pstDesignated
[chix
].pf
;
259 if( pf
== invalidFileStream
) return rv
;
261 /* Setting a possibly new output stream. */
262 PerStreamTags
*ppst
= isKnownWritable(pf
);
264 PerStreamTags pst
= *ppst
;
265 consoleInfo
.pstDesignated
[chix
] = pst
;
266 }else streamOfConsole(pf
, &consoleInfo
.pstDesignated
[chix
]);
271 SQLITE_INTERNAL_LINKAGE
FILE *setOutputStream(FILE *pf
){
272 return designateEmitStream(pf
, 1);
274 # ifdef CONSIO_SET_ERROR_STREAM
275 SQLITE_INTERNAL_LINKAGE
FILE *setErrorStream(FILE *pf
){
276 return designateEmitStream(pf
, 2);
279 #endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
281 #ifndef SQLITE_CIO_NO_SETMODE
282 # if CIO_WIN_WC_XLATE
283 static void setModeFlushQ(FILE *pf
, short bFlush
, int mode
){
284 if( bFlush
) fflush(pf
);
285 _setmode(_fileno(pf
), mode
);
288 # define setModeFlushQ(f, b, m) if(b) fflush(f)
291 SQLITE_INTERNAL_LINKAGE
void setBinaryMode(FILE *pf
, short bFlush
){
292 setModeFlushQ(pf
, bFlush
, _O_BINARY
);
294 SQLITE_INTERNAL_LINKAGE
void setTextMode(FILE *pf
, short bFlush
){
295 setModeFlushQ(pf
, bFlush
, _O_TEXT
);
297 # undef setModeFlushQ
299 #else /* defined(SQLITE_CIO_NO_SETMODE) */
300 # define setBinaryMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
301 # define setTextMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
302 #endif /* defined(SQLITE_CIO_NO_SETMODE) */
304 #ifndef SQLITE_CIO_NO_TRANSLATE
305 # if CIO_WIN_WC_XLATE
306 /* Write buffer cBuf as output to stream known to reach console,
307 ** limited to ncTake char's. Return ncTake on success, else 0. */
308 static int conZstrEmit(PerStreamTags
*ppst
, const char *z
, int ncTake
){
311 int nwc
= MultiByteToWideChar(CP_UTF8
,0, z
,ncTake
, 0,0);
313 WCHAR
*zw
= sqlite3_malloc64(nwc
*sizeof(WCHAR
));
315 nwc
= MultiByteToWideChar(CP_UTF8
,0, z
,ncTake
, zw
,nwc
);
317 /* Translation from UTF-8 to UTF-16, then WCHARs out. */
318 if( WriteConsoleW(ppst
->hx
, zw
,nwc
, 0, NULL
) ){
329 /* For {f,o,e}PrintfUtf8() when stream is known to reach console. */
330 static int conioVmPrintf(PerStreamTags
*ppst
, const char *zFormat
, va_list ap
){
331 char *z
= sqlite3_vmprintf(zFormat
, ap
);
333 int rv
= conZstrEmit(ppst
, z
, (int)strlen(z
));
338 # endif /* CIO_WIN_WC_XLATE */
340 # ifdef CONSIO_GET_EMIT_STREAM
341 static PerStreamTags
* getDesignatedEmitStream(FILE *pf
, unsigned chix
,
342 PerStreamTags
*ppst
){
343 PerStreamTags
*rv
= isKnownWritable(pf
);
344 short isValid
= (rv
!=0)? isValidStreamInfo(rv
) : 0;
345 if( rv
!= 0 && isValid
) return rv
;
346 streamOfConsole(pf
, ppst
);
351 /* Get stream info, either for designated output or error stream when
352 ** chix equals 1 or 2, or for an arbitrary stream when chix == 0.
353 ** In either case, ppst references a caller-owned PerStreamTags
354 ** struct which may be filled in if none of the known writable
355 ** streams is being held by consoleInfo. The ppf parameter is a
356 ** byref output when chix!=0 and a byref input when chix==0.
358 static PerStreamTags
*
359 getEmitStreamInfo(unsigned chix
, PerStreamTags
*ppst
,
360 /* in/out */ FILE **ppf
){
361 PerStreamTags
*ppstTry
;
364 ppstTry
= &consoleInfo
.pstDesignated
[chix
];
365 if( !isValidStreamInfo(ppstTry
) ){
366 ppstTry
= &consoleInfo
.pstSetup
[chix
];
368 }else pfEmit
= ppstTry
->pf
;
369 if( !isValidStreamInfo(ppstTry
) ){
370 pfEmit
= (chix
> 1)? stderr
: stdout
;
372 streamOfConsole(pfEmit
, ppstTry
);
376 ppstTry
= isKnownWritable(*ppf
);
377 if( ppstTry
!= 0 ) return ppstTry
;
378 streamOfConsole(*ppf
, ppst
);
384 SQLITE_INTERNAL_LINKAGE
int oPrintfUtf8(const char *zFormat
, ...){
388 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
389 # if CIO_WIN_WC_XLATE
390 PerStreamTags
*ppst
= getEmitStreamInfo(1, &pst
, &pfOut
);
392 getEmitStreamInfo(1, &pst
, &pfOut
);
395 va_start(ap
, zFormat
);
396 # if CIO_WIN_WC_XLATE
397 if( pstReachesConsole(ppst
) ){
398 rv
= conioVmPrintf(ppst
, zFormat
, ap
);
401 rv
= vfprintf(pfOut
, zFormat
, ap
);
402 # if CIO_WIN_WC_XLATE
409 SQLITE_INTERNAL_LINKAGE
int ePrintfUtf8(const char *zFormat
, ...){
413 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
414 # if CIO_WIN_WC_XLATE
415 PerStreamTags
*ppst
= getEmitStreamInfo(2, &pst
, &pfErr
);
417 getEmitStreamInfo(2, &pst
, &pfErr
);
420 va_start(ap
, zFormat
);
421 # if CIO_WIN_WC_XLATE
422 if( pstReachesConsole(ppst
) ){
423 rv
= conioVmPrintf(ppst
, zFormat
, ap
);
426 rv
= vfprintf(pfErr
, zFormat
, ap
);
427 # if CIO_WIN_WC_XLATE
434 SQLITE_INTERNAL_LINKAGE
int fPrintfUtf8(FILE *pfO
, const char *zFormat
, ...){
437 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
438 # if CIO_WIN_WC_XLATE
439 PerStreamTags
*ppst
= getEmitStreamInfo(0, &pst
, &pfO
);
441 getEmitStreamInfo(0, &pst
, &pfO
);
444 va_start(ap
, zFormat
);
445 # if CIO_WIN_WC_XLATE
446 if( pstReachesConsole(ppst
) ){
447 maybeSetupAsConsole(ppst
, 1);
448 rv
= conioVmPrintf(ppst
, zFormat
, ap
);
449 if( 0 == isKnownWritable(ppst
->pf
) ) restoreConsoleArb(ppst
);
452 rv
= vfprintf(pfO
, zFormat
, ap
);
453 # if CIO_WIN_WC_XLATE
460 SQLITE_INTERNAL_LINKAGE
int fPutsUtf8(const char *z
, FILE *pfO
){
461 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
462 # if CIO_WIN_WC_XLATE
463 PerStreamTags
*ppst
= getEmitStreamInfo(0, &pst
, &pfO
);
465 getEmitStreamInfo(0, &pst
, &pfO
);
468 # if CIO_WIN_WC_XLATE
469 if( pstReachesConsole(ppst
) ){
471 maybeSetupAsConsole(ppst
, 1);
472 rv
= conZstrEmit(ppst
, z
, (int)strlen(z
));
473 if( 0 == isKnownWritable(ppst
->pf
) ) restoreConsoleArb(ppst
);
477 return (fputs(z
, pfO
)<0)? 0 : (int)strlen(z
);
478 # if CIO_WIN_WC_XLATE
483 SQLITE_INTERNAL_LINKAGE
int ePutsUtf8(const char *z
){
485 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
486 # if CIO_WIN_WC_XLATE
487 PerStreamTags
*ppst
= getEmitStreamInfo(2, &pst
, &pfErr
);
489 getEmitStreamInfo(2, &pst
, &pfErr
);
492 # if CIO_WIN_WC_XLATE
493 if( pstReachesConsole(ppst
) ) return conZstrEmit(ppst
, z
, (int)strlen(z
));
496 return (fputs(z
, pfErr
)<0)? 0 : (int)strlen(z
);
497 # if CIO_WIN_WC_XLATE
502 SQLITE_INTERNAL_LINKAGE
int oPutsUtf8(const char *z
){
504 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
505 # if CIO_WIN_WC_XLATE
506 PerStreamTags
*ppst
= getEmitStreamInfo(1, &pst
, &pfOut
);
508 getEmitStreamInfo(1, &pst
, &pfOut
);
511 # if CIO_WIN_WC_XLATE
512 if( pstReachesConsole(ppst
) ) return conZstrEmit(ppst
, z
, (int)strlen(z
));
515 return (fputs(z
, pfOut
)<0)? 0 : (int)strlen(z
);
516 # if CIO_WIN_WC_XLATE
521 #endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
523 #if !(defined(SQLITE_CIO_NO_UTF8SCAN) && defined(SQLITE_CIO_NO_TRANSLATE))
524 /* Skip over as much z[] input char sequence as is valid UTF-8,
525 ** limited per nAccept char's or whole characters and containing
526 ** no char cn such that ((1<<cn) & ccm)!=0. On return, the
527 ** sequence z:return (inclusive:exclusive) is validated UTF-8.
528 ** Limit: nAccept>=0 => char count, nAccept<0 => character
530 SQLITE_INTERNAL_LINKAGE
const char*
531 zSkipValidUtf8(const char *z
, int nAccept
, long ccm
){
532 int ng
= (nAccept
<0)? -nAccept
: 0;
533 const char *pcLimit
= (nAccept
>=0)? z
+nAccept
: 0;
535 while( (pcLimit
)? (z
<pcLimit
) : (ng
-- != 0) ){
537 if( (c
& 0x80) == 0 ){
538 if( ccm
!= 0L && c
< 0x20 && ((1L<<c
) & ccm
) != 0 ) return z
;
540 }else if( (c
& 0xC0) != 0xC0 ) return z
; /* not a lead byte */
542 const char *zt
= z
+1; /* Got lead byte, look at trail bytes.*/
544 if( pcLimit
&& zt
>= pcLimit
) return z
;
547 if( ct
==0 || (zt
-z
)>4 || (ct
& 0xC0)!=0x80 ){
548 /* Trailing bytes are too few, too many, or invalid. */
552 } while( ((c
<<= 1) & 0x40) == 0x40 ); /* Eat lead byte's count. */
558 #endif /*!(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))*/
560 #ifndef SQLITE_CIO_NO_TRANSLATE
562 SQLITE_INTERNAL_LINKAGE
int
563 fPutbUtf8(FILE *pfO
, const char *cBuf
, int nAccept
){
565 # if CIO_WIN_WC_XLATE
566 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
567 PerStreamTags
*ppst
= getEmitStreamInfo(0, &pst
, &pfO
);
568 if( pstReachesConsole(ppst
) ){
570 maybeSetupAsConsole(ppst
, 1);
571 rv
= conZstrEmit(ppst
, cBuf
, nAccept
);
572 if( 0 == isKnownWritable(ppst
->pf
) ) restoreConsoleArb(ppst
);
576 return (int)fwrite(cBuf
, 1, nAccept
, pfO
);
577 # if CIO_WIN_WC_XLATE
583 SQLITE_INTERNAL_LINKAGE
int
584 oPutbUtf8(const char *cBuf
, int nAccept
){
586 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
587 # if CIO_WIN_WC_XLATE
588 PerStreamTags
*ppst
= getEmitStreamInfo(1, &pst
, &pfOut
);
590 getEmitStreamInfo(1, &pst
, &pfOut
);
592 # if CIO_WIN_WC_XLATE
593 if( pstReachesConsole(ppst
) ){
594 return conZstrEmit(ppst
, cBuf
, nAccept
);
597 return (int)fwrite(cBuf
, 1, nAccept
, pfOut
);
598 # if CIO_WIN_WC_XLATE
604 SQLITE_INTERNAL_LINKAGE
int
605 ePutbUtf8(const char *cBuf
, int nAccept
){
607 PerStreamTags pst
= PST_INITIALIZER
; /* for unknown streams */
608 PerStreamTags
*ppst
= getEmitStreamInfo(2, &pst
, &pfErr
);
609 # if CIO_WIN_WC_XLATE
610 if( pstReachesConsole(ppst
) ){
611 return conZstrEmit(ppst
, cBuf
, nAccept
);
614 return (int)fwrite(cBuf
, 1, nAccept
, pfErr
);
615 # if CIO_WIN_WC_XLATE
619 # endif /* defined(CONSIO_EPUTB) */
621 SQLITE_INTERNAL_LINKAGE
char* fGetsUtf8(char *cBuf
, int ncMax
, FILE *pfIn
){
622 if( pfIn
==0 ) pfIn
= stdin
;
623 # if CIO_WIN_WC_XLATE
624 if( pfIn
== consoleInfo
.pstSetup
[0].pf
625 && (consoleInfo
.sacSetup
& SAC_InConsole
)!=0 ){
626 # if CIO_WIN_WC_XLATE==1
627 # define SHELL_GULP 150 /* Count of WCHARS to be gulped at a time */
628 WCHAR wcBuf
[SHELL_GULP
+1];
629 int lend
= 0, noc
= 0;
630 if( ncMax
> 0 ) cBuf
[0] = 0;
631 while( noc
< ncMax
-8-1 && !lend
){
632 /* There is room for at least 2 more characters and a 0-terminator. */
633 int na
= (ncMax
> SHELL_GULP
*4+1 + noc
)? SHELL_GULP
: (ncMax
-1 - noc
)/4;
636 BOOL bRC
= ReadConsoleW(consoleInfo
.pstSetup
[0].hx
, wcBuf
, na
, &nbr
, 0);
637 if( bRC
&& nbr
>0 && (wcBuf
[nbr
-1]&0xF800)==0xD800 ){
638 /* Last WHAR read is first of a UTF-16 surrogate pair. Grab its mate. */
640 bRC
&= ReadConsoleW(consoleInfo
.pstSetup
[0].hx
, wcBuf
+nbr
, 1, &nbrx
, 0);
641 if( bRC
) nbr
+= nbrx
;
643 if( !bRC
|| (noc
==0 && nbr
==0) ) return 0;
645 int nmb
= WideCharToMultiByte(CP_UTF8
, 0, wcBuf
,nbr
,0,0,0,0);
646 if( nmb
!= 0 && noc
+nmb
<= ncMax
){
648 nmb
= WideCharToMultiByte(CP_UTF8
, 0, wcBuf
,nbr
,cBuf
+noc
,nmb
,0,0);
650 /* Fixup line-ends as coded by Windows for CR (or "Enter".)
651 ** This is done without regard for any setMode{Text,Binary}()
652 ** call that might have been done on the interactive input.
655 if( cBuf
[noc
-1]=='\n' ){
657 if( noc
> 1 && cBuf
[noc
-2]=='\r' ) cBuf
[--noc
-1] = '\n';
660 /* Check for ^Z (anywhere in line) too, to act as EOF. */
662 if( cBuf
[iseg
]=='\x1a' ){
663 noc
= iseg
; /* Chop ^Z and anything following. */
664 lend
= 1; /* Counts as end of line too. */
669 }else break; /* Drop apparent garbage in. (Could assert.) */
672 /* If got nothing, (after ^Z chop), must be at end-of-file. */
680 return fgets(cBuf
, ncMax
, pfIn
);
681 # if CIO_WIN_WC_XLATE
685 #endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
687 #if defined(_MSC_VER)
688 # pragma warning(default : 4204)
691 #undef SHELL_INVALID_FILE_PTR