]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Clean up the input reader in the command-line shell for improved legibility
authordrh <drh@noemail.net>
Tue, 6 Aug 2013 14:01:46 +0000 (14:01 +0000)
committerdrh <drh@noemail.net>
Tue, 6 Aug 2013 14:01:46 +0000 (14:01 +0000)
and performance.

FossilOrigin-Name: 2b1743d60171635c1e5a6ede6b4928f4671f948d

manifest
manifest.uuid
src/shell.c

index df242bb579969ee853384eced1b96b34e4317db6..0608ff28e739698f560b98a692fd8330b6407031 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C More\sthan\sdouble\sthe\sspeed\sof\sthe\sresolveP2Values()\sroutine\sin\svdbeaux.c\sby\nmoving\sfrom\san\sextended\sif-else\son\severy\sopcode\sto\sa\sswitch.\s\sOpcodes\sare\nreordered\sin\smkopcodesh.awk\sto\sput\sthe\sswitched\sopcodes\sclose\stogether,\nfor\sadditional\sperformance\sand\sto\sreduce\scode\sfootprint.
-D 2013-08-06T07:45:08.160
+C Clean\sup\sthe\sinput\sreader\sin\sthe\scommand-line\sshell\sfor\simproved\slegibility\nand\sperformance.
+D 2013-08-06T14:01:46.052
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -217,7 +217,7 @@ F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
 F src/resolve.c 17e670996729ac41aadf6a31f57b4e6f29b3d819
 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
 F src/select.c 8b148eb851f384412aea57091659d14b369918ca
-F src/shell.c 52f975eae87c8338c4dfbf4c2842d2a0971f01fd
+F src/shell.c 18be30ad43044f1d84441667c8b50df0b4996db9
 F src/sqlite.h.in 442c109e0c3447c34b1794971ecdb673ce08a843
 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
@@ -1105,7 +1105,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
-P c589b2fed7beabc2337d701094c22635914d9c23
-R 63c66722ef11a129368dbe6ccc84108b
+P 924f7e4d7a8fa2fe9100836663f3733b6e1a9084
+R a0a003b94645637a781f18f2495d5c36
 U drh
-Z db760ef775aca796d7a23f90b9b7ee9e
+Z 390282ae711b439a5d58cc71aa5c9578
index 43da133fc81f366087bfbfd4dc7c7831f20c611a..039cfbac29a103993ee8e21a69d08c07303fc9a9 100644 (file)
@@ -1 +1 @@
-924f7e4d7a8fa2fe9100836663f3733b6e1a9084
\ No newline at end of file
+2b1743d60171635c1e5a6ede6b4928f4671f948d
\ No newline at end of file
index 7b8a8ad7f305b2bdbbcb921b1938843440b4ba92..65bf5511d56a235cb590858ddd9ce3262812bd5c 100644 (file)
@@ -53,7 +53,6 @@
 # include <readline/history.h>
 #endif
 #if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1)
-# define readline(p) local_getline(p,stdin,0)
 # define add_history(X)
 # define read_history(X)
 # define write_history(X)
@@ -337,23 +336,13 @@ static void shellstaticFunc(
 ** to the text.  NULL is returned at end of file, or if malloc()
 ** fails.
 **
-** The interface is like "readline" but no command-line editing
-** is done.
+** If zLine is not NULL then it is a malloced buffer returned from
+** a previous call to this routine that may be reused.
 */
-static char *local_getline(char *zPrompt, FILE *in, int csvFlag){
-  char *zLine;
-  int nLine;
-  int n;
-  int inQuote = 0;
+static char *local_getline(char *zLine, FILE *in){
+  int nLine = zLine==0 ? 0 : 100;
+  int n = 0;
 
-  if( zPrompt && *zPrompt ){
-    printf("%s",zPrompt);
-    fflush(stdout);
-  }
-  nLine = 100;
-  zLine = malloc( nLine );
-  if( zLine==0 ) return 0;
-  n = 0;
   while( 1 ){
     if( n+100>nLine ){
       nLine = nLine*2 + 100;
@@ -368,42 +357,48 @@ static char *local_getline(char *zPrompt, FILE *in, int csvFlag){
       zLine[n] = 0;
       break;
     }
-    while( zLine[n] ){
-      if( zLine[n]=='"' ) inQuote = !inQuote;
-      n++;
-    }
-    if( n>0 && zLine[n-1]=='\n' && (!inQuote || !csvFlag) ){
+    while( zLine[n] ) n++;
+    if( n>0 && zLine[n-1]=='\n' ){
       n--;
       if( n>0 && zLine[n-1]=='\r' ) n--;
       zLine[n] = 0;
       break;
     }
   }
-  zLine = realloc( zLine, n+1 );
   return zLine;
 }
 
 /*
 ** Retrieve a single line of input text.
 **
-** zPrior is a string of prior text retrieved.  If not the empty
-** string, then issue a continuation prompt.
+** If in==0 then read from standard input and prompt before each line.
+** If isContinuation is true, then a continuation prompt is appropriate.
+** If isContinuation is zero, then the main prompt should be used.
+**
+** If zPrior is not NULL then it is a buffer from a prior call to this
+** routine that can be reused.
+**
+** The result is stored in space obtained from malloc() and must either
+** be freed by the caller or else passed back into this routine via the
+** zPrior argument for reuse.
 */
-static char *one_input_line(const char *zPrior, FILE *in){
+static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
   char *zPrompt;
   char *zResult;
   if( in!=0 ){
-    return local_getline(0, in, 0);
-  }
-  if( zPrior && zPrior[0] ){
-    zPrompt = continuePrompt;
+    zResult = local_getline(zPrior, in);
   }else{
-    zPrompt = mainPrompt;
-  }
-  zResult = readline(zPrompt);
+    zPrompt = isContinuation ? continuePrompt : mainPrompt;
 #if defined(HAVE_READLINE) && HAVE_READLINE==1
-  if( zResult && *zResult ) add_history(zResult);
+    free(zPrior);
+    zResult = readline(zPrompt);
+    if( zResult && *zResult ) add_history(zResult);
+#else
+    printf("%s", zPrompt);
+    fflush(stdout);
+    zResult = local_getline(zPrior, stdin);
 #endif
+  }
   return zResult;
 }
 
@@ -2781,7 +2776,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
 ** Return TRUE if a semicolon occurs anywhere in the first N characters
 ** of string z[].
 */
-static int _contains_semicolon(const char *z, int N){
+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;
@@ -2816,7 +2811,7 @@ static int _all_whitespace(const char *z){
 ** than a semi-colon.  The SQL Server style "go" command is understood
 ** as is the Oracle "/".
 */
-static int _is_command_terminator(const char *zLine){
+static int line_is_command_terminator(const char *zLine){
   while( IsSpace(zLine[0]) ){ zLine++; };
   if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
     return 1;  /* Oracle */
@@ -2832,7 +2827,7 @@ static int _is_command_terminator(const char *zLine){
 ** Return true if zSql is a complete SQL statement.  Return false if it
 ** ends in the middle of a string literal or C-style comment.
 */
-static int _is_complete(char *zSql, int nSql){
+static int line_is_complete(char *zSql, int nSql){
   int rc;
   if( zSql==0 ) return 1;
   zSql[nSql] = ';';
@@ -2852,20 +2847,21 @@ static int _is_complete(char *zSql, int nSql){
 ** Return the number of errors.
 */
 static int process_input(struct callback_data *p, FILE *in){
-  char *zLine = 0;
-  char *zSql = 0;
-  int nSql = 0;
-  int nSqlPrior = 0;
-  char *zErrMsg;
-  int rc;
-  int errCnt = 0;
-  int lineno = 0;
-  int startline = 0;
+  char *zLine = 0;          /* A single input line */
+  char *zSql = 0;           /* Accumulated SQL text */
+  int nLine;                /* Length of current line */
+  int nSql = 0;             /* Bytes of zSql[] used */
+  int nAlloc = 0;           /* Allocated zSql[] space */
+  int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */
+  char *zErrMsg;            /* Error message returned */
+  int rc;                   /* Error code */
+  int errCnt = 0;           /* Number of errors seen */
+  int lineno = 0;           /* Current line number */
+  int startline = 0;        /* Line number for start of current input */
 
   while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
     fflush(p->out);
-    free(zLine);
-    zLine = one_input_line(zSql, in);
+    zLine = one_input_line(in, zLine, nSql>0);
     if( zLine==0 ){
       /* End of input */
       if( stdin_is_interactive ) printf("\n");
@@ -2876,7 +2872,7 @@ static int process_input(struct callback_data *p, FILE *in){
       seenInterrupt = 0;
     }
     lineno++;
-    if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
+    if( nSql==0 && _all_whitespace(zLine) ) continue;
     if( zLine && zLine[0]=='.' && nSql==0 ){
       if( p->echoOn ) printf("%s\n", zLine);
       rc = do_meta_command(zLine, p);
@@ -2887,35 +2883,31 @@ static int process_input(struct callback_data *p, FILE *in){
       }
       continue;
     }
-    if( _is_command_terminator(zLine) && _is_complete(zSql, nSql) ){
+    if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){
       memcpy(zLine,";",2);
     }
+    nLine = strlen30(zLine);
+    if( nSql+nLine+2>=nAlloc ){
+      nAlloc = nSql+nLine+100;
+      zSql = realloc(zSql, nAlloc);
+      if( zSql==0 ){
+        fprintf(stderr, "Error: out of memory\n");
+        exit(1);
+      }
+    }
     nSqlPrior = nSql;
-    if( zSql==0 ){
+    if( nSql==0 ){
       int i;
       for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
-      if( zLine[i]!=0 ){
-        nSql = strlen30(zLine);
-        zSql = malloc( nSql+3 );
-        if( zSql==0 ){
-          fprintf(stderr, "Error: out of memory\n");
-          exit(1);
-        }
-        memcpy(zSql, zLine, nSql+1);
-        startline = lineno;
-      }
+      memcpy(zSql, zLine+i, nLine+1-i);
+      startline = lineno;
+      nSql = nLine-i;
     }else{
-      int len = strlen30(zLine);
-      zSql = realloc( zSql, nSql + len + 4 );
-      if( zSql==0 ){
-        fprintf(stderr,"Error: out of memory\n");
-        exit(1);
-      }
       zSql[nSql++] = '\n';
-      memcpy(&zSql[nSql], zLine, len+1);
-      nSql += len;
+      memcpy(zSql+nSql, zLine, nLine+1);
+      nSql += nLine;
     }
-    if( zSql && _contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
+    if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
                 && sqlite3_complete(zSql) ){
       p->cnt = 0;
       open_db(p);
@@ -2939,16 +2931,12 @@ static int process_input(struct callback_data *p, FILE *in){
         }
         errCnt++;
       }
-      free(zSql);
-      zSql = 0;
       nSql = 0;
-    }else if( zSql && _all_whitespace(zSql) ){
-      free(zSql);
-      zSql = 0;
+    }else if( nSql && _all_whitespace(zSql) ){
       nSql = 0;
     }
   }
-  if( zSql ){
+  if( nSql ){
     if( !_all_whitespace(zSql) ){
       fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);
     }