/ Check-in [9fb69919]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Improved shell "dot" command argument handling. Ticket [f12a9eeedc].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9fb699193378bf812ef97889adc0b1a98ad56d5b
User & Date: shaneh 2009-11-06 17:20:17
References
2009-11-06
17:22 Fixed ticket [f12a9eee]: Shell command argument parsing is lax plus 2 other changes artifact: 84f729d1 user: shane
Context
2009-11-10
01:12
Omit some code that is not used when SQLITE_SECURE_DELETE is defined. check-in: 5a9e7463 user: drh tags: trunk
2009-11-06
17:20
Improved shell "dot" command argument handling. Ticket [f12a9eeedc]. check-in: 9fb69919 user: shaneh tags: trunk
04:13
Fix the backup API so that a backup from an empty database to a non-empty database works. Ticket [0bf974bdf9]. The only changes are in assert() statements. check-in: ddb71cd9 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/shell.c.

  2136   2136     ".bail ON|OFF           Stop after hitting an error.  Default OFF\n"
  2137   2137     ".databases             List names and files of attached databases\n"
  2138   2138     ".dump ?TABLE? ...      Dump the database in an SQL text format\n"
  2139   2139     "                         If TABLE specified, only dump tables matching\n"
  2140   2140     "                         LIKE pattern TABLE.\n"
  2141   2141     ".echo ON|OFF           Turn command echo on or off\n"
  2142   2142     ".exit                  Exit this program\n"
  2143         -  ".explain ON|OFF        Turn output mode suitable for EXPLAIN on or off.\n"
         2143  +  ".explain ?ON|OFF?      Turn output mode suitable for EXPLAIN on or off.\n"
         2144  +  "                         With no args, it turns EXPLAIN on.\n"
  2144   2145   #if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_SUBQUERY)
  2145   2146     ".genfkey ?OPTIONS?     Options are:\n"
  2146   2147     "                         --no-drop: Do not drop old fkey triggers.\n"
  2147   2148     "                         --ignore-errors: Ignore tables with fkey errors\n"
  2148   2149     "                         --exec: Execute generated SQL immediately\n"
  2149   2150     "                       See file tool/genfkey.README in the source \n"
  2150   2151     "                       distribution for further information.\n"
................................................................................
  2182   2183     "                         LIKE pattern TABLE.\n"
  2183   2184     ".separator STRING      Change separator used by output mode and .import\n"
  2184   2185     ".show                  Show the current values for various settings\n"
  2185   2186     ".tables ?TABLE?        List names of tables\n"
  2186   2187     "                         If TABLE specified, only list tables matching\n"
  2187   2188     "                         LIKE pattern TABLE.\n"
  2188   2189     ".timeout MS            Try opening locked tables for MS milliseconds\n"
  2189         -  ".width NUM NUM ...     Set column widths for \"column\" mode\n"
         2190  +  ".width NUM1 NUM2 ...   Set column widths for \"column\" mode\n"
  2190   2191   ;
  2191   2192   
  2192   2193   static char zTimerHelp[] =
  2193   2194     ".timer ON|OFF          Turn the CPU timer measurement on or off\n"
  2194   2195   ;
  2195   2196   
  2196   2197   /* Forward reference */
................................................................................
  2309   2310     }
  2310   2311   
  2311   2312     /* Process the input line.
  2312   2313     */
  2313   2314     if( nArg==0 ) return 0; /* no tokens, no error */
  2314   2315     n = strlen30(azArg[0]);
  2315   2316     c = azArg[0][0];
  2316         -  if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 && nArg>1 ){
         2317  +  if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 && nArg>1 && nArg<4){
  2317   2318       const char *zDestFile;
  2318   2319       const char *zDb;
  2319   2320       sqlite3 *pDest;
  2320   2321       sqlite3_backup *pBackup;
  2321   2322       if( nArg==2 ){
  2322   2323         zDestFile = azArg[1];
  2323   2324         zDb = "main";
................................................................................
  2345   2346       }else{
  2346   2347         fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
  2347   2348         rc = 1;
  2348   2349       }
  2349   2350       sqlite3_close(pDest);
  2350   2351     }else
  2351   2352   
  2352         -  if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 && nArg>1 ){
         2353  +  if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 && nArg>1 && nArg<3 ){
  2353   2354       bail_on_error = booleanValue(azArg[1]);
  2354   2355     }else
  2355   2356   
  2356         -  if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
         2357  +  if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){
  2357   2358       struct callback_data data;
  2358   2359       char *zErrMsg = 0;
  2359   2360       open_db(p);
  2360   2361       memcpy(&data, p, sizeof(data));
  2361   2362       data.showHeader = 1;
  2362   2363       data.mode = MODE_Column;
  2363   2364       data.colWidth[0] = 3;
................................................................................
  2368   2369       if( zErrMsg ){
  2369   2370         fprintf(stderr,"Error: %s\n", zErrMsg);
  2370   2371         sqlite3_free(zErrMsg);
  2371   2372         rc = 1;
  2372   2373       }
  2373   2374     }else
  2374   2375   
  2375         -  if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
         2376  +  if( c=='d' && strncmp(azArg[0], "dump", n)==0 && nArg<3 ){
  2376   2377       char *zErrMsg = 0;
  2377   2378       open_db(p);
  2378   2379       /* When playing back a "dump", the content might appear in an order
  2379   2380       ** which causes immediate foreign key constraints to be violated.
  2380   2381       ** So disable foreign-key constraint enforcement to prevent problems. */
  2381   2382       fprintf(p->out, "PRAGMA foreign_keys=OFF;\n");
  2382   2383       fprintf(p->out, "BEGIN TRANSACTION;\n");
................................................................................
  2421   2422         fprintf(stderr,"Error: %s\n", zErrMsg);
  2422   2423         sqlite3_free(zErrMsg);
  2423   2424       }else{
  2424   2425         fprintf(p->out, "COMMIT;\n");
  2425   2426       }
  2426   2427     }else
  2427   2428   
  2428         -  if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){
         2429  +  if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){
  2429   2430       p->echoOn = booleanValue(azArg[1]);
  2430   2431     }else
  2431   2432   
  2432         -  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
         2433  +  if( c=='e' && strncmp(azArg[0], "exit", n)==0  && nArg==1 ){
  2433   2434       rc = 2;
  2434   2435     }else
  2435   2436   
  2436         -  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
         2437  +  if( c=='e' && strncmp(azArg[0], "explain", n)==0 && nArg<3 ){
  2437   2438       int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
  2438   2439       if(val == 1) {
  2439   2440         if(!p->explainPrev.valid) {
  2440   2441           p->explainPrev.valid = 1;
  2441   2442           p->explainPrev.mode = p->mode;
  2442   2443           p->explainPrev.showHeader = p->showHeader;
  2443   2444           memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth));
................................................................................
  2476   2477         cmd.pCb = p;
  2477   2478         genfkey_create_triggers(p->db, "main", (void *)&cmd, genfkeyCmdCb);
  2478   2479       }
  2479   2480     }else
  2480   2481   #endif
  2481   2482   
  2482   2483     if( c=='h' && (strncmp(azArg[0], "header", n)==0 ||
  2483         -                 strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){
         2484  +                 strncmp(azArg[0], "headers", n)==0) && nArg>1 && nArg<3 ){
  2484   2485       p->showHeader = booleanValue(azArg[1]);
  2485   2486     }else
  2486   2487   
  2487   2488     if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
  2488   2489       fprintf(stderr,"%s",zHelp);
  2489   2490       if( HAS_TIMER ){
  2490   2491         fprintf(stderr,"%s",zTimerHelp);
  2491   2492       }
  2492   2493     }else
  2493   2494   
  2494         -  if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg>=3 ){
         2495  +  if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){
  2495   2496       char *zTable = azArg[2];    /* Insert data into this table */
  2496   2497       char *zFile = azArg[1];     /* The file from which to extract data */
  2497   2498       sqlite3_stmt *pStmt = NULL; /* A statement */
  2498   2499       int nCol;                   /* Number of columns in the table */
  2499   2500       int nByte;                  /* Number of bytes in an SQL string */
  2500   2501       int i, j;                   /* Loop counters */
  2501   2502       int nSep;                   /* Number of bytes in p->separator[] */
................................................................................
  2604   2605       } /* end while */
  2605   2606       free(azCol);
  2606   2607       fclose(in);
  2607   2608       sqlite3_finalize(pStmt);
  2608   2609       sqlite3_exec(p->db, zCommit, 0, 0, 0);
  2609   2610     }else
  2610   2611   
  2611         -  if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){
         2612  +  if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){
  2612   2613       struct callback_data data;
  2613   2614       char *zErrMsg = 0;
  2614   2615       open_db(p);
  2615   2616       memcpy(&data, p, sizeof(data));
  2616   2617       data.showHeader = 0;
  2617   2618       data.mode = MODE_List;
  2618   2619       if( nArg==1 ){
................................................................................
  2683   2684         fprintf(stderr, "Error: %s\n", zErrMsg);
  2684   2685         sqlite3_free(zErrMsg);
  2685   2686         rc = 1;
  2686   2687       }
  2687   2688     }else
  2688   2689   #endif
  2689   2690   
  2690         -  if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){
         2691  +  if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==2 ){
  2691   2692       int n2 = strlen30(azArg[1]);
  2692         -    if( strncmp(azArg[1],"line",n2)==0
         2693  +    if( (n2==4 && strncmp(azArg[1],"line",n2)==0)
  2693   2694           ||
  2694         -        strncmp(azArg[1],"lines",n2)==0 ){
         2695  +        (n2==5 && strncmp(azArg[1],"lines",n2)==0) ){
  2695   2696         p->mode = MODE_Line;
  2696         -    }else if( strncmp(azArg[1],"column",n2)==0
         2697  +    }else if( (n2==6 && strncmp(azArg[1],"column",n2)==0)
  2697   2698                 ||
  2698         -              strncmp(azArg[1],"columns",n2)==0 ){
         2699  +              (n2==7 && strncmp(azArg[1],"columns",n2)==0) ){
  2699   2700         p->mode = MODE_Column;
  2700         -    }else if( strncmp(azArg[1],"list",n2)==0 ){
         2701  +    }else if( n2==4 && strncmp(azArg[1],"list",n2)==0 ){
  2701   2702         p->mode = MODE_List;
  2702         -    }else if( strncmp(azArg[1],"html",n2)==0 ){
         2703  +    }else if( n2==4 && strncmp(azArg[1],"html",n2)==0 ){
  2703   2704         p->mode = MODE_Html;
  2704         -    }else if( strncmp(azArg[1],"tcl",n2)==0 ){
         2705  +    }else if( n2==3 && strncmp(azArg[1],"tcl",n2)==0 ){
  2705   2706         p->mode = MODE_Tcl;
  2706         -    }else if( strncmp(azArg[1],"csv",n2)==0 ){
         2707  +    }else if( n2==3 && strncmp(azArg[1],"csv",n2)==0 ){
  2707   2708         p->mode = MODE_Csv;
  2708   2709         sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
  2709         -    }else if( strncmp(azArg[1],"tabs",n2)==0 ){
         2710  +    }else if( n2==4 && strncmp(azArg[1],"tabs",n2)==0 ){
  2710   2711         p->mode = MODE_List;
  2711   2712         sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
  2712         -    }else if( strncmp(azArg[1],"insert",n2)==0 ){
         2713  +    }else if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){
  2713   2714         p->mode = MODE_Insert;
  2714         -      if( nArg>=3 ){
  2715         -        set_table_name(p, azArg[2]);
  2716         -      }else{
  2717         -        set_table_name(p, "table");
  2718         -      }
         2715  +      set_table_name(p, "table");
  2719   2716       }else {
  2720   2717         fprintf(stderr,"Error: mode should be one of: "
  2721   2718            "column csv html insert line list tabs tcl\n");
  2722   2719         rc = 1;
  2723   2720       }
  2724   2721     }else
         2722  +
         2723  +  if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==3 ){
         2724  +    int n2 = strlen30(azArg[1]);
         2725  +    if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){
         2726  +      p->mode = MODE_Insert;
         2727  +      set_table_name(p, azArg[2]);
         2728  +    }else {
         2729  +      fprintf(stderr, "Error: invalid arguments: "
         2730  +        " \"%s\". Enter \".help\" for help\n", azArg[2]);
         2731  +      rc = 1;
         2732  +    }
         2733  +  }else
  2725   2734   
  2726   2735     if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) {
  2727   2736       sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue,
  2728   2737                        "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
  2729   2738     }else
  2730   2739   
  2731   2740     if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
................................................................................
  2752   2761         strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
  2753   2762       }
  2754   2763       if( nArg >= 3) {
  2755   2764         strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
  2756   2765       }
  2757   2766     }else
  2758   2767   
  2759         -  if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
         2768  +  if( c=='q' && strncmp(azArg[0], "quit", n)==0 && nArg==1 ){
  2760   2769       rc = 2;
  2761   2770     }else
  2762   2771   
  2763   2772     if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
  2764   2773       FILE *alt = fopen(azArg[1], "rb");
  2765   2774       if( alt==0 ){
  2766   2775         fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
................................................................................
  2767   2776         rc = 1;
  2768   2777       }else{
  2769   2778         rc = process_input(p, alt);
  2770   2779         fclose(alt);
  2771   2780       }
  2772   2781     }else
  2773   2782   
  2774         -  if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 && nArg>1 ){
         2783  +  if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 && nArg>1 && nArg<4){
  2775   2784       const char *zSrcFile;
  2776   2785       const char *zDb;
  2777   2786       sqlite3 *pSrc;
  2778   2787       sqlite3_backup *pBackup;
  2779   2788       int nTimeout = 0;
  2780   2789   
  2781   2790       if( nArg==2 ){
................................................................................
  2814   2823       }else{
  2815   2824         fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
  2816   2825         rc = 1;
  2817   2826       }
  2818   2827       sqlite3_close(pSrc);
  2819   2828     }else
  2820   2829   
  2821         -  if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
         2830  +  if( c=='s' && strncmp(azArg[0], "schema", n)==0 && nArg<3 ){
  2822   2831       struct callback_data data;
  2823   2832       char *zErrMsg = 0;
  2824   2833       open_db(p);
  2825   2834       memcpy(&data, p, sizeof(data));
  2826   2835       data.showHeader = 0;
  2827   2836       data.mode = MODE_Semi;
  2828   2837       if( nArg>1 ){
................................................................................
  2892   2901     }else
  2893   2902   
  2894   2903     if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
  2895   2904       sqlite3_snprintf(sizeof(p->separator), p->separator,
  2896   2905                        "%.*s", (int)sizeof(p->separator)-1, azArg[1]);
  2897   2906     }else
  2898   2907   
  2899         -  if( c=='s' && strncmp(azArg[0], "show", n)==0){
         2908  +  if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){
  2900   2909       int i;
  2901   2910       fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
  2902   2911       fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
  2903   2912       fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
  2904   2913       fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
  2905   2914       fprintf(p->out,"%9.9s: ", "nullvalue");
  2906   2915         output_c_string(p->out, p->nullvalue);
................................................................................
  2913   2922       fprintf(p->out,"%9.9s: ","width");
  2914   2923       for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
  2915   2924         fprintf(p->out,"%d ",p->colWidth[i]);
  2916   2925       }
  2917   2926       fprintf(p->out,"\n");
  2918   2927     }else
  2919   2928   
  2920         -  if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
         2929  +  if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){
  2921   2930       char **azResult;
  2922   2931       int nRow;
  2923   2932       char *zErrMsg;
  2924   2933       open_db(p);
  2925   2934       if( nArg==1 ){
  2926   2935         rc = sqlite3_get_table(p->db,
  2927   2936           "SELECT name FROM sqlite_master "
................................................................................
  2971   2980           }
  2972   2981           printf("\n");
  2973   2982         }
  2974   2983       }
  2975   2984       sqlite3_free_table(azResult);
  2976   2985     }else
  2977   2986   
  2978         -  if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){
         2987  +  if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg==2 ){
  2979   2988       open_db(p);
  2980   2989       sqlite3_busy_timeout(p->db, atoi(azArg[1]));
  2981         -  }else if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 && nArg>1 ){
         2990  +  }else
         2991  +    
         2992  +  if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 && nArg==2 ){
  2982   2993       enableTimer = booleanValue(azArg[1]);
  2983         -  }else if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
         2994  +  }else
         2995  +  
         2996  +  if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
  2984   2997       int j;
  2985   2998       assert( nArg<=ArraySize(azArg) );
  2986   2999       for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
  2987   3000         p->colWidth[j-1] = atoi(azArg[j]);
  2988   3001       }
  2989   3002     }else
  2990   3003   

Changes to tool/shell1.test.

    12     12   # The focus of this file is testing the CLI shell tool.
    13     13   #
    14     14   # $Id: shell1.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $
    15     15   #
    16     16   
    17     17   # Test plan:
    18     18   #
    19         -#   shell-1.*: Basic test that command can be called.
           19  +#   shell-1.*: Basic "dot" command token parsing.
           20  +#   shell-2.*: Basic test that "dot" command can be called.
    20     21   #
    21     22   
    22     23   package require sqlite3
    23     24   
    24     25   proc do_test {name cmd expected} {
    25     26     puts -nonewline "$name ..."
    26     27     set res [uplevel $cmd]
    27     28     if {$res eq $expected} {
    28     29       puts Ok
    29     30     } else {
    30     31       puts Error
    31     32       puts "  Got: $res"
    32     33       puts "  Expected: $expected"
           34  +    exit
    33     35     }
    34     36   }
    35     37   
    36     38   proc execsql {sql} {
    37     39     uplevel [list db eval $sql]
    38     40   }
    39     41   
................................................................................
    42     44     list $rc $msg
    43     45   }
    44     46   
    45     47   proc catchcmd {cmd} {
    46     48     set out [open cmds.txt w]
    47     49     puts $out $cmd
    48     50     close $out
    49         -  set rc [catch { exec ./sqlite3 test.db < cmds.txt } msg]
           51  +  set rc [catch { exec ./sqlite test.db < cmds.txt } msg]
    50     52     list $rc $msg
    51     53   }
    52     54   
    53     55   file delete -force test.db test.db.journal
    54     56   sqlite3 db test.db
           57  +
           58  +
           59  +#----------------------------------------------------------------------------
           60  +# Test cases shell-1.* Basic "dot" command token parsing.
           61  +#
           62  +
           63  +# check first token handling
           64  +do_test shell-1.1.1 {
           65  +  catchcmd ".foo"
           66  +} {1 {Error: unknown command or invalid arguments:  "foo". Enter ".help" for help}}
           67  +do_test shell-1.1.2 {
           68  +  catchcmd ".\"foo OFF\""
           69  +} {1 {Error: unknown command or invalid arguments:  "foo OFF". Enter ".help" for help}}
           70  +do_test shell-1.1.3 {
           71  +  catchcmd ".\'foo OFF\'"
           72  +} {1 {Error: unknown command or invalid arguments:  "foo OFF". Enter ".help" for help}}
           73  +
           74  +# unbalanced quotes
           75  +do_test shell-1.2.1 {
           76  +  catchcmd ".\"foo OFF"
           77  +} {1 {Error: unknown command or invalid arguments:  "foo OFF". Enter ".help" for help}}
           78  +do_test shell-1.2.2 {
           79  +  catchcmd ".\'foo OFF"
           80  +} {1 {Error: unknown command or invalid arguments:  "foo OFF". Enter ".help" for help}}
           81  +do_test shell-1.2.3 {
           82  +  catchcmd ".explain \"OFF"
           83  +} {0 {}}
           84  +do_test shell-1.2.4 {
           85  +  catchcmd ".explain \'OFF"
           86  +} {0 {}}
           87  +do_test shell-1.2.5 {
           88  +  catchcmd ".mode \"insert FOO"
           89  +} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
           90  +do_test shell-1.2.6 {
           91  +  catchcmd ".mode \'insert FOO"
           92  +} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
           93  +
           94  +# check multiple tokens, and quoted tokens
           95  +do_test shell-1.3.1 {
           96  +  catchcmd ".explain 1"
           97  +} {0 {}}
           98  +do_test shell-1.3.2 {
           99  +  catchcmd ".explain on"
          100  +} {0 {}}
          101  +do_test shell-1.3.3 {
          102  +  catchcmd ".explain \"1 2 3\""
          103  +} {0 {}}
          104  +do_test shell-1.3.4 {
          105  +  catchcmd ".explain \"OFF\""
          106  +} {0 {}}
          107  +do_test shell-1.3.5 {
          108  +  catchcmd ".\'explain\' \'OFF\'"
          109  +} {0 {}}
          110  +do_test shell-1.3.6 {
          111  +  catchcmd ".explain \'OFF\'"
          112  +} {0 {}}
          113  +do_test shell-1.3.7 {
          114  +  catchcmd ".\'explain\' \'OFF\'"
          115  +} {0 {}}
          116  +
          117  +# check quoted args are unquoted
          118  +do_test shell-1.4.1 {
          119  +  catchcmd ".mode FOO"
          120  +} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
          121  +do_test shell-1.4.2 {
          122  +  catchcmd ".mode csv"
          123  +} {0 {}}
          124  +do_test shell-1.4.2 {
          125  +  catchcmd ".mode \"csv\""
          126  +} {0 {}}
          127  +
    55    128   
    56    129   #----------------------------------------------------------------------------
    57         -# Test cases shell-1.* Basic test that command can be called.
          130  +# Test cases shell-2.* Basic test that "dot" command can be called.
    58    131   #
    59    132   
    60    133   # .backup ?DB? FILE      Backup DB (default "main") to FILE
    61         -do_test shell-1.1.1 {
          134  +do_test shell-2.1.1 {
          135  +  catchcmd ".backup"
          136  +} {1 {Error: unknown command or invalid arguments:  "backup". Enter ".help" for help}}
          137  +do_test shell-2.1.2 {
          138  +  # catchcmd ".backup FOO"
          139  +  #TBD!!! this asserts currently
    62    140   } {}
          141  +do_test shell-2.1.3 {
          142  +  catchcmd ".backup FOO BAR"
          143  +} {1 {Error: unknown database FOO}}
          144  +do_test shell-2.1.4 {
          145  +  # too many arguments
          146  +  catchcmd ".backup FOO BAR BAD"
          147  +} {1 {Error: unknown command or invalid arguments:  "backup". Enter ".help" for help}}
    63    148   
    64    149   # .bail ON|OFF           Stop after hitting an error.  Default OFF
    65         -do_test shell-1.2.1 {
          150  +do_test shell-2.2.1 {
    66    151     catchcmd ".bail"
    67    152   } {1 {Error: unknown command or invalid arguments:  "bail". Enter ".help" for help}}
    68         -do_test shell-1.2.2 {
          153  +do_test shell-2.2.2 {
    69    154     catchcmd ".bail ON"
    70    155   } {0 {}}
    71         -do_test shell-1.2.3 {
          156  +do_test shell-2.2.3 {
    72    157     catchcmd ".bail OFF"
    73    158   } {0 {}}
          159  +do_test shell-2.2.4 {
          160  +  # too many arguments
          161  +  catchcmd ".bail OFF BAD"
          162  +} {1 {Error: unknown command or invalid arguments:  "bail". Enter ".help" for help}}
    74    163   
    75    164   # .databases             List names and files of attached databases
    76         -do_test shell-1.3.1 {
          165  +do_test shell-2.3.1 {
    77    166     set res [catchcmd ".databases"]
    78    167     regexp {0.*main.*test\.db} $res
    79    168   } {1}
          169  +do_test shell-2.3.2 {
          170  +  # too many arguments
          171  +  catchcmd ".databases BAD"
          172  +} {1 {Error: unknown command or invalid arguments:  "databases". Enter ".help" for help}}
    80    173   
    81    174   # .dump ?TABLE? ...      Dump the database in an SQL text format
    82    175   #                          If TABLE specified, only dump tables matching
    83    176   #                          LIKE pattern TABLE.
    84         -do_test shell-1.4.1 {
          177  +do_test shell-2.4.1 {
    85    178     set res [catchcmd ".dump"]
    86    179     list [regexp {BEGIN TRANSACTION;} $res] \
    87    180          [regexp {COMMIT;} $res]
    88    181   } {1 1}
    89         -do_test shell-1.4.2 {
          182  +do_test shell-2.4.2 {
    90    183     set res [catchcmd ".dump FOO"]
    91    184     list [regexp {BEGIN TRANSACTION;} $res] \
    92    185          [regexp {COMMIT;} $res]
    93    186   } {1 1}
          187  +do_test shell-2.4.3 {
          188  +  # too many arguments
          189  +  catchcmd ".dump FOO BAD"
          190  +} {1 {Error: unknown command or invalid arguments:  "dump". Enter ".help" for help}}
    94    191   
    95    192   # .echo ON|OFF           Turn command echo on or off
    96         -do_test shell-1.5.1 {
          193  +do_test shell-2.5.1 {
    97    194     catchcmd ".echo"
    98    195   } {1 {Error: unknown command or invalid arguments:  "echo". Enter ".help" for help}}
    99         -do_test shell-1.5.2 {
          196  +do_test shell-2.5.2 {
   100    197     catchcmd ".echo ON"
   101    198   } {0 {}}
   102         -do_test shell-1.5.3 {
          199  +do_test shell-2.5.3 {
   103    200     catchcmd ".echo OFF"
   104    201   } {0 {}}
          202  +do_test shell-2.5.4 {
          203  +  # too many arguments
          204  +  catchcmd ".echo OFF BAD"
          205  +} {1 {Error: unknown command or invalid arguments:  "echo". Enter ".help" for help}}
   105    206   
   106    207   # .exit                  Exit this program
   107         -do_test shell-1.6.1 {
          208  +do_test shell-2.6.1 {
   108    209     catchcmd ".exit"
   109    210   } {0 {}}
          211  +do_test shell-2.6.2 {
          212  +  # too many arguments
          213  +  catchcmd ".exit BAD"
          214  +} {1 {Error: unknown command or invalid arguments:  "exit". Enter ".help" for help}}
   110    215   
   111    216   # .explain ON|OFF        Turn output mode suitable for EXPLAIN on or off.
   112         -do_test shell-1.7.1 {
   113         -  catchcmd ".echo"
   114         -} {1 {Error: unknown command or invalid arguments:  "echo". Enter ".help" for help}}
   115         -do_test shell-1.7.2 {
          217  +do_test shell-2.7.1 {
          218  +  catchcmd ".explain"
          219  +  # explain is the exception to the booleans.  without an option, it turns it on.
          220  +} {0 {}}
          221  +do_test shell-2.7.2 {
   116    222     catchcmd ".explain ON"
   117    223   } {0 {}}
   118         -do_test shell-1.7.3 {
          224  +do_test shell-2.7.3 {
   119    225     catchcmd ".explain OFF"
   120    226   } {0 {}}
          227  +do_test shell-2.7.4 {
          228  +  # too many arguments
          229  +  catchcmd ".explain OFF BAD"
          230  +} {1 {Error: unknown command or invalid arguments:  "explain". Enter ".help" for help}}
   121    231   
   122    232   # .genfkey ?OPTIONS?     Options are:
   123    233   #                          --no-drop: Do not drop old fkey triggers.
   124    234   #                          --ignore-errors: Ignore tables with fkey errors
   125    235   #                          --exec: Execute generated SQL immediately
   126    236   #                        See file tool/genfkey.README in the source
   127    237   #                        distribution for further information.
   128         -do_test shell-1.8.1 {
   129         -} {}
          238  +do_test shell-2.8.1 {
          239  +  catchcmd ".genfkey"
          240  +} {0 {}}
          241  +do_test shell-2.8.2 {
          242  +  catchcmd ".genfkey FOO"
          243  +} {1 {unknown option: FOO}}
   130    244   
   131    245   # .header(s) ON|OFF      Turn display of headers on or off
   132         -do_test shell-1.9.1 {
          246  +do_test shell-2.9.1 {
   133    247     catchcmd ".header"
   134    248   } {1 {Error: unknown command or invalid arguments:  "header". Enter ".help" for help}}
   135         -do_test shell-1.9.2 {
          249  +do_test shell-2.9.2 {
   136    250     catchcmd ".header ON"
   137    251   } {0 {}}
   138         -do_test shell-1.9.3 {
          252  +do_test shell-2.9.3 {
   139    253     catchcmd ".header OFF"
   140    254   } {0 {}}
   141         -do_test shell-1.9.4 {
          255  +do_test shell-2.9.4 {
          256  +  # too many arguments
          257  +  catchcmd ".header OFF BAD"
          258  +} {1 {Error: unknown command or invalid arguments:  "header". Enter ".help" for help}}
          259  +
          260  +do_test shell-2.9.5 {
   142    261     catchcmd ".headers"
   143    262   } {1 {Error: unknown command or invalid arguments:  "headers". Enter ".help" for help}}
   144         -do_test shell-1.9.5 {
          263  +do_test shell-2.9.6 {
   145    264     catchcmd ".headers ON"
   146    265   } {0 {}}
   147         -do_test shell-1.9.6 {
          266  +do_test shell-2.9.7 {
   148    267     catchcmd ".headers OFF"
   149    268   } {0 {}}
          269  +do_test shell-2.9.8 {
          270  +  # too many arguments
          271  +  catchcmd ".headers OFF BAD"
          272  +} {1 {Error: unknown command or invalid arguments:  "headers". Enter ".help" for help}}
   150    273   
   151    274   # .help                  Show this message
   152         -do_test shell-1.10.1 {
          275  +do_test shell-2.10.1 {
   153    276     set res [catchcmd ".help"]
   154    277     # look for a few of the possible help commands
   155    278     list [regexp {.help} $res] \
   156    279          [regexp {.quit} $res] \
   157    280          [regexp {.show} $res]
   158    281   } {1 1 1}
          282  +do_test shell-2.10.2 {
          283  +  # we allow .help to take extra args (it is help after all)
          284  +  set res [catchcmd ".help BAD"]
          285  +  # look for a few of the possible help commands
          286  +  list [regexp {.help} $res] \
          287  +       [regexp {.quit} $res] \
          288  +       [regexp {.show} $res]
          289  +} {1 1 1}
   159    290   
   160    291   # .import FILE TABLE     Import data from FILE into TABLE
   161         -do_test shell-1.11.1 {
          292  +do_test shell-2.11.1 {
   162    293     catchcmd ".import"
   163    294   } {1 {Error: unknown command or invalid arguments:  "import". Enter ".help" for help}}
   164         -do_test shell-1.11.2 {
          295  +do_test shell-2.11.2 {
   165    296     catchcmd ".import FOO"
   166    297   } {1 {Error: unknown command or invalid arguments:  "import". Enter ".help" for help}}
   167         -do_test shell-1.11.2 {
          298  +do_test shell-2.11.2 {
   168    299     catchcmd ".import FOO BAR"
   169    300   } {1 {Error: no such table: BAR}}
          301  +do_test shell-2.11.3 {
          302  +  # too many arguments
          303  +  catchcmd ".import FOO BAR BAD"
          304  +} {1 {Error: unknown command or invalid arguments:  "import". Enter ".help" for help}}
   170    305   
   171    306   # .indices ?TABLE?       Show names of all indices
   172    307   #                          If TABLE specified, only show indices for tables
   173    308   #                          matching LIKE pattern TABLE.
   174         -do_test shell-1.12.1 {
          309  +do_test shell-2.12.1 {
   175    310     catchcmd ".indices"
   176    311   } {0 {}}
   177         -do_test shell-1.12.2 {
          312  +do_test shell-2.12.2 {
   178    313     catchcmd ".indices FOO"
   179    314   } {0 {}}
          315  +do_test shell-2.12.3 {
          316  +  # too many arguments
          317  +  catchcmd ".indices FOO BAD"
          318  +} {1 {Error: unknown command or invalid arguments:  "indices". Enter ".help" for help}}
   180    319   
   181    320   # .mode MODE ?TABLE?     Set output mode where MODE is one of:
   182    321   #                          csv      Comma-separated values
   183    322   #                          column   Left-aligned columns.  (See .width)
   184    323   #                          html     HTML <table> code
   185    324   #                          insert   SQL insert statements for TABLE
   186    325   #                          line     One value per line
   187    326   #                          list     Values delimited by .separator string
   188    327   #                          tabs     Tab-separated values
   189    328   #                          tcl      TCL list elements
   190         -do_test shell-1.13.1 {
          329  +do_test shell-2.13.1 {
   191    330     catchcmd ".mode"
   192    331   } {1 {Error: unknown command or invalid arguments:  "mode". Enter ".help" for help}}
   193         -do_test shell-1.13.2 {
          332  +do_test shell-2.13.2 {
   194    333     catchcmd ".mode FOO"
   195    334   } {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
   196         -do_test shell-1.13.3 {
          335  +do_test shell-2.13.3 {
   197    336     catchcmd ".mode csv"
   198    337   } {0 {}}
   199         -do_test shell-1.13.4 {
          338  +do_test shell-2.13.4 {
   200    339     catchcmd ".mode column"
   201    340   } {0 {}}
   202         -do_test shell-1.13.5 {
          341  +do_test shell-2.13.5 {
   203    342     catchcmd ".mode html"
   204    343   } {0 {}}
   205         -do_test shell-1.13.6 {
          344  +do_test shell-2.13.6 {
   206    345     catchcmd ".mode insert"
   207    346   } {0 {}}
   208         -do_test shell-1.13.7 {
          347  +do_test shell-2.13.7 {
   209    348     catchcmd ".mode line"
   210    349   } {0 {}}
   211         -do_test shell-1.13.8 {
          350  +do_test shell-2.13.8 {
   212    351     catchcmd ".mode list"
   213    352   } {0 {}}
   214         -do_test shell-1.13.9 {
          353  +do_test shell-2.13.9 {
   215    354     catchcmd ".mode tabs"
   216    355   } {0 {}}
   217         -do_test shell-1.13.10 {
          356  +do_test shell-2.13.10 {
   218    357     catchcmd ".mode tcl"
   219    358   } {0 {}}
          359  +do_test shell-2.13.11 {
          360  +  # too many arguments
          361  +  catchcmd ".mode tcl BAD"
          362  +} {1 {Error: invalid arguments:  "BAD". Enter ".help" for help}}
          363  +
          364  +# don't allow partial mode type matches
          365  +do_test shell-2.13.12 {
          366  +  catchcmd ".mode l"
          367  +} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
          368  +do_test shell-2.13.13 {
          369  +  catchcmd ".mode li"
          370  +} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
          371  +do_test shell-2.13.14 {
          372  +  catchcmd ".mode lin"
          373  +} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
   220    374   
   221    375   # .nullvalue STRING      Print STRING in place of NULL values
   222         -do_test shell-1.14.1 {
          376  +do_test shell-2.14.1 {
   223    377     catchcmd ".nullvalue"
   224    378   } {1 {Error: unknown command or invalid arguments:  "nullvalue". Enter ".help" for help}}
   225         -do_test shell-1.14.2 {
          379  +do_test shell-2.14.2 {
   226    380     catchcmd ".nullvalue FOO"
   227    381   } {0 {}}
          382  +do_test shell-2.14.3 {
          383  +  # too many arguments
          384  +  catchcmd ".nullvalue FOO BAD"
          385  +} {1 {Error: unknown command or invalid arguments:  "nullvalue". Enter ".help" for help}}
   228    386   
   229    387   # .output FILENAME       Send output to FILENAME
   230         -do_test shell-1.15.1 {
          388  +do_test shell-2.15.1 {
   231    389     catchcmd ".output"
   232    390   } {1 {Error: unknown command or invalid arguments:  "output". Enter ".help" for help}}
   233         -do_test shell-1.15.2 {
          391  +do_test shell-2.15.2 {
   234    392     catchcmd ".output FOO"
   235    393   } {0 {}}
          394  +do_test shell-2.15.3 {
          395  +  # too many arguments
          396  +  catchcmd ".output FOO BAD"
          397  +} {1 {Error: unknown command or invalid arguments:  "output". Enter ".help" for help}}
   236    398   
   237    399   # .output stdout         Send output to the screen
   238         -do_test shell-1.16.1 {
          400  +do_test shell-2.16.1 {
   239    401     catchcmd ".output stdout"
   240    402   } {0 {}}
          403  +do_test shell-2.16.2 {
          404  +  # too many arguments
          405  +  catchcmd ".output stdout BAD"
          406  +} {1 {Error: unknown command or invalid arguments:  "output". Enter ".help" for help}}
   241    407   
   242    408   # .prompt MAIN CONTINUE  Replace the standard prompts
   243         -do_test shell-1.17.1 {
          409  +do_test shell-2.17.1 {
   244    410     catchcmd ".prompt"
   245    411   } {1 {Error: unknown command or invalid arguments:  "prompt". Enter ".help" for help}}
   246         -do_test shell-1.17.2 {
          412  +do_test shell-2.17.2 {
   247    413     catchcmd ".prompt FOO"
   248    414   } {0 {}}
   249         -do_test shell-1.17.3 {
          415  +do_test shell-2.17.3 {
   250    416     catchcmd ".prompt FOO BAR"
   251    417   } {0 {}}
          418  +do_test shell-2.17.4 {
          419  +  # too many arguments
          420  +  catchcmd ".prompt FOO BAR BAD"
          421  +} {1 {Error: unknown command or invalid arguments:  "prompt". Enter ".help" for help}}
   252    422   
   253    423   # .quit                  Exit this program
   254         -do_test shell-1.18.1 {
          424  +do_test shell-2.18.1 {
   255    425     catchcmd ".quit"
   256    426   } {0 {}}
          427  +do_test shell-2.18.2 {
          428  +  # too many arguments
          429  +  catchcmd ".quit BAD"
          430  +} {1 {Error: unknown command or invalid arguments:  "quit". Enter ".help" for help}}
   257    431   
   258    432   # .read FILENAME         Execute SQL in FILENAME
   259         -do_test shell-1.19.1 {
          433  +do_test shell-2.19.1 {
   260    434     catchcmd ".read"
   261    435   } {1 {Error: unknown command or invalid arguments:  "read". Enter ".help" for help}}
   262         -do_test shell-1.19.2 {
          436  +do_test shell-2.19.2 {
   263    437     file delete -force FOO
   264    438     catchcmd ".read FOO"
   265    439   } {1 {Error: cannot open "FOO"}}
          440  +do_test shell-2.19.3 {
          441  +  # too many arguments
          442  +  catchcmd ".read FOO BAD"
          443  +} {1 {Error: unknown command or invalid arguments:  "read". Enter ".help" for help}}
   266    444   
   267    445   # .restore ?DB? FILE     Restore content of DB (default "main") from FILE
   268         -do_test shell-1.20.1 {
          446  +do_test shell-2.20.1 {
   269    447     catchcmd ".restore"
   270    448   } {1 {Error: unknown command or invalid arguments:  "restore". Enter ".help" for help}}
   271         -do_test shell-1.20.2 {
          449  +do_test shell-2.20.2 {
   272    450     # catchcmd ".restore FOO"
   273    451     #TBD!!! this asserts currently
   274    452   } {}
          453  +do_test shell-2.20.3 {
          454  +  catchcmd ".restore FOO BAR"
          455  +} {1 {Error: unknown database FOO}}
          456  +do_test shell-2.20.4 {
          457  +  # too many arguments
          458  +  catchcmd ".restore FOO BAR BAD"
          459  +} {1 {Error: unknown command or invalid arguments:  "restore". Enter ".help" for help}}
   275    460   
   276    461   # .schema ?TABLE?        Show the CREATE statements
   277    462   #                          If TABLE specified, only show tables matching
   278    463   #                          LIKE pattern TABLE.
   279         -do_test shell-1.21.1 {
          464  +do_test shell-2.21.1 {
   280    465     catchcmd ".schema"
   281    466   } {0 {}}
   282         -do_test shell-1.21.2 {
          467  +do_test shell-2.21.2 {
   283    468     catchcmd ".schema FOO"
   284    469   } {0 {}}
          470  +do_test shell-2.21.3 {
          471  +  # too many arguments
          472  +  catchcmd ".schema FOO BAD"
          473  +} {1 {Error: unknown command or invalid arguments:  "schema". Enter ".help" for help}}
   285    474   
   286    475   # .separator STRING      Change separator used by output mode and .import
   287         -do_test shell-1.22.1 {
          476  +do_test shell-2.22.1 {
   288    477     catchcmd ".separator"
   289    478   } {1 {Error: unknown command or invalid arguments:  "separator". Enter ".help" for help}}
   290         -do_test shell-1.22.2 {
          479  +do_test shell-2.22.2 {
   291    480     catchcmd ".separator FOO"
   292    481   } {0 {}}
          482  +do_test shell-2.22.3 {
          483  +  # too many arguments
          484  +  catchcmd ".separator FOO BAD"
          485  +} {1 {Error: unknown command or invalid arguments:  "separator". Enter ".help" for help}}
   293    486   
   294    487   # .show                  Show the current values for various settings
   295         -do_test shell-1.23.1 {
          488  +do_test shell-2.23.1 {
   296    489     set res [catchcmd ".show"]
   297    490     list [regexp {echo:} $res] \
   298    491          [regexp {explain:} $res] \
   299    492          [regexp {headers:} $res] \
   300    493          [regexp {mode:} $res] \
   301    494          [regexp {nullvalue:} $res] \
   302    495          [regexp {output:} $res] \
   303    496          [regexp {separator:} $res] \
   304    497          [regexp {width:} $res]
   305    498   } {1 1 1 1 1 1 1 1}
          499  +do_test shell-2.23.2 {
          500  +  # too many arguments
          501  +  catchcmd ".show BAD"
          502  +} {1 {Error: unknown command or invalid arguments:  "show". Enter ".help" for help}}
   306    503   
   307    504   # .tables ?TABLE?        List names of tables
   308    505   #                          If TABLE specified, only list tables matching
   309    506   #                          LIKE pattern TABLE.
   310         -do_test shell-1.24.1 {
          507  +do_test shell-2.24.1 {
   311    508     catchcmd ".tables"
   312    509   } {0 {}}
   313         -do_test shell-1.24.2 {
          510  +do_test shell-2.24.2 {
   314    511     catchcmd ".tables FOO"
   315    512   } {0 {}}
          513  +do_test shell-2.24.3 {
          514  +  # too many arguments
          515  +  catchcmd ".tables FOO BAD"
          516  +} {1 {Error: unknown command or invalid arguments:  "tables". Enter ".help" for help}}
   316    517   
   317    518   # .timeout MS            Try opening locked tables for MS milliseconds
   318         -do_test shell-1.25.1 {
          519  +do_test shell-2.25.1 {
   319    520     catchcmd ".timeout"
   320    521   } {1 {Error: unknown command or invalid arguments:  "timeout". Enter ".help" for help}}
   321         -do_test shell-1.25.2 {
          522  +do_test shell-2.25.2 {
   322    523     catchcmd ".timeout zzz"
   323         -  #TBD!!! this should probably produce an error
          524  +  # this should be treated the same as a '0' timeout
   324    525   } {0 {}}
   325         -do_test shell-1.25.2 {
          526  +do_test shell-2.25.3 {
   326    527     catchcmd ".timeout 1"
   327    528   } {0 {}}
          529  +do_test shell-2.25.4 {
          530  +  # too many arguments
          531  +  catchcmd ".timeout 1 BAD"
          532  +} {1 {Error: unknown command or invalid arguments:  "timeout". Enter ".help" for help}}
   328    533   
   329    534   # .width NUM NUM ...     Set column widths for "column" mode
   330         -do_test shell-1.26.1 {
          535  +do_test shell-2.26.1 {
   331    536     catchcmd ".width"
   332         -  #TBD!!! this should probably produce an error
   333         -} {0 {}}
   334         -do_test shell-1.26.2 {
          537  +} {1 {Error: unknown command or invalid arguments:  "width". Enter ".help" for help}}
          538  +do_test shell-2.26.2 {
   335    539     catchcmd ".width xxx"
   336         -  #TBD!!! this should probably produce an error
          540  +  # this should be treated the same as a '0' width for col 1
   337    541   } {0 {}}
   338         -do_test shell-1.26.3 {
          542  +do_test shell-2.26.3 {
   339    543     catchcmd ".width xxx yyy"
   340         -  #TBD!!! this should probably produce an error
          544  +  # this should be treated the same as a '0' width for col 1 and 2
   341    545   } {0 {}}
   342         -do_test shell-1.26.4 {
          546  +do_test shell-2.26.4 {
   343    547     catchcmd ".width 1 1"
          548  +  # this should be treated the same as a '1' width for col 1 and 2
   344    549   } {0 {}}
   345    550   
   346    551   # .timer ON|OFF          Turn the CPU timer measurement on or off
   347         -do_test shell-1.27.1 {
          552  +do_test shell-2.27.1 {
   348    553     catchcmd ".timer"
   349    554   } {1 {Error: unknown command or invalid arguments:  "timer". Enter ".help" for help}}
   350         -do_test shell-1.27.2 {
          555  +do_test shell-2.27.2 {
   351    556     catchcmd ".timer ON"
   352    557   } {0 {}}
   353         -do_test shell-1.27.3 {
          558  +do_test shell-2.27.3 {
   354    559     catchcmd ".timer OFF"
   355    560   } {0 {}}
          561  +do_test shell-2.27.4 {
          562  +  # too many arguments
          563  +  catchcmd ".timer OFF BAD"
          564  +} {1 {Error: unknown command or invalid arguments:  "timer". Enter ".help" for help}}
   356    565   
   357    566   #