]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Three different --escape modes: symbol, ascii, off.
authordrh <>
Mon, 24 Feb 2025 00:18:12 +0000 (00:18 +0000)
committerdrh <>
Mon, 24 Feb 2025 00:18:12 +0000 (00:18 +0000)
FossilOrigin-Name: b5adb52fc0dc1838cb9c66cff422f2b8ec147e546cf909dd3c48731fa1edfe50

manifest
manifest.uuid
src/shell.c.in
test/shell1.test

index 2225ae1b75ac705bfebcfea45508c3772c5de815..388bc72c577991502daf9d4b6e57c1ea81f5eb70 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Further\simprovements\sto\scontrol-character\sescapes\sin\sthe\sCLI.
-D 2025-02-23T20:50:37.078
+C Three\sdifferent\s--escape\smodes:\s\ssymbol,\sascii,\soff.
+D 2025-02-24T00:18:12.616
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
@@ -782,7 +782,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c 626c24b258b111f75c22107aa5614ad89810df3026f5ca071116d3fe75925c75
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
 F src/select.c a076f7db3a0fcbd9f710d7746cfc07e0b3baadee45eb3136bedc29c598ef8f1c
-F src/shell.c.in 46794cfa6cdd9b0bbbe35fcf7726ac1f5f7f61bb8f6578ec12ceeab5e0242108
+F src/shell.c.in e846d86150299b4f49ee4ee6a2f3b59d9460c7dda9280b6046d80778b513deec
 F src/sqlite.h.in 8d4486fb28a90de818ac1e8c6206ea458e7de6bd8e0dfa3d554494f155be8c01
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
@@ -1638,7 +1638,7 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
 F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
 F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
-F test/shell1.test 069ad46cc5e576207e684168777b9d093ad419f4573ea96c47cba9d97b344ba9
+F test/shell1.test b9e7b85af3aa614536786f593684ca5317e356821ad505dad32afc2ea0e99f12
 F test/shell2.test 01a01f76ed98088ce598794fbf5b359e148271541a8ddbf79d21cc353cc67a24
 F test/shell3.test db1953a8e59d08e9240b7cc5948878e184f7eb2623591587f8fd1f1a5bd536d8
 F test/shell4.test 522fdc628c55eff697b061504fb0a9e4e6dfc5d9087a633ab0f3dd11bcc4f807
@@ -2210,8 +2210,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 44c44620e8648a4265053f194e32b3a5c65d25b4f1fff61ef9b944e7cb0ed624
-R b68c8cdbf574035092ab2e3bfafec994
+P 9c2f974c17e3dfac78f3808fdfe916f7617cfdaa64430af38eae21bd6592e6f5
+R 76a86dfe0f25913e8833da92cffca725
 U drh
-Z 1875645df727b6997bdc49f0eb677111
+Z b3eaebce72752a9b1304ed1c64dcf320
 # Remove this line to create a well-formed Fossil manifest.
index a486e0cfcf273fa154d36989df4a91e20fa07d0c..890ec996a046857c129826e86f5481fc2a54f297 100644 (file)
@@ -1 +1 @@
-9c2f974c17e3dfac78f3808fdfe916f7617cfdaa64430af38eae21bd6592e6f5
+b5adb52fc0dc1838cb9c66cff422f2b8ec147e546cf909dd3c48731fa1edfe50
index 515da6adae3f87665d2ee8ceb38d32968a5e0a36..3bc8d2717322789ff47c6af86cb89435a6af2226 100644 (file)
@@ -1549,8 +1549,11 @@ static ShellState shellState;
 
 /* Allowed values for ShellState.eEscMode
 */
-#define SHELL_ESC_GRAPHIC      0      /* Substitute U+2400 graphics */
-#define SHELL_ESC_OFF          1      /* Send characters verbatim */
+#define SHELL_ESC_SYMBOL       0      /* Substitute U+2400 graphics */
+#define SHELL_ESC_ASCII        1      /* Substitute ^Y for X where Y=X+0x40 */
+#define SHELL_ESC_OFF          2      /* Send characters verbatim */
+
+static const char *shell_EscModeNames[] = { "symbol", "ascii", "off" };
 
 /*
 ** These are the allowed shellFlgs values
@@ -2160,7 +2163,8 @@ static const char *escapeOutput(
     *ppFree = 0;
     return zInX;
   }
-  zOut = sqlite3_malloc64( i + 2*nCtrl + 1 );
+  if( p->eEscMode==SHELL_ESC_SYMBOL ) nCtrl *= 2;
+  zOut = sqlite3_malloc64( i + nCtrl + 1 );
   shell_check_oom(zOut);
   for(i=j=0; (c = zIn[i])!=0; i++){
     if( c>0x1f
@@ -2176,9 +2180,17 @@ static const char *escapeOutput(
     }
     zIn += i+1;
     i = -1;
-    zOut[j++] = 0xe2;
-    zOut[j++] = 0x90;
-    zOut[j++] = 0x80+c;
+    switch( p->eEscMode ){
+      case SHELL_ESC_SYMBOL: 
+        zOut[j++] = 0xe2;
+        zOut[j++] = 0x90;
+        zOut[j++] = 0x80+c;
+        break;
+      case SHELL_ESC_ASCII:
+        zOut[j++] = '^';
+        zOut[j++] = 0x40+c;
+        break;
+    }
   }
   if( i>0 ){
     memcpy(&zOut[j], zIn, i);
@@ -9833,28 +9845,50 @@ static int do_meta_command(char *zLine, ShellState *p){
     const char *zMode = 0;
     const char *zTabname = 0;
     int i, n2;
+    int chng = 0;
     ColModeOpts cmOpts = ColModeOpts_default;
     for(i=1; i<nArg; i++){
       const char *z = azArg[i];
       if( optionMatch(z,"wrap") && i+1<nArg ){
         cmOpts.iWrap = integerValue(azArg[++i]);
+        chng = 1;
       }else if( optionMatch(z,"ww") ){
         cmOpts.bWordWrap = 1;
+        chng = 1;
       }else if( optionMatch(z,"wordwrap") && i+1<nArg ){
         cmOpts.bWordWrap = (u8)booleanValue(azArg[++i]);
+        chng = 1;
       }else if( optionMatch(z,"quote") ){
         cmOpts.bQuote = 1;
+        chng = 1;
       }else if( optionMatch(z,"noquote") ){
         cmOpts.bQuote = 0;
-      }else if( optionMatch(z,"escape") ){
-        p->eEscMode = SHELL_ESC_GRAPHIC;
-      }else if( optionMatch(z,"noescape") ){
-        p->eEscMode = SHELL_ESC_OFF;
+        chng = 1;
+      }else if( optionMatch(z,"escape") && i+1<nArg ){
+        const char *zEsc = azArg[++i];
+        int k;
+        for(k=0; k<ArraySize(shell_EscModeNames); k++){
+          if( sqlite3_stricmp(zEsc,shell_EscModeNames[k])==0 ){
+            p->eEscMode = k;
+            chng = 1;
+            break;
+          }
+        }
+        if( k>=ArraySize(shell_EscModeNames) ){
+          sqlite3_fprintf(stderr, "unknown escape mod \"%s\" - choices:", zEsc);
+          for(k=0; k<ArraySize(shell_EscModeNames); k++){
+            sqlite3_fprintf(stderr, " %s", shell_EscModeNames[k]);
+          }
+          sqlite3_fprintf(stderr, "\n");
+          rc = 1;
+          goto meta_command_exit;
+        }
       }else if( zMode==0 ){
         zMode = z;
         /* Apply defaults for qbox pseudo-mode.  If that
          * overwrites already-set values, user was informed of this.
          */
+        chng = 1;
         if( cli_strcmp(z, "qbox")==0 ){
           ColModeOpts cmo = ColModeOpts_default_qbox;
           zMode = "box";
@@ -9865,6 +9899,7 @@ static int do_meta_command(char *zLine, ShellState *p){
       }else if( z[0]=='-' ){
         sqlite3_fprintf(stderr,"unknown option: %s\n", z);
         eputz("options:\n"
+              "  --escape MODE\n"
               "  --noquote\n"
               "  --quote\n"
               "  --wordwrap on/off\n"
@@ -9878,25 +9913,27 @@ static int do_meta_command(char *zLine, ShellState *p){
         goto meta_command_exit;
       }
     }
-    if( zMode==0 ){
+    if( !chng ){
       if( p->mode==MODE_Column
        || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
       ){
         sqlite3_fprintf(p->out,
               "current output mode: %s --wrap %d --wordwrap %s "
-              "--%squote --%sescape\n",
+              "--%squote --escape %s\n",
               modeDescr[p->mode], p->cmOpts.iWrap,
               p->cmOpts.bWordWrap ? "on" : "off",
               p->cmOpts.bQuote ? "" : "no",
-              p->eEscMode ? "no" : ""
+              shell_EscModeNames[p->eEscMode]
         );
       }else{
         sqlite3_fprintf(p->out,
-              "current output mode: %s --%sescape\n",
+              "current output mode: %s --escape %s\n",
               modeDescr[p->mode],
-              p->eEscMode ? "no" : ""
+              shell_EscModeNames[p->eEscMode]
         );
       }
+    }
+    if( zMode==0 ){
       zMode = modeDescr[p->mode];
     }
     n2 = strlen30(zMode);
@@ -12650,7 +12687,7 @@ static const char zOptions[] =
   "   -deserialize         open the database using sqlite3_deserialize()\n"
 #endif
   "   -echo                print inputs before execution\n"
-  "   -escape              print control character XX as U+24XX\n"
+  "   -escape MODE         ctrl-char escape mode, one of: symbol, ascii, off\n"
   "   -init FILENAME       read/process named file\n"
   "   -[no]header          turn headers on or off\n"
 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
@@ -12673,7 +12710,6 @@ static const char zOptions[] =
   "   -multiplex           enable the multiplexor VFS\n"
 #endif
   "   -newline SEP         set output row separator. Default: '\\n'\n"
-  "   -noescape            output control characters unmodified\n"
   "   -nofollow            refuse to open symbolic links to database files\n"
   "   -nonce STRING        set the safe-mode escape nonce\n"
   "   -no-rowid-in-view    Disable rowid-in-view using sqlite3_config()\n"
@@ -13085,6 +13121,9 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
       ShellSetFlag(&data,SHFLG_TestingMode);
     }else if( cli_strcmp(z,"-safe")==0 ){
       /* no-op - catch this on the second pass */
+    }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
+      /* skip over the argument */
+      i++;
     }
   }
 #ifndef SQLITE_SHELL_FIDDLE
@@ -13184,10 +13223,23 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
     }else if( cli_strcmp(z,"-csv")==0 ){
       data.mode = MODE_Csv;
       memcpy(data.colSeparator,",",2);
-    }else if( cli_strcmp(z,"-noescape")==0 ){
-      data.eEscMode = SHELL_ESC_OFF;
-    }else if( cli_strcmp(z,"-escape")==0 ){
-      data.eEscMode = SHELL_ESC_GRAPHIC;
+    }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
+      const char *zEsc = argv[++i];
+      int k;
+      for(k=0; k<ArraySize(shell_EscModeNames); k++){
+        if( sqlite3_stricmp(zEsc,shell_EscModeNames[k])==0 ){
+          data.eEscMode = k;
+          break;
+        }
+      }
+      if( k>=ArraySize(shell_EscModeNames) ){
+        sqlite3_fprintf(stderr, "unknown escape mode \"%s\" - choices:", zEsc);
+        for(k=0; k<ArraySize(shell_EscModeNames); k++){
+          sqlite3_fprintf(stderr, " %s", shell_EscModeNames[k]);
+        }
+        sqlite3_fprintf(stderr, "\n");
+        exit(1);
+      }
 #ifdef SQLITE_HAVE_ZLIB
     }else if( cli_strcmp(z,"-zip")==0 ){
       data.openMode = SHELL_OPEN_ZIPFILE;
index 6189ff83a02064376b9c7e20f9644b7c8d956537..1aa974cde3f960770114cc384fec709e42571701 100644 (file)
@@ -450,7 +450,7 @@ do_test shell1-3.12.3 {
 #                          tcl      TCL list elements
 do_test shell1-3.13.1 {
   catchcmd "test.db" ".mode"
-} {0 {current output mode: list --escape}}
+} {0 {current output mode: list --escape symbol}}
 do_test shell1-3.13.2 {
   catchcmd "test.db" ".mode FOO"
 } {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl}}