/ Check-in [3bd5ad09]
Login

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

Overview
Comment:Enhance the shell to provide more flexibility when entering numeric arguments on dot-commands. In particular, allow hexadecimal arguments to .wheretrace and .testctrl commands. Cherrypick from [b9578c371ee5].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3bd5ad095b23102dd3379cb62997cbf23cc67b7a
User & Date: drh 2013-06-03 12:47:43
Context
2013-06-03
20:39
Fix a typo in a collating function inside the e_reindex.test script. check-in: 4d74fccf user: drh tags: trunk
12:47
Enhance the shell to provide more flexibility when entering numeric arguments on dot-commands. In particular, allow hexadecimal arguments to .wheretrace and .testctrl commands. Cherrypick from [b9578c371ee5]. check-in: 3bd5ad09 user: drh tags: trunk
12:34
Further improvements to error handling of the run-time loading of SQLite into TCL. check-in: 7cc0c4ee user: drh tags: trunk
2013-05-31
14:31
Enhance the shell to provide more flexibility when entering numeric arguments on dot-commands. In particular, allow hex arguments to .wheretrace. check-in: b9578c37 user: drh tags: nextgen-query-plan-exp
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/shell.c.

  1519   1519       }
  1520   1520       z[j] = c;
  1521   1521     }
  1522   1522     z[j] = 0;
  1523   1523   }
  1524   1524   
  1525   1525   /*
  1526         -** Interpret zArg as a boolean value.  Return either 0 or 1.
         1526  +** Return the value of a hexadecimal digit.  Return -1 if the input
         1527  +** is not a hex digit.
  1527   1528   */
  1528         -static int booleanValue(char *zArg){
  1529         -  int i;
  1530         -  for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
  1531         -  if( i>0 && zArg[i]==0 ) return atoi(zArg);
  1532         -  if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
  1533         -    return 1;
  1534         -  }
  1535         -  if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
  1536         -    return 0;
  1537         -  }
  1538         -  fprintf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
  1539         -          zArg);
  1540         -  return 0;
         1529  +static int hexDigitValue(char c){
         1530  +  if( c>='0' && c<='9' ) return c - '0';
         1531  +  if( c>='a' && c<='f' ) return c - 'a' + 10;
         1532  +  if( c>='A' && c<='F' ) return c - 'A' + 10;
         1533  +  return -1;
  1541   1534   }
  1542   1535   
  1543   1536   /*
  1544   1537   ** Interpret zArg as an integer value, possibly with suffixes.
  1545   1538   */
  1546   1539   static sqlite3_int64 integerValue(const char *zArg){
  1547   1540     sqlite3_int64 v = 0;
................................................................................
  1560   1553     int isNeg = 0;
  1561   1554     if( zArg[0]=='-' ){
  1562   1555       isNeg = 1;
  1563   1556       zArg++;
  1564   1557     }else if( zArg[0]=='+' ){
  1565   1558       zArg++;
  1566   1559     }
  1567         -  while( IsDigit(zArg[0]) ){
  1568         -    v = v*10 + zArg[0] - '0';
  1569         -    zArg++;
         1560  +  if( zArg[0]=='0' && zArg[1]=='x' ){
         1561  +    int x;
         1562  +    zArg += 2;
         1563  +    while( (x = hexDigitValue(zArg[0]))>=0 ){
         1564  +      v = (v<<4) + x;
         1565  +      zArg++;
         1566  +    }
         1567  +  }else{
         1568  +    while( IsDigit(zArg[0]) ){
         1569  +      v = v*10 + zArg[0] - '0';
         1570  +      zArg++;
         1571  +    }
  1570   1572     }
  1571   1573     for(i=0; i<ArraySize(aMult); i++){
  1572   1574       if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
  1573   1575         v *= aMult[i].iMult;
  1574   1576         break;
  1575   1577       }
  1576   1578     }
  1577   1579     return isNeg? -v : v;
  1578   1580   }
         1581  +
         1582  +/*
         1583  +** Interpret zArg as either an integer or a boolean value.  Return 1 or 0
         1584  +** for TRUE and FALSE.  Return the integer value if appropriate.
         1585  +*/
         1586  +static int booleanValue(char *zArg){
         1587  +  int i;
         1588  +  if( zArg[0]=='0' && zArg[1]=='x' ){
         1589  +    for(i=2; hexDigitValue(zArg[i])>=0; i++){}
         1590  +  }else{
         1591  +    for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
         1592  +  }
         1593  +  if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
         1594  +  if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
         1595  +    return 1;
         1596  +  }
         1597  +  if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
         1598  +    return 0;
         1599  +  }
         1600  +  fprintf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
         1601  +          zArg);
         1602  +  return 0;
         1603  +}
  1579   1604   
  1580   1605   /*
  1581   1606   ** Close an output file, assuming it is not stderr or stdout
  1582   1607   */
  1583   1608   static void output_file_close(FILE *f){
  1584   1609     if( f && f!=stdout && f!=stderr ) fclose(f);
  1585   1610   }
................................................................................
  1804   1829     }else
  1805   1830   
  1806   1831     if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){
  1807   1832       p->echoOn = booleanValue(azArg[1]);
  1808   1833     }else
  1809   1834   
  1810   1835     if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
  1811         -    if( nArg>1 && (rc = atoi(azArg[1]))!=0 ) exit(rc);
         1836  +    if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
  1812   1837       rc = 2;
  1813   1838     }else
  1814   1839   
  1815   1840     if( c=='e' && strncmp(azArg[0], "explain", n)==0 && nArg<3 ){
  1816   1841       int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
  1817   1842       if(val == 1) {
  1818   1843         if(!p->explainPrev.valid) {
................................................................................
  2300   2325       }else if( rc != SQLITE_OK ){
  2301   2326         fprintf(stderr,"Error: querying schema information\n");
  2302   2327         rc = 1;
  2303   2328       }else{
  2304   2329         rc = 0;
  2305   2330       }
  2306   2331     }else
         2332  +
         2333  +  /* Undocumented commands for internal testing.  Subject to change
         2334  +  ** without notice. */
         2335  +  if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
         2336  +    if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
         2337  +      int i, v;
         2338  +      for(i=1; i<nArg; i++){
         2339  +        v = booleanValue(azArg[i]);
         2340  +        fprintf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
         2341  +      }
         2342  +    }
         2343  +    if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
         2344  +      int i; sqlite3_int64 v;
         2345  +      for(i=1; i<nArg; i++){
         2346  +        v = integerValue(azArg[i]);
         2347  +        fprintf(p->out, "%s: %lld 0x%llx\n", azArg[i], v, v);
         2348  +      }
         2349  +    }
         2350  +  }else
  2307   2351   
  2308   2352     if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
  2309   2353       sqlite3_snprintf(sizeof(p->separator), p->separator,
  2310   2354                        "%.*s", (int)sizeof(p->separator)-1, azArg[1]);
  2311   2355     }else
  2312   2356   
  2313   2357     if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){
................................................................................
  2454   2498           }else{
  2455   2499             fprintf(stderr, "ambiguous option name: \"%s\"\n", azArg[1]);
  2456   2500             testctrl = -1;
  2457   2501             break;
  2458   2502           }
  2459   2503         }
  2460   2504       }
  2461         -    if( testctrl<0 ) testctrl = atoi(azArg[1]);
         2505  +    if( testctrl<0 ) testctrl = (int)integerValue(azArg[1]);
  2462   2506       if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){
  2463   2507         fprintf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]);
  2464   2508       }else{
  2465   2509         switch(testctrl){
  2466   2510   
  2467   2511           /* sqlite3_test_control(int, db, int) */
  2468   2512           case SQLITE_TESTCTRL_OPTIMIZATIONS:
................................................................................
  2501   2545             }
  2502   2546             break;
  2503   2547             
  2504   2548           /* sqlite3_test_control(int, int) */
  2505   2549           case SQLITE_TESTCTRL_ASSERT:              
  2506   2550           case SQLITE_TESTCTRL_ALWAYS:              
  2507   2551             if( nArg==3 ){
  2508         -            int opt = atoi(azArg[2]);        
         2552  +            int opt = booleanValue(azArg[2]);        
  2509   2553               rc = sqlite3_test_control(testctrl, opt);
  2510   2554               fprintf(p->out, "%d (0x%08x)\n", rc, rc);
  2511   2555             } else {
  2512   2556               fprintf(stderr,"Error: testctrl %s takes a single int option\n",
  2513   2557                               azArg[1]);
  2514   2558             }
  2515   2559             break;
................................................................................
  2538   2582             break;
  2539   2583         }
  2540   2584       }
  2541   2585     }else
  2542   2586   
  2543   2587     if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg==2 ){
  2544   2588       open_db(p);
  2545         -    sqlite3_busy_timeout(p->db, atoi(azArg[1]));
         2589  +    sqlite3_busy_timeout(p->db, (int)integerValue(azArg[1]));
  2546   2590     }else
  2547   2591       
  2548   2592     if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0
  2549   2593      && nArg==2
  2550   2594     ){
  2551   2595       enableTimer = booleanValue(azArg[1]);
  2552   2596     }else
................................................................................
  2588   2632     }else
  2589   2633   #endif
  2590   2634   
  2591   2635     if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
  2592   2636       int j;
  2593   2637       assert( nArg<=ArraySize(azArg) );
  2594   2638       for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
  2595         -      p->colWidth[j-1] = atoi(azArg[j]);
         2639  +      p->colWidth[j-1] = (int)integerValue(azArg[j]);
  2596   2640       }
  2597   2641     }else
  2598   2642   
  2599   2643     {
  2600   2644       fprintf(stderr, "Error: unknown command or invalid arguments: "
  2601   2645         " \"%s\". Enter \".help\" for help\n", azArg[0]);
  2602   2646       rc = 1;