- C CLI\sprescanner\smade\sto\smatch\sSQLite's\srules\sfor\sdelimited\sidentifiers.\sTests\sbegun.
- D 2021-09-11T02:42:04.707
-C Further\stests\sfor\slegacy\srtree\sgeom\scallbacks.
-D 2021-09-18T16:15:54.996
++C Sync\sw/trunk,\sfurther\sstreamline\sshell's\sresumable\sprescan.
++D 2021-09-18T21:35:22.366
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c 42b94d37a54200707a95566eff4f7e8a380e32d080016b699f23bd79a73a5028
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
- F src/select.c b2c48dfc02b486fd2da2be1605503615958ba1997d40d994c2946975d0150a31
- F src/shell.c.in be7cd92c042b5e16bfd727404c5b2ec72c8e177ee2e092da6fe3ea031bbf8ece
+ F src/select.c 030c3d07326708343208418c84da607752aebc13c92df929b7c68c7c08e7df54
-F src/shell.c.in b6cf46c676e89a21dd70b2dfb1312116ae4411fc8140af56c794192c1c8270f2
++F src/shell.c.in 639c01f9a743ed73beb1d4b1e982b07b731c3801811d8344063f43b11008582a
F src/sqlite.h.in 4e977a5e2ed1a9e8987ff65a2cab5f99a4298ebf040ea5ff636e1753339ff45a
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
- P 968aed690ba7240f8a256f5ba679cc971f432ff9af0ff99744824af79b952545
- Q +2dd61dd97b0326b59b0bc3c83b4d4b9acf811c5acae4d1003e7525ba7a26daf5
- R 646f691d304e0a026b7432ed79848447
-P 929bcc4098549692c573779d65c4c28027b0a2f48ebbf5b3f038deee24374b67
-R b53a2568f9f1adf1f421cbce84f79cd1
-U dan
-Z 0f8167edfa350ba64179ebda312bfead
++P 15b105c520968855ad960d8929f80af9e9bedc155237af9af1956f7b546947f2 99d6bb22e8735681443bfe67287aa15ce2c57d0d63e304abf8aa01fde50dd021
++R 49a56387d26f2bce27d3217e1e0550b1
+U larrybr
- Z d0aaf8bc6b08262fe824a57812c4fb12
++Z f54f51b048cd8993f1718034d535befc
return rc;
}
-/*
-** Return TRUE if a semicolon occurs anywhere in the first N characters
-** of string z[].
-*/
-static int line_contains_semicolon(const char *z, int N){
- int i;
- for(i=0; i<N; i++){ if( z[i]==';' ) return 1; }
- return 0;
-}
-
-/*
-** Test to see if a line consists entirely of whitespace.
-*/
-static int _all_whitespace(const char *z){
- for(; *z; z++){
- if( IsSpace(z[0]) ) continue;
- if( *z=='/' && z[1]=='*' ){
- z += 2;
- while( *z && (*z!='*' || z[1]!='/') ){ z++; }
- if( *z==0 ) return 0;
- z++;
- continue;
+/* Line scan result and intermediate states (supporting scan resumption)
+*/
+typedef enum {
- QSS_InPlain = 0, QSS_InQuote = 1, QSS_InBlockComment = 2,
- QSS_NoDark = 0, QSS_HasDark = 1<<2, QSS_EndingSemi = 1<<3,
- QSS_ScanMask = 0x3, QSS_DarkMask = 1<<2,
- QSS_CharShift = 4, QSS_StateMask = ((1<<QSS_CharShift)-1),
++ QSS_HasDark = 1<<CHAR_BIT, QSS_EndingSemi = 2<<CHAR_BIT,
++ QSS_CharMask = (1<<CHAR_BIT)-1, QSS_ScanMask = 3<<CHAR_BIT,
+ QSS_Start = 0
+} QuickScanState;
- #define QSS_STATE(qss) ((qss) & QSS_ScanMask)
- #define QSS_SETV(qss, newst) (newst | ((qss) & (QSS_StateMask^QSS_ScanMask)))
- #define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_NoDark)
++#define QSS_SETV(qss, newst) ((newst) | ((qss) & QSS_ScanMask))
++#define QSS_INPLAIN(qss) (((qss)&QSS_CharMask)==QSS_Start)
++#define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_Start)
+#define QSS_PLAINDARK(qss) (((qss)&~QSS_EndingSemi)==QSS_HasDark)
- #define QSS_SEMITERM(qss) \
- (((qss)&(QSS_ScanMask|QSS_EndingSemi))==QSS_EndingSemi)
++#define QSS_SEMITERM(qss) (((qss)&~QSS_HasDark)==QSS_EndingSemi)
+
+/*
+** Scan line for classification to guide shell's handling.
+** The scan is resumable for subsequent lines when prior
+** return values are passed as the 2nd argument.
+*/
+static QuickScanState quickscan(char *zLine, QuickScanState qss){
+ char cin;
- switch( QSS_STATE(qss) ){
- case QSS_InPlain:
- InPlainSet:
- qss = QSS_SETV(qss, QSS_InPlain);
++ char cWait = (char)qss; /* intentional narrowing loss */
++ if( cWait==0 ){
++ PlainScan:
+ while (cin = *zLine++){
+ if( IsSpace(cin) )
+ continue;
+ switch (cin){
+ case '-':
- if( *zLine=='-' ){
- while((cin = *++zLine)!=0 ){
- if( cin=='\n')
- continue;
- }
- return qss;
- }
- break;
++ if( *zLine!='-' )
++ break;
++ while((cin = *++zLine)!=0 )
++ if( cin=='\n')
++ goto PlainScan;
++ return qss;
+ case ';':
+ qss |= QSS_EndingSemi;
+ continue;
+ case '/':
+ if( *zLine=='*' ){
+ ++zLine;
- qss = QSS_SETV(qss, QSS_InBlockComment);
- goto InBlockComment;
++ cWait = '*';
++ qss = QSS_SETV(qss, cWait);
++ goto TermScan;
+ }
+ break;
+ case '[':
+ cin = ']';
+ /* fall thru */
+ case '`': case '\'': case '"':
- qss = qss & ~QSS_EndingSemi | QSS_HasDark;
- qss = QSS_SETV(qss, QSS_InQuote) | (cin<<QSS_CharShift);
- goto InQuote;
++ cWait = cin;
++ qss = QSS_HasDark | cWait;
++ goto TermScan;
+ default:
+ break;
+ }
- qss = qss & ~QSS_EndingSemi | QSS_HasDark;
++ qss = (qss & ~QSS_EndingSemi) | QSS_HasDark;
}
- break;
- case QSS_InQuote:
- InQuote: {
- char cLeave = qss >> QSS_CharShift;
- while (cin = *zLine++){
- if( cin==cLeave ){
- if(*zLine==cLeave && cLeave!=']')
- if( *z=='-' && z[1]=='-' ){
- z += 2;
- while( *z && *z!='\n' ){ z++; }
- if( *z==0 ) return 1;
- continue;
++ }else{
++ TermScan:
++ while (cin = *zLine++){
++ if( cin==cWait ){
++ switch( cWait ){
++ case '*':
++ if( *zLine != '/' )
++ continue;
++ ++zLine;
++ cWait = 0;
++ qss = QSS_SETV(qss, 0);
++ goto PlainScan;
++ case '`': case '\'': case '"':
++ if(*zLine==cWait){
+ ++zLine;
- else
- goto InPlainSet;
++ continue;
++ }
++ /* fall thru */
++ case ']':
++ cWait = 0;
++ qss = QSS_SETV(qss, 0);
++ goto PlainScan;
++ default: assert(0);
+ }
+ }
}
- break;
- case QSS_InBlockComment:
- InBlockComment:
- while (cin = *zLine++){
- if( cin=='*' && *zLine=='/' ){
- ++zLine;
- goto InPlainSet;
- }
- }
- break;
- default:;
- return 0;
}
- return 1;
+ return qss;
}
/*
int rc; /* Error code */
int errCnt = 0; /* Number of errors seen */
int startline = 0; /* Line number for start of current input */
- QuickScanState qss = QSS_InPlain; /* Accumulated line status (so far) */
- int bAllWhite = 1; /* Accumulated line empty or all whitespace */
++ QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */
p->lineno = 0;
while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
seenInterrupt = 0;
}
p->lineno++;
- if( QSS_STATE(qss)==QSS_InPlain
- if( _all_whitespace(zLine) ){
- if( nSql==0 ){
- if( ShellHasFlag(p, SHFLG_Echo) )
- printf("%s\n", zLine);
- continue;
- }
- }else{
- bAllWhite = 0;
++ if( QSS_INPLAIN(qss)
+ && line_is_command_terminator(zLine)
+ && line_is_complete(zSql, nSql) ){
+ memcpy(zLine,";",2);
+ }
+ qss = quickscan(zLine, qss);
+ if( QSS_PLAINWHITE(qss) && nSql==0 ){
+ if( ShellHasFlag(p, SHFLG_Echo) )
+ printf("%s\n", zLine);
+ /* Just swallow leading whitespace */
+ continue;
}
if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);