Fossil

Check-in Differences
Login

Check-in Differences

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

Difference From release To trunk

2024-04-11
12:38
Adjust the "fossil add" command so that on systems with case-insensitive filenames, the named added to the repository is the operating-systems preferred case for the name. ... (Leaf check-in: 78e63995 user: drh tags: trunk)
2024-04-10
20:27
Use fossil_path_free() instead of fossil_free() for names allocated (or not) by fossil_path_to_utf8(). ... (Closed-Leaf check-in: a9fa7d3c user: stephan tags: preserve-case-on-add)
11:31
When preparing a pattern for FTS search, if the pattern is empty convert it into a double-quoted empty string, to avoid FTS5 errors. ... (check-in: 5bb323ff user: drh tags: trunk)
2023-11-02
19:37
For the "fossil sync" command if the -v option is repeated, then the HTTP_VERBOSE flag is set on the http_exchange() call, resulting in additional debugging output for the wire protocol. ... (check-in: 80896224 user: drh tags: trunk)
12:44
Check if markdown paragraphs contains lists. Fixes issue reported in b598ac56defddb2a. ... (Closed-Leaf check-in: 25028896 user: preben tags: markdown-multiple-sublists)
2023-11-01
18:56
Version 2.23 ... (check-in: 47362306 user: drh tags: trunk, release, version-2.23)
14:13
Update the built-in SQLite to version 3.44.0. ... (check-in: 72e14351 user: drh tags: trunk)

Changes to Dockerfile.

79
80
81
82
83
84
85
86
87
88
89
90

## ---------------------------------------------------------------------
## RUN!
## ---------------------------------------------------------------------

ENV PATH "/bin"
EXPOSE 8080/tcp
USER fossil
ENTRYPOINT [ "fossil", "server", "museum/repo.fossil" ]
CMD [                       \
    "--create",             \
    "--jsmode", "bundled",  \
    "--user",   "admin" ]








|



|
>
79
80
81
82
83
84
85
86
87
88
89
90
91
## ---------------------------------------------------------------------
## RUN!
## ---------------------------------------------------------------------

ENV PATH "/bin"
EXPOSE 8080/tcp
USER fossil
ENTRYPOINT [ "fossil", "server" ]
CMD [                       \
    "--create",             \
    "--jsmode", "bundled",  \
    "--user",   "admin",    \
    "museum/repo.fossil" ]

Changes to VERSION.

1
2.23
|
1
2.24

Changes to auto.def.

453
454
455
456
457
458
459


460
461
462
463
464
465
466
            }
        }
    }
    if {$found} {
        define FOSSIL_ENABLE_SSL
        define-append EXTRA_CFLAGS $cflags
        define-append EXTRA_LDFLAGS $ldflags


        if {[info exists ssllibs]} {
            define-append LIBS $ssllibs
        } else {
            define-append LIBS -lssl -lcrypto
        }
        if {[info exists ::zlib_lib]} {
            define-append LIBS $::zlib_lib







>
>







453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
            }
        }
    }
    if {$found} {
        define FOSSIL_ENABLE_SSL
        define-append EXTRA_CFLAGS $cflags
        define-append EXTRA_LDFLAGS $ldflags
        define-append CFLAGS $cflags
        define-append LDFLAGS $ldflags
        if {[info exists ssllibs]} {
            define-append LIBS $ssllibs
        } else {
            define-append LIBS -lssl -lcrypto
        }
        if {[info exists ::zlib_lib]} {
            define-append LIBS $::zlib_lib
653
654
655
656
657
658
659

660
661
662
663
664
665
666
    }
    set version $tclconfig(TCL_VERSION)$tclconfig(TCL_PATCH_LEVEL)
    msg-result "Found Tcl $version at $tclconfig(TCL_PREFIX)"
    if {!$tclprivatestubs} {
        define-append LIBS $libs
    }
    define-append EXTRA_CFLAGS $cflags

    if {[info exists zlibpath] && $zlibpath eq "tree"} {
      #
      # NOTE: When using zlib in the source tree, prevent Tcl from
      #       pulling in the system one.
      #
      set tclconfig(TCL_LD_FLAGS) [string map [list -lz ""] \
          $tclconfig(TCL_LD_FLAGS)]







>







655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
    }
    set version $tclconfig(TCL_VERSION)$tclconfig(TCL_PATCH_LEVEL)
    msg-result "Found Tcl $version at $tclconfig(TCL_PREFIX)"
    if {!$tclprivatestubs} {
        define-append LIBS $libs
    }
    define-append EXTRA_CFLAGS $cflags
    define-append CFLAGS $cflags
    if {[info exists zlibpath] && $zlibpath eq "tree"} {
      #
      # NOTE: When using zlib in the source tree, prevent Tcl from
      #       pulling in the system one.
      #
      set tclconfig(TCL_LD_FLAGS) [string map [list -lz ""] \
          $tclconfig(TCL_LD_FLAGS)]

Changes to autosetup/autosetup-find-tclsh.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/sh
# Looks for a suitable tclsh or jimsh in the PATH
# If not found, builds a bootstrap jimsh from source
# Prefer $autosetup_tclsh if is set in the environment
d=`dirname "$0"`
{ "$d/jimsh0" "$d/autosetup-test-tclsh"; } 2>/dev/null && exit 0
PATH="$PATH:$d"; export PATH
for tclsh in $autosetup_tclsh jimsh tclsh tclsh8.5 tclsh8.6; do
	{ $tclsh "$d/autosetup-test-tclsh"; } 2>/dev/null && exit 0
done
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
for cc in ${CC_FOR_BUILD:-cc} gcc; do
	{ $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue
	"$d/jimsh0" "$d/autosetup-test-tclsh" && exit 0
done
echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc."
echo false












|




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/sh
# Looks for a suitable tclsh or jimsh in the PATH
# If not found, builds a bootstrap jimsh from source
# Prefer $autosetup_tclsh if is set in the environment
d=`dirname "$0"`
{ "$d/jimsh0" "$d/autosetup-test-tclsh"; } 2>/dev/null && exit 0
PATH="$PATH:$d"; export PATH
for tclsh in $autosetup_tclsh jimsh tclsh tclsh8.5 tclsh8.6; do
	{ $tclsh "$d/autosetup-test-tclsh"; } 2>/dev/null && exit 0
done
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
for cc in ${CC_FOR_BUILD:-cc} gcc; do
	{ $cc -o "$d/jimsh0" "$d/jimsh0.c"; } >/dev/null 2>&1 || continue
	"$d/jimsh0" "$d/autosetup-test-tclsh" && exit 0
done
echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc."
echo false

Changes to extsrc/pikchr.c.

1
2

3
4
5
6
7
8
9
/* This file is automatically generated by Lemon from input grammar
** source file "pikchr.y". */

/*
** Zero-Clause BSD license:
**
** Copyright (C) 2020-09-01 by D. Richard Hipp <drh@sqlite.org>
**
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted.

|
>







1
2
3
4
5
6
7
8
9
10
/* This file is automatically generated by Lemon from input grammar
** source file "pikchr.y".
*/
/*
** Zero-Clause BSD license:
**
** Copyright (C) 2020-09-01 by D. Richard Hipp <drh@sqlite.org>
**
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted.
317
318
319
320
321
322
323

324
325
326
327
328
329
330
  PPoint with;             /* Position constraint from WITH clause */
  char eWith;              /* Type of heading point on WITH clause */
  char cw;                 /* True for clockwise arc */
  char larrow;             /* Arrow at beginning (<- or <->) */
  char rarrow;             /* Arrow at end  (-> or <->) */
  char bClose;             /* True if "close" is seen */
  char bChop;              /* True if "chop" is seen */

  unsigned char nTxt;      /* Number of text values */
  unsigned mProp;          /* Masks of properties set so far */
  unsigned mCalc;          /* Values computed from other constraints */
  PToken aTxt[5];          /* Text with .eCode holding TP flags */
  int iLayer;              /* Rendering order */
  int inDir, outDir;       /* Entry and exit directions */
  int nPath;               /* Number of path points */







>







318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
  PPoint with;             /* Position constraint from WITH clause */
  char eWith;              /* Type of heading point on WITH clause */
  char cw;                 /* True for clockwise arc */
  char larrow;             /* Arrow at beginning (<- or <->) */
  char rarrow;             /* Arrow at end  (-> or <->) */
  char bClose;             /* True if "close" is seen */
  char bChop;              /* True if "chop" is seen */
  char bAltAutoFit;        /* Always send both h and w into xFit() */        
  unsigned char nTxt;      /* Number of text values */
  unsigned mProp;          /* Masks of properties set so far */
  unsigned mCalc;          /* Values computed from other constraints */
  PToken aTxt[5];          /* Text with .eCode holding TP flags */
  int iLayer;              /* Rendering order */
  int inDir, outDir;       /* Entry and exit directions */
  int nPath;               /* Number of path points */
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
static void pik_behind(Pik*,PObj*);
static PObj *pik_assert(Pik*,PNum,PToken*,PNum);
static PObj *pik_position_assert(Pik*,PPoint*,PToken*,PPoint*);
static PNum pik_dist(PPoint*,PPoint*);
static void pik_add_macro(Pik*,PToken *pId,PToken *pCode);


#line 521 "pikchr.c"
/**************** End of %include directives **********************************/
/* These constants specify the various numeric values for terminal symbols.
***************** Begin token definitions *************************************/
#ifndef T_ID
#define T_ID                              1
#define T_EDGEPT                          2
#define T_OF                              3







|







490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
static void pik_behind(Pik*,PObj*);
static PObj *pik_assert(Pik*,PNum,PToken*,PNum);
static PObj *pik_position_assert(Pik*,PPoint*,PToken*,PPoint*);
static PNum pik_dist(PPoint*,PPoint*);
static void pik_add_macro(Pik*,PToken *pId,PToken *pCode);


#line 523 "pikchr.c"
/**************** End of %include directives **********************************/
/* These constants specify the various numeric values for terminal symbols.
***************** Begin token definitions *************************************/
#ifndef T_ID
#define T_ID                              1
#define T_EDGEPT                          2
#define T_OF                              3
632
633
634
635
636
637
638



639
640
641
642
643
644
645
646
647
648
649
650
651


652
653
654
655
656
657
658
**                       zero the stack is dynamically sized using realloc()
**    pik_parserARG_SDECL     A static variable declaration for the %extra_argument
**    pik_parserARG_PDECL     A parameter declaration for the %extra_argument
**    pik_parserARG_PARAM     Code to pass %extra_argument as a subroutine parameter
**    pik_parserARG_STORE     Code to store %extra_argument into yypParser
**    pik_parserARG_FETCH     Code to extract %extra_argument from yypParser
**    pik_parserCTX_*         As pik_parserARG_ except for %extra_context



**    YYERRORSYMBOL      is the code number of the error symbol.  If not
**                       defined, then do no error processing.
**    YYNSTATE           the combined number of states.
**    YYNRULE            the number of rules in the grammar
**    YYNTOKEN           Number of terminal symbols
**    YY_MAX_SHIFT       Maximum value for shift actions
**    YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
**    YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
**    YY_ERROR_ACTION    The yy_action[] code for syntax error
**    YY_ACCEPT_ACTION   The yy_action[] code for accept
**    YY_NO_ACTION       The yy_action[] code for no-op
**    YY_MIN_REDUCE      Minimum value for reduce actions
**    YY_MAX_REDUCE      Maximum value for reduce actions


*/
#ifndef INTERFACE
# define INTERFACE 1
#endif
/************* Begin control #defines *****************************************/
#define YYCODETYPE unsigned char
#define YYNOCODE 136







>
>
>













>
>







634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
**                       zero the stack is dynamically sized using realloc()
**    pik_parserARG_SDECL     A static variable declaration for the %extra_argument
**    pik_parserARG_PDECL     A parameter declaration for the %extra_argument
**    pik_parserARG_PARAM     Code to pass %extra_argument as a subroutine parameter
**    pik_parserARG_STORE     Code to store %extra_argument into yypParser
**    pik_parserARG_FETCH     Code to extract %extra_argument from yypParser
**    pik_parserCTX_*         As pik_parserARG_ except for %extra_context
**    YYREALLOC          Name of the realloc() function to use
**    YYFREE             Name of the free() function to use
**    YYDYNSTACK         True if stack space should be extended on heap
**    YYERRORSYMBOL      is the code number of the error symbol.  If not
**                       defined, then do no error processing.
**    YYNSTATE           the combined number of states.
**    YYNRULE            the number of rules in the grammar
**    YYNTOKEN           Number of terminal symbols
**    YY_MAX_SHIFT       Maximum value for shift actions
**    YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
**    YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
**    YY_ERROR_ACTION    The yy_action[] code for syntax error
**    YY_ACCEPT_ACTION   The yy_action[] code for accept
**    YY_NO_ACTION       The yy_action[] code for no-op
**    YY_MIN_REDUCE      Minimum value for reduce actions
**    YY_MAX_REDUCE      Maximum value for reduce actions
**    YY_MIN_DSTRCTR     Minimum symbol value that has a destructor
**    YY_MAX_DSTRCTR     Maximum symbol value that has a destructor
*/
#ifndef INTERFACE
# define INTERFACE 1
#endif
/************* Begin control #defines *****************************************/
#define YYCODETYPE unsigned char
#define YYNOCODE 136
672
673
674
675
676
677
678



679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696


697
698
699
700
701
702
703
704
705
706
707
708
709
710
















711
712
713
714
715
716
717
#define YYSTACKDEPTH 100
#endif
#define pik_parserARG_SDECL
#define pik_parserARG_PDECL
#define pik_parserARG_PARAM
#define pik_parserARG_FETCH
#define pik_parserARG_STORE



#define pik_parserCTX_SDECL Pik *p;
#define pik_parserCTX_PDECL ,Pik *p
#define pik_parserCTX_PARAM ,p
#define pik_parserCTX_FETCH Pik *p=yypParser->p;
#define pik_parserCTX_STORE yypParser->p=p;
#define YYFALLBACK 1
#define YYNSTATE             164
#define YYNRULE              156
#define YYNRULE_WITH_ACTION  116
#define YYNTOKEN             100
#define YY_MAX_SHIFT         163
#define YY_MIN_SHIFTREDUCE   287
#define YY_MAX_SHIFTREDUCE   442
#define YY_ERROR_ACTION      443
#define YY_ACCEPT_ACTION     444
#define YY_NO_ACTION         445
#define YY_MIN_REDUCE        446
#define YY_MAX_REDUCE        601


/************* End control #defines *******************************************/
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))

/* Define the yytestcase() macro to be a no-op if is not already defined
** otherwise.
**
** Applications can choose to define yytestcase() in the %include section
** to a macro that can assist in verifying code coverage.  For production
** code the yytestcase() macro should be turned off.  But it is useful
** for testing.
*/
#ifndef yytestcase
# define yytestcase(X)
#endif


















/* Next are the tables used to determine what action to take based on the
** current state and lookahead token.  These tables are used to implement
** functions that take a state number and lookahead value and return an
** action integer.  
**







>
>
>


















>
>














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
#define YYSTACKDEPTH 100
#endif
#define pik_parserARG_SDECL
#define pik_parserARG_PDECL
#define pik_parserARG_PARAM
#define pik_parserARG_FETCH
#define pik_parserARG_STORE
#define YYREALLOC realloc
#define YYFREE free
#define YYDYNSTACK 0
#define pik_parserCTX_SDECL Pik *p;
#define pik_parserCTX_PDECL ,Pik *p
#define pik_parserCTX_PARAM ,p
#define pik_parserCTX_FETCH Pik *p=yypParser->p;
#define pik_parserCTX_STORE yypParser->p=p;
#define YYFALLBACK 1
#define YYNSTATE             164
#define YYNRULE              156
#define YYNRULE_WITH_ACTION  116
#define YYNTOKEN             100
#define YY_MAX_SHIFT         163
#define YY_MIN_SHIFTREDUCE   287
#define YY_MAX_SHIFTREDUCE   442
#define YY_ERROR_ACTION      443
#define YY_ACCEPT_ACTION     444
#define YY_NO_ACTION         445
#define YY_MIN_REDUCE        446
#define YY_MAX_REDUCE        601
#define YY_MIN_DSTRCTR       100
#define YY_MAX_DSTRCTR       103
/************* End control #defines *******************************************/
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))

/* Define the yytestcase() macro to be a no-op if is not already defined
** otherwise.
**
** Applications can choose to define yytestcase() in the %include section
** to a macro that can assist in verifying code coverage.  For production
** code the yytestcase() macro should be turned off.  But it is useful
** for testing.
*/
#ifndef yytestcase
# define yytestcase(X)
#endif

/* Macro to determine if stack space has the ability to grow using
** heap memory.
*/
#if YYSTACKDEPTH<=0 || YYDYNSTACK
# define YYGROWABLESTACK 1
#else
# define YYGROWABLESTACK 0
#endif

/* Guarantee a minimum number of initial stack slots.
*/
#if YYSTACKDEPTH<=0
# undef YYSTACKDEPTH
# define YYSTACKDEPTH 2  /* Need a minimum stack size */
#endif


/* Next are the tables used to determine what action to take based on the
** current state and lookahead token.  These tables are used to implement
** functions that take a state number and lookahead value and return an
** action integer.  
**
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
  int yyhwm;                    /* High-water mark of the stack */
#endif
#ifndef YYNOERRORRECOVERY
  int yyerrcnt;                 /* Shifts left before out of the error */
#endif
  pik_parserARG_SDECL                /* A place to hold %extra_argument */
  pik_parserCTX_SDECL                /* A place to hold %extra_context */
#if YYSTACKDEPTH<=0
  int yystksz;                  /* Current side of the stack */
  yyStackEntry *yystack;        /* The parser's stack */
  yyStackEntry yystk0;          /* First stack entry */
#else
  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */
  yyStackEntry *yystackEnd;            /* Last entry in the stack */
#endif
};
typedef struct yyParser yyParser;

#include <assert.h>
#ifndef NDEBUG
#include <stdio.h>
static FILE *yyTraceFILE = 0;







<
|
|
|
<
<
<
<







1276
1277
1278
1279
1280
1281
1282

1283
1284
1285




1286
1287
1288
1289
1290
1291
1292
  int yyhwm;                    /* High-water mark of the stack */
#endif
#ifndef YYNOERRORRECOVERY
  int yyerrcnt;                 /* Shifts left before out of the error */
#endif
  pik_parserARG_SDECL                /* A place to hold %extra_argument */
  pik_parserCTX_SDECL                /* A place to hold %extra_context */

  yyStackEntry *yystackEnd;           /* Last entry in the stack */
  yyStackEntry *yystack;              /* The parser stack */
  yyStackEntry yystk0[YYSTACKDEPTH];  /* Initial stack space */




};
typedef struct yyParser yyParser;

#include <assert.h>
#ifndef NDEBUG
#include <stdio.h>
static FILE *yyTraceFILE = 0;
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611

1612
1613
1614
1615
1616
1617
1618
1619
1620

1621
1622

1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633

1634
1635

1636





1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
 /* 153 */ "edge ::= RIGHT",
 /* 154 */ "edge ::= LEFT",
 /* 155 */ "object ::= objectname",
};
#endif /* NDEBUG */


#if YYSTACKDEPTH<=0
/*
** Try to increase the size of the parser stack.  Return the number
** of errors.  Return 0 on success.
*/
static int yyGrowStack(yyParser *p){

  int newSize;
  int idx;
  yyStackEntry *pNew;

  newSize = p->yystksz*2 + 100;
  idx = p->yytos ? (int)(p->yytos - p->yystack) : 0;
  if( p->yystack==&p->yystk0 ){
    pNew = malloc(newSize*sizeof(pNew[0]));
    if( pNew ) pNew[0] = p->yystk0;

  }else{
    pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));

  }
  if( pNew ){
    p->yystack = pNew;
    p->yytos = &p->yystack[idx];
#ifndef NDEBUG
    if( yyTraceFILE ){
      fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n",
              yyTracePrompt, p->yystksz, newSize);
    }
#endif
    p->yystksz = newSize;

  }
  return pNew==0; 

}





#endif

/* Datatype of the argument to the memory allocated passed as the
** second argument to pik_parserAlloc() below.  This can be changed by
** putting an appropriate #define in the %include section of the input
** grammar.
*/
#ifndef YYMALLOCARGTYPE
# define YYMALLOCARGTYPE size_t
#endif

/* Initialize a new parser that has already been allocated.
*/
void pik_parserInit(void *yypRawParser pik_parserCTX_PDECL){
  yyParser *yypParser = (yyParser*)yypRawParser;
  pik_parserCTX_STORE
#ifdef YYTRACKMAXSTACKDEPTH
  yypParser->yyhwm = 0;
#endif
#if YYSTACKDEPTH<=0
  yypParser->yytos = NULL;
  yypParser->yystack = NULL;
  yypParser->yystksz = 0;
  if( yyGrowStack(yypParser) ){
    yypParser->yystack = &yypParser->yystk0;
    yypParser->yystksz = 1;
  }
#endif
#ifndef YYNOERRORRECOVERY
  yypParser->yyerrcnt = -1;
#endif
  yypParser->yytos = yypParser->yystack;
  yypParser->yystack[0].stateno = 0;
  yypParser->yystack[0].major = 0;
#if YYSTACKDEPTH>0
  yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1];
#endif
}

#ifndef pik_parser_ENGINEALWAYSONSTACK
/* 
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
** malloc.







|





>




|
|
|
|
|
>

|
>

<
|
|

|
|
|
|

|
>
|
<
>
|
>
>
>
>
>



















<
<
|
|
<
<
<
<
<






<
<
<







1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649

1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660

1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686


1687
1688





1689
1690
1691
1692
1693
1694



1695
1696
1697
1698
1699
1700
1701
 /* 153 */ "edge ::= RIGHT",
 /* 154 */ "edge ::= LEFT",
 /* 155 */ "object ::= objectname",
};
#endif /* NDEBUG */


#if YYGROWABLESTACK
/*
** Try to increase the size of the parser stack.  Return the number
** of errors.  Return 0 on success.
*/
static int yyGrowStack(yyParser *p){
  int oldSize = 1 + (int)(p->yystackEnd - p->yystack);
  int newSize;
  int idx;
  yyStackEntry *pNew;

  newSize = oldSize*2 + 100;
  idx = (int)(p->yytos - p->yystack);
  if( p->yystack==p->yystk0 ){
    pNew = YYREALLOC(0, newSize*sizeof(pNew[0]));
    if( pNew==0 ) return 1;
    memcpy(pNew, p->yystack, oldSize*sizeof(pNew[0]));
  }else{
    pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0]));
    if( pNew==0 ) return 1;
  }

  p->yystack = pNew;
  p->yytos = &p->yystack[idx];
#ifndef NDEBUG
  if( yyTraceFILE ){
    fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n",
            yyTracePrompt, oldSize, newSize);
  }
#endif
  p->yystackEnd = &p->yystack[newSize-1];
  return 0;
}

#endif /* YYGROWABLESTACK */

#if !YYGROWABLESTACK
/* For builds that do no have a growable stack, yyGrowStack always
** returns an error.
*/
# define yyGrowStack(X) 1
#endif

/* Datatype of the argument to the memory allocated passed as the
** second argument to pik_parserAlloc() below.  This can be changed by
** putting an appropriate #define in the %include section of the input
** grammar.
*/
#ifndef YYMALLOCARGTYPE
# define YYMALLOCARGTYPE size_t
#endif

/* Initialize a new parser that has already been allocated.
*/
void pik_parserInit(void *yypRawParser pik_parserCTX_PDECL){
  yyParser *yypParser = (yyParser*)yypRawParser;
  pik_parserCTX_STORE
#ifdef YYTRACKMAXSTACKDEPTH
  yypParser->yyhwm = 0;
#endif


  yypParser->yystack = yypParser->yystk0;
  yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1];





#ifndef YYNOERRORRECOVERY
  yypParser->yyerrcnt = -1;
#endif
  yypParser->yytos = yypParser->yystack;
  yypParser->yystack[0].stateno = 0;
  yypParser->yystack[0].major = 0;



}

#ifndef pik_parser_ENGINEALWAYSONSTACK
/* 
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
** malloc.
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
    ** Note: during a reduce, the only symbols destroyed are those
    ** which appear on the RHS of the rule, but which are *not* used
    ** inside the C code.
    */
/********* Begin destructor definitions ***************************************/
    case 100: /* statement_list */
{
#line 510 "pikchr.y"
pik_elist_free(p,(yypminor->yy235));
#line 1756 "pikchr.c"
}
      break;
    case 101: /* statement */
    case 102: /* unnamed_statement */
    case 103: /* basetype */
{
#line 512 "pikchr.y"
pik_elem_free(p,(yypminor->yy162));
#line 1765 "pikchr.c"
}
      break;
/********* End destructor definitions *****************************************/
    default:  break;   /* If no destructor action specified: do nothing */
  }
}








|

|






|

|







1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
    ** Note: during a reduce, the only symbols destroyed are those
    ** which appear on the RHS of the rule, but which are *not* used
    ** inside the C code.
    */
/********* Begin destructor definitions ***************************************/
    case 100: /* statement_list */
{
#line 511 "pikchr.y"
pik_elist_free(p,(yypminor->yy235));
#line 1777 "pikchr.c"
}
      break;
    case 101: /* statement */
    case 102: /* unnamed_statement */
    case 103: /* basetype */
{
#line 513 "pikchr.y"
pik_elem_free(p,(yypminor->yy162));
#line 1786 "pikchr.c"
}
      break;
/********* End destructor definitions *****************************************/
    default:  break;   /* If no destructor action specified: do nothing */
  }
}

1767
1768
1769
1770
1771
1772
1773




1774












1775

1776
1777
1778
1779
1780
1781
1782
1783
}

/*
** Clear all secondary memory allocations from the parser
*/
void pik_parserFinalize(void *p){
  yyParser *pParser = (yyParser*)p;




  while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);












#if YYSTACKDEPTH<=0

  if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
#endif
}

#ifndef pik_parser_ENGINEALWAYSONSTACK
/* 
** Deallocate and destroy a parser.  Destructors are called for
** all stack elements before shutting the parser down.







>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|







1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
}

/*
** Clear all secondary memory allocations from the parser
*/
void pik_parserFinalize(void *p){
  yyParser *pParser = (yyParser*)p;

  /* In-lined version of calling yy_pop_parser_stack() for each
  ** element left in the stack */
  yyStackEntry *yytos = pParser->yytos;
  while( yytos>pParser->yystack ){
#ifndef NDEBUG
    if( yyTraceFILE ){
      fprintf(yyTraceFILE,"%sPopping %s\n",
        yyTracePrompt,
        yyTokenName[yytos->major]);
    }
#endif
    if( yytos->major>=YY_MIN_DSTRCTR ){
      yy_destructor(pParser, yytos->major, &yytos->minor);
    }
    yytos--;
  }

#if YYGROWABLESTACK
  if( pParser->yystack!=pParser->yystk0 ) YYFREE(pParser->yystack);
#endif
}

#ifndef pik_parser_ENGINEALWAYSONSTACK
/* 
** Deallocate and destroy a parser.  Destructors are called for
** all stack elements before shutting the parser down.
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
     fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
   }
#endif
   while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
   /* Here code is inserted which will execute if the parser
   ** stack every overflows */
/******** Begin %stack_overflow code ******************************************/
#line 544 "pikchr.y"

  pik_error(p, 0, "parser stack overflow");
#line 1986 "pikchr.c"
/******** End %stack_overflow code ********************************************/
   pik_parserARG_STORE /* Suppress warning about unused %extra_argument var */
   pik_parserCTX_STORE
}

/*
** Print tracing information for a SHIFT action







|


|







1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
     fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
   }
#endif
   while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
   /* Here code is inserted which will execute if the parser
   ** stack every overflows */
/******** Begin %stack_overflow code ******************************************/
#line 545 "pikchr.y"

  pik_error(p, 0, "parser stack overflow");
#line 2024 "pikchr.c"
/******** End %stack_overflow code ********************************************/
   pik_parserARG_STORE /* Suppress warning about unused %extra_argument var */
   pik_parserCTX_STORE
}

/*
** Print tracing information for a SHIFT action
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017


2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
  yypParser->yytos++;
#ifdef YYTRACKMAXSTACKDEPTH
  if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
    yypParser->yyhwm++;
    assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) );
  }
#endif
#if YYSTACKDEPTH>0 
  if( yypParser->yytos>yypParser->yystackEnd ){
    yypParser->yytos--;
    yyStackOverflow(yypParser);
    return;
  }
#else
  if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){
    if( yyGrowStack(yypParser) ){
      yypParser->yytos--;
      yyStackOverflow(yypParser);
      return;
    }


  }
#endif
  if( yyNewState > YY_MAX_SHIFT ){
    yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
  }
  yytos = yypParser->yytos;
  yytos->stateno = yyNewState;
  yytos->major = yyMajor;
  yytos->minor.yy0 = yyMinor;
  yyTraceShift(yypParser, yyNewState, "Shift");
}

/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side







<
<
|
<
<
<
<
|





>
>

<



<







2036
2037
2038
2039
2040
2041
2042


2043




2044
2045
2046
2047
2048
2049
2050
2051
2052

2053
2054
2055

2056
2057
2058
2059
2060
2061
2062
  yypParser->yytos++;
#ifdef YYTRACKMAXSTACKDEPTH
  if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
    yypParser->yyhwm++;
    assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) );
  }
#endif


  yytos = yypParser->yytos;




  if( yytos>yypParser->yystackEnd ){
    if( yyGrowStack(yypParser) ){
      yypParser->yytos--;
      yyStackOverflow(yypParser);
      return;
    }
    yytos = yypParser->yytos;
    assert( yytos <= yypParser->yystackEnd );
  }

  if( yyNewState > YY_MAX_SHIFT ){
    yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
  }

  yytos->stateno = yyNewState;
  yytos->major = yyMajor;
  yytos->minor.yy0 = yyMinor;
  yyTraceShift(yypParser, yyNewState, "Shift");
}

/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
  **     { ... }           // User supplied code
  **  #line <lineno> <thisfile>
  **     break;
  */
/********** Begin reduce actions **********************************************/
        YYMINORTYPE yylhsminor;
      case 0: /* document ::= statement_list */
#line 548 "pikchr.y"
{pik_render(p,yymsp[0].minor.yy235);}
#line 2419 "pikchr.c"
        break;
      case 1: /* statement_list ::= statement */
#line 551 "pikchr.y"
{ yylhsminor.yy235 = pik_elist_append(p,0,yymsp[0].minor.yy162); }
#line 2424 "pikchr.c"
  yymsp[0].minor.yy235 = yylhsminor.yy235;
        break;
      case 2: /* statement_list ::= statement_list EOL statement */
#line 553 "pikchr.y"
{ yylhsminor.yy235 = pik_elist_append(p,yymsp[-2].minor.yy235,yymsp[0].minor.yy162); }
#line 2430 "pikchr.c"
  yymsp[-2].minor.yy235 = yylhsminor.yy235;
        break;
      case 3: /* statement ::= */
#line 556 "pikchr.y"
{ yymsp[1].minor.yy162 = 0; }
#line 2436 "pikchr.c"
        break;
      case 4: /* statement ::= direction */
#line 557 "pikchr.y"
{ pik_set_direction(p,yymsp[0].minor.yy0.eCode);  yylhsminor.yy162=0; }
#line 2441 "pikchr.c"
  yymsp[0].minor.yy162 = yylhsminor.yy162;
        break;
      case 5: /* statement ::= lvalue ASSIGN rvalue */
#line 558 "pikchr.y"
{pik_set_var(p,&yymsp[-2].minor.yy0,yymsp[0].minor.yy21,&yymsp[-1].minor.yy0); yylhsminor.yy162=0;}
#line 2447 "pikchr.c"
  yymsp[-2].minor.yy162 = yylhsminor.yy162;
        break;
      case 6: /* statement ::= PLACENAME COLON unnamed_statement */
#line 560 "pikchr.y"
{ yylhsminor.yy162 = yymsp[0].minor.yy162;  pik_elem_setname(p,yymsp[0].minor.yy162,&yymsp[-2].minor.yy0); }
#line 2453 "pikchr.c"
  yymsp[-2].minor.yy162 = yylhsminor.yy162;
        break;
      case 7: /* statement ::= PLACENAME COLON position */
#line 562 "pikchr.y"
{ yylhsminor.yy162 = pik_elem_new(p,0,0,0);
                 if(yylhsminor.yy162){ yylhsminor.yy162->ptAt = yymsp[0].minor.yy63; pik_elem_setname(p,yylhsminor.yy162,&yymsp[-2].minor.yy0); }}
#line 2460 "pikchr.c"
  yymsp[-2].minor.yy162 = yylhsminor.yy162;
        break;
      case 8: /* statement ::= unnamed_statement */
#line 564 "pikchr.y"
{yylhsminor.yy162 = yymsp[0].minor.yy162;}
#line 2466 "pikchr.c"
  yymsp[0].minor.yy162 = yylhsminor.yy162;
        break;
      case 9: /* statement ::= print prlist */
#line 565 "pikchr.y"
{pik_append(p,"<br>\n",5); yymsp[-1].minor.yy162=0;}
#line 2472 "pikchr.c"
        break;
      case 10: /* statement ::= ASSERT LP expr EQ expr RP */
#line 570 "pikchr.y"
{yymsp[-5].minor.yy162=pik_assert(p,yymsp[-3].minor.yy21,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy21);}
#line 2477 "pikchr.c"
        break;
      case 11: /* statement ::= ASSERT LP position EQ position RP */
#line 572 "pikchr.y"
{yymsp[-5].minor.yy162=pik_position_assert(p,&yymsp[-3].minor.yy63,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy63);}
#line 2482 "pikchr.c"
        break;
      case 12: /* statement ::= DEFINE ID CODEBLOCK */
#line 573 "pikchr.y"
{yymsp[-2].minor.yy162=0; pik_add_macro(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
#line 2487 "pikchr.c"
        break;
      case 13: /* rvalue ::= PLACENAME */
#line 584 "pikchr.y"
{yylhsminor.yy21 = pik_lookup_color(p,&yymsp[0].minor.yy0);}
#line 2492 "pikchr.c"
  yymsp[0].minor.yy21 = yylhsminor.yy21;
        break;
      case 14: /* pritem ::= FILL */
      case 15: /* pritem ::= COLOR */ yytestcase(yyruleno==15);
      case 16: /* pritem ::= THICKNESS */ yytestcase(yyruleno==16);
#line 589 "pikchr.y"
{pik_append_num(p,"",pik_value(p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.n,0));}
#line 2500 "pikchr.c"
        break;
      case 17: /* pritem ::= rvalue */
#line 592 "pikchr.y"
{pik_append_num(p,"",yymsp[0].minor.yy21);}
#line 2505 "pikchr.c"
        break;
      case 18: /* pritem ::= STRING */
#line 593 "pikchr.y"
{pik_append_text(p,yymsp[0].minor.yy0.z+1,yymsp[0].minor.yy0.n-2,0);}
#line 2510 "pikchr.c"
        break;
      case 19: /* prsep ::= COMMA */
#line 594 "pikchr.y"
{pik_append(p, " ", 1);}
#line 2515 "pikchr.c"
        break;
      case 20: /* unnamed_statement ::= basetype attribute_list */
#line 597 "pikchr.y"
{yylhsminor.yy162 = yymsp[-1].minor.yy162; pik_after_adding_attributes(p,yylhsminor.yy162);}
#line 2520 "pikchr.c"
  yymsp[-1].minor.yy162 = yylhsminor.yy162;
        break;
      case 21: /* basetype ::= CLASSNAME */
#line 599 "pikchr.y"
{yylhsminor.yy162 = pik_elem_new(p,&yymsp[0].minor.yy0,0,0); }
#line 2526 "pikchr.c"
  yymsp[0].minor.yy162 = yylhsminor.yy162;
        break;
      case 22: /* basetype ::= STRING textposition */
#line 601 "pikchr.y"
{yymsp[-1].minor.yy0.eCode = yymsp[0].minor.yy188; yylhsminor.yy162 = pik_elem_new(p,0,&yymsp[-1].minor.yy0,0); }
#line 2532 "pikchr.c"
  yymsp[-1].minor.yy162 = yylhsminor.yy162;
        break;
      case 23: /* basetype ::= LB savelist statement_list RB */
#line 603 "pikchr.y"
{ p->list = yymsp[-2].minor.yy235; yymsp[-3].minor.yy162 = pik_elem_new(p,0,0,yymsp[-1].minor.yy235); if(yymsp[-3].minor.yy162) yymsp[-3].minor.yy162->errTok = yymsp[0].minor.yy0; }
#line 2538 "pikchr.c"
        break;
      case 24: /* savelist ::= */
#line 608 "pikchr.y"
{yymsp[1].minor.yy235 = p->list; p->list = 0;}
#line 2543 "pikchr.c"
        break;
      case 25: /* relexpr ::= expr */
#line 615 "pikchr.y"
{yylhsminor.yy72.rAbs = yymsp[0].minor.yy21; yylhsminor.yy72.rRel = 0;}
#line 2548 "pikchr.c"
  yymsp[0].minor.yy72 = yylhsminor.yy72;
        break;
      case 26: /* relexpr ::= expr PERCENT */
#line 616 "pikchr.y"
{yylhsminor.yy72.rAbs = 0; yylhsminor.yy72.rRel = yymsp[-1].minor.yy21/100;}
#line 2554 "pikchr.c"
  yymsp[-1].minor.yy72 = yylhsminor.yy72;
        break;
      case 27: /* optrelexpr ::= */
#line 618 "pikchr.y"
{yymsp[1].minor.yy72.rAbs = 0; yymsp[1].minor.yy72.rRel = 1.0;}
#line 2560 "pikchr.c"
        break;
      case 28: /* attribute_list ::= relexpr alist */
#line 620 "pikchr.y"
{pik_add_direction(p,0,&yymsp[-1].minor.yy72);}
#line 2565 "pikchr.c"
        break;
      case 29: /* attribute ::= numproperty relexpr */
#line 624 "pikchr.y"
{ pik_set_numprop(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy72); }
#line 2570 "pikchr.c"
        break;
      case 30: /* attribute ::= dashproperty expr */
#line 625 "pikchr.y"
{ pik_set_dashed(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy21); }
#line 2575 "pikchr.c"
        break;
      case 31: /* attribute ::= dashproperty */
#line 626 "pikchr.y"
{ pik_set_dashed(p,&yymsp[0].minor.yy0,0);  }
#line 2580 "pikchr.c"
        break;
      case 32: /* attribute ::= colorproperty rvalue */
#line 627 "pikchr.y"
{ pik_set_clrprop(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy21); }
#line 2585 "pikchr.c"
        break;
      case 33: /* attribute ::= go direction optrelexpr */
#line 628 "pikchr.y"
{ pik_add_direction(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy72);}
#line 2590 "pikchr.c"
        break;
      case 34: /* attribute ::= go direction even position */
#line 629 "pikchr.y"
{pik_evenwith(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy63);}
#line 2595 "pikchr.c"
        break;
      case 35: /* attribute ::= CLOSE */
#line 630 "pikchr.y"
{ pik_close_path(p,&yymsp[0].minor.yy0); }
#line 2600 "pikchr.c"
        break;
      case 36: /* attribute ::= CHOP */
#line 631 "pikchr.y"
{ p->cur->bChop = 1; }
#line 2605 "pikchr.c"
        break;
      case 37: /* attribute ::= FROM position */
#line 632 "pikchr.y"
{ pik_set_from(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy63); }
#line 2610 "pikchr.c"
        break;
      case 38: /* attribute ::= TO position */
#line 633 "pikchr.y"
{ pik_add_to(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy63); }
#line 2615 "pikchr.c"
        break;
      case 39: /* attribute ::= THEN */
#line 634 "pikchr.y"
{ pik_then(p, &yymsp[0].minor.yy0, p->cur); }
#line 2620 "pikchr.c"
        break;
      case 40: /* attribute ::= THEN optrelexpr HEADING expr */
      case 42: /* attribute ::= GO optrelexpr HEADING expr */ yytestcase(yyruleno==42);
#line 636 "pikchr.y"
{pik_move_hdg(p,&yymsp[-2].minor.yy72,&yymsp[-1].minor.yy0,yymsp[0].minor.yy21,0,&yymsp[-3].minor.yy0);}
#line 2626 "pikchr.c"
        break;
      case 41: /* attribute ::= THEN optrelexpr EDGEPT */
      case 43: /* attribute ::= GO optrelexpr EDGEPT */ yytestcase(yyruleno==43);
#line 637 "pikchr.y"
{pik_move_hdg(p,&yymsp[-1].minor.yy72,0,0,&yymsp[0].minor.yy0,&yymsp[-2].minor.yy0);}
#line 2632 "pikchr.c"
        break;
      case 44: /* attribute ::= AT position */
#line 642 "pikchr.y"
{ pik_set_at(p,0,&yymsp[0].minor.yy63,&yymsp[-1].minor.yy0); }
#line 2637 "pikchr.c"
        break;
      case 45: /* attribute ::= SAME */
#line 644 "pikchr.y"
{pik_same(p,0,&yymsp[0].minor.yy0);}
#line 2642 "pikchr.c"
        break;
      case 46: /* attribute ::= SAME AS object */
#line 645 "pikchr.y"
{pik_same(p,yymsp[0].minor.yy162,&yymsp[-2].minor.yy0);}
#line 2647 "pikchr.c"
        break;
      case 47: /* attribute ::= STRING textposition */
#line 646 "pikchr.y"
{pik_add_txt(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy188);}
#line 2652 "pikchr.c"
        break;
      case 48: /* attribute ::= FIT */
#line 647 "pikchr.y"
{pik_size_to_fit(p,&yymsp[0].minor.yy0,3); }
#line 2657 "pikchr.c"
        break;
      case 49: /* attribute ::= BEHIND object */
#line 648 "pikchr.y"
{pik_behind(p,yymsp[0].minor.yy162);}
#line 2662 "pikchr.c"
        break;
      case 50: /* withclause ::= DOT_E edge AT position */
      case 51: /* withclause ::= edge AT position */ yytestcase(yyruleno==51);
#line 656 "pikchr.y"
{ pik_set_at(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy63,&yymsp[-1].minor.yy0); }
#line 2668 "pikchr.c"
        break;
      case 52: /* numproperty ::= HEIGHT|WIDTH|RADIUS|DIAMETER|THICKNESS */
#line 660 "pikchr.y"
{yylhsminor.yy0 = yymsp[0].minor.yy0;}
#line 2673 "pikchr.c"
  yymsp[0].minor.yy0 = yylhsminor.yy0;
        break;
      case 53: /* boolproperty ::= CW */
#line 671 "pikchr.y"
{p->cur->cw = 1;}
#line 2679 "pikchr.c"
        break;
      case 54: /* boolproperty ::= CCW */
#line 672 "pikchr.y"
{p->cur->cw = 0;}
#line 2684 "pikchr.c"
        break;
      case 55: /* boolproperty ::= LARROW */
#line 673 "pikchr.y"
{p->cur->larrow=1; p->cur->rarrow=0; }
#line 2689 "pikchr.c"
        break;
      case 56: /* boolproperty ::= RARROW */
#line 674 "pikchr.y"
{p->cur->larrow=0; p->cur->rarrow=1; }
#line 2694 "pikchr.c"
        break;
      case 57: /* boolproperty ::= LRARROW */
#line 675 "pikchr.y"
{p->cur->larrow=1; p->cur->rarrow=1; }
#line 2699 "pikchr.c"
        break;
      case 58: /* boolproperty ::= INVIS */
#line 676 "pikchr.y"
{p->cur->sw = -0.00001;}
#line 2704 "pikchr.c"
        break;
      case 59: /* boolproperty ::= THICK */
#line 677 "pikchr.y"
{p->cur->sw *= 1.5;}
#line 2709 "pikchr.c"
        break;
      case 60: /* boolproperty ::= THIN */
#line 678 "pikchr.y"
{p->cur->sw *= 0.67;}
#line 2714 "pikchr.c"
        break;
      case 61: /* boolproperty ::= SOLID */
#line 679 "pikchr.y"
{p->cur->sw = pik_value(p,"thickness",9,0);
                               p->cur->dotted = p->cur->dashed = 0.0;}
#line 2720 "pikchr.c"
        break;
      case 62: /* textposition ::= */
#line 682 "pikchr.y"
{yymsp[1].minor.yy188 = 0;}
#line 2725 "pikchr.c"
        break;
      case 63: /* textposition ::= textposition CENTER|LJUST|RJUST|ABOVE|BELOW|ITALIC|BOLD|MONO|ALIGNED|BIG|SMALL */
#line 685 "pikchr.y"
{yylhsminor.yy188 = (short int)pik_text_position(yymsp[-1].minor.yy188,&yymsp[0].minor.yy0);}
#line 2730 "pikchr.c"
  yymsp[-1].minor.yy188 = yylhsminor.yy188;
        break;
      case 64: /* position ::= expr COMMA expr */
#line 688 "pikchr.y"
{yylhsminor.yy63.x=yymsp[-2].minor.yy21; yylhsminor.yy63.y=yymsp[0].minor.yy21;}
#line 2736 "pikchr.c"
  yymsp[-2].minor.yy63 = yylhsminor.yy63;
        break;
      case 65: /* position ::= place PLUS expr COMMA expr */
#line 690 "pikchr.y"
{yylhsminor.yy63.x=yymsp[-4].minor.yy63.x+yymsp[-2].minor.yy21; yylhsminor.yy63.y=yymsp[-4].minor.yy63.y+yymsp[0].minor.yy21;}
#line 2742 "pikchr.c"
  yymsp[-4].minor.yy63 = yylhsminor.yy63;
        break;
      case 66: /* position ::= place MINUS expr COMMA expr */
#line 691 "pikchr.y"
{yylhsminor.yy63.x=yymsp[-4].minor.yy63.x-yymsp[-2].minor.yy21; yylhsminor.yy63.y=yymsp[-4].minor.yy63.y-yymsp[0].minor.yy21;}
#line 2748 "pikchr.c"
  yymsp[-4].minor.yy63 = yylhsminor.yy63;
        break;
      case 67: /* position ::= place PLUS LP expr COMMA expr RP */
#line 693 "pikchr.y"
{yylhsminor.yy63.x=yymsp[-6].minor.yy63.x+yymsp[-3].minor.yy21; yylhsminor.yy63.y=yymsp[-6].minor.yy63.y+yymsp[-1].minor.yy21;}
#line 2754 "pikchr.c"
  yymsp[-6].minor.yy63 = yylhsminor.yy63;
        break;
      case 68: /* position ::= place MINUS LP expr COMMA expr RP */
#line 695 "pikchr.y"
{yylhsminor.yy63.x=yymsp[-6].minor.yy63.x-yymsp[-3].minor.yy21; yylhsminor.yy63.y=yymsp[-6].minor.yy63.y-yymsp[-1].minor.yy21;}
#line 2760 "pikchr.c"
  yymsp[-6].minor.yy63 = yylhsminor.yy63;
        break;
      case 69: /* position ::= LP position COMMA position RP */
#line 696 "pikchr.y"
{yymsp[-4].minor.yy63.x=yymsp[-3].minor.yy63.x; yymsp[-4].minor.yy63.y=yymsp[-1].minor.yy63.y;}
#line 2766 "pikchr.c"
        break;
      case 70: /* position ::= LP position RP */
#line 697 "pikchr.y"
{yymsp[-2].minor.yy63=yymsp[-1].minor.yy63;}
#line 2771 "pikchr.c"
        break;
      case 71: /* position ::= expr between position AND position */
#line 699 "pikchr.y"
{yylhsminor.yy63 = pik_position_between(yymsp[-4].minor.yy21,yymsp[-2].minor.yy63,yymsp[0].minor.yy63);}
#line 2776 "pikchr.c"
  yymsp[-4].minor.yy63 = yylhsminor.yy63;
        break;
      case 72: /* position ::= expr LT position COMMA position GT */
#line 701 "pikchr.y"
{yylhsminor.yy63 = pik_position_between(yymsp[-5].minor.yy21,yymsp[-3].minor.yy63,yymsp[-1].minor.yy63);}
#line 2782 "pikchr.c"
  yymsp[-5].minor.yy63 = yylhsminor.yy63;
        break;
      case 73: /* position ::= expr ABOVE position */
#line 702 "pikchr.y"
{yylhsminor.yy63=yymsp[0].minor.yy63; yylhsminor.yy63.y += yymsp[-2].minor.yy21;}
#line 2788 "pikchr.c"
  yymsp[-2].minor.yy63 = yylhsminor.yy63;
        break;
      case 74: /* position ::= expr BELOW position */
#line 703 "pikchr.y"
{yylhsminor.yy63=yymsp[0].minor.yy63; yylhsminor.yy63.y -= yymsp[-2].minor.yy21;}
#line 2794 "pikchr.c"
  yymsp[-2].minor.yy63 = yylhsminor.yy63;
        break;
      case 75: /* position ::= expr LEFT OF position */
#line 704 "pikchr.y"
{yylhsminor.yy63=yymsp[0].minor.yy63; yylhsminor.yy63.x -= yymsp[-3].minor.yy21;}
#line 2800 "pikchr.c"
  yymsp[-3].minor.yy63 = yylhsminor.yy63;
        break;
      case 76: /* position ::= expr RIGHT OF position */
#line 705 "pikchr.y"
{yylhsminor.yy63=yymsp[0].minor.yy63; yylhsminor.yy63.x += yymsp[-3].minor.yy21;}
#line 2806 "pikchr.c"
  yymsp[-3].minor.yy63 = yylhsminor.yy63;
        break;
      case 77: /* position ::= expr ON HEADING EDGEPT OF position */
#line 707 "pikchr.y"
{yylhsminor.yy63 = pik_position_at_hdg(yymsp[-5].minor.yy21,&yymsp[-2].minor.yy0,yymsp[0].minor.yy63);}
#line 2812 "pikchr.c"
  yymsp[-5].minor.yy63 = yylhsminor.yy63;
        break;
      case 78: /* position ::= expr HEADING EDGEPT OF position */
#line 709 "pikchr.y"
{yylhsminor.yy63 = pik_position_at_hdg(yymsp[-4].minor.yy21,&yymsp[-2].minor.yy0,yymsp[0].minor.yy63);}
#line 2818 "pikchr.c"
  yymsp[-4].minor.yy63 = yylhsminor.yy63;
        break;
      case 79: /* position ::= expr EDGEPT OF position */
#line 711 "pikchr.y"
{yylhsminor.yy63 = pik_position_at_hdg(yymsp[-3].minor.yy21,&yymsp[-2].minor.yy0,yymsp[0].minor.yy63);}
#line 2824 "pikchr.c"
  yymsp[-3].minor.yy63 = yylhsminor.yy63;
        break;
      case 80: /* position ::= expr ON HEADING expr FROM position */
#line 713 "pikchr.y"
{yylhsminor.yy63 = pik_position_at_angle(yymsp[-5].minor.yy21,yymsp[-2].minor.yy21,yymsp[0].minor.yy63);}
#line 2830 "pikchr.c"
  yymsp[-5].minor.yy63 = yylhsminor.yy63;
        break;
      case 81: /* position ::= expr HEADING expr FROM position */
#line 715 "pikchr.y"
{yylhsminor.yy63 = pik_position_at_angle(yymsp[-4].minor.yy21,yymsp[-2].minor.yy21,yymsp[0].minor.yy63);}
#line 2836 "pikchr.c"
  yymsp[-4].minor.yy63 = yylhsminor.yy63;
        break;
      case 82: /* place ::= edge OF object */
#line 727 "pikchr.y"
{yylhsminor.yy63 = pik_place_of_elem(p,yymsp[0].minor.yy162,&yymsp[-2].minor.yy0);}
#line 2842 "pikchr.c"
  yymsp[-2].minor.yy63 = yylhsminor.yy63;
        break;
      case 83: /* place2 ::= object */
#line 728 "pikchr.y"
{yylhsminor.yy63 = pik_place_of_elem(p,yymsp[0].minor.yy162,0);}
#line 2848 "pikchr.c"
  yymsp[0].minor.yy63 = yylhsminor.yy63;
        break;
      case 84: /* place2 ::= object DOT_E edge */
#line 729 "pikchr.y"
{yylhsminor.yy63 = pik_place_of_elem(p,yymsp[-2].minor.yy162,&yymsp[0].minor.yy0);}
#line 2854 "pikchr.c"
  yymsp[-2].minor.yy63 = yylhsminor.yy63;
        break;
      case 85: /* place2 ::= NTH VERTEX OF object */
#line 730 "pikchr.y"
{yylhsminor.yy63 = pik_nth_vertex(p,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,yymsp[0].minor.yy162);}
#line 2860 "pikchr.c"
  yymsp[-3].minor.yy63 = yylhsminor.yy63;
        break;
      case 86: /* object ::= nth */
#line 742 "pikchr.y"
{yylhsminor.yy162 = pik_find_nth(p,0,&yymsp[0].minor.yy0);}
#line 2866 "pikchr.c"
  yymsp[0].minor.yy162 = yylhsminor.yy162;
        break;
      case 87: /* object ::= nth OF|IN object */
#line 743 "pikchr.y"
{yylhsminor.yy162 = pik_find_nth(p,yymsp[0].minor.yy162,&yymsp[-2].minor.yy0);}
#line 2872 "pikchr.c"
  yymsp[-2].minor.yy162 = yylhsminor.yy162;
        break;
      case 88: /* objectname ::= THIS */
#line 745 "pikchr.y"
{yymsp[0].minor.yy162 = p->cur;}
#line 2878 "pikchr.c"
        break;
      case 89: /* objectname ::= PLACENAME */
#line 746 "pikchr.y"
{yylhsminor.yy162 = pik_find_byname(p,0,&yymsp[0].minor.yy0);}
#line 2883 "pikchr.c"
  yymsp[0].minor.yy162 = yylhsminor.yy162;
        break;
      case 90: /* objectname ::= objectname DOT_U PLACENAME */
#line 748 "pikchr.y"
{yylhsminor.yy162 = pik_find_byname(p,yymsp[-2].minor.yy162,&yymsp[0].minor.yy0);}
#line 2889 "pikchr.c"
  yymsp[-2].minor.yy162 = yylhsminor.yy162;
        break;
      case 91: /* nth ::= NTH CLASSNAME */
#line 750 "pikchr.y"
{yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-1].minor.yy0); }
#line 2895 "pikchr.c"
  yymsp[-1].minor.yy0 = yylhsminor.yy0;
        break;
      case 92: /* nth ::= NTH LAST CLASSNAME */
#line 751 "pikchr.y"
{yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-2].minor.yy0); }
#line 2901 "pikchr.c"
  yymsp[-2].minor.yy0 = yylhsminor.yy0;
        break;
      case 93: /* nth ::= LAST CLASSNAME */
#line 752 "pikchr.y"
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.eCode = -1;}
#line 2907 "pikchr.c"
        break;
      case 94: /* nth ::= LAST */
#line 753 "pikchr.y"
{yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -1;}
#line 2912 "pikchr.c"
  yymsp[0].minor.yy0 = yylhsminor.yy0;
        break;
      case 95: /* nth ::= NTH LB RB */
#line 754 "pikchr.y"
{yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-2].minor.yy0);}
#line 2918 "pikchr.c"
  yymsp[-2].minor.yy0 = yylhsminor.yy0;
        break;
      case 96: /* nth ::= NTH LAST LB RB */
#line 755 "pikchr.y"
{yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-3].minor.yy0);}
#line 2924 "pikchr.c"
  yymsp[-3].minor.yy0 = yylhsminor.yy0;
        break;
      case 97: /* nth ::= LAST LB RB */
#line 756 "pikchr.y"
{yymsp[-2].minor.yy0=yymsp[-1].minor.yy0; yymsp[-2].minor.yy0.eCode = -1; }
#line 2930 "pikchr.c"
        break;
      case 98: /* expr ::= expr PLUS expr */
#line 758 "pikchr.y"
{yylhsminor.yy21=yymsp[-2].minor.yy21+yymsp[0].minor.yy21;}
#line 2935 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      case 99: /* expr ::= expr MINUS expr */
#line 759 "pikchr.y"
{yylhsminor.yy21=yymsp[-2].minor.yy21-yymsp[0].minor.yy21;}
#line 2941 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      case 100: /* expr ::= expr STAR expr */
#line 760 "pikchr.y"
{yylhsminor.yy21=yymsp[-2].minor.yy21*yymsp[0].minor.yy21;}
#line 2947 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      case 101: /* expr ::= expr SLASH expr */
#line 761 "pikchr.y"
{
  if( yymsp[0].minor.yy21==0.0 ){ pik_error(p, &yymsp[-1].minor.yy0, "division by zero"); yylhsminor.yy21 = 0.0; }
  else{ yylhsminor.yy21 = yymsp[-2].minor.yy21/yymsp[0].minor.yy21; }
}
#line 2956 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      case 102: /* expr ::= MINUS expr */
#line 765 "pikchr.y"
{yymsp[-1].minor.yy21=-yymsp[0].minor.yy21;}
#line 2962 "pikchr.c"
        break;
      case 103: /* expr ::= PLUS expr */
#line 766 "pikchr.y"
{yymsp[-1].minor.yy21=yymsp[0].minor.yy21;}
#line 2967 "pikchr.c"
        break;
      case 104: /* expr ::= LP expr RP */
#line 767 "pikchr.y"
{yymsp[-2].minor.yy21=yymsp[-1].minor.yy21;}
#line 2972 "pikchr.c"
        break;
      case 105: /* expr ::= LP FILL|COLOR|THICKNESS RP */
#line 768 "pikchr.y"
{yymsp[-2].minor.yy21=pik_get_var(p,&yymsp[-1].minor.yy0);}
#line 2977 "pikchr.c"
        break;
      case 106: /* expr ::= NUMBER */
#line 769 "pikchr.y"
{yylhsminor.yy21=pik_atof(&yymsp[0].minor.yy0);}
#line 2982 "pikchr.c"
  yymsp[0].minor.yy21 = yylhsminor.yy21;
        break;
      case 107: /* expr ::= ID */
#line 770 "pikchr.y"
{yylhsminor.yy21=pik_get_var(p,&yymsp[0].minor.yy0);}
#line 2988 "pikchr.c"
  yymsp[0].minor.yy21 = yylhsminor.yy21;
        break;
      case 108: /* expr ::= FUNC1 LP expr RP */
#line 771 "pikchr.y"
{yylhsminor.yy21 = pik_func(p,&yymsp[-3].minor.yy0,yymsp[-1].minor.yy21,0.0);}
#line 2994 "pikchr.c"
  yymsp[-3].minor.yy21 = yylhsminor.yy21;
        break;
      case 109: /* expr ::= FUNC2 LP expr COMMA expr RP */
#line 772 "pikchr.y"
{yylhsminor.yy21 = pik_func(p,&yymsp[-5].minor.yy0,yymsp[-3].minor.yy21,yymsp[-1].minor.yy21);}
#line 3000 "pikchr.c"
  yymsp[-5].minor.yy21 = yylhsminor.yy21;
        break;
      case 110: /* expr ::= DIST LP position COMMA position RP */
#line 773 "pikchr.y"
{yymsp[-5].minor.yy21 = pik_dist(&yymsp[-3].minor.yy63,&yymsp[-1].minor.yy63);}
#line 3006 "pikchr.c"
        break;
      case 111: /* expr ::= place2 DOT_XY X */
#line 774 "pikchr.y"
{yylhsminor.yy21 = yymsp[-2].minor.yy63.x;}
#line 3011 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      case 112: /* expr ::= place2 DOT_XY Y */
#line 775 "pikchr.y"
{yylhsminor.yy21 = yymsp[-2].minor.yy63.y;}
#line 3017 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      case 113: /* expr ::= object DOT_L numproperty */
      case 114: /* expr ::= object DOT_L dashproperty */ yytestcase(yyruleno==114);
      case 115: /* expr ::= object DOT_L colorproperty */ yytestcase(yyruleno==115);
#line 776 "pikchr.y"
{yylhsminor.yy21=pik_property_of(yymsp[-2].minor.yy162,&yymsp[0].minor.yy0);}
#line 3025 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      default:
      /* (116) lvalue ::= ID */ yytestcase(yyruleno==116);
      /* (117) lvalue ::= FILL */ yytestcase(yyruleno==117);
      /* (118) lvalue ::= COLOR */ yytestcase(yyruleno==118);
      /* (119) lvalue ::= THICKNESS */ yytestcase(yyruleno==119);







|

|


|

|



|

|



|

|


|

|



|

|



|

|



|


|



|

|



|

|


|

|


|

|


|

|


|

|





|

|


|

|


|

|


|

|


|

|



|

|



|

|



|

|


|

|


|

|



|

|



|

|


|

|


|

|


|

|


|

|


|

|


|

|


|

|


|

|


|

|


|

|


|

|


|

|



|

|



|

|


|

|


|

|


|

|


|

|


|

|


|

|



|

|


|

|



|

|


|

|


|

|


|

|


|

|


|

|


|

|


|

|


|


|


|

|


|

|



|

|



|

|



|

|



|

|



|

|



|

|


|

|


|

|



|

|



|

|



|

|



|

|



|

|



|

|



|

|



|

|



|

|



|

|



|

|



|

|



|

|



|

|



|

|



|

|



|

|


|

|



|

|



|

|



|

|



|

|


|

|



|

|



|

|



|

|


|

|



|

|



|

|



|




|



|

|


|

|


|

|


|

|


|

|



|

|



|

|



|

|



|

|


|

|



|

|





|

|







2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
  **     { ... }           // User supplied code
  **  #line <lineno> <thisfile>
  **     break;
  */
/********** Begin reduce actions **********************************************/
        YYMINORTYPE yylhsminor;
      case 0: /* document ::= statement_list */
#line 549 "pikchr.y"
{pik_render(p,yymsp[0].minor.yy235);}
#line 2451 "pikchr.c"
        break;
      case 1: /* statement_list ::= statement */
#line 552 "pikchr.y"
{ yylhsminor.yy235 = pik_elist_append(p,0,yymsp[0].minor.yy162); }
#line 2456 "pikchr.c"
  yymsp[0].minor.yy235 = yylhsminor.yy235;
        break;
      case 2: /* statement_list ::= statement_list EOL statement */
#line 554 "pikchr.y"
{ yylhsminor.yy235 = pik_elist_append(p,yymsp[-2].minor.yy235,yymsp[0].minor.yy162); }
#line 2462 "pikchr.c"
  yymsp[-2].minor.yy235 = yylhsminor.yy235;
        break;
      case 3: /* statement ::= */
#line 557 "pikchr.y"
{ yymsp[1].minor.yy162 = 0; }
#line 2468 "pikchr.c"
        break;
      case 4: /* statement ::= direction */
#line 558 "pikchr.y"
{ pik_set_direction(p,yymsp[0].minor.yy0.eCode);  yylhsminor.yy162=0; }
#line 2473 "pikchr.c"
  yymsp[0].minor.yy162 = yylhsminor.yy162;
        break;
      case 5: /* statement ::= lvalue ASSIGN rvalue */
#line 559 "pikchr.y"
{pik_set_var(p,&yymsp[-2].minor.yy0,yymsp[0].minor.yy21,&yymsp[-1].minor.yy0); yylhsminor.yy162=0;}
#line 2479 "pikchr.c"
  yymsp[-2].minor.yy162 = yylhsminor.yy162;
        break;
      case 6: /* statement ::= PLACENAME COLON unnamed_statement */
#line 561 "pikchr.y"
{ yylhsminor.yy162 = yymsp[0].minor.yy162;  pik_elem_setname(p,yymsp[0].minor.yy162,&yymsp[-2].minor.yy0); }
#line 2485 "pikchr.c"
  yymsp[-2].minor.yy162 = yylhsminor.yy162;
        break;
      case 7: /* statement ::= PLACENAME COLON position */
#line 563 "pikchr.y"
{ yylhsminor.yy162 = pik_elem_new(p,0,0,0);
                 if(yylhsminor.yy162){ yylhsminor.yy162->ptAt = yymsp[0].minor.yy63; pik_elem_setname(p,yylhsminor.yy162,&yymsp[-2].minor.yy0); }}
#line 2492 "pikchr.c"
  yymsp[-2].minor.yy162 = yylhsminor.yy162;
        break;
      case 8: /* statement ::= unnamed_statement */
#line 565 "pikchr.y"
{yylhsminor.yy162 = yymsp[0].minor.yy162;}
#line 2498 "pikchr.c"
  yymsp[0].minor.yy162 = yylhsminor.yy162;
        break;
      case 9: /* statement ::= print prlist */
#line 566 "pikchr.y"
{pik_append(p,"<br>\n",5); yymsp[-1].minor.yy162=0;}
#line 2504 "pikchr.c"
        break;
      case 10: /* statement ::= ASSERT LP expr EQ expr RP */
#line 571 "pikchr.y"
{yymsp[-5].minor.yy162=pik_assert(p,yymsp[-3].minor.yy21,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy21);}
#line 2509 "pikchr.c"
        break;
      case 11: /* statement ::= ASSERT LP position EQ position RP */
#line 573 "pikchr.y"
{yymsp[-5].minor.yy162=pik_position_assert(p,&yymsp[-3].minor.yy63,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy63);}
#line 2514 "pikchr.c"
        break;
      case 12: /* statement ::= DEFINE ID CODEBLOCK */
#line 574 "pikchr.y"
{yymsp[-2].minor.yy162=0; pik_add_macro(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
#line 2519 "pikchr.c"
        break;
      case 13: /* rvalue ::= PLACENAME */
#line 585 "pikchr.y"
{yylhsminor.yy21 = pik_lookup_color(p,&yymsp[0].minor.yy0);}
#line 2524 "pikchr.c"
  yymsp[0].minor.yy21 = yylhsminor.yy21;
        break;
      case 14: /* pritem ::= FILL */
      case 15: /* pritem ::= COLOR */ yytestcase(yyruleno==15);
      case 16: /* pritem ::= THICKNESS */ yytestcase(yyruleno==16);
#line 590 "pikchr.y"
{pik_append_num(p,"",pik_value(p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.n,0));}
#line 2532 "pikchr.c"
        break;
      case 17: /* pritem ::= rvalue */
#line 593 "pikchr.y"
{pik_append_num(p,"",yymsp[0].minor.yy21);}
#line 2537 "pikchr.c"
        break;
      case 18: /* pritem ::= STRING */
#line 594 "pikchr.y"
{pik_append_text(p,yymsp[0].minor.yy0.z+1,yymsp[0].minor.yy0.n-2,0);}
#line 2542 "pikchr.c"
        break;
      case 19: /* prsep ::= COMMA */
#line 595 "pikchr.y"
{pik_append(p, " ", 1);}
#line 2547 "pikchr.c"
        break;
      case 20: /* unnamed_statement ::= basetype attribute_list */
#line 598 "pikchr.y"
{yylhsminor.yy162 = yymsp[-1].minor.yy162; pik_after_adding_attributes(p,yylhsminor.yy162);}
#line 2552 "pikchr.c"
  yymsp[-1].minor.yy162 = yylhsminor.yy162;
        break;
      case 21: /* basetype ::= CLASSNAME */
#line 600 "pikchr.y"
{yylhsminor.yy162 = pik_elem_new(p,&yymsp[0].minor.yy0,0,0); }
#line 2558 "pikchr.c"
  yymsp[0].minor.yy162 = yylhsminor.yy162;
        break;
      case 22: /* basetype ::= STRING textposition */
#line 602 "pikchr.y"
{yymsp[-1].minor.yy0.eCode = yymsp[0].minor.yy188; yylhsminor.yy162 = pik_elem_new(p,0,&yymsp[-1].minor.yy0,0); }
#line 2564 "pikchr.c"
  yymsp[-1].minor.yy162 = yylhsminor.yy162;
        break;
      case 23: /* basetype ::= LB savelist statement_list RB */
#line 604 "pikchr.y"
{ p->list = yymsp[-2].minor.yy235; yymsp[-3].minor.yy162 = pik_elem_new(p,0,0,yymsp[-1].minor.yy235); if(yymsp[-3].minor.yy162) yymsp[-3].minor.yy162->errTok = yymsp[0].minor.yy0; }
#line 2570 "pikchr.c"
        break;
      case 24: /* savelist ::= */
#line 609 "pikchr.y"
{yymsp[1].minor.yy235 = p->list; p->list = 0;}
#line 2575 "pikchr.c"
        break;
      case 25: /* relexpr ::= expr */
#line 616 "pikchr.y"
{yylhsminor.yy72.rAbs = yymsp[0].minor.yy21; yylhsminor.yy72.rRel = 0;}
#line 2580 "pikchr.c"
  yymsp[0].minor.yy72 = yylhsminor.yy72;
        break;
      case 26: /* relexpr ::= expr PERCENT */
#line 617 "pikchr.y"
{yylhsminor.yy72.rAbs = 0; yylhsminor.yy72.rRel = yymsp[-1].minor.yy21/100;}
#line 2586 "pikchr.c"
  yymsp[-1].minor.yy72 = yylhsminor.yy72;
        break;
      case 27: /* optrelexpr ::= */
#line 619 "pikchr.y"
{yymsp[1].minor.yy72.rAbs = 0; yymsp[1].minor.yy72.rRel = 1.0;}
#line 2592 "pikchr.c"
        break;
      case 28: /* attribute_list ::= relexpr alist */
#line 621 "pikchr.y"
{pik_add_direction(p,0,&yymsp[-1].minor.yy72);}
#line 2597 "pikchr.c"
        break;
      case 29: /* attribute ::= numproperty relexpr */
#line 625 "pikchr.y"
{ pik_set_numprop(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy72); }
#line 2602 "pikchr.c"
        break;
      case 30: /* attribute ::= dashproperty expr */
#line 626 "pikchr.y"
{ pik_set_dashed(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy21); }
#line 2607 "pikchr.c"
        break;
      case 31: /* attribute ::= dashproperty */
#line 627 "pikchr.y"
{ pik_set_dashed(p,&yymsp[0].minor.yy0,0);  }
#line 2612 "pikchr.c"
        break;
      case 32: /* attribute ::= colorproperty rvalue */
#line 628 "pikchr.y"
{ pik_set_clrprop(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy21); }
#line 2617 "pikchr.c"
        break;
      case 33: /* attribute ::= go direction optrelexpr */
#line 629 "pikchr.y"
{ pik_add_direction(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy72);}
#line 2622 "pikchr.c"
        break;
      case 34: /* attribute ::= go direction even position */
#line 630 "pikchr.y"
{pik_evenwith(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy63);}
#line 2627 "pikchr.c"
        break;
      case 35: /* attribute ::= CLOSE */
#line 631 "pikchr.y"
{ pik_close_path(p,&yymsp[0].minor.yy0); }
#line 2632 "pikchr.c"
        break;
      case 36: /* attribute ::= CHOP */
#line 632 "pikchr.y"
{ p->cur->bChop = 1; }
#line 2637 "pikchr.c"
        break;
      case 37: /* attribute ::= FROM position */
#line 633 "pikchr.y"
{ pik_set_from(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy63); }
#line 2642 "pikchr.c"
        break;
      case 38: /* attribute ::= TO position */
#line 634 "pikchr.y"
{ pik_add_to(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy63); }
#line 2647 "pikchr.c"
        break;
      case 39: /* attribute ::= THEN */
#line 635 "pikchr.y"
{ pik_then(p, &yymsp[0].minor.yy0, p->cur); }
#line 2652 "pikchr.c"
        break;
      case 40: /* attribute ::= THEN optrelexpr HEADING expr */
      case 42: /* attribute ::= GO optrelexpr HEADING expr */ yytestcase(yyruleno==42);
#line 637 "pikchr.y"
{pik_move_hdg(p,&yymsp[-2].minor.yy72,&yymsp[-1].minor.yy0,yymsp[0].minor.yy21,0,&yymsp[-3].minor.yy0);}
#line 2658 "pikchr.c"
        break;
      case 41: /* attribute ::= THEN optrelexpr EDGEPT */
      case 43: /* attribute ::= GO optrelexpr EDGEPT */ yytestcase(yyruleno==43);
#line 638 "pikchr.y"
{pik_move_hdg(p,&yymsp[-1].minor.yy72,0,0,&yymsp[0].minor.yy0,&yymsp[-2].minor.yy0);}
#line 2664 "pikchr.c"
        break;
      case 44: /* attribute ::= AT position */
#line 643 "pikchr.y"
{ pik_set_at(p,0,&yymsp[0].minor.yy63,&yymsp[-1].minor.yy0); }
#line 2669 "pikchr.c"
        break;
      case 45: /* attribute ::= SAME */
#line 645 "pikchr.y"
{pik_same(p,0,&yymsp[0].minor.yy0);}
#line 2674 "pikchr.c"
        break;
      case 46: /* attribute ::= SAME AS object */
#line 646 "pikchr.y"
{pik_same(p,yymsp[0].minor.yy162,&yymsp[-2].minor.yy0);}
#line 2679 "pikchr.c"
        break;
      case 47: /* attribute ::= STRING textposition */
#line 647 "pikchr.y"
{pik_add_txt(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy188);}
#line 2684 "pikchr.c"
        break;
      case 48: /* attribute ::= FIT */
#line 648 "pikchr.y"
{pik_size_to_fit(p,&yymsp[0].minor.yy0,3); }
#line 2689 "pikchr.c"
        break;
      case 49: /* attribute ::= BEHIND object */
#line 649 "pikchr.y"
{pik_behind(p,yymsp[0].minor.yy162);}
#line 2694 "pikchr.c"
        break;
      case 50: /* withclause ::= DOT_E edge AT position */
      case 51: /* withclause ::= edge AT position */ yytestcase(yyruleno==51);
#line 657 "pikchr.y"
{ pik_set_at(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy63,&yymsp[-1].minor.yy0); }
#line 2700 "pikchr.c"
        break;
      case 52: /* numproperty ::= HEIGHT|WIDTH|RADIUS|DIAMETER|THICKNESS */
#line 661 "pikchr.y"
{yylhsminor.yy0 = yymsp[0].minor.yy0;}
#line 2705 "pikchr.c"
  yymsp[0].minor.yy0 = yylhsminor.yy0;
        break;
      case 53: /* boolproperty ::= CW */
#line 672 "pikchr.y"
{p->cur->cw = 1;}
#line 2711 "pikchr.c"
        break;
      case 54: /* boolproperty ::= CCW */
#line 673 "pikchr.y"
{p->cur->cw = 0;}
#line 2716 "pikchr.c"
        break;
      case 55: /* boolproperty ::= LARROW */
#line 674 "pikchr.y"
{p->cur->larrow=1; p->cur->rarrow=0; }
#line 2721 "pikchr.c"
        break;
      case 56: /* boolproperty ::= RARROW */
#line 675 "pikchr.y"
{p->cur->larrow=0; p->cur->rarrow=1; }
#line 2726 "pikchr.c"
        break;
      case 57: /* boolproperty ::= LRARROW */
#line 676 "pikchr.y"
{p->cur->larrow=1; p->cur->rarrow=1; }
#line 2731 "pikchr.c"
        break;
      case 58: /* boolproperty ::= INVIS */
#line 677 "pikchr.y"
{p->cur->sw = -0.00001;}
#line 2736 "pikchr.c"
        break;
      case 59: /* boolproperty ::= THICK */
#line 678 "pikchr.y"
{p->cur->sw *= 1.5;}
#line 2741 "pikchr.c"
        break;
      case 60: /* boolproperty ::= THIN */
#line 679 "pikchr.y"
{p->cur->sw *= 0.67;}
#line 2746 "pikchr.c"
        break;
      case 61: /* boolproperty ::= SOLID */
#line 680 "pikchr.y"
{p->cur->sw = pik_value(p,"thickness",9,0);
                               p->cur->dotted = p->cur->dashed = 0.0;}
#line 2752 "pikchr.c"
        break;
      case 62: /* textposition ::= */
#line 683 "pikchr.y"
{yymsp[1].minor.yy188 = 0;}
#line 2757 "pikchr.c"
        break;
      case 63: /* textposition ::= textposition CENTER|LJUST|RJUST|ABOVE|BELOW|ITALIC|BOLD|MONO|ALIGNED|BIG|SMALL */
#line 686 "pikchr.y"
{yylhsminor.yy188 = (short int)pik_text_position(yymsp[-1].minor.yy188,&yymsp[0].minor.yy0);}
#line 2762 "pikchr.c"
  yymsp[-1].minor.yy188 = yylhsminor.yy188;
        break;
      case 64: /* position ::= expr COMMA expr */
#line 689 "pikchr.y"
{yylhsminor.yy63.x=yymsp[-2].minor.yy21; yylhsminor.yy63.y=yymsp[0].minor.yy21;}
#line 2768 "pikchr.c"
  yymsp[-2].minor.yy63 = yylhsminor.yy63;
        break;
      case 65: /* position ::= place PLUS expr COMMA expr */
#line 691 "pikchr.y"
{yylhsminor.yy63.x=yymsp[-4].minor.yy63.x+yymsp[-2].minor.yy21; yylhsminor.yy63.y=yymsp[-4].minor.yy63.y+yymsp[0].minor.yy21;}
#line 2774 "pikchr.c"
  yymsp[-4].minor.yy63 = yylhsminor.yy63;
        break;
      case 66: /* position ::= place MINUS expr COMMA expr */
#line 692 "pikchr.y"
{yylhsminor.yy63.x=yymsp[-4].minor.yy63.x-yymsp[-2].minor.yy21; yylhsminor.yy63.y=yymsp[-4].minor.yy63.y-yymsp[0].minor.yy21;}
#line 2780 "pikchr.c"
  yymsp[-4].minor.yy63 = yylhsminor.yy63;
        break;
      case 67: /* position ::= place PLUS LP expr COMMA expr RP */
#line 694 "pikchr.y"
{yylhsminor.yy63.x=yymsp[-6].minor.yy63.x+yymsp[-3].minor.yy21; yylhsminor.yy63.y=yymsp[-6].minor.yy63.y+yymsp[-1].minor.yy21;}
#line 2786 "pikchr.c"
  yymsp[-6].minor.yy63 = yylhsminor.yy63;
        break;
      case 68: /* position ::= place MINUS LP expr COMMA expr RP */
#line 696 "pikchr.y"
{yylhsminor.yy63.x=yymsp[-6].minor.yy63.x-yymsp[-3].minor.yy21; yylhsminor.yy63.y=yymsp[-6].minor.yy63.y-yymsp[-1].minor.yy21;}
#line 2792 "pikchr.c"
  yymsp[-6].minor.yy63 = yylhsminor.yy63;
        break;
      case 69: /* position ::= LP position COMMA position RP */
#line 697 "pikchr.y"
{yymsp[-4].minor.yy63.x=yymsp[-3].minor.yy63.x; yymsp[-4].minor.yy63.y=yymsp[-1].minor.yy63.y;}
#line 2798 "pikchr.c"
        break;
      case 70: /* position ::= LP position RP */
#line 698 "pikchr.y"
{yymsp[-2].minor.yy63=yymsp[-1].minor.yy63;}
#line 2803 "pikchr.c"
        break;
      case 71: /* position ::= expr between position AND position */
#line 700 "pikchr.y"
{yylhsminor.yy63 = pik_position_between(yymsp[-4].minor.yy21,yymsp[-2].minor.yy63,yymsp[0].minor.yy63);}
#line 2808 "pikchr.c"
  yymsp[-4].minor.yy63 = yylhsminor.yy63;
        break;
      case 72: /* position ::= expr LT position COMMA position GT */
#line 702 "pikchr.y"
{yylhsminor.yy63 = pik_position_between(yymsp[-5].minor.yy21,yymsp[-3].minor.yy63,yymsp[-1].minor.yy63);}
#line 2814 "pikchr.c"
  yymsp[-5].minor.yy63 = yylhsminor.yy63;
        break;
      case 73: /* position ::= expr ABOVE position */
#line 703 "pikchr.y"
{yylhsminor.yy63=yymsp[0].minor.yy63; yylhsminor.yy63.y += yymsp[-2].minor.yy21;}
#line 2820 "pikchr.c"
  yymsp[-2].minor.yy63 = yylhsminor.yy63;
        break;
      case 74: /* position ::= expr BELOW position */
#line 704 "pikchr.y"
{yylhsminor.yy63=yymsp[0].minor.yy63; yylhsminor.yy63.y -= yymsp[-2].minor.yy21;}
#line 2826 "pikchr.c"
  yymsp[-2].minor.yy63 = yylhsminor.yy63;
        break;
      case 75: /* position ::= expr LEFT OF position */
#line 705 "pikchr.y"
{yylhsminor.yy63=yymsp[0].minor.yy63; yylhsminor.yy63.x -= yymsp[-3].minor.yy21;}
#line 2832 "pikchr.c"
  yymsp[-3].minor.yy63 = yylhsminor.yy63;
        break;
      case 76: /* position ::= expr RIGHT OF position */
#line 706 "pikchr.y"
{yylhsminor.yy63=yymsp[0].minor.yy63; yylhsminor.yy63.x += yymsp[-3].minor.yy21;}
#line 2838 "pikchr.c"
  yymsp[-3].minor.yy63 = yylhsminor.yy63;
        break;
      case 77: /* position ::= expr ON HEADING EDGEPT OF position */
#line 708 "pikchr.y"
{yylhsminor.yy63 = pik_position_at_hdg(yymsp[-5].minor.yy21,&yymsp[-2].minor.yy0,yymsp[0].minor.yy63);}
#line 2844 "pikchr.c"
  yymsp[-5].minor.yy63 = yylhsminor.yy63;
        break;
      case 78: /* position ::= expr HEADING EDGEPT OF position */
#line 710 "pikchr.y"
{yylhsminor.yy63 = pik_position_at_hdg(yymsp[-4].minor.yy21,&yymsp[-2].minor.yy0,yymsp[0].minor.yy63);}
#line 2850 "pikchr.c"
  yymsp[-4].minor.yy63 = yylhsminor.yy63;
        break;
      case 79: /* position ::= expr EDGEPT OF position */
#line 712 "pikchr.y"
{yylhsminor.yy63 = pik_position_at_hdg(yymsp[-3].minor.yy21,&yymsp[-2].minor.yy0,yymsp[0].minor.yy63);}
#line 2856 "pikchr.c"
  yymsp[-3].minor.yy63 = yylhsminor.yy63;
        break;
      case 80: /* position ::= expr ON HEADING expr FROM position */
#line 714 "pikchr.y"
{yylhsminor.yy63 = pik_position_at_angle(yymsp[-5].minor.yy21,yymsp[-2].minor.yy21,yymsp[0].minor.yy63);}
#line 2862 "pikchr.c"
  yymsp[-5].minor.yy63 = yylhsminor.yy63;
        break;
      case 81: /* position ::= expr HEADING expr FROM position */
#line 716 "pikchr.y"
{yylhsminor.yy63 = pik_position_at_angle(yymsp[-4].minor.yy21,yymsp[-2].minor.yy21,yymsp[0].minor.yy63);}
#line 2868 "pikchr.c"
  yymsp[-4].minor.yy63 = yylhsminor.yy63;
        break;
      case 82: /* place ::= edge OF object */
#line 728 "pikchr.y"
{yylhsminor.yy63 = pik_place_of_elem(p,yymsp[0].minor.yy162,&yymsp[-2].minor.yy0);}
#line 2874 "pikchr.c"
  yymsp[-2].minor.yy63 = yylhsminor.yy63;
        break;
      case 83: /* place2 ::= object */
#line 729 "pikchr.y"
{yylhsminor.yy63 = pik_place_of_elem(p,yymsp[0].minor.yy162,0);}
#line 2880 "pikchr.c"
  yymsp[0].minor.yy63 = yylhsminor.yy63;
        break;
      case 84: /* place2 ::= object DOT_E edge */
#line 730 "pikchr.y"
{yylhsminor.yy63 = pik_place_of_elem(p,yymsp[-2].minor.yy162,&yymsp[0].minor.yy0);}
#line 2886 "pikchr.c"
  yymsp[-2].minor.yy63 = yylhsminor.yy63;
        break;
      case 85: /* place2 ::= NTH VERTEX OF object */
#line 731 "pikchr.y"
{yylhsminor.yy63 = pik_nth_vertex(p,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,yymsp[0].minor.yy162);}
#line 2892 "pikchr.c"
  yymsp[-3].minor.yy63 = yylhsminor.yy63;
        break;
      case 86: /* object ::= nth */
#line 743 "pikchr.y"
{yylhsminor.yy162 = pik_find_nth(p,0,&yymsp[0].minor.yy0);}
#line 2898 "pikchr.c"
  yymsp[0].minor.yy162 = yylhsminor.yy162;
        break;
      case 87: /* object ::= nth OF|IN object */
#line 744 "pikchr.y"
{yylhsminor.yy162 = pik_find_nth(p,yymsp[0].minor.yy162,&yymsp[-2].minor.yy0);}
#line 2904 "pikchr.c"
  yymsp[-2].minor.yy162 = yylhsminor.yy162;
        break;
      case 88: /* objectname ::= THIS */
#line 746 "pikchr.y"
{yymsp[0].minor.yy162 = p->cur;}
#line 2910 "pikchr.c"
        break;
      case 89: /* objectname ::= PLACENAME */
#line 747 "pikchr.y"
{yylhsminor.yy162 = pik_find_byname(p,0,&yymsp[0].minor.yy0);}
#line 2915 "pikchr.c"
  yymsp[0].minor.yy162 = yylhsminor.yy162;
        break;
      case 90: /* objectname ::= objectname DOT_U PLACENAME */
#line 749 "pikchr.y"
{yylhsminor.yy162 = pik_find_byname(p,yymsp[-2].minor.yy162,&yymsp[0].minor.yy0);}
#line 2921 "pikchr.c"
  yymsp[-2].minor.yy162 = yylhsminor.yy162;
        break;
      case 91: /* nth ::= NTH CLASSNAME */
#line 751 "pikchr.y"
{yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-1].minor.yy0); }
#line 2927 "pikchr.c"
  yymsp[-1].minor.yy0 = yylhsminor.yy0;
        break;
      case 92: /* nth ::= NTH LAST CLASSNAME */
#line 752 "pikchr.y"
{yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-2].minor.yy0); }
#line 2933 "pikchr.c"
  yymsp[-2].minor.yy0 = yylhsminor.yy0;
        break;
      case 93: /* nth ::= LAST CLASSNAME */
#line 753 "pikchr.y"
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.eCode = -1;}
#line 2939 "pikchr.c"
        break;
      case 94: /* nth ::= LAST */
#line 754 "pikchr.y"
{yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -1;}
#line 2944 "pikchr.c"
  yymsp[0].minor.yy0 = yylhsminor.yy0;
        break;
      case 95: /* nth ::= NTH LB RB */
#line 755 "pikchr.y"
{yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-2].minor.yy0);}
#line 2950 "pikchr.c"
  yymsp[-2].minor.yy0 = yylhsminor.yy0;
        break;
      case 96: /* nth ::= NTH LAST LB RB */
#line 756 "pikchr.y"
{yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-3].minor.yy0);}
#line 2956 "pikchr.c"
  yymsp[-3].minor.yy0 = yylhsminor.yy0;
        break;
      case 97: /* nth ::= LAST LB RB */
#line 757 "pikchr.y"
{yymsp[-2].minor.yy0=yymsp[-1].minor.yy0; yymsp[-2].minor.yy0.eCode = -1; }
#line 2962 "pikchr.c"
        break;
      case 98: /* expr ::= expr PLUS expr */
#line 759 "pikchr.y"
{yylhsminor.yy21=yymsp[-2].minor.yy21+yymsp[0].minor.yy21;}
#line 2967 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      case 99: /* expr ::= expr MINUS expr */
#line 760 "pikchr.y"
{yylhsminor.yy21=yymsp[-2].minor.yy21-yymsp[0].minor.yy21;}
#line 2973 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      case 100: /* expr ::= expr STAR expr */
#line 761 "pikchr.y"
{yylhsminor.yy21=yymsp[-2].minor.yy21*yymsp[0].minor.yy21;}
#line 2979 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      case 101: /* expr ::= expr SLASH expr */
#line 762 "pikchr.y"
{
  if( yymsp[0].minor.yy21==0.0 ){ pik_error(p, &yymsp[-1].minor.yy0, "division by zero"); yylhsminor.yy21 = 0.0; }
  else{ yylhsminor.yy21 = yymsp[-2].minor.yy21/yymsp[0].minor.yy21; }
}
#line 2988 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      case 102: /* expr ::= MINUS expr */
#line 766 "pikchr.y"
{yymsp[-1].minor.yy21=-yymsp[0].minor.yy21;}
#line 2994 "pikchr.c"
        break;
      case 103: /* expr ::= PLUS expr */
#line 767 "pikchr.y"
{yymsp[-1].minor.yy21=yymsp[0].minor.yy21;}
#line 2999 "pikchr.c"
        break;
      case 104: /* expr ::= LP expr RP */
#line 768 "pikchr.y"
{yymsp[-2].minor.yy21=yymsp[-1].minor.yy21;}
#line 3004 "pikchr.c"
        break;
      case 105: /* expr ::= LP FILL|COLOR|THICKNESS RP */
#line 769 "pikchr.y"
{yymsp[-2].minor.yy21=pik_get_var(p,&yymsp[-1].minor.yy0);}
#line 3009 "pikchr.c"
        break;
      case 106: /* expr ::= NUMBER */
#line 770 "pikchr.y"
{yylhsminor.yy21=pik_atof(&yymsp[0].minor.yy0);}
#line 3014 "pikchr.c"
  yymsp[0].minor.yy21 = yylhsminor.yy21;
        break;
      case 107: /* expr ::= ID */
#line 771 "pikchr.y"
{yylhsminor.yy21=pik_get_var(p,&yymsp[0].minor.yy0);}
#line 3020 "pikchr.c"
  yymsp[0].minor.yy21 = yylhsminor.yy21;
        break;
      case 108: /* expr ::= FUNC1 LP expr RP */
#line 772 "pikchr.y"
{yylhsminor.yy21 = pik_func(p,&yymsp[-3].minor.yy0,yymsp[-1].minor.yy21,0.0);}
#line 3026 "pikchr.c"
  yymsp[-3].minor.yy21 = yylhsminor.yy21;
        break;
      case 109: /* expr ::= FUNC2 LP expr COMMA expr RP */
#line 773 "pikchr.y"
{yylhsminor.yy21 = pik_func(p,&yymsp[-5].minor.yy0,yymsp[-3].minor.yy21,yymsp[-1].minor.yy21);}
#line 3032 "pikchr.c"
  yymsp[-5].minor.yy21 = yylhsminor.yy21;
        break;
      case 110: /* expr ::= DIST LP position COMMA position RP */
#line 774 "pikchr.y"
{yymsp[-5].minor.yy21 = pik_dist(&yymsp[-3].minor.yy63,&yymsp[-1].minor.yy63);}
#line 3038 "pikchr.c"
        break;
      case 111: /* expr ::= place2 DOT_XY X */
#line 775 "pikchr.y"
{yylhsminor.yy21 = yymsp[-2].minor.yy63.x;}
#line 3043 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      case 112: /* expr ::= place2 DOT_XY Y */
#line 776 "pikchr.y"
{yylhsminor.yy21 = yymsp[-2].minor.yy63.y;}
#line 3049 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      case 113: /* expr ::= object DOT_L numproperty */
      case 114: /* expr ::= object DOT_L dashproperty */ yytestcase(yyruleno==114);
      case 115: /* expr ::= object DOT_L colorproperty */ yytestcase(yyruleno==115);
#line 777 "pikchr.y"
{yylhsminor.yy21=pik_property_of(yymsp[-2].minor.yy162,&yymsp[0].minor.yy0);}
#line 3057 "pikchr.c"
  yymsp[-2].minor.yy21 = yylhsminor.yy21;
        break;
      default:
      /* (116) lvalue ::= ID */ yytestcase(yyruleno==116);
      /* (117) lvalue ::= FILL */ yytestcase(yyruleno==117);
      /* (118) lvalue ::= COLOR */ yytestcase(yyruleno==118);
      /* (119) lvalue ::= THICKNESS */ yytestcase(yyruleno==119);
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
  int yymajor,                   /* The major type of the error token */
  pik_parserTOKENTYPE yyminor         /* The minor type of the error token */
){
  pik_parserARG_FETCH
  pik_parserCTX_FETCH
#define TOKEN yyminor
/************ Begin %syntax_error code ****************************************/
#line 536 "pikchr.y"

  if( TOKEN.z && TOKEN.z[0] ){
    pik_error(p, &TOKEN, "syntax error");
  }else{
    pik_error(p, 0, "syntax error");
  }
  UNUSED_PARAMETER(yymajor);
#line 3136 "pikchr.c"
/************ End %syntax_error code ******************************************/
  pik_parserARG_STORE /* Suppress warning about unused %extra_argument variable */
  pik_parserCTX_STORE
}

/*
** The following is executed when the parser accepts







|







|







3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
  int yymajor,                   /* The major type of the error token */
  pik_parserTOKENTYPE yyminor         /* The minor type of the error token */
){
  pik_parserARG_FETCH
  pik_parserCTX_FETCH
#define TOKEN yyminor
/************ Begin %syntax_error code ****************************************/
#line 537 "pikchr.y"

  if( TOKEN.z && TOKEN.z[0] ){
    pik_error(p, &TOKEN, "syntax error");
  }else{
    pik_error(p, 0, "syntax error");
  }
  UNUSED_PARAMETER(yymajor);
#line 3168 "pikchr.c"
/************ End %syntax_error code ******************************************/
  pik_parserARG_STORE /* Suppress warning about unused %extra_argument variable */
  pik_parserCTX_STORE
}

/*
** The following is executed when the parser accepts
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
#ifdef YYTRACKMAXSTACKDEPTH
        if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
          yypParser->yyhwm++;
          assert( yypParser->yyhwm ==
                  (int)(yypParser->yytos - yypParser->yystack));
        }
#endif
#if YYSTACKDEPTH>0 
        if( yypParser->yytos>=yypParser->yystackEnd ){
          yyStackOverflow(yypParser);
          break;
        }
#else
        if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
          if( yyGrowStack(yypParser) ){
            yyStackOverflow(yypParser);
            break;
          }
        }
#endif
      }
      yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor pik_parserCTX_PARAM);
    }else if( yyact <= YY_MAX_SHIFTREDUCE ){
      yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor);
#ifndef YYNOERRORRECOVERY
      yypParser->yyerrcnt--;
#endif







<

<
<
<
<
<





<







3257
3258
3259
3260
3261
3262
3263

3264





3265
3266
3267
3268
3269

3270
3271
3272
3273
3274
3275
3276
#ifdef YYTRACKMAXSTACKDEPTH
        if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
          yypParser->yyhwm++;
          assert( yypParser->yyhwm ==
                  (int)(yypParser->yytos - yypParser->yystack));
        }
#endif

        if( yypParser->yytos>=yypParser->yystackEnd ){





          if( yyGrowStack(yypParser) ){
            yyStackOverflow(yypParser);
            break;
          }
        }

      }
      yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor pik_parserCTX_PARAM);
    }else if( yyact <= YY_MAX_SHIFTREDUCE ){
      yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor);
#ifndef YYNOERRORRECOVERY
      yypParser->yyerrcnt--;
#endif
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
  assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) );
  return yyFallback[iToken];
#else
  (void)iToken;
  return 0;
#endif
}
#line 781 "pikchr.y"



/* Chart of the 148 official CSS color names with their
** corresponding RGB values thru Color Module Level 4:
** https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
**







|







3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
  assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) );
  return yyFallback[iToken];
#else
  (void)iToken;
  return 0;
#endif
}
#line 782 "pikchr.y"



/* Chart of the 148 official CSS color names with their
** corresponding RGB values thru Color Module Level 4:
** https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
**
3575
3576
3577
3578
3579
3580
3581


3582
3583
3584
3585
3586
3587
3588
  { "charwid",     0.08  },
  { "circlerad",   0.25  },
  { "color",       0.0   },
  { "cylht",       0.5   },
  { "cylrad",      0.075 },
  { "cylwid",      0.75  },
  { "dashwid",     0.05  },


  { "dotrad",      0.015 },
  { "ellipseht",   0.5   },
  { "ellipsewid",  0.75  },
  { "fileht",      0.75  },
  { "filerad",     0.15  },
  { "filewid",     0.5   },
  { "fill",        -1.0  },







>
>







3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
  { "charwid",     0.08  },
  { "circlerad",   0.25  },
  { "color",       0.0   },
  { "cylht",       0.5   },
  { "cylrad",      0.075 },
  { "cylwid",      0.75  },
  { "dashwid",     0.05  },
  { "diamondht",   0.75  },
  { "diamondwid",  1.0   },
  { "dotrad",      0.015 },
  { "ellipseht",   0.5   },
  { "ellipsewid",  0.75  },
  { "fileht",      0.75  },
  { "filerad",     0.15  },
  { "filewid",     0.5   },
  { "fill",        -1.0  },
3955
3956
3957
3958
3959
3960
3961























































3962
3963
3964
3965
3966
3967
3968
    pik_append_dis(p," r=\"", r, "\"");
    pik_append_style(p,pObj,2);
    pik_append(p,"\" />\n", -1);
  }
  pik_append_txt(p, pObj, 0);
}


























































/* Methods for the "ellipse" class */
static void ellipseInit(Pik *p, PObj *pObj){
  pObj->w = pik_value(p, "ellipsewid",10,0);
  pObj->h = pik_value(p, "ellipseht",9,0);
}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
    pik_append_dis(p," r=\"", r, "\"");
    pik_append_style(p,pObj,2);
    pik_append(p,"\" />\n", -1);
  }
  pik_append_txt(p, pObj, 0);
}

/* Methods for the "diamond" class */
static void diamondInit(Pik *p, PObj *pObj){
  pObj->w = pik_value(p, "diamondwid",10,0);
  pObj->h = pik_value(p, "diamondht",9,0);
  pObj->bAltAutoFit = 1;
}
/* Return offset from the center of the box to the compass point 
** given by parameter cp */
static PPoint diamondOffset(Pik *p, PObj *pObj, int cp){
  PPoint pt = cZeroPoint;
  PNum w2 = 0.5*pObj->w;
  PNum w4 = 0.25*pObj->w;
  PNum h2 = 0.5*pObj->h;
  PNum h4 = 0.25*pObj->h;
  switch( cp ){
    case CP_C:                                   break;
    case CP_N:   pt.x = 0.0;      pt.y = h2;     break;
    case CP_NE:  pt.x = w4;       pt.y = h4;     break;
    case CP_E:   pt.x = w2;       pt.y = 0.0;    break;
    case CP_SE:  pt.x = w4;       pt.y = -h4;    break;
    case CP_S:   pt.x = 0.0;      pt.y = -h2;    break;
    case CP_SW:  pt.x = -w4;      pt.y = -h4;    break;
    case CP_W:   pt.x = -w2;      pt.y = 0.0;    break;
    case CP_NW:  pt.x = -w4;      pt.y = h4;     break;
    default:     assert(0);
  }
  UNUSED_PARAMETER(p);
  return pt;
}
static void diamondFit(Pik *p, PObj *pObj, PNum w, PNum h){
  if( pObj->w<=0 ) pObj->w = w*1.5;
  if( pObj->h<=0 ) pObj->h = h*1.5;
  if( pObj->w>0 && pObj->h>0 ){
    PNum x = pObj->w*h/pObj->h + w;
    PNum y = pObj->h*x/pObj->w;
    pObj->w = x;
    pObj->h = y;
  }
  UNUSED_PARAMETER(p);
}
static void diamondRender(Pik *p, PObj *pObj){
  PNum w2 = 0.5*pObj->w;
  PNum h2 = 0.5*pObj->h;
  PPoint pt = pObj->ptAt;
  if( pObj->sw>=0.0 ){
    pik_append_xy(p,"<path d=\"M", pt.x-w2,pt.y);
    pik_append_xy(p,"L", pt.x,pt.y-h2);
    pik_append_xy(p,"L", pt.x+w2,pt.y);
    pik_append_xy(p,"L", pt.x,pt.y+h2);
    pik_append(p,"Z\" ",-1);
    pik_append_style(p,pObj,3);
    pik_append(p,"\" />\n", -1);
  }
  pik_append_txt(p, pObj, 0);
}


/* Methods for the "ellipse" class */
static void ellipseInit(Pik *p, PObj *pObj){
  pObj->w = pik_value(p, "ellipsewid",10,0);
  pObj->h = pik_value(p, "ellipseht",9,0);
}
4339
4340
4341
4342
4343
4344
4345











4346
4347
4348
4349
4350
4351
4352
      /* xNumProp */      0,
      /* xCheck */        0,
      /* xChop */         boxChop,
      /* xOffset */       cylinderOffset,
      /* xFit */          cylinderFit,
      /* xRender */       cylinderRender
   },











   {  /* name */          "dot",
      /* isline */        0,
      /* eJust */         0,
      /* xInit */         dotInit,
      /* xNumProp */      dotNumProp,
      /* xCheck */        dotCheck,
      /* xChop */         circleChop,







>
>
>
>
>
>
>
>
>
>
>







4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
      /* xNumProp */      0,
      /* xCheck */        0,
      /* xChop */         boxChop,
      /* xOffset */       cylinderOffset,
      /* xFit */          cylinderFit,
      /* xRender */       cylinderRender
   },
   {  /* name */          "diamond",
      /* isline */        0,
      /* eJust */         0,
      /* xInit */         diamondInit,
      /* xNumProp */      0,
      /* xCheck */        0,
      /* xChop */         boxChop,
      /* xOffset */       diamondOffset,
      /* xFit */          diamondFit,
      /* xRender */       diamondRender 
   },
   {  /* name */          "dot",
      /* isline */        0,
      /* eJust */         0,
      /* xInit */         dotInit,
      /* xNumProp */      dotNumProp,
      /* xCheck */        dotCheck,
      /* xChop */         circleChop,
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
  int iErrCol;          /* Column of the error token on its line */
  int iStart;           /* Start position of the error context */
  int iEnd;             /* End position of the error context */
  int iLineno;          /* Line number of the error */
  int iFirstLineno;     /* Line number of start of error context */
  int i;                /* Loop counter */
  int iBump = 0;        /* Bump the location of the error cursor */
  char zLineno[20];     /* Buffer in which to generate line numbers */

  iErrPt = (int)(pErr->z - p->sIn.z);
  if( iErrPt>=(int)p->sIn.n ){
    iErrPt = p->sIn.n-1;
    iBump = 1;
  }else{
    while( iErrPt>0 && (p->sIn.z[iErrPt]=='\n' || p->sIn.z[iErrPt]=='\r') ){







|







5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
  int iErrCol;          /* Column of the error token on its line */
  int iStart;           /* Start position of the error context */
  int iEnd;             /* End position of the error context */
  int iLineno;          /* Line number of the error */
  int iFirstLineno;     /* Line number of start of error context */
  int i;                /* Loop counter */
  int iBump = 0;        /* Bump the location of the error cursor */
  char zLineno[24];     /* Buffer in which to generate line numbers */

  iErrPt = (int)(pErr->z - p->sIn.z);
  if( iErrPt>=(int)p->sIn.n ){
    iErrPt = p->sIn.n-1;
    iBump = 1;
  }else{
    while( iErrPt>0 && (p->sIn.z[iErrPt]=='\n' || p->sIn.z[iErrPt]=='\r') ){
6267
6268
6269
6270
6271
6272
6273

6274



6275
6276
6277
6278
6279
6280
6281
6282
    pik_error(0, pFit, "no text to fit to");
    return;
  }
  if( pObj->type->xFit==0 ) return;
  pik_bbox_init(&bbox);
  pik_compute_layout_settings(p);
  pik_append_txt(p, pObj, &bbox);

  w = (eWhich & 1)!=0 ? (bbox.ne.x - bbox.sw.x) + p->charWidth : 0;



  if( eWhich & 2 ){
    PNum h1, h2;
    h1 = (bbox.ne.y - pObj->ptAt.y);
    h2 = (pObj->ptAt.y - bbox.sw.y);
    h = 2.0*( h1<h2 ? h2 : h1 ) + 0.5*p->charHeight;
  }else{
    h = 0;
  }







>
|
>
>
>
|







6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
    pik_error(0, pFit, "no text to fit to");
    return;
  }
  if( pObj->type->xFit==0 ) return;
  pik_bbox_init(&bbox);
  pik_compute_layout_settings(p);
  pik_append_txt(p, pObj, &bbox);
  if( (eWhich & 1)!=0 || pObj->bAltAutoFit ){
    w = (bbox.ne.x - bbox.sw.x) + p->charWidth;
  }else{
    w = 0;
  }
  if( (eWhich & 2)!=0 || pObj->bAltAutoFit ){
    PNum h1, h2;
    h1 = (bbox.ne.y - pObj->ptAt.y);
    h2 = (pObj->ptAt.y - bbox.sw.y);
    h = 2.0*( h1<h2 ? h2 : h1 ) + 0.5*p->charHeight;
  }else{
    h = 0;
  }
8141
8142
8143
8144
8145
8146
8147
8148
  return TCL_OK;
}


#endif /* PIKCHR_TCL */


#line 8173 "pikchr.c"







|
8238
8239
8240
8241
8242
8243
8244
8245
  return TCL_OK;
}


#endif /* PIKCHR_TCL */


#line 8270 "pikchr.c"

Changes to extsrc/pikchr.js.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

var initPikchrModule = (() => {
  var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
  
  return (
function(config) {
  var initPikchrModule = config || {};

var Module = typeof initPikchrModule != "undefined" ? initPikchrModule : {};

var readyPromiseResolve, readyPromiseReject;

Module["ready"] = new Promise(function(resolve, reject) {
 readyPromiseResolve = resolve;
 readyPromiseReject = reject;
});

var moduleOverrides = Object.assign({}, Module);

var arguments_ = [];





|
<

|



|







1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19

var initPikchrModule = (() => {
  var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
  
  return (
function(moduleArg = {}) {


var Module = moduleArg;

var readyPromiseResolve, readyPromiseReject;

Module["ready"] = new Promise((resolve, reject) => {
 readyPromiseResolve = resolve;
 readyPromiseReject = reject;
});

var moduleOverrides = Object.assign({}, Module);

var arguments_ = [];
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
function locateFile(path) {
 if (Module["locateFile"]) {
  return Module["locateFile"](path, scriptDirectory);
 }
 return scriptDirectory + path;
}

var read_, readAsync, readBinary, setWindowTitle;

if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
 if (ENVIRONMENT_IS_WORKER) {
  scriptDirectory = self.location.href;
 } else if (typeof document != "undefined" && document.currentScript) {
  scriptDirectory = document.currentScript.src;
 }
 if (_scriptDir) {
  scriptDirectory = _scriptDir;
 }
 if (scriptDirectory.indexOf("blob:") !== 0) {
  scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1);
 } else {
  scriptDirectory = "";
 }
 {
  read_ = url => {
   var xhr = new XMLHttpRequest();
   xhr.open("GET", url, false);
   xhr.send(null);
   return xhr.responseText;
  };
  if (ENVIRONMENT_IS_WORKER) {
   readBinary = url => {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, false);
    xhr.responseType = "arraybuffer";
    xhr.send(null);
    return new Uint8Array(xhr.response);
   };
  }
  readAsync = (url, onload, onerror) => {
   var xhr = new XMLHttpRequest();
   xhr.open("GET", url, true);
   xhr.responseType = "arraybuffer";
   xhr.onload = () => {
    if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
     onload(xhr.response);
     return;
    }
    onerror();
   };
   xhr.onerror = onerror;
   xhr.send(null);
  };
 }
 setWindowTitle = title => document.title = title;
} else {}

var out = Module["print"] || console.log.bind(console);

var err = Module["printErr"] || console.warn.bind(console);

Object.assign(Module, moduleOverrides);

moduleOverrides = null;

if (Module["arguments"]) arguments_ = Module["arguments"];

if (Module["thisProgram"]) thisProgram = Module["thisProgram"];

if (Module["quit"]) quit_ = Module["quit"];

var wasmBinary;

if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];

var noExitRuntime = Module["noExitRuntime"] || true;

if (typeof WebAssembly != "object") {
 abort("no native wasm support detected");
}

var wasmMemory;

var ABORT = false;

var EXITSTATUS;

var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined;

function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) {
 var endIdx = idx + maxBytesToRead;
 var endPtr = idx;
 while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
 if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
  return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
 }
 var str = "";
 while (idx < endPtr) {
  var u0 = heapOrArray[idx++];
  if (!(u0 & 128)) {
   str += String.fromCharCode(u0);
   continue;
  }
  var u1 = heapOrArray[idx++] & 63;
  if ((u0 & 224) == 192) {
   str += String.fromCharCode((u0 & 31) << 6 | u1);
   continue;
  }
  var u2 = heapOrArray[idx++] & 63;
  if ((u0 & 240) == 224) {
   u0 = (u0 & 15) << 12 | u1 << 6 | u2;
  } else {
   u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63;
  }
  if (u0 < 65536) {
   str += String.fromCharCode(u0);
  } else {
   var ch = u0 - 65536;
   str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
  }
 }
 return str;
}

function UTF8ToString(ptr, maxBytesToRead) {
 return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
}

function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
 if (!(maxBytesToWrite > 0)) return 0;
 var startIdx = outIdx;
 var endIdx = outIdx + maxBytesToWrite - 1;
 for (var i = 0; i < str.length; ++i) {
  var u = str.charCodeAt(i);
  if (u >= 55296 && u <= 57343) {
   var u1 = str.charCodeAt(++i);
   u = 65536 + ((u & 1023) << 10) | u1 & 1023;
  }
  if (u <= 127) {
   if (outIdx >= endIdx) break;
   heap[outIdx++] = u;
  } else if (u <= 2047) {
   if (outIdx + 1 >= endIdx) break;
   heap[outIdx++] = 192 | u >> 6;
   heap[outIdx++] = 128 | u & 63;
  } else if (u <= 65535) {
   if (outIdx + 2 >= endIdx) break;
   heap[outIdx++] = 224 | u >> 12;
   heap[outIdx++] = 128 | u >> 6 & 63;
   heap[outIdx++] = 128 | u & 63;
  } else {
   if (outIdx + 3 >= endIdx) break;
   heap[outIdx++] = 240 | u >> 18;
   heap[outIdx++] = 128 | u >> 12 & 63;
   heap[outIdx++] = 128 | u >> 6 & 63;
   heap[outIdx++] = 128 | u & 63;
  }
 }
 heap[outIdx] = 0;
 return outIdx - startIdx;
}

function stringToUTF8(str, outPtr, maxBytesToWrite) {
 return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
}

var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;

function updateMemoryViews() {
 var b = wasmMemory.buffer;
 Module["HEAP8"] = HEAP8 = new Int8Array(b);
 Module["HEAP16"] = HEAP16 = new Int16Array(b);
 Module["HEAP32"] = HEAP32 = new Int32Array(b);
 Module["HEAPU8"] = HEAPU8 = new Uint8Array(b);
 Module["HEAPU16"] = HEAPU16 = new Uint16Array(b);

 Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
 Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
 Module["HEAPF64"] = HEAPF64 = new Float64Array(b);
}

var INITIAL_MEMORY = Module["INITIAL_MEMORY"] || 16777216;

var wasmTable;

var __ATPRERUN__ = [];

var __ATINIT__ = [];

var __ATPOSTRUN__ = [];

var runtimeInitialized = false;

function keepRuntimeAlive() {
 return noExitRuntime;
}

function preRun() {
 if (Module["preRun"]) {
  if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
  while (Module["preRun"].length) {
   addOnPreRun(Module["preRun"].shift());
  }
 }







|










|
|

|



|






|



|



|



|









<




|















<
<










<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





<


>





<
<
<
<








<
<
<
<







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106


107
108
109
110
111
112
113
114
115
116

117














































































118
119
120
121
122

123
124
125
126
127
128
129
130




131
132
133
134
135
136
137
138




139
140
141
142
143
144
145
function locateFile(path) {
 if (Module["locateFile"]) {
  return Module["locateFile"](path, scriptDirectory);
 }
 return scriptDirectory + path;
}

var read_, readAsync, readBinary;

if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
 if (ENVIRONMENT_IS_WORKER) {
  scriptDirectory = self.location.href;
 } else if (typeof document != "undefined" && document.currentScript) {
  scriptDirectory = document.currentScript.src;
 }
 if (_scriptDir) {
  scriptDirectory = _scriptDir;
 }
 if (scriptDirectory.startsWith("blob:")) {
  scriptDirectory = "";
 } else {
  scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1);
 }
 {
  read_ = url => {
   var xhr = new XMLHttpRequest;
   xhr.open("GET", url, false);
   xhr.send(null);
   return xhr.responseText;
  };
  if (ENVIRONMENT_IS_WORKER) {
   readBinary = url => {
    var xhr = new XMLHttpRequest;
    xhr.open("GET", url, false);
    xhr.responseType = "arraybuffer";
    xhr.send(null);
    return new Uint8Array(/** @type{!ArrayBuffer} */ (xhr.response));
   };
  }
  readAsync = (url, onload, onerror) => {
   var xhr = new XMLHttpRequest;
   xhr.open("GET", url, true);
   xhr.responseType = "arraybuffer";
   xhr.onload = () => {
    if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) {
     onload(xhr.response);
     return;
    }
    onerror();
   };
   xhr.onerror = onerror;
   xhr.send(null);
  };
 }

} else {}

var out = Module["print"] || console.log.bind(console);

var err = Module["printErr"] || console.error.bind(console);

Object.assign(Module, moduleOverrides);

moduleOverrides = null;

if (Module["arguments"]) arguments_ = Module["arguments"];

if (Module["thisProgram"]) thisProgram = Module["thisProgram"];

if (Module["quit"]) quit_ = Module["quit"];

var wasmBinary;

if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];



if (typeof WebAssembly != "object") {
 abort("no native wasm support detected");
}

var wasmMemory;

var ABORT = false;

var EXITSTATUS;


var /** @type {!Int8Array} */ HEAP8, /** @type {!Uint8Array} */ HEAPU8, /** @type {!Int16Array} */ HEAP16, /** @type {!Uint16Array} */ HEAPU16, /** @type {!Int32Array} */ HEAP32, /** @type {!Uint32Array} */ HEAPU32, /** @type {!Float32Array} */ HEAPF32, /** @type {!Float64Array} */ HEAPF64;















































































function updateMemoryViews() {
 var b = wasmMemory.buffer;
 Module["HEAP8"] = HEAP8 = new Int8Array(b);
 Module["HEAP16"] = HEAP16 = new Int16Array(b);

 Module["HEAPU8"] = HEAPU8 = new Uint8Array(b);
 Module["HEAPU16"] = HEAPU16 = new Uint16Array(b);
 Module["HEAP32"] = HEAP32 = new Int32Array(b);
 Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
 Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
 Module["HEAPF64"] = HEAPF64 = new Float64Array(b);
}





var __ATPRERUN__ = [];

var __ATINIT__ = [];

var __ATPOSTRUN__ = [];

var runtimeInitialized = false;





function preRun() {
 if (Module["preRun"]) {
  if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
  while (Module["preRun"].length) {
   addOnPreRun(Module["preRun"].shift());
  }
 }
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

314

315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350




351




352
353
354
355

356







357

358

359

360
361
362
363
364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386

387
388
389

390
391
392
393
394
395
396
397
398
399
400


401
402
403
404
405
406
407

408
409
410

411








412

413
414


415
416


417
418

419
420

421


422
423


424


425
426
427
428
429
430

431




432
433
434
435
436

437
438
439

440
441
442

443
444
445

446
447

448



449




450


451



452
453
454
455
456






457






458





459
460
461



462
463
464
465
466
467

468
469
470

471


472
473
474


475
476
477
478
479
480
481
482

483

484
485
486
487
488
489
490








491

492
493
494
495



496
497
498

499

500
501



502
503
504

505
506
507

508





509
510
511

512
513
514

515
516
517

518
519
520
521
522
523
524
525
526
527
528
529
530


531
532
533
534


535

536
537





538
539
540


541


542


543
544



545


















546
547
548
549
550
551
552
553

554




555
556
557





558
559
560
561
562
563
564
565
566
567
568
569
570
571
572

var runDependencyWatcher = null;

var dependenciesFulfilled = null;

function addRunDependency(id) {
 runDependencies++;
 if (Module["monitorRunDependencies"]) {
  Module["monitorRunDependencies"](runDependencies);
 }
}

function removeRunDependency(id) {
 runDependencies--;
 if (Module["monitorRunDependencies"]) {
  Module["monitorRunDependencies"](runDependencies);
 }
 if (runDependencies == 0) {
  if (runDependencyWatcher !== null) {
   clearInterval(runDependencyWatcher);
   runDependencyWatcher = null;
  }
  if (dependenciesFulfilled) {
   var callback = dependenciesFulfilled;
   dependenciesFulfilled = null;
   callback();
  }
 }
}

function abort(what) {
 if (Module["onAbort"]) {
  Module["onAbort"](what);
 }
 what = "Aborted(" + what + ")";
 err(what);
 ABORT = true;
 EXITSTATUS = 1;
 what += ". Build with -sASSERTIONS for more info.";
 var e = new WebAssembly.RuntimeError(what);
 readyPromiseReject(e);
 throw e;
}

var dataURIPrefix = "data:application/octet-stream;base64,";


function isDataURI(filename) {

 return filename.startsWith(dataURIPrefix);
}

var wasmBinaryFile;

wasmBinaryFile = "pikchr.wasm";

if (!isDataURI(wasmBinaryFile)) {
 wasmBinaryFile = locateFile(wasmBinaryFile);
}

function getBinary(file) {
 try {
  if (file == wasmBinaryFile && wasmBinary) {
   return new Uint8Array(wasmBinary);
  }
  if (readBinary) {
   return readBinary(file);
  }
  throw "both async and sync fetching of the wasm failed";
 } catch (err) {
  abort(err);
 }
}

function getBinaryPromise() {
 if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
  if (typeof fetch == "function") {
   return fetch(wasmBinaryFile, {
    credentials: "same-origin"
   }).then(function(response) {
    if (!response["ok"]) {
     throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
    }
    return response["arrayBuffer"]();
   }).catch(function() {




    return getBinary(wasmBinaryFile);




   });
  }
 }
 return Promise.resolve().then(function() {

  return getBinary(wasmBinaryFile);







 });

}



function createWasm() {
 var info = {
  "a": asmLibraryArg
 };
 function receiveInstance(instance, module) {
  var exports = instance.exports;
  Module["asm"] = exports;
  wasmMemory = Module["asm"]["d"];
  updateMemoryViews();
  wasmTable = Module["asm"]["g"];
  addOnInit(Module["asm"]["e"]);
  removeRunDependency("wasm-instantiate");

 }
 addRunDependency("wasm-instantiate");
 function receiveInstantiationResult(result) {
  receiveInstance(result["instance"]);
 }
 function instantiateArrayBuffer(receiver) {
  return getBinaryPromise().then(function(binary) {
   return WebAssembly.instantiate(binary, info);
  }).then(function(instance) {
   return instance;
  }).then(receiver, function(reason) {
   err("failed to asynchronously prepare wasm: " + reason);
   abort(reason);
  });
 }

 function instantiateAsync() {
  if (!wasmBinary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(wasmBinaryFile) && typeof fetch == "function") {
   return fetch(wasmBinaryFile, {

    credentials: "same-origin"
   }).then(function(response) {
    var result = WebAssembly.instantiateStreaming(response, info);
    return result.then(receiveInstantiationResult, function(reason) {
     err("wasm streaming compile failed: " + reason);
     err("falling back to ArrayBuffer instantiation");
     return instantiateArrayBuffer(receiveInstantiationResult);
    });
   });
  } else {
   return instantiateArrayBuffer(receiveInstantiationResult);


  }
 }
 if (Module["instantiateWasm"]) {
  try {
   var exports = Module["instantiateWasm"](info, receiveInstance);
   return exports;
  } catch (e) {

   err("Module.instantiateWasm callback failed with error: " + e);
   readyPromiseReject(e);
  }

 }








 instantiateAsync().catch(readyPromiseReject);

 return {};
}



var tempDouble;



var tempI64;


function ExitStatus(status) {

 this.name = "ExitStatus";


 this.message = "Program terminated with exit(" + status + ")";
 this.status = status;


}



function callRuntimeCallbacks(callbacks) {
 while (callbacks.length > 0) {
  callbacks.shift()(Module);
 }
}






function getValue(ptr, type = "i8") {
 if (type.endsWith("*")) type = "*";
 switch (type) {
 case "i1":
  return HEAP8[ptr >> 0];


 case "i8":
  return HEAP8[ptr >> 0];


 case "i16":
  return HEAP16[ptr >> 1];


 case "i32":
  return HEAP32[ptr >> 2];


 case "i64":

  return HEAP32[ptr >> 2];








 case "float":


  return HEAPF32[ptr >> 2];




 case "double":
  return HEAPF64[ptr >> 3];

 case "*":






  return HEAPU32[ptr >> 2];












 default:
  abort("invalid type for getValue: " + type);
 }



 return null;
}

function setValue(ptr, value, type = "i8") {
 if (type.endsWith("*")) type = "*";
 switch (type) {

 case "i1":
  HEAP8[ptr >> 0] = value;
  break;




 case "i8":
  HEAP8[ptr >> 0] = value;
  break;



 case "i16":
  HEAP16[ptr >> 1] = value;
  break;

 case "i32":
  HEAP32[ptr >> 2] = value;
  break;



 case "i64":
  tempI64 = [ value >>> 0, (tempDouble = value, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], 
  HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1];
  break;

 case "float":
  HEAPF32[ptr >> 2] = value;








  break;


 case "double":
  HEAPF64[ptr >> 3] = value;
  break;




 case "*":
  HEAPU32[ptr >> 2] = value;

  break;


 default:



  abort("invalid type for setValue: " + type);
 }
}


function ___assert_fail(condition, filename, line, func) {
 abort("Assertion failed: " + UTF8ToString(condition) + ", at: " + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]);

}






function abortOnCannotGrowMemory(requestedSize) {
 abort("OOM");

}

function _emscripten_resize_heap(requestedSize) {

 var oldSize = HEAPU8.length;
 requestedSize = requestedSize >>> 0;
 abortOnCannotGrowMemory(requestedSize);

}

var SYSCALLS = {
 varargs: undefined,
 get: function() {
  SYSCALLS.varargs += 4;
  var ret = HEAP32[SYSCALLS.varargs - 4 >> 2];
  return ret;
 },
 getStr: function(ptr) {
  var ret = UTF8ToString(ptr);
  return ret;
 }


};

function _proc_exit(code) {
 EXITSTATUS = code;


 if (!keepRuntimeAlive()) {

  if (Module["onExit"]) Module["onExit"](code);
  ABORT = true;





 }
 quit_(code, new ExitStatus(code));
}





function exitJS(status, implicit) {


 EXITSTATUS = status;
 _proc_exit(status);



}



















var _exit = exitJS;

function getCFunc(ident) {
 var func = Module["_" + ident];
 return func;
}


function writeArrayToMemory(array, buffer) {




 HEAP8.set(array, buffer);
}






function ccall(ident, returnType, argTypes, args, opts) {
 var toC = {
  "string": str => {
   var ret = 0;
   if (str !== null && str !== undefined && str !== 0) {
    var len = (str.length << 2) + 1;
    ret = stackAlloc(len);
    stringToUTF8(str, ret, len);
   }
   return ret;
  },
  "array": arr => {
   var ret = stackAlloc(arr.length);
   writeArrayToMemory(arr, ret);
   return ret;







<
|
<




<
|
<













|
<
|
<





|






>
|
>
|
<









|
<
|
|
|
|
|
|
|
<
<
|
|
<
|


|

|

|


|
>
>
>
>
|
>
>
>
>
|
|
|
|
>
|
>
>
>
>
>
>
>
|
>
|
>
|
>


|

|
|
<
|

<
|

>





|
|
|
|
|
<
<
|
<
|
>
|
<
|
>
|
|
<
<
<
<
<
<
<
|
<
>
>
|
|
<
<
<
<
|
>
|
<
|
>
|
>
>
>
>
>
>
>
>
|
>
|
|
>
>

<
>
>

|
>

|
>
|
>
>
|
<
>
>
|
>
>
|
<
<
<
|
|
>

>
>
>
>
|



|
>


|
>


|
>


|
>


>
|
>
>
>

>
>
>
>
|
>
>
|
>
>
>
|
|
|

|
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
|
<
|
>
>
>
|
|
|
<
|
<
>
|
<
<
>
|
>
>
|
<
<
>
>
|
<
<
<
|
<
<
|
>

>
|
|
<
<
|
<
|
>
>
>
>
>
>
>
>
|
>

<
<
<
>
>
>

<
<
>
|
>

<
>
>
>
|
|
|
>

<
<
>
|
>
>
>
>
>
|
<
<
>
|

<
>
|
<
<
>
|

|
|
|
|
<
|
|
<
<
<
|
>
>


|
|
>
>
|
>
|
|
>
>
>
>
>
|
<
|
>
>

>
>
|
>
>
|
<
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
|
<
|
|
|

>
|
>
>
>
>
|
|

>
>
>
>
>
|




<
<
|







177
178
179
180
181
182
183

184

185
186
187
188

189

190
191
192
193
194
195
196
197
198
199
200
201
202
203

204

205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228
229
230

231
232
233
234
235
236
237


238
239

240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284

285
286

287
288
289
290
291
292
293
294
295
296
297
298
299


300

301
302
303

304
305
306
307







308

309
310
311
312




313
314
315

316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333

334
335
336
337
338
339
340
341
342
343
344
345

346
347
348
349
350
351



352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421

422
423
424
425
426
427
428

429

430
431


432
433
434
435
436


437
438
439



440


441
442
443
444
445
446


447

448
449
450
451
452
453
454
455
456
457
458
459



460
461
462
463


464
465
466
467

468
469
470
471
472
473
474
475


476
477
478
479
480
481
482
483


484
485
486

487
488


489
490
491
492
493
494
495

496
497



498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516

517
518
519
520
521
522
523
524
525
526

527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549

550

551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573


574
575
576
577
578
579
580
581

var runDependencyWatcher = null;

var dependenciesFulfilled = null;

function addRunDependency(id) {
 runDependencies++;

 Module["monitorRunDependencies"]?.(runDependencies);

}

function removeRunDependency(id) {
 runDependencies--;

 Module["monitorRunDependencies"]?.(runDependencies);

 if (runDependencies == 0) {
  if (runDependencyWatcher !== null) {
   clearInterval(runDependencyWatcher);
   runDependencyWatcher = null;
  }
  if (dependenciesFulfilled) {
   var callback = dependenciesFulfilled;
   dependenciesFulfilled = null;
   callback();
  }
 }
}

/** @param {string|number=} what */ function abort(what) {

 Module["onAbort"]?.(what);

 what = "Aborted(" + what + ")";
 err(what);
 ABORT = true;
 EXITSTATUS = 1;
 what += ". Build with -sASSERTIONS for more info.";
 /** @suppress {checkTypes} */ var e = new WebAssembly.RuntimeError(what);
 readyPromiseReject(e);
 throw e;
}

var dataURIPrefix = "data:application/octet-stream;base64,";

/**
 * Indicates whether filename is a base64 data URI.
 * @noinline
 */ var isDataURI = filename => filename.startsWith(dataURIPrefix);


var wasmBinaryFile;

wasmBinaryFile = "pikchr.wasm";

if (!isDataURI(wasmBinaryFile)) {
 wasmBinaryFile = locateFile(wasmBinaryFile);
}

function getBinarySync(file) {

 if (file == wasmBinaryFile && wasmBinary) {
  return new Uint8Array(wasmBinary);
 }
 if (readBinary) {
  return readBinary(file);
 }
 throw "both async and sync fetching of the wasm failed";


}


function getBinaryPromise(binaryFile) {
 if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
  if (typeof fetch == "function") {
   return fetch(binaryFile, {
    credentials: "same-origin"
   }).then(response => {
    if (!response["ok"]) {
     throw `failed to load wasm binary file at '${binaryFile}'`;
    }
    return response["arrayBuffer"]();
   }).catch(() => getBinarySync(binaryFile));
  }
 }
 return Promise.resolve().then(() => getBinarySync(binaryFile));
}

function instantiateArrayBuffer(binaryFile, imports, receiver) {
 return getBinaryPromise(binaryFile).then(binary => WebAssembly.instantiate(binary, imports)).then(instance => instance).then(receiver, reason => {
  err(`failed to asynchronously prepare wasm: ${reason}`);
  abort(reason);
 });
}

function instantiateAsync(binary, binaryFile, imports, callback) {
 if (!binary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(binaryFile) && typeof fetch == "function") {
  return fetch(binaryFile, {
   credentials: "same-origin"
  }).then(response => {
   /** @suppress {checkTypes} */ var result = WebAssembly.instantiateStreaming(response, imports);
   return result.then(callback, function(reason) {
    err(`wasm streaming compile failed: ${reason}`);
    err("falling back to ArrayBuffer instantiation");
    return instantiateArrayBuffer(binaryFile, imports, callback);
   });
  });
 }
 return instantiateArrayBuffer(binaryFile, imports, callback);
}

function createWasm() {
 var info = {
  "a": wasmImports
 };
 /** @param {WebAssembly.Module=} module*/ function receiveInstance(instance, module) {
  wasmExports = instance.exports;

  wasmMemory = wasmExports["d"];
  updateMemoryViews();

  addOnInit(wasmExports["e"]);
  removeRunDependency("wasm-instantiate");
  return wasmExports;
 }
 addRunDependency("wasm-instantiate");
 function receiveInstantiationResult(result) {
  receiveInstance(result["instance"]);
 }
 if (Module["instantiateWasm"]) {
  try {
   return Module["instantiateWasm"](info, receiveInstance);
  } catch (e) {
   err(`Module.instantiateWasm callback failed with error: ${e}`);


   readyPromiseReject(e);

  }
 }
 instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult).catch(readyPromiseReject);

 return {};
}

/** @constructor */ function ExitStatus(status) {







 this.name = "ExitStatus";

 this.message = `Program terminated with exit(${status})`;
 this.status = status;
}





var callRuntimeCallbacks = callbacks => {
 while (callbacks.length > 0) {
  callbacks.shift()(Module);

 }
};

/**
     * @param {number} ptr
     * @param {string} type
     */ function getValue(ptr, type = "i8") {
 if (type.endsWith("*")) type = "*";
 switch (type) {
 case "i1":
  return HEAP8[((ptr) >> 0)];

 case "i8":
  return HEAP8[((ptr) >> 0)];

 case "i16":
  return HEAP16[((ptr) >> 1)];


 case "i32":
  return HEAP32[((ptr) >> 2)];

 case "i64":
  abort("to do getValue(i64) use WASM_BIGINT");

 case "float":
  return HEAPF32[((ptr) >> 2)];

 case "double":
  return HEAPF64[((ptr) >> 3)];


 case "*":
  return HEAPU32[((ptr) >> 2)];

 default:
  abort(`invalid type for getValue: ${type}`);
 }



}

var noExitRuntime = Module["noExitRuntime"] || true;

/**
     * @param {number} ptr
     * @param {number} value
     * @param {string} type
     */ function setValue(ptr, value, type = "i8") {
 if (type.endsWith("*")) type = "*";
 switch (type) {
 case "i1":
  HEAP8[((ptr) >> 0)] = value;
  break;

 case "i8":
  HEAP8[((ptr) >> 0)] = value;
  break;

 case "i16":
  HEAP16[((ptr) >> 1)] = value;
  break;

 case "i32":
  HEAP32[((ptr) >> 2)] = value;
  break;

 case "i64":
  abort("to do setValue(i64) use WASM_BIGINT");

 case "float":
  HEAPF32[((ptr) >> 2)] = value;
  break;

 case "double":
  HEAPF64[((ptr) >> 3)] = value;
  break;

 case "*":
  HEAPU32[((ptr) >> 2)] = value;
  break;

 default:
  abort(`invalid type for setValue: ${type}`);
 }
}

var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined;

/**
     * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
     * array that contains uint8 values, returns a copy of that string as a
     * Javascript String object.
     * heapOrArray is either a regular array, or a JavaScript typed array view.
     * @param {number} idx
     * @param {number=} maxBytesToRead
     * @return {string}
     */ var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => {
 var endIdx = idx + maxBytesToRead;
 var endPtr = idx;
 while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
 if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
  return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
 }
 var str = "";
 while (idx < endPtr) {
  var u0 = heapOrArray[idx++];
  if (!(u0 & 128)) {
   str += String.fromCharCode(u0);
   continue;

  }
  var u1 = heapOrArray[idx++] & 63;
  if ((u0 & 224) == 192) {
   str += String.fromCharCode(((u0 & 31) << 6) | u1);
   continue;
  }
  var u2 = heapOrArray[idx++] & 63;

  if ((u0 & 240) == 224) {

   u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
  } else {


   u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
  }
  if (u0 < 65536) {
   str += String.fromCharCode(u0);
  } else {


   var ch = u0 - 65536;
   str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023));
  }



 }


 return str;
};

/**
     * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
     * emscripten HEAP, returns a copy of that string as a Javascript String object.


     *

     * @param {number} ptr
     * @param {number=} maxBytesToRead - An optional length that specifies the
     *   maximum number of bytes to read. You can omit this parameter to scan the
     *   string until the first 0 byte. If maxBytesToRead is passed, and the string
     *   at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
     *   string will cut short at that byte index (i.e. maxBytesToRead will not
     *   produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing
     *   frequent uses of UTF8ToString() with and without maxBytesToRead may throw
     *   JS JIT optimizations off, so it is worth to consider consistently using one
     * @return {string}
     */ var UTF8ToString = (ptr, maxBytesToRead) => ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";




var ___assert_fail = (condition, filename, line, func) => {
 abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]);
};



var abortOnCannotGrowMemory = requestedSize => {
 abort("OOM");
};


var _emscripten_resize_heap = requestedSize => {
 var oldSize = HEAPU8.length;
 requestedSize >>>= 0;
 abortOnCannotGrowMemory(requestedSize);
};

var runtimeKeepaliveCounter = 0;



var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;

var _proc_exit = code => {
 EXITSTATUS = code;
 if (!keepRuntimeAlive()) {
  Module["onExit"]?.(code);
  ABORT = true;
 }


 quit_(code, new ExitStatus(code));
};


/** @param {boolean|number=} implicit */ var exitJS = (status, implicit) => {
 EXITSTATUS = status;


 _proc_exit(status);
};

var _exit = exitJS;

var getCFunc = ident => {
 var func = Module["_" + ident];

 return func;
};




var writeArrayToMemory = (array, buffer) => {
 HEAP8.set(array, buffer);
};

var lengthBytesUTF8 = str => {
 var len = 0;
 for (var i = 0; i < str.length; ++i) {
  var c = str.charCodeAt(i);
  if (c <= 127) {
   len++;
  } else if (c <= 2047) {
   len += 2;
  } else if (c >= 55296 && c <= 57343) {
   len += 4;
   ++i;
  } else {
   len += 3;
  }

 }
 return len;
};

var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
 if (!(maxBytesToWrite > 0)) return 0;
 var startIdx = outIdx;
 var endIdx = outIdx + maxBytesToWrite - 1;
 for (var i = 0; i < str.length; ++i) {
  var u = str.charCodeAt(i);

  if (u >= 55296 && u <= 57343) {
   var u1 = str.charCodeAt(++i);
   u = 65536 + ((u & 1023) << 10) | (u1 & 1023);
  }
  if (u <= 127) {
   if (outIdx >= endIdx) break;
   heap[outIdx++] = u;
  } else if (u <= 2047) {
   if (outIdx + 1 >= endIdx) break;
   heap[outIdx++] = 192 | (u >> 6);
   heap[outIdx++] = 128 | (u & 63);
  } else if (u <= 65535) {
   if (outIdx + 2 >= endIdx) break;
   heap[outIdx++] = 224 | (u >> 12);
   heap[outIdx++] = 128 | ((u >> 6) & 63);
   heap[outIdx++] = 128 | (u & 63);
  } else {
   if (outIdx + 3 >= endIdx) break;
   heap[outIdx++] = 240 | (u >> 18);
   heap[outIdx++] = 128 | ((u >> 12) & 63);
   heap[outIdx++] = 128 | ((u >> 6) & 63);
   heap[outIdx++] = 128 | (u & 63);
  }

 }

 heap[outIdx] = 0;
 return outIdx - startIdx;
};

var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);

var stringToUTF8OnStack = str => {
 var size = lengthBytesUTF8(str) + 1;
 var ret = stackAlloc(size);
 stringToUTF8(str, ret, size);
 return ret;
};

/**
     * @param {string|null=} returnType
     * @param {Array=} argTypes
     * @param {Arguments|Array=} args
     * @param {Object=} opts
     */ var ccall = (ident, returnType, argTypes, args, opts) => {
 var toC = {
  "string": str => {
   var ret = 0;
   if (str !== null && str !== undefined && str !== 0) {


    ret = stringToUTF8OnStack(str);
   }
   return ret;
  },
  "array": arr => {
   var ret = stackAlloc(arr.length);
   writeArrayToMemory(arr, ret);
   return ret;
596
597
598
599
600
601
602
603
604




605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639

640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
 var ret = func.apply(null, cArgs);
 function onDone(ret) {
  if (stack !== 0) stackRestore(stack);
  return convertReturnValue(ret);
 }
 ret = onDone(ret);
 return ret;
}





function cwrap(ident, returnType, argTypes, opts) {
 argTypes = argTypes || [];
 var numericArgs = argTypes.every(type => type === "number" || type === "boolean");
 var numericRet = returnType !== "string";
 if (numericRet && numericArgs && !opts) {
  return getCFunc(ident);
 }
 return function() {
  return ccall(ident, returnType, argTypes, arguments, opts);
 };
}

var asmLibraryArg = {
 "a": ___assert_fail,
 "b": _emscripten_resize_heap,
 "c": _exit
};

var asm = createWasm();

var ___wasm_call_ctors = Module["___wasm_call_ctors"] = function() {
 return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["e"]).apply(null, arguments);
};

var _pikchr = Module["_pikchr"] = function() {
 return (_pikchr = Module["_pikchr"] = Module["asm"]["f"]).apply(null, arguments);
};

var stackSave = Module["stackSave"] = function() {
 return (stackSave = Module["stackSave"] = Module["asm"]["h"]).apply(null, arguments);
};

var stackRestore = Module["stackRestore"] = function() {
 return (stackRestore = Module["stackRestore"] = Module["asm"]["i"]).apply(null, arguments);
};


var stackAlloc = Module["stackAlloc"] = function() {
 return (stackAlloc = Module["stackAlloc"] = Module["asm"]["j"]).apply(null, arguments);
};

Module["stackSave"] = stackSave;

Module["stackRestore"] = stackRestore;

Module["cwrap"] = cwrap;

Module["setValue"] = setValue;

Module["getValue"] = getValue;

var calledRun;

dependenciesFulfilled = function runCaller() {
 if (!calledRun) run();
 if (!calledRun) dependenciesFulfilled = runCaller;
};

function run(args) {
 args = args || arguments_;
 if (runDependencies > 0) {
  return;
 }
 preRun();
 if (runDependencies > 0) {
  return;
 }







|

>
>
>
>
|
<
|







|

|
|
|
|


|

|
<
<

|
<
<

|
<
<

|
|
<
>

|
<
<


















|
<







605
606
607
608
609
610
611
612
613
614
615
616
617
618

619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637


638
639


640
641


642
643
644

645
646
647


648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666

667
668
669
670
671
672
673
 var ret = func.apply(null, cArgs);
 function onDone(ret) {
  if (stack !== 0) stackRestore(stack);
  return convertReturnValue(ret);
 }
 ret = onDone(ret);
 return ret;
};

/**
     * @param {string=} returnType
     * @param {Array=} argTypes
     * @param {Object=} opts
     */ var cwrap = (ident, returnType, argTypes, opts) => {

 var numericArgs = !argTypes || argTypes.every(type => type === "number" || type === "boolean");
 var numericRet = returnType !== "string";
 if (numericRet && numericArgs && !opts) {
  return getCFunc(ident);
 }
 return function() {
  return ccall(ident, returnType, argTypes, arguments, opts);
 };
};

var wasmImports = {
 /** @export */ a: ___assert_fail,
 /** @export */ b: _emscripten_resize_heap,
 /** @export */ c: _exit
};

var wasmExports = createWasm();

var ___wasm_call_ctors = () => (___wasm_call_ctors = wasmExports["e"])();



var _pikchr = Module["_pikchr"] = (a0, a1, a2, a3, a4) => (_pikchr = Module["_pikchr"] = wasmExports["f"])(a0, a1, a2, a3, a4);



var stackSave = () => (stackSave = wasmExports["h"])();



var stackRestore = a0 => (stackRestore = wasmExports["i"])(a0);


var stackAlloc = a0 => (stackAlloc = wasmExports["j"])(a0);

Module["stackAlloc"] = stackAlloc;



Module["stackSave"] = stackSave;

Module["stackRestore"] = stackRestore;

Module["cwrap"] = cwrap;

Module["setValue"] = setValue;

Module["getValue"] = getValue;

var calledRun;

dependenciesFulfilled = function runCaller() {
 if (!calledRun) run();
 if (!calledRun) dependenciesFulfilled = runCaller;
};

function run() {

 if (runDependencies > 0) {
  return;
 }
 preRun();
 if (runDependencies > 0) {
  return;
 }
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
  Module["preInit"].pop()();
 }
}

run();


  return initPikchrModule.ready
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
  module.exports = initPikchrModule;
else if (typeof define === 'function' && define['amd'])
  define([], function() { return initPikchrModule; });
else if (typeof exports === 'object')
  exports["initPikchrModule"] = initPikchrModule;







|






<
<
|
700
701
702
703
704
705
706
707
708
709
710
711
712
713


714
  Module["preInit"].pop()();
 }
}

run();


  return moduleArg.ready
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
  module.exports = initPikchrModule;
else if (typeof define === 'function' && define['amd'])


  define([], () => initPikchrModule);

Changes to extsrc/pikchr.wasm.

cannot compute difference between binary files

Changes to extsrc/shell.c.

248
249
250
251
252
253
254
255
256
257
258
259


260













































261





























































































262













263












264






























































































265

































































266


















































267






268








269















































































































270









































































































































































































































































271


















272


















273

274










































































































































































































275










276

277

278
279
280
281
282
283
284
#endif
#undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

/* string conversion routines only needed on Win32 */
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
#endif



/* On Windows, we normally run with output mode of TEXT so that \n characters













































** are automatically translated into \r\n.  However, this behavior needs





























































































** to be disabled in some cases (ex: when generating CSV output and when













** rendering quoted strings that contain \n characters).  The following












** routines take care of that.






























































































*/

































































#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT


















































static void setBinaryMode(FILE *file, int isOutput){






  if( isOutput ) fflush(file);








  _setmode(_fileno(file), _O_BINARY);















































































































}









































































































































































































































































static void setTextMode(FILE *file, int isOutput){


















  if( isOutput ) fflush(file);


















  _setmode(_fileno(file), _O_TEXT);

}










































































































































































































#else










# define setBinaryMode(X,Y)

# define setTextMode(X,Y)

#endif

/* True if the timer is enabled */
static int enableTimer = 0;

/* A version of strcmp() that works with NULL values */
static int cli_strcmp(const char *a, const char *b){







<
<



>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
|
>
|
>







248
249
250
251
252
253
254


255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
#endif
#undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

/* string conversion routines only needed on Win32 */
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);


extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
#endif

/* Use console I/O package as a direct INCLUDE. */
#define SQLITE_INTERNAL_LINKAGE static

#ifdef SQLITE_SHELL_FIDDLE
/* Deselect most features from the console I/O package for Fiddle. */
# define SQLITE_CIO_NO_REDIRECT
# define SQLITE_CIO_NO_CLASSIFY
# define SQLITE_CIO_NO_TRANSLATE
# define SQLITE_CIO_NO_SETMODE
#endif
/************************* Begin ../ext/consio/console_io.h ******************/
/*
** 2023 November 1
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
********************************************************************************
** This file exposes various interfaces used for console and other I/O
** by the SQLite project command-line tools. These interfaces are used
** at either source conglomeration time, compilation time, or run time.
** This source provides for either inclusion into conglomerated,
** "single-source" forms or separate compilation then linking.
**
** Platform dependencies are "hidden" here by various stratagems so
** that, provided certain conditions are met, the programs using this
** source or object code compiled from it need no explicit conditional
** compilation in their source for their console and stream I/O.
**
** The symbols and functionality exposed here are not a public API.
** This code may change in tandem with other project code as needed.
**
** When this .h file and its companion .c are directly incorporated into
** a source conglomeration (such as shell.c), the preprocessor symbol
** CIO_WIN_WC_XLATE is defined as 0 or 1, reflecting whether console I/O
** translation for Windows is effected for the build.
*/
#define HAVE_CONSOLE_IO_H 1
#ifndef SQLITE_INTERNAL_LINKAGE
# define SQLITE_INTERNAL_LINKAGE extern /* external to translation unit */
# include <stdio.h>
#else
# define SHELL_NO_SYSINC /* Better yet, modify mkshellc.tcl for this. */
#endif

#ifndef SQLITE3_H
/* # include "sqlite3.h" */
#endif

#ifndef SQLITE_CIO_NO_CLASSIFY

/* Define enum for use with following function. */
typedef enum StreamsAreConsole {
  SAC_NoConsole = 0,
  SAC_InConsole = 1, SAC_OutConsole = 2, SAC_ErrConsole = 4,
  SAC_AnyConsole = 0x7
} StreamsAreConsole;

/*
** Classify the three standard I/O streams according to whether
** they are connected to a console attached to the process.
**
** Returns the bit-wise OR of SAC_{In,Out,Err}Console values,
** or SAC_NoConsole if none of the streams reaches a console.
**
** This function should be called before any I/O is done with
** the given streams. As a side-effect, the given inputs are
** recorded so that later I/O operations on them may be done
** differently than the C library FILE* I/O would be done,
** iff the stream is used for the I/O functions that follow,
** and to support the ones that use an implicit stream.
**
** On some platforms, stream or console mode alteration (aka
** "Setup") may be made which is undone by consoleRestore().
*/
SQLITE_INTERNAL_LINKAGE StreamsAreConsole
consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr );
/* A usual call for convenience: */
#define SQLITE_STD_CONSOLE_INIT() consoleClassifySetup(stdin,stdout,stderr)

/*
** After an initial call to consoleClassifySetup(...), renew
** the same setup it effected. (A call not after is an error.)
** This will restore state altered by consoleRestore();
**
** Applications which run an inferior (child) process which
** inherits the same I/O streams may call this function after
** such a process exits to guard against console mode changes.
*/
SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void);

/*
** Undo any side-effects left by consoleClassifySetup(...).
**
** This should be called after consoleClassifySetup() and
** before the process terminates normally. It is suitable
** for use with the atexit() C library procedure. After
** this call, no console I/O should be done until one of
** console{Classify or Renew}Setup(...) is called again.
**
** Applications which run an inferior (child) process that
** inherits the same I/O streams might call this procedure
** before so that said process will have a console setup
** however users have configured it or come to expect.
*/
SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void );

#else /* defined(SQLITE_CIO_NO_CLASSIFY) */
# define consoleClassifySetup(i,o,e)
# define consoleRenewSetup()
# define consoleRestore()
#endif /* defined(SQLITE_CIO_NO_CLASSIFY) */

#ifndef SQLITE_CIO_NO_REDIRECT
/*
** Set stream to be used for the functions below which write
** to "the designated X stream", where X is Output or Error.
** Returns the previous value.
**
** Alternatively, pass the special value, invalidFileStream,
** to get the designated stream value without setting it.
**
** Before the designated streams are set, they default to
** those passed to consoleClassifySetup(...), and before
** that is called they default to stdout and stderr.
**
** It is error to close a stream so designated, then, without
** designating another, use the corresponding {o,e}Emit(...).
*/
SQLITE_INTERNAL_LINKAGE FILE *invalidFileStream;
SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf);
# ifdef CONSIO_SET_ERROR_STREAM
SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf);
# endif
#else
# define setOutputStream(pf)
# define setErrorStream(pf)
#endif /* !defined(SQLITE_CIO_NO_REDIRECT) */

#ifndef SQLITE_CIO_NO_TRANSLATE
/*
** Emit output like fprintf(). If the output is going to the
** console and translation from UTF-8 is necessary, perform
** the needed translation. Otherwise, write formatted output
** to the provided stream almost as-is, possibly with newline
** translation as specified by set{Binary,Text}Mode().
*/
SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...);
/* Like fPrintfUtf8 except stream is always the designated output. */
SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...);
/* Like fPrintfUtf8 except stream is always the designated error. */
SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...);

/*
** Emit output like fputs(). If the output is going to the
** console and translation from UTF-8 is necessary, perform
** the needed translation. Otherwise, write given text to the
** provided stream almost as-is, possibly with newline
** translation as specified by set{Binary,Text}Mode().
*/
SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO);
/* Like fPutsUtf8 except stream is always the designated output. */
SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z);
/* Like fPutsUtf8 except stream is always the designated error. */
SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z);

/*
** Emit output like fPutsUtf8(), except that the length of the
** accepted char or character sequence is limited by nAccept.
**
** Returns the number of accepted char values.
*/
#ifdef CONSIO_SPUTB
SQLITE_INTERNAL_LINKAGE int
fPutbUtf8(FILE *pfOut, const char *cBuf, int nAccept);
/* Like fPutbUtf8 except stream is always the designated output. */
#endif
SQLITE_INTERNAL_LINKAGE int
oPutbUtf8(const char *cBuf, int nAccept);
/* Like fPutbUtf8 except stream is always the designated error. */
#ifdef CONSIO_EPUTB
SQLITE_INTERNAL_LINKAGE int
ePutbUtf8(const char *cBuf, int nAccept);
#endif

/*
** Collect input like fgets(...) with special provisions for input
** from the console on platforms that require same. Defers to the
** C library fgets() when input is not from the console. Newline
** translation may be done as set by set{Binary,Text}Mode(). As a
** convenience, pfIn==NULL is treated as stdin.
*/
SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn);
/* Like fGetsUtf8 except stream is always the designated input. */
/* SQLITE_INTERNAL_LINKAGE char* iGetsUtf8(char *cBuf, int ncMax); */

#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */

#ifndef SQLITE_CIO_NO_SETMODE
/*
** Set given stream for binary mode, where newline translation is
** not done, or for text mode where, for some platforms, newlines
** are translated to the platform's conventional char sequence.
** If bFlush true, flush the stream.
**
** An additional side-effect is that if the stream is one passed
** to consoleClassifySetup() as an output, it is flushed first.
**
** Note that binary/text mode has no effect on console I/O
** translation. On all platforms, newline to the console starts
** a new line and CR,LF chars from the console become a newline.
*/
SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *, short bFlush);
SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *, short bFlush);
#endif

#ifdef SQLITE_CIO_PROMPTED_IN
typedef struct Prompts {
  int numPrompts;
  const char **azPrompts;
} Prompts;

/*
** Macros for use of a line editor.
**
** The following macros define operations involving use of a
** line-editing library or simple console interaction.
** A "T" argument is a text (char *) buffer or filename.
** A "N" argument is an integer.
**
** SHELL_ADD_HISTORY(T) // Record text as line(s) of history.
** SHELL_READ_HISTORY(T) // Read history from file named by T.
** SHELL_WRITE_HISTORY(T) // Write history to file named by T.
** SHELL_STIFLE_HISTORY(N) // Limit history to N entries.
**
** A console program which does interactive console input is
** expected to call:
** SHELL_READ_HISTORY(T) before collecting such input;
** SHELL_ADD_HISTORY(T) as record-worthy input is taken;
** SHELL_STIFLE_HISTORY(N) after console input ceases; then
** SHELL_WRITE_HISTORY(T) before the program exits.
*/

/*
** Retrieve a single line of input text from an input stream.
**
** If pfIn is the input stream passed to consoleClassifySetup(),
** and azPrompt is not NULL, then a prompt is issued before the
** line is collected, as selected by the isContinuation flag.
** Array azPrompt[{0,1}] holds the {main,continuation} prompt.
**
** If zBufPrior is not NULL then it is a buffer from a prior
** call to this routine that can be reused, or will be freed.
**
** The result is stored in space obtained from malloc() and
** must either be freed by the caller or else passed back to
** this function as zBufPrior for reuse.
**
** This function may call upon services of a line-editing
** library to interactively collect line edited input.
*/
SQLITE_INTERNAL_LINKAGE char *
shellGetLine(FILE *pfIn, char *zBufPrior, int nLen,
             short isContinuation, Prompts azPrompt);
#endif /* defined(SQLITE_CIO_PROMPTED_IN) */
/*
** TBD: Define an interface for application(s) to generate
** completion candidates for use by the line-editor.
**
** This may be premature; the CLI is the only application
** that does this. Yet, getting line-editing melded into
** console I/O is desirable because a line-editing library
** may have to establish console operating mode, possibly
** in a way that interferes with the above functionality.
*/

#if !(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))
/* Skip over as much z[] input char sequence as is valid UTF-8,
** limited per nAccept char's or whole characters and containing
** no char cn such that ((1<<cn) & ccm)!=0. On return, the
** sequence z:return (inclusive:exclusive) is validated UTF-8.
** Limit: nAccept>=0 => char count, nAccept<0 => character
 */
SQLITE_INTERNAL_LINKAGE const char*
zSkipValidUtf8(const char *z, int nAccept, long ccm);

#endif

/************************* End ../ext/consio/console_io.h ********************/
/************************* Begin ../ext/consio/console_io.c ******************/
/*
** 2023 November 4
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
********************************************************************************
** This file implements various interfaces used for console and stream I/O
** by the SQLite project command-line tools, as explained in console_io.h .
** Functions prefixed by "SQLITE_INTERNAL_LINKAGE" behave as described there.
*/

#ifndef SQLITE_CDECL
# define SQLITE_CDECL
#endif

#ifndef SHELL_NO_SYSINC
# include <stdarg.h>
# include <string.h>
# include <stdlib.h>
# include <limits.h>
# include <assert.h>
/* # include "sqlite3.h" */
#endif
#ifndef HAVE_CONSOLE_IO_H
# include "console_io.h"
#endif
#if defined(_MSC_VER)
# pragma warning(disable : 4204)
#endif

#ifndef SQLITE_CIO_NO_TRANSLATE
# if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
#  ifndef SHELL_NO_SYSINC
#   include <io.h>
#   include <fcntl.h>
#   undef WIN32_LEAN_AND_MEAN
#   define WIN32_LEAN_AND_MEAN
#   include <windows.h>
#  endif
#  define CIO_WIN_WC_XLATE 1 /* Use WCHAR Windows APIs for console I/O */
# else
#  ifndef SHELL_NO_SYSINC
#   include <unistd.h>
#  endif
#  define CIO_WIN_WC_XLATE 0 /* Use plain C library stream I/O at console */
# endif
#else
# define CIO_WIN_WC_XLATE 0 /* Not exposing translation routines at all */
#endif

#if CIO_WIN_WC_XLATE
/* Character used to represent a known-incomplete UTF-8 char group (�) */
static WCHAR cBadGroup = 0xfffd;
#endif

#if CIO_WIN_WC_XLATE
static HANDLE handleOfFile(FILE *pf){
  int fileDesc = _fileno(pf);
  union { intptr_t osfh; HANDLE fh; } fid = {
    (fileDesc>=0)? _get_osfhandle(fileDesc) : (intptr_t)INVALID_HANDLE_VALUE
  };
  return fid.fh;
}
#endif

#ifndef SQLITE_CIO_NO_TRANSLATE
typedef struct PerStreamTags {
# if CIO_WIN_WC_XLATE
  HANDLE hx;
  DWORD consMode;
  char acIncomplete[4];
# else
  short reachesConsole;
# endif
  FILE *pf;
} PerStreamTags;

/* Define NULL-like value for things which can validly be 0. */
# define SHELL_INVALID_FILE_PTR ((FILE *)~0)
# if CIO_WIN_WC_XLATE
#  define SHELL_INVALID_CONS_MODE 0xFFFF0000
# endif

# if CIO_WIN_WC_XLATE
#  define PST_INITIALIZER { INVALID_HANDLE_VALUE, SHELL_INVALID_CONS_MODE, \
      {0,0,0,0}, SHELL_INVALID_FILE_PTR }
# else
#  define PST_INITIALIZER { 0, SHELL_INVALID_FILE_PTR }
# endif

/* Quickly say whether a known output is going to the console. */
# if CIO_WIN_WC_XLATE
static short pstReachesConsole(PerStreamTags *ppst){
  return (ppst->hx != INVALID_HANDLE_VALUE);
}
# else
#  define pstReachesConsole(ppst) 0
# endif

# if CIO_WIN_WC_XLATE
static void restoreConsoleArb(PerStreamTags *ppst){
  if( pstReachesConsole(ppst) ) SetConsoleMode(ppst->hx, ppst->consMode);
}
# else
#  define restoreConsoleArb(ppst)
# endif

/* Say whether FILE* appears to be a console, collect associated info. */
static short streamOfConsole(FILE *pf, /* out */ PerStreamTags *ppst){
# if CIO_WIN_WC_XLATE
  short rv = 0;
  DWORD dwCM = SHELL_INVALID_CONS_MODE;
  HANDLE fh = handleOfFile(pf);
  ppst->pf = pf;
  if( INVALID_HANDLE_VALUE != fh ){
    rv = (GetFileType(fh) == FILE_TYPE_CHAR && GetConsoleMode(fh,&dwCM));
  }
  ppst->hx = (rv)? fh : INVALID_HANDLE_VALUE;
  ppst->consMode = dwCM;
  return rv;
# else
  ppst->pf = pf;
  ppst->reachesConsole = ( (short)isatty(fileno(pf)) );
  return ppst->reachesConsole;
# endif
}

# ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#  define ENABLE_VIRTUAL_TERMINAL_PROCESSING  (0x4)
# endif

# if CIO_WIN_WC_XLATE
/* Define console modes for use with the Windows Console API. */
#  define SHELL_CONI_MODE \
  (ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT | 0x80 \
  | ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_PROCESSED_INPUT)
#  define SHELL_CONO_MODE (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT \
  | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
# endif

typedef struct ConsoleInfo {
  PerStreamTags pstSetup[3];
  PerStreamTags pstDesignated[3];
  StreamsAreConsole sacSetup;
} ConsoleInfo;

static short isValidStreamInfo(PerStreamTags *ppst){
  return (ppst->pf != SHELL_INVALID_FILE_PTR);
}

static ConsoleInfo consoleInfo = {
  { /* pstSetup */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER },
  { /* pstDesignated[] */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER },
  SAC_NoConsole /* sacSetup */
};

SQLITE_INTERNAL_LINKAGE FILE* invalidFileStream = (FILE *)~0;

# if CIO_WIN_WC_XLATE
static void maybeSetupAsConsole(PerStreamTags *ppst, short odir){
  if( pstReachesConsole(ppst) ){
    DWORD cm = odir? SHELL_CONO_MODE : SHELL_CONI_MODE;
    SetConsoleMode(ppst->hx, cm);
  }
}
# else
#  define maybeSetupAsConsole(ppst,odir)
# endif

SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void){
# if CIO_WIN_WC_XLATE
  int ix = 0;
  while( ix < 6 ){
    PerStreamTags *ppst = (ix<3)?
      &consoleInfo.pstSetup[ix] : &consoleInfo.pstDesignated[ix-3];
    maybeSetupAsConsole(ppst, (ix % 3)>0);
    ++ix;
  }
# endif
}

SQLITE_INTERNAL_LINKAGE StreamsAreConsole
consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ){
  StreamsAreConsole rv = SAC_NoConsole;
  FILE* apf[3] = { pfIn, pfOut, pfErr };
  int ix;
  for( ix = 2; ix >= 0; --ix ){
    PerStreamTags *ppst = &consoleInfo.pstSetup[ix];
    if( streamOfConsole(apf[ix], ppst) ){
      rv |= (SAC_InConsole<<ix);
    }
    consoleInfo.pstDesignated[ix] = *ppst;
    if( ix > 0 ) fflush(apf[ix]);
  }
  consoleInfo.sacSetup = rv;
  consoleRenewSetup();
  return rv;
}

SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void ){
# if CIO_WIN_WC_XLATE
  static ConsoleInfo *pci = &consoleInfo;
  if( pci->sacSetup ){
    int ix;
    for( ix=0; ix<3; ++ix ){
      if( pci->sacSetup & (SAC_InConsole<<ix) ){
        PerStreamTags *ppst = &pci->pstSetup[ix];
        SetConsoleMode(ppst->hx, ppst->consMode);
      }
    }
  }
# endif
}
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */

#ifdef SQLITE_CIO_INPUT_REDIR
/* Say whether given FILE* is among those known, via either
** consoleClassifySetup() or set{Output,Error}Stream, as
** readable, and return an associated PerStreamTags pointer
** if so. Otherwise, return 0.
*/
static PerStreamTags * isKnownReadable(FILE *pf){
  static PerStreamTags *apst[] = {
    &consoleInfo.pstDesignated[0], &consoleInfo.pstSetup[0], 0
  };
  int ix = 0;
  do {
    if( apst[ix]->pf == pf ) break;
  } while( apst[++ix] != 0 );
  return apst[ix];
}
#endif

#ifndef SQLITE_CIO_NO_TRANSLATE
/* Say whether given FILE* is among those known, via either
** consoleClassifySetup() or set{Output,Error}Stream, as
** writable, and return an associated PerStreamTags pointer
** if so. Otherwise, return 0.
*/
static PerStreamTags * isKnownWritable(FILE *pf){
  static PerStreamTags *apst[] = {
    &consoleInfo.pstDesignated[1], &consoleInfo.pstDesignated[2],
    &consoleInfo.pstSetup[1], &consoleInfo.pstSetup[2], 0
  };
  int ix = 0;
  do {
    if( apst[ix]->pf == pf ) break;
  } while( apst[++ix] != 0 );
  return apst[ix];
}

static FILE *designateEmitStream(FILE *pf, unsigned chix){
  FILE *rv = consoleInfo.pstDesignated[chix].pf;
  if( pf == invalidFileStream ) return rv;
  else{
    /* Setting a possibly new output stream. */
    PerStreamTags *ppst = isKnownWritable(pf);
    if( ppst != 0 ){
      PerStreamTags pst = *ppst;
      consoleInfo.pstDesignated[chix] = pst;
    }else streamOfConsole(pf, &consoleInfo.pstDesignated[chix]);
  }
  return rv;
}

SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf){
  return designateEmitStream(pf, 1);
}
# ifdef CONSIO_SET_ERROR_STREAM
SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf){
  return designateEmitStream(pf, 2);
}
# endif
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */

#ifndef SQLITE_CIO_NO_SETMODE
# if CIO_WIN_WC_XLATE
static void setModeFlushQ(FILE *pf, short bFlush, int mode){
  if( bFlush ) fflush(pf);
  _setmode(_fileno(pf), mode);
}
# else
#  define setModeFlushQ(f, b, m) if(b) fflush(f)
# endif

SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *pf, short bFlush){
  setModeFlushQ(pf, bFlush, _O_BINARY);
}
SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *pf, short bFlush){
  setModeFlushQ(pf, bFlush, _O_TEXT);
}
# undef setModeFlushQ

#else /* defined(SQLITE_CIO_NO_SETMODE) */
# define setBinaryMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
# define setTextMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
#endif /* defined(SQLITE_CIO_NO_SETMODE) */

#ifndef SQLITE_CIO_NO_TRANSLATE
# if CIO_WIN_WC_XLATE
/* Write buffer cBuf as output to stream known to reach console,
** limited to ncTake char's. Return ncTake on success, else 0. */
static int conZstrEmit(PerStreamTags *ppst, const char *z, int ncTake){
  int rv = 0;
  if( z!=NULL ){
    int nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, 0,0);
    if( nwc > 0 ){
      WCHAR *zw = sqlite3_malloc64(nwc*sizeof(WCHAR));
      if( zw!=NULL ){
        nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, zw,nwc);
        if( nwc > 0 ){
          /* Translation from UTF-8 to UTF-16, then WCHARs out. */
          if( WriteConsoleW(ppst->hx, zw,nwc, 0, NULL) ){
            rv = ncTake;
          }
        }
        sqlite3_free(zw);
      }
    }
  }
  return rv;
}

/* For {f,o,e}PrintfUtf8() when stream is known to reach console. */
static int conioVmPrintf(PerStreamTags *ppst, const char *zFormat, va_list ap){
  char *z = sqlite3_vmprintf(zFormat, ap);
  if( z ){
    int rv = conZstrEmit(ppst, z, (int)strlen(z));
    sqlite3_free(z);
    return rv;
  }else return 0;
}
# endif /* CIO_WIN_WC_XLATE */

# ifdef CONSIO_GET_EMIT_STREAM
static PerStreamTags * getDesignatedEmitStream(FILE *pf, unsigned chix,
                                               PerStreamTags *ppst){
  PerStreamTags *rv = isKnownWritable(pf);
  short isValid = (rv!=0)? isValidStreamInfo(rv) : 0;
  if( rv != 0 && isValid ) return rv;
  streamOfConsole(pf, ppst);
  return ppst;
}
# endif

/* Get stream info, either for designated output or error stream when
** chix equals 1 or 2, or for an arbitrary stream when chix == 0.
** In either case, ppst references a caller-owned PerStreamTags
** struct which may be filled in if none of the known writable
** streams is being held by consoleInfo. The ppf parameter is a
** byref output when chix!=0 and a byref input when chix==0.
 */
static PerStreamTags *
getEmitStreamInfo(unsigned chix, PerStreamTags *ppst,
                  /* in/out */ FILE **ppf){
  PerStreamTags *ppstTry;
  FILE *pfEmit;
  if( chix > 0 ){
    ppstTry = &consoleInfo.pstDesignated[chix];
    if( !isValidStreamInfo(ppstTry) ){
      ppstTry = &consoleInfo.pstSetup[chix];
      pfEmit = ppst->pf;
    }else pfEmit = ppstTry->pf;
    if( !isValidStreamInfo(ppstTry) ){
      pfEmit = (chix > 1)? stderr : stdout;
      ppstTry = ppst;
      streamOfConsole(pfEmit, ppstTry);
    }
    *ppf = pfEmit;
  }else{
    ppstTry = isKnownWritable(*ppf);
    if( ppstTry != 0 ) return ppstTry;
    streamOfConsole(*ppf, ppst);
    return ppst;
  }
  return ppstTry;
}

SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...){
  va_list ap;
  int rv;
  FILE *pfOut;
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
# if CIO_WIN_WC_XLATE
  PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
# else
  getEmitStreamInfo(1, &pst, &pfOut);
# endif
  assert(zFormat!=0);
  va_start(ap, zFormat);
# if CIO_WIN_WC_XLATE
  if( pstReachesConsole(ppst) ){
    rv = conioVmPrintf(ppst, zFormat, ap);
  }else{
# endif
    rv = vfprintf(pfOut, zFormat, ap);
# if CIO_WIN_WC_XLATE
  }
# endif
  va_end(ap);
  return rv;
}

SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...){
  va_list ap;
  int rv;
  FILE *pfErr;
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
# if CIO_WIN_WC_XLATE
  PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
# else
  getEmitStreamInfo(2, &pst, &pfErr);
# endif
  assert(zFormat!=0);
  va_start(ap, zFormat);
# if CIO_WIN_WC_XLATE
  if( pstReachesConsole(ppst) ){
    rv = conioVmPrintf(ppst, zFormat, ap);
  }else{
# endif
    rv = vfprintf(pfErr, zFormat, ap);
# if CIO_WIN_WC_XLATE
  }
# endif
  va_end(ap);
  return rv;
}

SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...){
  va_list ap;
  int rv;
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
# if CIO_WIN_WC_XLATE
  PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
# else
  getEmitStreamInfo(0, &pst, &pfO);
# endif
  assert(zFormat!=0);
  va_start(ap, zFormat);
# if CIO_WIN_WC_XLATE
  if( pstReachesConsole(ppst) ){
    maybeSetupAsConsole(ppst, 1);
    rv = conioVmPrintf(ppst, zFormat, ap);
    if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
  }else{
# endif
    rv = vfprintf(pfO, zFormat, ap);
# if CIO_WIN_WC_XLATE
  }
# endif
  va_end(ap);
  return rv;
}

SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO){
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
# if CIO_WIN_WC_XLATE
  PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
# else
  getEmitStreamInfo(0, &pst, &pfO);
# endif
  assert(z!=0);
# if CIO_WIN_WC_XLATE
  if( pstReachesConsole(ppst) ){
    int rv;
    maybeSetupAsConsole(ppst, 1);
    rv = conZstrEmit(ppst, z, (int)strlen(z));
    if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
    return rv;
  }else {
# endif
    return (fputs(z, pfO)<0)? 0 : (int)strlen(z);
# if CIO_WIN_WC_XLATE
  }
# endif
}

SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z){
  FILE *pfErr;
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
# if CIO_WIN_WC_XLATE
  PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
# else
  getEmitStreamInfo(2, &pst, &pfErr);
# endif
  assert(z!=0);
# if CIO_WIN_WC_XLATE
  if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z));
  else {
# endif
    return (fputs(z, pfErr)<0)? 0 : (int)strlen(z);
# if CIO_WIN_WC_XLATE
  }
# endif
}

SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z){
  FILE *pfOut;
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
# if CIO_WIN_WC_XLATE
  PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
# else
  getEmitStreamInfo(1, &pst, &pfOut);
# endif
  assert(z!=0);
# if CIO_WIN_WC_XLATE
  if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z));
  else {
# endif
    return (fputs(z, pfOut)<0)? 0 : (int)strlen(z);
# if CIO_WIN_WC_XLATE
  }
# endif
}

#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */

#if !(defined(SQLITE_CIO_NO_UTF8SCAN) && defined(SQLITE_CIO_NO_TRANSLATE))
/* Skip over as much z[] input char sequence as is valid UTF-8,
** limited per nAccept char's or whole characters and containing
** no char cn such that ((1<<cn) & ccm)!=0. On return, the
** sequence z:return (inclusive:exclusive) is validated UTF-8.
** Limit: nAccept>=0 => char count, nAccept<0 => character
 */
SQLITE_INTERNAL_LINKAGE const char*
zSkipValidUtf8(const char *z, int nAccept, long ccm){
  int ng = (nAccept<0)? -nAccept : 0;
  const char *pcLimit = (nAccept>=0)? z+nAccept : 0;
  assert(z!=0);
  while( (pcLimit)? (z<pcLimit) : (ng-- != 0) ){
    char c = *z;
    if( (c & 0x80) == 0 ){
      if( ccm != 0L && c < 0x20 && ((1L<<c) & ccm) != 0 ) return z;
      ++z; /* ASCII */
    }else if( (c & 0xC0) != 0xC0 ) return z; /* not a lead byte */
    else{
      const char *zt = z+1; /* Got lead byte, look at trail bytes.*/
      do{
        if( pcLimit && zt >= pcLimit ) return z;
        else{
          char ct = *zt++;
          if( ct==0 || (zt-z)>4 || (ct & 0xC0)!=0x80 ){
            /* Trailing bytes are too few, too many, or invalid. */
            return z;
          }
        }
      } while( ((c <<= 1) & 0x40) == 0x40 ); /* Eat lead byte's count. */
      z = zt;
    }
  }
  return z;
}
#endif /*!(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))*/

#ifndef SQLITE_CIO_NO_TRANSLATE
# ifdef CONSIO_SPUTB
SQLITE_INTERNAL_LINKAGE int
fPutbUtf8(FILE *pfO, const char *cBuf, int nAccept){
  assert(pfO!=0);
#  if CIO_WIN_WC_XLATE
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
  PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
  if( pstReachesConsole(ppst) ){
    int rv;
    maybeSetupAsConsole(ppst, 1);
    rv = conZstrEmit(ppst, cBuf, nAccept);
    if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
    return rv;
  }else {
#  endif
    return (int)fwrite(cBuf, 1, nAccept, pfO);
#  if CIO_WIN_WC_XLATE
  }
#  endif
}
# endif

SQLITE_INTERNAL_LINKAGE int
oPutbUtf8(const char *cBuf, int nAccept){
  FILE *pfOut;
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
# if CIO_WIN_WC_XLATE
  PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
# else
  getEmitStreamInfo(1, &pst, &pfOut);
# endif
# if CIO_WIN_WC_XLATE
  if( pstReachesConsole(ppst) ){
    return conZstrEmit(ppst, cBuf, nAccept);
  }else {
# endif
    return (int)fwrite(cBuf, 1, nAccept, pfOut);
# if CIO_WIN_WC_XLATE
  }
# endif
}

# ifdef CONSIO_EPUTB
SQLITE_INTERNAL_LINKAGE int
ePutbUtf8(const char *cBuf, int nAccept){
  FILE *pfErr;
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
  PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
#  if CIO_WIN_WC_XLATE
  if( pstReachesConsole(ppst) ){
    return conZstrEmit(ppst, cBuf, nAccept);
  }else {
#  endif
    return (int)fwrite(cBuf, 1, nAccept, pfErr);
#  if CIO_WIN_WC_XLATE
  }
#  endif
}
# endif /* defined(CONSIO_EPUTB) */

SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){
  if( pfIn==0 ) pfIn = stdin;
# if CIO_WIN_WC_XLATE
  if( pfIn == consoleInfo.pstSetup[0].pf
      && (consoleInfo.sacSetup & SAC_InConsole)!=0 ){
#  if CIO_WIN_WC_XLATE==1
#   define SHELL_GULP 150 /* Count of WCHARS to be gulped at a time */
    WCHAR wcBuf[SHELL_GULP+1];
    int lend = 0, noc = 0;
    if( ncMax > 0 ) cBuf[0] = 0;
    while( noc < ncMax-8-1 && !lend ){
      /* There is room for at least 2 more characters and a 0-terminator. */
      int na = (ncMax > SHELL_GULP*4+1 + noc)? SHELL_GULP : (ncMax-1 - noc)/4;
#   undef SHELL_GULP
      DWORD nbr = 0;
      BOOL bRC = ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf, na, &nbr, 0);
      if( bRC && nbr>0 && (wcBuf[nbr-1]&0xF800)==0xD800 ){
        /* Last WHAR read is first of a UTF-16 surrogate pair. Grab its mate. */
        DWORD nbrx;
        bRC &= ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf+nbr, 1, &nbrx, 0);
        if( bRC ) nbr += nbrx;
      }
      if( !bRC || (noc==0 && nbr==0) ) return 0;
      if( nbr > 0 ){
        int nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,0,0,0,0);
        if( nmb != 0 && noc+nmb <= ncMax ){
          int iseg = noc;
          nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,cBuf+noc,nmb,0,0);
          noc += nmb;
          /* Fixup line-ends as coded by Windows for CR (or "Enter".)
          ** This is done without regard for any setMode{Text,Binary}()
          ** call that might have been done on the interactive input.
          */
          if( noc > 0 ){
            if( cBuf[noc-1]=='\n' ){
              lend = 1;
              if( noc > 1 && cBuf[noc-2]=='\r' ) cBuf[--noc-1] = '\n';
            }
          }
          /* Check for ^Z (anywhere in line) too, to act as EOF. */
          while( iseg < noc ){
            if( cBuf[iseg]=='\x1a' ){
              noc = iseg; /* Chop ^Z and anything following. */
              lend = 1; /* Counts as end of line too. */
              break;
            }
            ++iseg;
          }
        }else break; /* Drop apparent garbage in. (Could assert.) */
      }else break;
    }
    /* If got nothing, (after ^Z chop), must be at end-of-file. */
    if( noc > 0 ){
      cBuf[noc] = 0;
      return cBuf;
    }else return 0;
#  endif
  }else{
# endif
    return fgets(cBuf, ncMax, pfIn);
# if CIO_WIN_WC_XLATE
  }
# endif
}
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */

#if defined(_MSC_VER)
# pragma warning(default : 4204)
#endif

#undef SHELL_INVALID_FILE_PTR

/************************* End ../ext/consio/console_io.c ********************/

#ifndef SQLITE_SHELL_FIDDLE

/* From here onward, fgets() is redirected to the console_io library. */
# define fgets(b,n,f) fGetsUtf8(b,n,f)
/*
 * Define macros for emitting output text in various ways:
 *  sputz(s, z)      => emit 0-terminated string z to given stream s
 *  sputf(s, f, ...) => emit varargs per format f to given stream s
 *  oputz(z)         => emit 0-terminated string z to default stream
 *  oputf(f, ...)    => emit varargs per format f to default stream
 *  eputz(z)         => emit 0-terminated string z to error stream
 *  eputf(f, ...)    => emit varargs per format f to error stream
 *  oputb(b, n)      => emit char buffer b[0..n-1] to default stream
 *
 * Note that the default stream is whatever has been last set via:
 *   setOutputStream(FILE *pf)
 * This is normally the stream that CLI normal output goes to.
 * For the stand-alone CLI, it is stdout with no .output redirect.
 *
 * The ?putz(z) forms are required for the Fiddle builds for string literal
 * output, in aid of enforcing format string to argument correspondence.
 */
# define sputz(s,z) fPutsUtf8(z,s)
# define sputf fPrintfUtf8
# define oputz(z) oPutsUtf8(z)
# define oputf oPrintfUtf8
# define eputz(z) ePutsUtf8(z)
# define eputf ePrintfUtf8
# define oputb(buf,na) oPutbUtf8(buf,na)

#else
/* For Fiddle, all console handling and emit redirection is omitted. */
/* These next 3 macros are for emitting formatted output. When complaints
 * from the WASM build are issued for non-formatted output, (when a mere
 * string literal is to be emitted, the ?putz(z) forms should be used.
 * (This permits compile-time checking of format string / argument mismatch.)
 */
# define oputf(fmt, ...) printf(fmt,__VA_ARGS__)
# define eputf(fmt, ...) fprintf(stderr,fmt,__VA_ARGS__)
# define sputf(fp,fmt, ...) fprintf(fp,fmt,__VA_ARGS__)
/* These next 3 macros are for emitting simple string literals. */
# define oputz(z) fputs(z,stdout)
# define eputz(z) fputs(z,stderr)
# define sputz(fp,z) fputs(z,fp)
# define oputb(buf,na) fwrite(buf,1,na,stdout)
#endif

/* True if the timer is enabled */
static int enableTimer = 0;

/* A version of strcmp() that works with NULL values */
static int cli_strcmp(const char *a, const char *b){
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
** Print the timing results.
*/
static void endTimer(void){
  if( enableTimer ){
    sqlite3_int64 iEnd = timeOfDay();
    struct rusage sEnd;
    getrusage(RUSAGE_SELF, &sEnd);
    printf("Run Time: real %.3f user %f sys %f\n",
       (iEnd - iBegin)*0.001,
       timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
       timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
  }
}

#define BEGIN_TIMER beginTimer()
#define END_TIMER endTimer()
#define HAS_TIMER 1








|
|
|
|







1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
** Print the timing results.
*/
static void endTimer(void){
  if( enableTimer ){
    sqlite3_int64 iEnd = timeOfDay();
    struct rusage sEnd;
    getrusage(RUSAGE_SELF, &sEnd);
    sputf(stdout, "Run Time: real %.3f user %f sys %f\n",
          (iEnd - iBegin)*0.001,
          timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
          timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
  }
}

#define BEGIN_TIMER beginTimer()
#define END_TIMER endTimer()
#define HAS_TIMER 1

424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
** Print the timing results.
*/
static void endTimer(void){
  if( enableTimer && getProcessTimesAddr){
    FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
    sqlite3_int64 ftWallEnd = timeOfDay();
    getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
    printf("Run Time: real %.3f user %f sys %f\n",
       (ftWallEnd - ftWallBegin)*0.001,
       timeDiff(&ftUserBegin, &ftUserEnd),
       timeDiff(&ftKernelBegin, &ftKernelEnd));
  }
}

#define BEGIN_TIMER beginTimer()
#define END_TIMER endTimer()
#define HAS_TIMER hasTimer()








|
|
|
|







1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
** Print the timing results.
*/
static void endTimer(void){
  if( enableTimer && getProcessTimesAddr){
    FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
    sqlite3_int64 ftWallEnd = timeOfDay();
    getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
    sputf(stdout, "Run Time: real %.3f user %f sys %f\n",
          (ftWallEnd - ftWallBegin)*0.001,
          timeDiff(&ftUserBegin, &ftUserEnd),
          timeDiff(&ftKernelBegin, &ftKernelEnd));
  }
}

#define BEGIN_TIMER beginTimer()
#define END_TIMER endTimer()
#define HAS_TIMER hasTimer()

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
/*
** Treat stdin as an interactive input if the following variable
** is true.  Otherwise, assume stdin is connected to a file or pipe.
*/
static int stdin_is_interactive = 1;

/*
** If build is for non-RT Windows, without 3rd-party line editing,
** console input and output may be done in a UTF-8 compatible way,
** if the OS is capable of it and the --no-utf8 option is not seen.
*/
#if (defined(_WIN32) || defined(WIN32)) && SHELL_USE_LOCAL_GETLINE \
  && !defined(SHELL_OMIT_WIN_UTF8) && !SQLITE_OS_WINRT
# define SHELL_WIN_UTF8_OPT 1
/* Record whether to do UTF-8 console I/O translation per stream. */
  static int console_utf8_in = 0;
  static int console_utf8_out = 0;
/* Record whether can do UTF-8 or --no-utf8 seen in invocation. */
  static int mbcs_opted = 1; /* Assume cannot do until shown otherwise. */
#else
# define console_utf8_in 0
# define console_utf8_out 0
# define SHELL_WIN_UTF8_OPT 0
#endif

/*
** On Windows systems we have to know if standard output is a console
** in order to translate UTF-8 into MBCS.  The following variable is
** true if translation is required.
*/
static int stdout_is_console = 1;

/*
** The following is the open SQLite database.  We make a pointer
** to this database a static variable so that it can be accessed
** by the SIGINT handler to interrupt database processing.







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|







1477
1478
1479
1480
1481
1482
1483



















1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
/*
** Treat stdin as an interactive input if the following variable
** is true.  Otherwise, assume stdin is connected to a file or pipe.
*/
static int stdin_is_interactive = 1;

/*



















** On Windows systems we need to know if standard output is a console
** in order to show that UTF-16 translation is done in the sign-on
** banner. The following variable is true if it is the console.
*/
static int stdout_is_console = 1;

/*
** The following is the open SQLite database.  We make a pointer
** to this database a static variable so that it can be accessed
** by the SIGINT handler to interrupt database processing.
607
608
609
610
611
612
613
614

615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
        shell_strncpy(dynPrompt.dynamicPrompt, "(..", 4);
      }else if( dynPrompt.inParenLevel<0 ){
        shell_strncpy(dynPrompt.dynamicPrompt, ")x!", 4);
      }else{
        shell_strncpy(dynPrompt.dynamicPrompt, "(x.", 4);
        dynPrompt.dynamicPrompt[2] = (char)('0'+dynPrompt.inParenLevel);
      }
      shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, PROMPT_LEN_MAX-4);

    }
  }
  return dynPrompt.dynamicPrompt;
}
#endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */

#if SHELL_WIN_UTF8_OPT
/* Following struct is used for UTF-8 console I/O. */
static struct ConsoleState {
  int stdinEof;      /* EOF has been seen on console input */
  int infsMode;      /* Input file stream mode upon shell start */
  UINT inCodePage;   /* Input code page upon shell start */
  UINT outCodePage;  /* Output code page upon shell start */
  HANDLE hConsole;   /* Console input or output handle */
  DWORD consoleMode; /* Console mode upon shell start */
} conState = { 0, 0, 0, 0, INVALID_HANDLE_VALUE, 0 };

#ifndef _O_U16TEXT /* For build environments lacking this constant: */
# define _O_U16TEXT 0x20000
#endif

/*
** If given stream number is a console, return 1 and get some attributes,
** else return 0 and set the output attributes to invalid values.
*/
static short console_attrs(unsigned stnum, HANDLE *pH, DWORD *pConsMode){
  static int stid[3] = { STD_INPUT_HANDLE,STD_OUTPUT_HANDLE,STD_ERROR_HANDLE };
  HANDLE h;
  *pH = INVALID_HANDLE_VALUE;
  *pConsMode = 0;
  if( stnum > 2 ) return 0;
  h = GetStdHandle(stid[stnum]);
  if( h!=*pH && GetFileType(h)==FILE_TYPE_CHAR && GetConsoleMode(h,pConsMode) ){
    *pH = h;
    return 1;
  }
  return 0;
}

/*
** Perform a runtime test of Windows console to determine if it can
** do char-stream I/O correctly when the code page is set to CP_UTF8.
** Returns are: 1 => yes it can, 0 => no it cannot
**
** The console's output code page is momentarily set, then restored.
** So this should only be run when the process is given use of the
** console for either input or output.
*/
static short ConsoleDoesUTF8(void){
  UINT ocp = GetConsoleOutputCP();
  const char TrialUtf8[] = { '\xC8', '\xAB' }; /* "ȫ" or 2 MBCS characters */
  WCHAR aReadBack[1] = { 0 }; /* Read back as 0x022B when decoded as UTF-8. */
  CONSOLE_SCREEN_BUFFER_INFO csbInfo = {0};
  /* Create an inactive screen buffer with which to do the experiment. */
  HANDLE hCSB = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE, 0, 0,
                                          CONSOLE_TEXTMODE_BUFFER, NULL);
  if( hCSB!=INVALID_HANDLE_VALUE ){
    COORD cpos = {0,0};
    DWORD rbc;
    SetConsoleCursorPosition(hCSB, cpos);
    SetConsoleOutputCP(CP_UTF8);
    /* Write 2 chars which are a single character in UTF-8 but more in MBCS. */
    WriteConsoleA(hCSB, TrialUtf8, sizeof(TrialUtf8), NULL, NULL);
    ReadConsoleOutputCharacterW(hCSB, &aReadBack[0], 1, cpos, &rbc);
    GetConsoleScreenBufferInfo(hCSB, &csbInfo);
    SetConsoleOutputCP(ocp);
    CloseHandle(hCSB);
  }
  /* Return 1 if cursor advanced by 1 position, else 0. */
  return (short)(csbInfo.dwCursorPosition.X == 1 && aReadBack[0] == 0x022B);
}

static short in_console = 0;
static short out_console = 0;

/*
** Determine whether either normal I/O stream is the console,
** and whether it can do UTF-8 translation, setting globals
** in_console, out_console and mbcs_opted accordingly.
*/
static void probe_console(void){
  HANDLE h;
  DWORD cMode;
  in_console = console_attrs(0, &h, &cMode);
  out_console = console_attrs(1, &h, &cMode);
  if( in_console || out_console ) mbcs_opted = !ConsoleDoesUTF8();
}

/*
** If console is used for normal I/O, absent a --no-utf8 option,
** prepare console for UTF-8 input (from either typing or suitable
** paste operations) and/or for UTF-8 output rendering.
**
** The console state upon entry is preserved, in conState, so that
** console_restore() can later restore the same console state.
**
** The globals console_utf8_in and console_utf8_out are set, for
** later use in selecting UTF-8 or MBCS console I/O translations.
** This routine depends upon globals set by probe_console().
*/
static void console_prepare_utf8(void){
  struct ConsoleState csWork = { 0, 0, 0, 0, INVALID_HANDLE_VALUE, 0 };

  console_utf8_in = console_utf8_out = 0;
  if( (!in_console && !out_console) || mbcs_opted ) return;
  console_attrs((in_console)? 0 : 1, &conState.hConsole, &conState.consoleMode);
  conState.inCodePage = GetConsoleCP();
  conState.outCodePage = GetConsoleOutputCP();
  if( in_console ){
    SetConsoleCP(CP_UTF8);
    DWORD newConsoleMode = conState.consoleMode
      | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
    SetConsoleMode(conState.hConsole, newConsoleMode);
    conState.infsMode = _setmode(_fileno(stdin), _O_U16TEXT);
    console_utf8_in = 1;
  }
  if( out_console ){
    SetConsoleOutputCP(CP_UTF8);
    console_utf8_out = 1;
  }
}

/*
** Undo the effects of console_prepare_utf8(), if any.
*/
static void SQLITE_CDECL console_restore(void){
  if( (console_utf8_in||console_utf8_out)
      && conState.hConsole!=INVALID_HANDLE_VALUE ){
    if( console_utf8_in ){
      SetConsoleCP(conState.inCodePage);
      _setmode(_fileno(stdin), conState.infsMode);
    }
    if( console_utf8_out ) SetConsoleOutputCP(conState.outCodePage);
    SetConsoleMode(conState.hConsole, conState.consoleMode);
    /* Avoid multiple calls. */
    conState.hConsole = INVALID_HANDLE_VALUE;
    conState.consoleMode = 0;
    console_utf8_in = 0;
    console_utf8_out = 0;
  }
}

/*
** Collect input like fgets(...) with special provisions for input
** from the Windows console to get around its strange coding issues.
** Defers to plain fgets() when input is not interactive or when the
** UTF-8 input is unavailable or opted out.
*/
static char* utf8_fgets(char *buf, int ncmax, FILE *fin){
  if( fin==0 ) fin = stdin;
  if( fin==stdin && stdin_is_interactive && console_utf8_in ){
# define SQLITE_IALIM 150
    wchar_t wbuf[SQLITE_IALIM];
    int lend = 0;
    int noc = 0;
    if( ncmax==0 || conState.stdinEof ) return 0;
    buf[0] = 0;
    while( noc<ncmax-7-1 && !lend ){
      /* There is room for at least 2 more characters and a 0-terminator. */
      int na = (ncmax > SQLITE_IALIM*4+1 + noc)
        ? SQLITE_IALIM : (ncmax-1 - noc)/4;
# undef SQLITE_IALIM
      DWORD nbr = 0;
      BOOL bRC = ReadConsoleW(conState.hConsole, wbuf, na, &nbr, 0);
      if( !bRC || (noc==0 && nbr==0) ) return 0;
      if( nbr > 0 ){
        int nmb = WideCharToMultiByte(CP_UTF8,WC_COMPOSITECHECK|WC_DEFAULTCHAR,
                                      wbuf,nbr,0,0,0,0);
        if( nmb !=0 && noc+nmb <= ncmax ){
          int iseg = noc;
          nmb = WideCharToMultiByte(CP_UTF8,WC_COMPOSITECHECK|WC_DEFAULTCHAR,
                                    wbuf,nbr,buf+noc,nmb,0,0);
          noc += nmb;
          /* Fixup line-ends as coded by Windows for CR (or "Enter".)*/
          if( noc > 0 ){
            if( buf[noc-1]=='\n' ){
              lend = 1;
              if( noc > 1 && buf[noc-2]=='\r' ){
                buf[noc-2] = '\n';
                --noc;
              }
            }
          }
          /* Check for ^Z (anywhere in line) too. */
          while( iseg < noc ){
            if( buf[iseg]==0x1a ){
              conState.stdinEof = 1;
              noc = iseg; /* Chop ^Z and anything following. */
              break;
            }
            ++iseg;
          }
        }else break; /* Drop apparent garbage in. (Could assert.) */
      }else break;
    }
    /* If got nothing, (after ^Z chop), must be at end-of-file. */
    if( noc == 0 ) return 0;
    buf[noc] = 0;
    return buf;
  }else{
    return fgets(buf, ncmax, fin);
  }
}

# define fgets(b,n,f) utf8_fgets(b,n,f)
#endif /* SHELL_WIN_UTF8_OPT */

/*
** Render output like fprintf().  Except, if the output is going to the
** console and if this is running on a Windows machine, and if UTF-8
** output unavailable (or available but opted out), translate the
** output from UTF-8 into MBCS for output through 8-bit stdout stream.
** (Without -no-utf8, no translation is needed and must not be done.)
*/
#if defined(_WIN32) || defined(WIN32)
void utf8_printf(FILE *out, const char *zFormat, ...){
  va_list ap;
  va_start(ap, zFormat);
  if( stdout_is_console && (out==stdout || out==stderr) && !console_utf8_out ){
    char *z1 = sqlite3_vmprintf(zFormat, ap);
    char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
    sqlite3_free(z1);
    fputs(z2, out);
    sqlite3_free(z2);
  }else{
    vfprintf(out, zFormat, ap);
  }
  va_end(ap);
}
#elif !defined(utf8_printf)
# define utf8_printf fprintf
#endif

/*
** Render output like fprintf().  This should not be used on anything that
** includes string formatting (e.g. "%s").
*/
#if !defined(raw_printf)
# define raw_printf fprintf
#endif

/* Indicate out-of-memory and exit. */
static void shell_out_of_memory(void){
  raw_printf(stderr,"Error: out of memory\n");
  exit(1);
}

/* Check a pointer to see if it is NULL.  If it is NULL, exit with an
** out-of-memory error.
*/
static void shell_check_oom(const void *p){







|
>






<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|







1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615











































































































































































































































1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
        shell_strncpy(dynPrompt.dynamicPrompt, "(..", 4);
      }else if( dynPrompt.inParenLevel<0 ){
        shell_strncpy(dynPrompt.dynamicPrompt, ")x!", 4);
      }else{
        shell_strncpy(dynPrompt.dynamicPrompt, "(x.", 4);
        dynPrompt.dynamicPrompt[2] = (char)('0'+dynPrompt.inParenLevel);
      }
      shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3,
                    PROMPT_LEN_MAX-4);
    }
  }
  return dynPrompt.dynamicPrompt;
}
#endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */












































































































































































































































/* Indicate out-of-memory and exit. */
static void shell_out_of_memory(void){
  eputz("Error: out of memory\n");
  exit(1);
}

/* Check a pointer to see if it is NULL.  If it is NULL, exit with an
** out-of-memory error.
*/
static void shell_check_oom(const void *p){
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
  va_list ap;
  char *z;
  if( iotrace==0 ) return;
  va_start(ap, zFormat);
  z = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  utf8_printf(iotrace, "%s", z);
  sqlite3_free(z);
}
#endif

/*
** Output string zUtf to stream pOut as w characters.  If w is negative,
** then right-justify the text.  W is the width in UTF-8 characters, not
** in bytes.  This is different from the %*.*s specification in printf
** since with %*.*s the width is measured in bytes, not characters.
*/
static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
  int i;
  int n;
  int aw = w<0 ? -w : w;
  if( zUtf==0 ) zUtf = "";
  for(i=n=0; zUtf[i]; i++){
    if( (zUtf[i]&0xc0)!=0x80 ){
      n++;
      if( n==aw ){
        do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
        break;
      }
    }
  }
  if( n>=aw ){
    utf8_printf(pOut, "%.*s", i, zUtf);
  }else if( w<0 ){
    utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
  }else{
    utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
  }
}


/*
** Determines if a string is a number of not.
*/







|





|




|














|

|

|







1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
  va_list ap;
  char *z;
  if( iotrace==0 ) return;
  va_start(ap, zFormat);
  z = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  sputf(iotrace, "%s", z);
  sqlite3_free(z);
}
#endif

/*
** Output string zUtf to Out stream as w characters.  If w is negative,
** then right-justify the text.  W is the width in UTF-8 characters, not
** in bytes.  This is different from the %*.*s specification in printf
** since with %*.*s the width is measured in bytes, not characters.
*/
static void utf8_width_print(int w, const char *zUtf){
  int i;
  int n;
  int aw = w<0 ? -w : w;
  if( zUtf==0 ) zUtf = "";
  for(i=n=0; zUtf[i]; i++){
    if( (zUtf[i]&0xc0)!=0x80 ){
      n++;
      if( n==aw ){
        do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
        break;
      }
    }
  }
  if( n>=aw ){
    oputf("%.*s", i, zUtf);
  }else if( w<0 ){
    oputf("%*s%s", aw-n, "", zUtf);
  }else{
    oputf("%s%*s", zUtf, aw-n, "");
  }
}


/*
** Determines if a string is a number of not.
*/
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995

/*
** Return open FILE * if zFile exists, can be opened for read
** and is an ordinary file or a character stream source.
** Otherwise return 0.
*/
static FILE * openChrSource(const char *zFile){
#ifdef _WIN32
  struct _stat x = {0};
# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
  /* On Windows, open first, then check the stream nature. This order
  ** is necessary because _stat() and sibs, when checking a named pipe,
  ** effectively break the pipe as its supplier sees it. */
  FILE *rv = fopen(zFile, "rb");
  if( rv==0 ) return 0;
  if( _fstat(_fileno(rv), &x) != 0
      || !STAT_CHR_SRC(x.st_mode)){
    fclose(rv);
    rv = 0;
  }
  return rv;
#else
  struct stat x = {0};







|
|






|







1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755

/*
** Return open FILE * if zFile exists, can be opened for read
** and is an ordinary file or a character stream source.
** Otherwise return 0.
*/
static FILE * openChrSource(const char *zFile){
#if defined(_WIN32) || defined(WIN32)
  struct __stat64 x = {0};
# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
  /* On Windows, open first, then check the stream nature. This order
  ** is necessary because _stat() and sibs, when checking a named pipe,
  ** effectively break the pipe as its supplier sees it. */
  FILE *rv = fopen(zFile, "rb");
  if( rv==0 ) return 0;
  if( _fstat64(_fileno(rv), &x) != 0
      || !STAT_CHR_SRC(x.st_mode)){
    fclose(rv);
    rv = 0;
  }
  return rv;
#else
  struct stat x = {0};
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
    if( n>0 && zLine[n-1]=='\n' ){
      n--;
      if( n>0 && zLine[n-1]=='\r' ) n--;
      zLine[n] = 0;
      break;
    }
  }
#if defined(_WIN32) || defined(WIN32)
  /* For interactive input on Windows systems, with -no-utf8,
  ** translate the multi-byte characterset characters into UTF-8.
  ** This is the translation that predates console UTF-8 input. */
  if( stdin_is_interactive && in==stdin && !console_utf8_in ){
    char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
    if( zTrans ){
      i64 nTrans = strlen(zTrans)+1;
      if( nTrans>nLine ){
        zLine = realloc(zLine, nTrans);
        shell_check_oom(zLine);
      }
      memcpy(zLine, zTrans, nTrans);
      sqlite3_free(zTrans);
    }
  }
#endif /* defined(_WIN32) || defined(WIN32) */
  return zLine;
}

/*
** Retrieve a single line of input text.
**
** If in==0 then read from standard input and prompt before each line.







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1796
1797
1798
1799
1800
1801
1802

















1803
1804
1805
1806
1807
1808
1809
    if( n>0 && zLine[n-1]=='\n' ){
      n--;
      if( n>0 && zLine[n-1]=='\r' ) n--;
      zLine[n] = 0;
      break;
    }
  }

















  return zLine;
}

/*
** Retrieve a single line of input text.
**
** If in==0 then read from standard input and prompt before each line.
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
  char *zPrompt;
  char *zResult;
  if( in!=0 ){
    zResult = local_getline(zPrior, in);
  }else{
    zPrompt = isContinuation ? CONTINUATION_PROMPT : mainPrompt;
#if SHELL_USE_LOCAL_GETLINE
    printf("%s", zPrompt);
    fflush(stdout);
    do{
      zResult = local_getline(zPrior, stdin);
      zPrior = 0;
      /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */
      if( zResult==0 ) sqlite3_sleep(50);
    }while( zResult==0 && seenInterrupt>0 );







|







1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
  char *zPrompt;
  char *zResult;
  if( in!=0 ){
    zResult = local_getline(zPrior, in);
  }else{
    zPrompt = isContinuation ? CONTINUATION_PROMPT : mainPrompt;
#if SHELL_USE_LOCAL_GETLINE
    sputz(stdout, zPrompt);
    fflush(stdout);
    do{
      zResult = local_getline(zPrior, stdin);
      zPrior = 0;
      /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */
      if( zResult==0 ) sqlite3_sleep(50);
    }while( zResult==0 && seenInterrupt>0 );
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
  sqlite3_value **apVal
){
  double r = sqlite3_value_double(apVal[0]);
  int n = nVal>=2 ? sqlite3_value_int(apVal[1]) : 26;
  char z[400];
  if( n<1 ) n = 1;
  if( n>350 ) n = 350;
  snprintf(z, sizeof(z)-1, "%#+.*e", n, r);
  sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
}


/*
** SQL function:  shell_module_schema(X)
**







|







2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
  sqlite3_value **apVal
){
  double r = sqlite3_value_double(apVal[0]);
  int n = nVal>=2 ? sqlite3_value_int(apVal[1]) : 26;
  char z[400];
  if( n<1 ) n = 1;
  if( n>350 ) n = 350;
  sqlite3_snprintf(sizeof(z), z, "%#+.*e", n, r);
  sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
}


/*
** SQL function:  shell_module_schema(X)
**
4984
4985
4986
4987
4988
4989
4990
4991

4992
4993

4994


4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007

#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Return that member of a generate_series(...) sequence whose 0-based
** index is ix. The 0th member is given by smBase. The sequence members
** progress per ix increment by smStep.
*/
static sqlite3_int64 genSeqMember(sqlite3_int64 smBase,

                                  sqlite3_int64 smStep,
                                  sqlite3_uint64 ix){

  if( ix>=(sqlite3_uint64)LLONG_MAX ){


    /* Get ix into signed i64 range. */
    ix -= (sqlite3_uint64)LLONG_MAX;
    /* With 2's complement ALU, this next can be 1 step, but is split into
     * 2 for UBSAN's satisfaction (and hypothetical 1's complement ALUs.) */
    smBase += (LLONG_MAX/2) * smStep;
    smBase += (LLONG_MAX - LLONG_MAX/2) * smStep;
  }
  /* Under UBSAN (or on 1's complement machines), must do this last term
   * in steps to avoid the dreaded (and harmless) signed multiply overlow. */
  if( ix>=2 ){
    sqlite3_int64 ix2 = (sqlite3_int64)ix/2;
    smBase += ix2*smStep;
    ix -= ix2;







|
>
|
|
>
|
>
>

|


|
|







5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754

#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Return that member of a generate_series(...) sequence whose 0-based
** index is ix. The 0th member is given by smBase. The sequence members
** progress per ix increment by smStep.
*/
static sqlite3_int64 genSeqMember(
  sqlite3_int64 smBase,
  sqlite3_int64 smStep,
  sqlite3_uint64 ix
){
  static const sqlite3_uint64 mxI64 =
      ((sqlite3_uint64)0x7fffffff)<<32 | 0xffffffff;
  if( ix>=mxI64 ){
    /* Get ix into signed i64 range. */
    ix -= mxI64;
    /* With 2's complement ALU, this next can be 1 step, but is split into
     * 2 for UBSAN's satisfaction (and hypothetical 1's complement ALUs.) */
    smBase += (mxI64/2) * smStep;
    smBase += (mxI64 - mxI64/2) * smStep;
  }
  /* Under UBSAN (or on 1's complement machines), must do this last term
   * in steps to avoid the dreaded (and harmless) signed multiply overlow. */
  if( ix>=2 ){
    sqlite3_int64 ix2 = (sqlite3_int64)ix/2;
    smBase += ix2*smStep;
    ix -= ix2;
13057
13058
13059
13060
13061
13062
13063
13064
13065
13066
13067
13068
13069
13070
13071
#endif

  /* Copy the entire schema of database [db] into [dbm]. */
  if( rc==SQLITE_OK ){
    sqlite3_stmt *pSql = 0;
    rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, 
        "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
        " AND sql NOT LIKE 'CREATE VIRTUAL %%'"
    );
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
      const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
      if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
    }
    idxFinalize(&rc, pSql);
  }







|







13804
13805
13806
13807
13808
13809
13810
13811
13812
13813
13814
13815
13816
13817
13818
#endif

  /* Copy the entire schema of database [db] into [dbm]. */
  if( rc==SQLITE_OK ){
    sqlite3_stmt *pSql = 0;
    rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, 
        "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
        " AND sql NOT LIKE 'CREATE VIRTUAL %%' ORDER BY rowid"
    );
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
      const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
      if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
    }
    idxFinalize(&rc, pSql);
  }
13258
13259
13260
13261
13262
13263
13264






























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































13265
13266
13267
13268
13269
13270
13271
    sqlite3_free(p);
  }
}

#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */

/************************* End ../ext/expert/sqlite3expert.c ********************/































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
#define SQLITE_SHELL_HAVE_RECOVER 1
#else
#define SQLITE_SHELL_HAVE_RECOVER 0
#endif
#if SQLITE_SHELL_HAVE_RECOVER







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







14005
14006
14007
14008
14009
14010
14011
14012
14013
14014
14015
14016
14017
14018
14019
14020
14021
14022
14023
14024
14025
14026
14027
14028
14029
14030
14031
14032
14033
14034
14035
14036
14037
14038
14039
14040
14041
14042
14043
14044
14045
14046
14047
14048
14049
14050
14051
14052
14053
14054
14055
14056
14057
14058
14059
14060
14061
14062
14063
14064
14065
14066
14067
14068
14069
14070
14071
14072
14073
14074
14075
14076
14077
14078
14079
14080
14081
14082
14083
14084
14085
14086
14087
14088
14089
14090
14091
14092
14093
14094
14095
14096
14097
14098
14099
14100
14101
14102
14103
14104
14105
14106
14107
14108
14109
14110
14111
14112
14113
14114
14115
14116
14117
14118
14119
14120
14121
14122
14123
14124
14125
14126
14127
14128
14129
14130
14131
14132
14133
14134
14135
14136
14137
14138
14139
14140
14141
14142
14143
14144
14145
14146
14147
14148
14149
14150
14151
14152
14153
14154
14155
14156
14157
14158
14159
14160
14161
14162
14163
14164
14165
14166
14167
14168
14169
14170
14171
14172
14173
14174
14175
14176
14177
14178
14179
14180
14181
14182
14183
14184
14185
14186
14187
14188
14189
14190
14191
14192
14193
14194
14195
14196
14197
14198
14199
14200
14201
14202
14203
14204
14205
14206
14207
14208
14209
14210
14211
14212
14213
14214
14215
14216
14217
14218
14219
14220
14221
14222
14223
14224
14225
14226
14227
14228
14229
14230
14231
14232
14233
14234
14235
14236
14237
14238
14239
14240
14241
14242
14243
14244
14245
14246
14247
14248
14249
14250
14251
14252
14253
14254
14255
14256
14257
14258
14259
14260
14261
14262
14263
14264
14265
14266
14267
14268
14269
14270
14271
14272
14273
14274
14275
14276
14277
14278
14279
14280
14281
14282
14283
14284
14285
14286
14287
14288
14289
14290
14291
14292
14293
14294
14295
14296
14297
14298
14299
14300
14301
14302
14303
14304
14305
14306
14307
14308
14309
14310
14311
14312
14313
14314
14315
14316
14317
14318
14319
14320
14321
14322
14323
14324
14325
14326
14327
14328
14329
14330
14331
14332
14333
14334
14335
14336
14337
14338
14339
14340
14341
14342
14343
14344
14345
14346
14347
14348
14349
14350
14351
14352
14353
14354
14355
14356
14357
14358
14359
14360
14361
14362
14363
14364
14365
14366
14367
14368
14369
14370
14371
14372
14373
14374
14375
14376
14377
14378
14379
14380
14381
14382
14383
14384
14385
14386
14387
14388
14389
14390
14391
14392
14393
14394
14395
14396
14397
14398
14399
14400
14401
14402
14403
14404
14405
14406
14407
14408
14409
14410
14411
14412
14413
14414
14415
14416
14417
14418
14419
14420
14421
14422
14423
14424
14425
14426
14427
14428
14429
14430
14431
14432
14433
14434
14435
14436
14437
14438
14439
14440
14441
14442
14443
14444
14445
14446
14447
14448
14449
14450
14451
14452
14453
14454
14455
14456
14457
14458
14459
14460
14461
14462
14463
14464
14465
14466
14467
14468
14469
14470
14471
14472
14473
14474
14475
14476
14477
14478
14479
14480
14481
14482
14483
14484
14485
14486
14487
14488
14489
14490
14491
14492
14493
14494
14495
14496
14497
14498
14499
14500
14501
14502
14503
14504
14505
14506
14507
14508
14509
14510
14511
14512
14513
14514
14515
14516
14517
14518
14519
14520
14521
14522
14523
14524
14525
14526
14527
14528
14529
14530
14531
14532
14533
14534
14535
14536
14537
14538
14539
14540
14541
14542
14543
14544
14545
14546
14547
14548
14549
14550
14551
14552
14553
14554
14555
14556
14557
14558
14559
14560
14561
14562
14563
14564
14565
14566
14567
14568
14569
14570
14571
14572
14573
14574
14575
14576
14577
14578
14579
14580
14581
14582
14583
14584
14585
14586
14587
14588
14589
14590
14591
14592
14593
14594
14595
14596
14597
14598
14599
14600
14601
14602
14603
14604
14605
14606
14607
14608
14609
14610
14611
14612
14613
14614
14615
14616
14617
14618
14619
14620
14621
14622
14623
14624
14625
14626
14627
14628
14629
14630
14631
14632
14633
14634
14635
14636
14637
14638
14639
14640
14641
14642
14643
14644
14645
14646
14647
14648
14649
14650
14651
14652
14653
14654
14655
14656
14657
14658
14659
14660
14661
14662
14663
14664
14665
14666
14667
14668
14669
14670
14671
14672
14673
14674
14675
14676
14677
14678
14679
14680
14681
14682
14683
14684
14685
14686
14687
14688
14689
14690
14691
14692
14693
14694
14695
14696
14697
14698
14699
14700
14701
14702
14703
14704
14705
14706
14707
14708
14709
14710
14711
14712
14713
14714
14715
14716
14717
14718
14719
14720
14721
14722
14723
14724
14725
14726
14727
14728
14729
14730
14731
14732
14733
14734
14735
14736
14737
14738
14739
14740
14741
14742
14743
14744
14745
14746
14747
14748
14749
14750
14751
14752
14753
14754
14755
14756
14757
14758
14759
14760
14761
14762
14763
14764
14765
14766
14767
14768
14769
14770
14771
14772
14773
14774
14775
14776
14777
14778
14779
14780
14781
14782
14783
14784
14785
14786
14787
14788
14789
14790
14791
14792
14793
14794
14795
14796
14797
14798
14799
14800
14801
14802
14803
14804
14805
14806
14807
14808
14809
14810
14811
14812
14813
14814
14815
14816
14817
14818
14819
14820
14821
14822
14823
14824
14825
14826
14827
14828
14829
14830
14831
14832
14833
14834
14835
14836
14837
14838
14839
14840
14841
14842
14843
14844
14845
14846
14847
14848
14849
14850
14851
14852
14853
14854
14855
14856
14857
14858
14859
14860
14861
14862
14863
14864
14865
14866
14867
14868
14869
14870
14871
14872
14873
14874
14875
14876
14877
14878
14879
14880
14881
14882
14883
14884
14885
14886
14887
14888
14889
14890
14891
14892
14893
14894
14895
14896
14897
14898
14899
14900
14901
14902
14903
14904
14905
14906
14907
14908
14909
14910
14911
14912
14913
14914
14915
14916
14917
14918
14919
14920
14921
14922
14923
14924
14925
14926
14927
14928
14929
14930
14931
14932
14933
14934
14935
14936
14937
14938
14939
14940
14941
14942
14943
14944
14945
14946
14947
14948
14949
14950
14951
14952
14953
14954
14955
14956
14957
14958
14959
14960
14961
14962
14963
14964
14965
14966
14967
14968
14969
14970
14971
14972
14973
14974
14975
14976
14977
14978
14979
14980
14981
14982
14983
14984
14985
14986
14987
14988
14989
14990
14991
14992
14993
14994
14995
14996
14997
14998
14999
15000
15001
15002
15003
15004
15005
15006
15007
15008
15009
15010
15011
15012
15013
15014
15015
15016
15017
15018
15019
15020
15021
15022
15023
15024
15025
15026
15027
15028
15029
15030
15031
15032
15033
15034
15035
15036
15037
15038
15039
15040
15041
15042
15043
15044
15045
15046
15047
15048
15049
15050
15051
15052
15053
15054
15055
15056
15057
15058
15059
15060
15061
15062
15063
15064
15065
15066
15067
15068
15069
15070
15071
15072
15073
15074
15075
15076
15077
15078
15079
15080
15081
15082
15083
15084
15085
15086
15087
15088
15089
15090
15091
15092
15093
15094
15095
15096
15097
15098
15099
15100
15101
15102
15103
15104
15105
15106
15107
15108
15109
15110
15111
15112
15113
15114
15115
15116
15117
15118
15119
15120
15121
15122
15123
15124
15125
15126
15127
15128
15129
15130
15131
15132
15133
15134
15135
15136
    sqlite3_free(p);
  }
}

#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */

/************************* End ../ext/expert/sqlite3expert.c ********************/

/************************* Begin ../ext/intck/sqlite3intck.h ******************/
/*
** 2024-02-08
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
*/

/*
** Incremental Integrity-Check Extension
** -------------------------------------
**
** This module contains code to check whether or not an SQLite database
** is well-formed or corrupt. This is the same task as performed by SQLite's
** built-in "PRAGMA integrity_check" command. This module differs from
** "PRAGMA integrity_check" in that:
**
**   +  It is less thorough - this module does not detect certain types
**      of corruption that are detected by the PRAGMA command. However,
**      it does detect all kinds of corruption that are likely to cause
**      errors in SQLite applications.
**
**   +  It is slower. Sometimes up to three times slower.
**
**   +  It allows integrity-check operations to be split into multiple
**      transactions, so that the database does not need to be read-locked
**      for the duration of the integrity-check.
**
** One way to use the API to run integrity-check on the "main" database
** of handle db is:
**
**   int rc = SQLITE_OK;
**   sqlite3_intck *p = 0;
**
**   sqlite3_intck_open(db, "main", &p);
**   while( SQLITE_OK==sqlite3_intck_step(p) ){
**     const char *zMsg = sqlite3_intck_message(p);
**     if( zMsg ) printf("corruption: %s\n", zMsg);
**   }
**   rc = sqlite3_intck_error(p, &zErr);
**   if( rc!=SQLITE_OK ){
**     printf("error occured (rc=%d), (errmsg=%s)\n", rc, zErr);
**   }
**   sqlite3_intck_close(p);
**
** Usually, the sqlite3_intck object opens a read transaction within the
** first call to sqlite3_intck_step() and holds it open until the 
** integrity-check is complete. However, if sqlite3_intck_unlock() is
** called, the read transaction is ended and a new read transaction opened
** by the subsequent call to sqlite3_intck_step().
*/

#ifndef _SQLITE_INTCK_H
#define _SQLITE_INTCK_H

/* #include "sqlite3.h" */

#ifdef __cplusplus
extern "C" {
#endif

/*
** An ongoing incremental integrity-check operation is represented by an
** opaque pointer of the following type.
*/
typedef struct sqlite3_intck sqlite3_intck;

/*
** Open a new incremental integrity-check object. If successful, populate
** output variable (*ppOut) with the new object handle and return SQLITE_OK.
** Or, if an error occurs, set (*ppOut) to NULL and return an SQLite error
** code (e.g. SQLITE_NOMEM).
**
** The integrity-check will be conducted on database zDb (which must be "main",
** "temp", or the name of an attached database) of database handle db. Once
** this function has been called successfully, the caller should not use 
** database handle db until the integrity-check object has been destroyed
** using sqlite3_intck_close().
*/
int sqlite3_intck_open(
  sqlite3 *db,                    /* Database handle */
  const char *zDb,                /* Database name ("main", "temp" etc.) */
  sqlite3_intck **ppOut           /* OUT: New sqlite3_intck handle */
);

/*
** Close and release all resources associated with a handle opened by an
** earlier call to sqlite3_intck_open(). The results of using an
** integrity-check handle after it has been passed to this function are
** undefined.
*/
void sqlite3_intck_close(sqlite3_intck *pCk);

/*
** Do the next step of the integrity-check operation specified by the handle
** passed as the only argument. This function returns SQLITE_DONE if the 
** integrity-check operation is finished, or an SQLite error code if
** an error occurs, or SQLITE_OK if no error occurs but the integrity-check
** is not finished. It is not considered an error if database corruption
** is encountered.
**
** Following a successful call to sqlite3_intck_step() (one that returns
** SQLITE_OK), sqlite3_intck_message() returns a non-NULL value if 
** corruption was detected in the db.
**
** If an error occurs and a value other than SQLITE_OK or SQLITE_DONE is
** returned, then the integrity-check handle is placed in an error state.
** In this state all subsequent calls to sqlite3_intck_step() or 
** sqlite3_intck_unlock() will immediately return the same error. The 
** sqlite3_intck_error() method may be used to obtain an English language 
** error message in this case.
*/
int sqlite3_intck_step(sqlite3_intck *pCk);

/*
** If the previous call to sqlite3_intck_step() encountered corruption 
** within the database, then this function returns a pointer to a buffer
** containing a nul-terminated string describing the corruption in 
** English. If the previous call to sqlite3_intck_step() did not encounter
** corruption, or if there was no previous call, this function returns 
** NULL.
*/
const char *sqlite3_intck_message(sqlite3_intck *pCk);

/*
** Close any read-transaction opened by an earlier call to 
** sqlite3_intck_step(). Any subsequent call to sqlite3_intck_step() will
** open a new transaction. Return SQLITE_OK if successful, or an SQLite error
** code otherwise.
**
** If an error occurs, then the integrity-check handle is placed in an error
** state. In this state all subsequent calls to sqlite3_intck_step() or 
** sqlite3_intck_unlock() will immediately return the same error. The 
** sqlite3_intck_error() method may be used to obtain an English language 
** error message in this case.
*/
int sqlite3_intck_unlock(sqlite3_intck *pCk);

/*
** If an error has occurred in an earlier call to sqlite3_intck_step()
** or sqlite3_intck_unlock(), then this method returns the associated 
** SQLite error code. Additionally, if pzErr is not NULL, then (*pzErr)
** may be set to point to a nul-terminated string containing an English
** language error message. Or, if no error message is available, to
** NULL.
**
** If no error has occurred within sqlite3_intck_step() or
** sqlite_intck_unlock() calls on the handle passed as the first argument, 
** then SQLITE_OK is returned and (*pzErr) set to NULL.
*/
int sqlite3_intck_error(sqlite3_intck *pCk, const char **pzErr);

/*
** This API is used for testing only. It returns the full-text of an SQL
** statement used to test object zObj, which may be a table or index.
** The returned buffer is valid until the next call to either this function
** or sqlite3_intck_close() on the same sqlite3_intck handle.
*/
const char *sqlite3_intck_test_sql(sqlite3_intck *pCk, const char *zObj);


#ifdef __cplusplus
}  /* end of the 'extern "C"' block */
#endif

#endif /* ifndef _SQLITE_INTCK_H */

/************************* End ../ext/intck/sqlite3intck.h ********************/
/************************* Begin ../ext/intck/sqlite3intck.c ******************/
/*
** 2024-02-08
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
*/

/* #include "sqlite3intck.h" */
#include <string.h>
#include <assert.h>

#include <stdio.h>
#include <stdlib.h>

/*
** nKeyVal:
**   The number of values that make up the 'key' for the current pCheck
**   statement.
**
** rc:
**   Error code returned by most recent sqlite3_intck_step() or 
**   sqlite3_intck_unlock() call. This is set to SQLITE_DONE when
**   the integrity-check operation is finished.
**
** zErr:
**   If the object has entered the error state, this is the error message.
**   Is freed using sqlite3_free() when the object is deleted.
**
** zTestSql:
**   The value returned by the most recent call to sqlite3_intck_testsql().
**   Each call to testsql() frees the previous zTestSql value (using
**   sqlite3_free()) and replaces it with the new value it will return.
*/
struct sqlite3_intck {
  sqlite3 *db;
  const char *zDb;                /* Copy of zDb parameter to _open() */
  char *zObj;                     /* Current object. Or NULL. */

  sqlite3_stmt *pCheck;           /* Current check statement */
  char *zKey;
  int nKeyVal;

  char *zMessage;
  int bCorruptSchema;

  int rc;                         /* Error code */
  char *zErr;                     /* Error message */
  char *zTestSql;                 /* Returned by sqlite3_intck_test_sql() */
};


/*
** Some error has occurred while using database p->db. Save the error message
** and error code currently held by the database handle in p->rc and p->zErr.
*/
static void intckSaveErrmsg(sqlite3_intck *p){
  p->rc = sqlite3_errcode(p->db);
  sqlite3_free(p->zErr);
  p->zErr = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
}

/*
** If the handle passed as the first argument is already in the error state,
** then this function is a no-op (returns NULL immediately). Otherwise, if an
** error occurs within this function, it leaves an error in said handle.
**
** Otherwise, this function attempts to prepare SQL statement zSql and
** return the resulting statement handle to the user.
*/
static sqlite3_stmt *intckPrepare(sqlite3_intck *p, const char *zSql){
  sqlite3_stmt *pRet = 0;
  if( p->rc==SQLITE_OK ){
    p->rc = sqlite3_prepare_v2(p->db, zSql, -1, &pRet, 0);
    if( p->rc!=SQLITE_OK ){
      intckSaveErrmsg(p);
      assert( pRet==0 );
    }
  }
  return pRet;
}

/*
** If the handle passed as the first argument is already in the error state,
** then this function is a no-op (returns NULL immediately). Otherwise, if an
** error occurs within this function, it leaves an error in said handle.
**
** Otherwise, this function treats argument zFmt as a printf() style format
** string. It formats it according to the trailing arguments and then 
** attempts to prepare the results and return the resulting prepared
** statement.
*/
static sqlite3_stmt *intckPrepareFmt(sqlite3_intck *p, const char *zFmt, ...){
  sqlite3_stmt *pRet = 0;
  va_list ap;
  char *zSql = 0;
  va_start(ap, zFmt);
  zSql = sqlite3_vmprintf(zFmt, ap);
  if( p->rc==SQLITE_OK && zSql==0 ){
    p->rc = SQLITE_NOMEM;
  }
  pRet = intckPrepare(p, zSql);
  sqlite3_free(zSql);
  va_end(ap);
  return pRet;
}

/*
** Finalize SQL statement pStmt. If an error occurs and the handle passed
** as the first argument does not already contain an error, store the
** error in the handle.
*/
static void intckFinalize(sqlite3_intck *p, sqlite3_stmt *pStmt){
  int rc = sqlite3_finalize(pStmt);
  if( p->rc==SQLITE_OK && rc!=SQLITE_OK ){
    intckSaveErrmsg(p);
  }
}

/*
** If there is already an error in handle p, return it. Otherwise, call
** sqlite3_step() on the statement handle and return that value.
*/
static int intckStep(sqlite3_intck *p, sqlite3_stmt *pStmt){
  if( p->rc ) return p->rc;
  return sqlite3_step(pStmt);
}

/*
** Execute SQL statement zSql. There is no way to obtain any results 
** returned by the statement. This function uses the sqlite3_intck error
** code convention.
*/
static void intckExec(sqlite3_intck *p, const char *zSql){
  sqlite3_stmt *pStmt = 0;
  pStmt = intckPrepare(p, zSql);
  intckStep(p, pStmt);
  intckFinalize(p, pStmt);
}

/*
** A wrapper around sqlite3_mprintf() that uses the sqlite3_intck error
** code convention.
*/
static char *intckMprintf(sqlite3_intck *p, const char *zFmt, ...){
  va_list ap;
  char *zRet = 0;
  va_start(ap, zFmt);
  zRet = sqlite3_vmprintf(zFmt, ap);
  if( p->rc==SQLITE_OK ){
    if( zRet==0 ){
      p->rc = SQLITE_NOMEM;
    }
  }else{
    sqlite3_free(zRet);
    zRet = 0;
  }
  return zRet;
}

/*
** This is used by sqlite3_intck_unlock() to save the vector key value 
** required to restart the current pCheck query as a nul-terminated string 
** in p->zKey.
*/
static void intckSaveKey(sqlite3_intck *p){
  int ii;
  char *zSql = 0;
  sqlite3_stmt *pStmt = 0;
  sqlite3_stmt *pXinfo = 0;
  const char *zDir = 0;

  assert( p->pCheck );
  assert( p->zKey==0 );

  pXinfo = intckPrepareFmt(p, 
      "SELECT group_concat(desc, '') FROM %Q.sqlite_schema s, "
      "pragma_index_xinfo(%Q, %Q) "
      "WHERE s.type='index' AND s.name=%Q",
      p->zDb, p->zObj, p->zDb, p->zObj
  );
  if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXinfo) ){
    zDir = (const char*)sqlite3_column_text(pXinfo, 0);
  }

  if( zDir==0 ){
    /* Object is a table, not an index. This is the easy case,as there are 
    ** no DESC columns or NULL values in a primary key.  */
    const char *zSep = "SELECT '(' || ";
    for(ii=0; ii<p->nKeyVal; ii++){
      zSql = intckMprintf(p, "%z%squote(?)", zSql, zSep);
      zSep = " || ', ' || ";
    }
    zSql = intckMprintf(p, "%z || ')'", zSql);
  }else{

    /* Object is an index. */
    assert( p->nKeyVal>1 );
    for(ii=p->nKeyVal; ii>0; ii--){
      int bLastIsDesc = zDir[ii-1]=='1';
      int bLastIsNull = sqlite3_column_type(p->pCheck, ii)==SQLITE_NULL;
      const char *zLast = sqlite3_column_name(p->pCheck, ii);
      char *zLhs = 0;
      char *zRhs = 0;
      char *zWhere = 0;

      if( bLastIsNull ){
        if( bLastIsDesc ) continue;
        zWhere = intckMprintf(p, "'%s IS NOT NULL'", zLast);
      }else{
        const char *zOp = bLastIsDesc ? "<" : ">";
        zWhere = intckMprintf(p, "'%s %s ' || quote(?%d)", zLast, zOp, ii);
      }

      if( ii>1 ){
        const char *zLhsSep = "";
        const char *zRhsSep = "";
        int jj;
        for(jj=0; jj<ii-1; jj++){
          const char *zAlias = (const char*)sqlite3_column_name(p->pCheck,jj+1);
          zLhs = intckMprintf(p, "%z%s%s", zLhs, zLhsSep, zAlias);
          zRhs = intckMprintf(p, "%z%squote(?%d)", zRhs, zRhsSep, jj+1);
          zLhsSep = ",";
          zRhsSep = " || ',' || ";
        }

        zWhere = intckMprintf(p, 
            "'(%z) IS (' || %z || ') AND ' || %z",
            zLhs, zRhs, zWhere);
      }
      zWhere = intckMprintf(p, "'WHERE ' || %z", zWhere);

      zSql = intckMprintf(p, "%z%s(quote( %z ) )",
          zSql,
          (zSql==0 ? "VALUES" : ",\n      "),
          zWhere
      );
    }
    zSql = intckMprintf(p, 
        "WITH wc(q) AS (\n%z\n)"
        "SELECT 'VALUES' || group_concat('(' || q || ')', ',\n      ') FROM wc"
        , zSql
    );
  }

  pStmt = intckPrepare(p, zSql);
  if( p->rc==SQLITE_OK ){
    for(ii=0; ii<p->nKeyVal; ii++){
      sqlite3_bind_value(pStmt, ii+1, sqlite3_column_value(p->pCheck, ii+1));
    }
    if( SQLITE_ROW==sqlite3_step(pStmt) ){
      p->zKey = intckMprintf(p,"%s",(const char*)sqlite3_column_text(pStmt, 0));
    }
    intckFinalize(p, pStmt);
  }

  sqlite3_free(zSql);
  intckFinalize(p, pXinfo);
}

/*
** Find the next database object (table or index) to check. If successful,
** set sqlite3_intck.zObj to point to a nul-terminated buffer containing
** the object's name before returning.
*/
static void intckFindObject(sqlite3_intck *p){
  sqlite3_stmt *pStmt = 0;
  char *zPrev = p->zObj;
  p->zObj = 0;

  assert( p->rc==SQLITE_OK );
  assert( p->pCheck==0 );

  pStmt = intckPrepareFmt(p, 
    "WITH tables(table_name) AS (" 
    "  SELECT name"
    "  FROM %Q.sqlite_schema WHERE (type='table' OR type='index') AND rootpage"
    "  UNION ALL "
    "  SELECT 'sqlite_schema'"
    ")"
    "SELECT table_name FROM tables "
    "WHERE ?1 IS NULL OR table_name%s?1 "
    "ORDER BY 1"
    , p->zDb, (p->zKey ? ">=" : ">")
  );

  if( p->rc==SQLITE_OK ){
    sqlite3_bind_text(pStmt, 1, zPrev, -1, SQLITE_TRANSIENT);
    if( sqlite3_step(pStmt)==SQLITE_ROW ){
      p->zObj = intckMprintf(p,"%s",(const char*)sqlite3_column_text(pStmt, 0));
    }
  }
  intckFinalize(p, pStmt);

  /* If this is a new object, ensure the previous key value is cleared. */
  if( sqlite3_stricmp(p->zObj, zPrev) ){
    sqlite3_free(p->zKey);
    p->zKey = 0;
  }

  sqlite3_free(zPrev);
}

/*
** Return the size in bytes of the first token in nul-terminated buffer z.
** For the purposes of this call, a token is either:
**
**   *  a quoted SQL string,
*    *  a contiguous series of ascii alphabet characters, or
*    *  any other single byte.
*/
static int intckGetToken(const char *z){
  char c = z[0];
  int iRet = 1;
  if( c=='\'' || c=='"' || c=='`' ){
    while( 1 ){
      if( z[iRet]==c ){
        iRet++;
        if( z[iRet]!=c ) break;
      }
      iRet++;
    }
  }
  else if( c=='[' ){
    while( z[iRet++]!=']' && z[iRet] );
  }
  else if( (c>='A' && c<='Z') || (c>='a' && c<='z') ){
    while( (z[iRet]>='A' && z[iRet]<='Z') || (z[iRet]>='a' && z[iRet]<='z') ){
      iRet++;
    }
  }

  return iRet;
}

/*
** Return true if argument c is an ascii whitespace character.
*/
static int intckIsSpace(char c){
  return (c==' ' || c=='\t' || c=='\n' || c=='\r');
}

/*
** Argument z points to the text of a CREATE INDEX statement. This function
** identifies the part of the text that contains either the index WHERE 
** clause (if iCol<0) or the iCol'th column of the index.
**
** If (iCol<0), the identified fragment does not include the "WHERE" keyword,
** only the expression that follows it. If (iCol>=0) then the identified
** fragment does not include any trailing sort-order keywords - "ASC" or 
** "DESC".
**
** If the CREATE INDEX statement does not contain the requested field or
** clause, NULL is returned and (*pnByte) is set to 0. Otherwise, a pointer to
** the identified fragment is returned and output parameter (*pnByte) set
** to its size in bytes.
*/
static const char *intckParseCreateIndex(const char *z, int iCol, int *pnByte){
  int iOff = 0;
  int iThisCol = 0;
  int iStart = 0;
  int nOpen = 0;

  const char *zRet = 0;
  int nRet = 0;

  int iEndOfCol = 0;

  /* Skip forward until the first "(" token */
  while( z[iOff]!='(' ){
    iOff += intckGetToken(&z[iOff]);
    if( z[iOff]=='\0' ) return 0;
  }
  assert( z[iOff]=='(' );

  nOpen = 1;
  iOff++;
  iStart = iOff;
  while( z[iOff] ){
    const char *zToken = &z[iOff];
    int nToken = 0;

    /* Check if this is the end of the current column - either a "," or ")"
    ** when nOpen==1.  */
    if( nOpen==1 ){
      if( z[iOff]==',' || z[iOff]==')' ){
        if( iCol==iThisCol ){
          int iEnd = iEndOfCol ? iEndOfCol : iOff;
          nRet = (iEnd - iStart);
          zRet = &z[iStart];
          break;
        }
        iStart = iOff+1;
        while( intckIsSpace(z[iStart]) ) iStart++;
        iThisCol++;
      }
      if( z[iOff]==')' ) break;
    }
    if( z[iOff]=='(' ) nOpen++;
    if( z[iOff]==')' ) nOpen--;
    nToken = intckGetToken(zToken);

    if( (nToken==3 && 0==sqlite3_strnicmp(zToken, "ASC", nToken))
     || (nToken==4 && 0==sqlite3_strnicmp(zToken, "DESC", nToken))
    ){
      iEndOfCol = iOff;
    }else if( 0==intckIsSpace(zToken[0]) ){
      iEndOfCol = 0;
    }

    iOff += nToken;
  }

  /* iStart is now the byte offset of 1 byte passed the final ')' in the
  ** CREATE INDEX statement. Try to find a WHERE clause to return.  */
  while( zRet==0 && z[iOff] ){
    int n = intckGetToken(&z[iOff]);
    if( n==5 && 0==sqlite3_strnicmp(&z[iOff], "where", 5) ){
      zRet = &z[iOff+5];
      nRet = (int)strlen(zRet);
    }
    iOff += n;
  }

  /* Trim any whitespace from the start and end of the returned string. */
  if( zRet ){
    while( intckIsSpace(zRet[0]) ){
      nRet--;
      zRet++;
    }
    while( nRet>0 && intckIsSpace(zRet[nRet-1]) ) nRet--;
  }

  *pnByte = nRet;
  return zRet;
}

/*
** User-defined SQL function wrapper for intckParseCreateIndex():
**
**     SELECT parse_create_index(<sql>, <icol>);
*/
static void intckParseCreateIndexFunc(
  sqlite3_context *pCtx, 
  int nVal, 
  sqlite3_value **apVal
){
  const char *zSql = (const char*)sqlite3_value_text(apVal[0]);
  int idx = sqlite3_value_int(apVal[1]);
  const char *zRes = 0;
  int nRes = 0;

  assert( nVal==2 );
  if( zSql ){
    zRes = intckParseCreateIndex(zSql, idx, &nRes);
  }
  sqlite3_result_text(pCtx, zRes, nRes, SQLITE_TRANSIENT);
}

/*
** Return true if sqlite3_intck.db has automatic indexes enabled, false
** otherwise.
*/
static int intckGetAutoIndex(sqlite3_intck *p){
  int bRet = 0;
  sqlite3_stmt *pStmt = 0;
  pStmt = intckPrepare(p, "PRAGMA automatic_index");
  if( SQLITE_ROW==intckStep(p, pStmt) ){
    bRet = sqlite3_column_int(pStmt, 0);
  }
  intckFinalize(p, pStmt);
  return bRet;
}

/*
** Return true if zObj is an index, or false otherwise.
*/
static int intckIsIndex(sqlite3_intck *p, const char *zObj){
  int bRet = 0;
  sqlite3_stmt *pStmt = 0;
  pStmt = intckPrepareFmt(p, 
      "SELECT 1 FROM %Q.sqlite_schema WHERE name=%Q AND type='index'",
      p->zDb, zObj
  );
  if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
    bRet = 1;
  }
  intckFinalize(p, pStmt);
  return bRet;
}

/*
** Return a pointer to a nul-terminated buffer containing the SQL statement
** used to check database object zObj (a table or index) for corruption.
** If parameter zPrev is not NULL, then it must be a string containing the
** vector key required to restart the check where it left off last time.
** If pnKeyVal is not NULL, then (*pnKeyVal) is set to the number of
** columns in the vector key value for the specified object.
**
** This function uses the sqlite3_intck error code convention.
*/
static char *intckCheckObjectSql(
  sqlite3_intck *p,               /* Integrity check object */
  const char *zObj,               /* Object (table or index) to scan */
  const char *zPrev,              /* Restart key vector, if any */
  int *pnKeyVal                   /* OUT: Number of key-values for this scan */
){
  char *zRet = 0;
  sqlite3_stmt *pStmt = 0;
  int bAutoIndex = 0;
  int bIsIndex = 0;

  const char *zCommon = 
      /* Relation without_rowid also contains just one row. Column "b" is
      ** set to true if the table being examined is a WITHOUT ROWID table,
      ** or false otherwise.  */
      ", without_rowid(b) AS ("
      "  SELECT EXISTS ("
      "    SELECT 1 FROM tabname, pragma_index_list(tab, db) AS l"
      "      WHERE origin='pk' "
      "      AND NOT EXISTS (SELECT 1 FROM sqlite_schema WHERE name=l.name)"
      "  )"
      ")"
      ""
      /* Table idx_cols contains 1 row for each column in each index on the
      ** table being checked. Columns are:
      **
      **   idx_name: Name of the index.
      **   idx_ispk: True if this index is the PK of a WITHOUT ROWID table.
      **   col_name: Name of indexed column, or NULL for index on expression.
      **   col_expr: Indexed expression, including COLLATE clause.
      **   col_alias: Alias used for column in 'intck_wrapper' table.
      */
      ", idx_cols(idx_name, idx_ispk, col_name, col_expr, col_alias) AS ("
      "  SELECT l.name, (l.origin=='pk' AND w.b), i.name, COALESCE(("
      "    SELECT parse_create_index(sql, i.seqno) FROM "
      "    sqlite_schema WHERE name = l.name"
      "  ), format('\"%w\"', i.name) || ' COLLATE ' || quote(i.coll)),"
      "  'c' || row_number() OVER ()"
      "  FROM "
      "      tabname t,"
      "      without_rowid w,"
      "      pragma_index_list(t.tab, t.db) l,"
      "      pragma_index_xinfo(l.name) i"
      "      WHERE i.key"
      "  UNION ALL"
      "  SELECT '', 1, '_rowid_', '_rowid_', 'r1' FROM without_rowid WHERE b=0"
      ")"
      ""
      ""
      /*
      ** For a PK declared as "PRIMARY KEY(a, b) ... WITHOUT ROWID", where
      ** the intck_wrapper aliases of "a" and "b" are "c1" and "c2":
      **
      **   o_pk:   "o.c1, o.c2"
      **   i_pk:   "i.'a', i.'b'"
      **   ...
      **   n_pk:   2
      */ 
      ", tabpk(db, tab, idx, o_pk, i_pk, q_pk, eq_pk, ps_pk, pk_pk, n_pk) AS ("
      "    WITH pkfields(f, a) AS ("
      "      SELECT i.col_name, i.col_alias FROM idx_cols i WHERE i.idx_ispk"
      "    )"
      "    SELECT t.db, t.tab, t.idx, "
      "           group_concat(a, ', '), "
      "           group_concat('i.'||quote(f), ', '), "
      "           group_concat('quote(o.'||a||')', ' || '','' || '),  "
      "           format('(%s)==(%s)',"
      "               group_concat('o.'||a, ', '), "
      "               group_concat(format('\"%w\"', f), ', ')"
      "           ),"
      "           group_concat('%s', ','),"
      "           group_concat('quote('||a||')', ', '),  "
      "           count(*)"
      "    FROM tabname t, pkfields"
      ")"
      ""
      ", idx(name, match_expr, partial, partial_alias, idx_ps, idx_idx) AS ("
      "  SELECT idx_name,"
      "    format('(%s,%s) IS (%s,%s)', "
      "           group_concat(i.col_expr, ', '), i_pk,"
      "           group_concat('o.'||i.col_alias, ', '), o_pk"
      "    ), "
      "    parse_create_index("
      "        (SELECT sql FROM sqlite_schema WHERE name=idx_name), -1"
      "    ),"
      "    'cond' || row_number() OVER ()"
      "    , group_concat('%s', ',')"
      "    , group_concat('quote('||i.col_alias||')', ', ')"
      "  FROM tabpk t, "
      "       without_rowid w,"
      "       idx_cols i"
      "  WHERE i.idx_ispk==0 "
      "  GROUP BY idx_name"
      ")"
      ""
      ", wrapper_with(s) AS ("
      "  SELECT 'intck_wrapper AS (\n  SELECT\n    ' || ("
      "      WITH f(a, b) AS ("
      "        SELECT col_expr, col_alias FROM idx_cols"
      "          UNION ALL "
      "        SELECT partial, partial_alias FROM idx WHERE partial IS NOT NULL"
      "      )"
      "      SELECT group_concat(format('%s AS %s', a, b), ',\n    ') FROM f"
      "    )"
      "    || format('\n  FROM %Q.%Q ', t.db, t.tab)"
           /* If the object being checked is a table, append "NOT INDEXED".
           ** Otherwise, append "INDEXED BY <index>", and then, if the index 
           ** is a partial index " WHERE <condition>".  */
      "    || CASE WHEN t.idx IS NULL THEN "
      "        'NOT INDEXED'"
      "       ELSE"
      "        format('INDEXED BY %Q%s', t.idx, ' WHERE '||i.partial)"
      "       END"
      "    || '\n)'"
      "    FROM tabname t LEFT JOIN idx i ON (i.name=t.idx)"
      ")"
      ""
  ;

  bAutoIndex = intckGetAutoIndex(p);
  if( bAutoIndex ) intckExec(p, "PRAGMA automatic_index = 0");

  bIsIndex = intckIsIndex(p, zObj);
  if( bIsIndex ){
    pStmt = intckPrepareFmt(p,
      /* Table idxname contains a single row. The first column, "db", contains
      ** the name of the db containing the table (e.g. "main") and the second,
      ** "tab", the name of the table itself.  */
      "WITH tabname(db, tab, idx) AS ("
      "  SELECT %Q, (SELECT tbl_name FROM %Q.sqlite_schema WHERE name=%Q), %Q "
      ")"
      ""
      ", whereclause(w_c) AS (%s)"
      ""
      "%s" /* zCommon */
      ""
      ", case_statement(c) AS ("
      "  SELECT "
      "    'CASE WHEN (' || group_concat(col_alias, ', ') || ', 1) IS (\n' "
      "    || '      SELECT ' || group_concat(col_expr, ', ') || ', 1 FROM '"
      "    || format('%%Q.%%Q NOT INDEXED WHERE %%s\n', t.db, t.tab, p.eq_pk)"
      "    || '    )\n  THEN NULL\n    '"
      "    || 'ELSE format(''surplus entry ('"
      "    ||   group_concat('%%s', ',') || ',' || p.ps_pk"
      "    || ') in index ' || t.idx || ''', ' "
      "    ||   group_concat('quote('||i.col_alias||')', ', ') || ', ' || p.pk_pk"
      "    || ')'"
      "    || '\n  END AS error_message'"
      "  FROM tabname t, tabpk p, idx_cols i WHERE i.idx_name=t.idx"
      ")"
      ""
      ", thiskey(k, n) AS ("
      "    SELECT group_concat(i.col_alias, ', ') || ', ' || p.o_pk, "
      "           count(*) + p.n_pk "
      "    FROM tabpk p, idx_cols i WHERE i.idx_name=p.idx"
      ")"
      ""
      ", main_select(m, n) AS ("
      "  SELECT format("
      "      'WITH %%s\n' ||"
      "      ', idx_checker AS (\n' ||"
      "      '  SELECT %%s,\n' ||"
      "      '  %%s\n' || "
      "      '  FROM intck_wrapper AS o\n' ||"
      "      ')\n',"
      "      ww.s, c, t.k"
      "  ), t.n"
      "  FROM case_statement, wrapper_with ww, thiskey t"
      ")"

      "SELECT m || "
      "    group_concat('SELECT * FROM idx_checker ' || w_c, ' UNION ALL '), n"
      " FROM "
      "main_select, whereclause "
      , p->zDb, p->zDb, zObj, zObj
      , zPrev ? zPrev : "VALUES('')", zCommon
      );
  }else{
    pStmt = intckPrepareFmt(p,
      /* Table tabname contains a single row. The first column, "db", contains
      ** the name of the db containing the table (e.g. "main") and the second,
      ** "tab", the name of the table itself.  */
      "WITH tabname(db, tab, idx, prev) AS (SELECT %Q, %Q, NULL, %Q)"
      ""
      "%s" /* zCommon */

      /* expr(e) contains one row for each index on table zObj. Value e
      ** is set to an expression that evaluates to NULL if the required
      ** entry is present in the index, or an error message otherwise.  */
      ", expr(e, p) AS ("
      "  SELECT format('CASE WHEN EXISTS \n"
      "    (SELECT 1 FROM %%Q.%%Q AS i INDEXED BY %%Q WHERE %%s%%s)\n"
      "    THEN NULL\n"
      "    ELSE format(''entry (%%s,%%s) missing from index %%s'', %%s, %%s)\n"
      "  END\n'"
      "    , t.db, t.tab, i.name, i.match_expr, ' AND (' || partial || ')',"
      "      i.idx_ps, t.ps_pk, i.name, i.idx_idx, t.pk_pk),"
      "    CASE WHEN partial IS NULL THEN NULL ELSE i.partial_alias END"
      "  FROM tabpk t, idx i"
      ")"

      ", numbered(ii, cond, e) AS ("
      "  SELECT 0, 'n.ii=0', 'NULL'"
      "    UNION ALL "
      "  SELECT row_number() OVER (),"
      "      '(n.ii='||row_number() OVER ()||COALESCE(' AND '||p||')', ')'), e"
      "  FROM expr"
      ")"

      ", counter_with(w) AS ("
      "    SELECT 'WITH intck_counter(ii) AS (\n  ' || "
      "       group_concat('SELECT '||ii, ' UNION ALL\n  ') "
      "    || '\n)' FROM numbered"
      ")"
      ""
      ", case_statement(c) AS ("
      "    SELECT 'CASE ' || "
      "    group_concat(format('\n  WHEN %%s THEN (%%s)', cond, e), '') ||"
      "    '\nEND AS error_message'"
      "    FROM numbered"
      ")"
      ""

      /* This table contains a single row consisting of a single value -
      ** the text of an SQL expression that may be used by the main SQL
      ** statement to output an SQL literal that can be used to resume
      ** the scan if it is suspended. e.g. for a rowid table, an expression
      ** like:
      **
      **     format('(%d,%d)', _rowid_, n.ii)
      */
      ", thiskey(k, n) AS ("
      "    SELECT o_pk || ', ii', n_pk+1 FROM tabpk"
      ")"
      ""
      ", whereclause(w_c) AS ("
      "    SELECT CASE WHEN prev!='' THEN "
      "    '\nWHERE (' || o_pk ||', n.ii) > ' || prev"
      "    ELSE ''"
      "    END"
      "    FROM tabpk, tabname"
      ")"
      ""
      ", main_select(m, n) AS ("
      "  SELECT format("
      "      '%%s, %%s\nSELECT %%s,\n%%s\nFROM intck_wrapper AS o"
               ", intck_counter AS n%%s\nORDER BY %%s', "
      "      w, ww.s, c, thiskey.k, whereclause.w_c, t.o_pk"
      "  ), thiskey.n"
      "  FROM case_statement, tabpk t, counter_with, "
      "       wrapper_with ww, thiskey, whereclause"
      ")"

      "SELECT m, n FROM main_select",
      p->zDb, zObj, zPrev, zCommon
    );
  }

  while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
    zRet = intckMprintf(p, "%s", (const char*)sqlite3_column_text(pStmt, 0));
    if( pnKeyVal ){
      *pnKeyVal = sqlite3_column_int(pStmt, 1);
    }
  }
  intckFinalize(p, pStmt);

  if( bAutoIndex ) intckExec(p, "PRAGMA automatic_index = 1");
  return zRet;
}

/*
** Open a new integrity-check object.
*/
int sqlite3_intck_open(
  sqlite3 *db,                    /* Database handle to operate on */
  const char *zDbArg,             /* "main", "temp" etc. */
  sqlite3_intck **ppOut           /* OUT: New integrity-check handle */
){
  sqlite3_intck *pNew = 0;
  int rc = SQLITE_OK;
  const char *zDb = zDbArg ? zDbArg : "main";
  int nDb = (int)strlen(zDb);

  pNew = (sqlite3_intck*)sqlite3_malloc(sizeof(*pNew) + nDb + 1);
  if( pNew==0 ){
    rc = SQLITE_NOMEM;
  }else{
    memset(pNew, 0, sizeof(*pNew));
    pNew->db = db;
    pNew->zDb = (const char*)&pNew[1];
    memcpy(&pNew[1], zDb, nDb+1);
    rc = sqlite3_create_function(db, "parse_create_index", 
        2, SQLITE_UTF8, 0, intckParseCreateIndexFunc, 0, 0
    );
    if( rc!=SQLITE_OK ){
      sqlite3_intck_close(pNew);
      pNew = 0;
    }
  }

  *ppOut = pNew;
  return rc;
}

/*
** Free the integrity-check object.
*/
void sqlite3_intck_close(sqlite3_intck *p){
  if( p ){
    sqlite3_finalize(p->pCheck);
    sqlite3_create_function(
        p->db, "parse_create_index", 1, SQLITE_UTF8, 0, 0, 0, 0
    );
    sqlite3_free(p->zObj);
    sqlite3_free(p->zKey);
    sqlite3_free(p->zTestSql);
    sqlite3_free(p->zErr);
    sqlite3_free(p->zMessage);
    sqlite3_free(p);
  }
}

/*
** Step the integrity-check object.
*/
int sqlite3_intck_step(sqlite3_intck *p){
  if( p->rc==SQLITE_OK ){

    if( p->zMessage ){
      sqlite3_free(p->zMessage);
      p->zMessage = 0;
    }

    if( p->bCorruptSchema ){
      p->rc = SQLITE_DONE;
    }else
    if( p->pCheck==0 ){
      intckFindObject(p);
      if( p->rc==SQLITE_OK ){
        if( p->zObj ){
          char *zSql = 0;
          zSql = intckCheckObjectSql(p, p->zObj, p->zKey, &p->nKeyVal);
          p->pCheck = intckPrepare(p, zSql);
          sqlite3_free(zSql);
          sqlite3_free(p->zKey);
          p->zKey = 0;
        }else{
          p->rc = SQLITE_DONE;
        }
      }else if( p->rc==SQLITE_CORRUPT ){
        p->rc = SQLITE_OK;
        p->zMessage = intckMprintf(p, "%s",
            "corruption found while reading database schema"
        );
        p->bCorruptSchema = 1;
      }
    }

    if( p->pCheck ){
      assert( p->rc==SQLITE_OK );
      if( sqlite3_step(p->pCheck)==SQLITE_ROW ){
        /* Normal case, do nothing. */
      }else{
        intckFinalize(p, p->pCheck);
        p->pCheck = 0;
        p->nKeyVal = 0;
        if( p->rc==SQLITE_CORRUPT ){
          p->rc = SQLITE_OK;
          p->zMessage = intckMprintf(p, 
              "corruption found while scanning database object %s", p->zObj
          );
        }
      }
    }
  }

  return p->rc;
}

/*
** Return a message describing the corruption encountered by the most recent
** call to sqlite3_intck_step(), or NULL if no corruption was encountered.
*/
const char *sqlite3_intck_message(sqlite3_intck *p){
  assert( p->pCheck==0 || p->zMessage==0 );
  if( p->zMessage ){
    return p->zMessage;
  }
  if( p->pCheck ){
    return (const char*)sqlite3_column_text(p->pCheck, 0);
  }
  return 0;
}

/*
** Return the error code and message.
*/
int sqlite3_intck_error(sqlite3_intck *p, const char **pzErr){
  if( pzErr ) *pzErr = p->zErr;
  return (p->rc==SQLITE_DONE ? SQLITE_OK : p->rc);
}

/*
** Close any read transaction the integrity-check object is holding open
** on the database.
*/
int sqlite3_intck_unlock(sqlite3_intck *p){
  if( p->rc==SQLITE_OK && p->pCheck ){
    assert( p->zKey==0 && p->nKeyVal>0 );
    intckSaveKey(p);
    intckFinalize(p, p->pCheck);
    p->pCheck = 0;
  }
  return p->rc;
}

/*
** Return the SQL statement used to check object zObj. Or, if zObj is 
** NULL, the current SQL statement.
*/
const char *sqlite3_intck_test_sql(sqlite3_intck *p, const char *zObj){
  sqlite3_free(p->zTestSql);
  if( zObj ){
    p->zTestSql = intckCheckObjectSql(p, zObj, 0, 0);
  }else{
    if( p->zObj ){
      p->zTestSql = intckCheckObjectSql(p, p->zObj, p->zKey, 0);
    }else{
      sqlite3_free(p->zTestSql);
      p->zTestSql = 0;
    }
  }
  return p->zTestSql;
}

/************************* End ../ext/intck/sqlite3intck.c ********************/

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
#define SQLITE_SHELL_HAVE_RECOVER 1
#else
#define SQLITE_SHELL_HAVE_RECOVER 0
#endif
#if SQLITE_SHELL_HAVE_RECOVER
14103
14104
14105
14106
14107
14108
14109

14110
14111
14112
14113
14114
14115
14116
          iOff += nPointer;
    
          /* Load the "byte of payload including overflow" field */
          if( bNextPage || iOff>pCsr->nPage ){
            bNextPage = 1;
          }else{
            iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);

          }
    
          /* If this is a leaf intkey cell, load the rowid */
          if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
            iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
          }
    







>







15968
15969
15970
15971
15972
15973
15974
15975
15976
15977
15978
15979
15980
15981
15982
          iOff += nPointer;
    
          /* Load the "byte of payload including overflow" field */
          if( bNextPage || iOff>pCsr->nPage ){
            bNextPage = 1;
          }else{
            iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
            if( nPayload>0x7fffff00 ) nPayload &= 0x3fff;
          }
    
          /* If this is a leaf intkey cell, load the rowid */
          if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
            iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
          }
    
17419
17420
17421
17422
17423
17424
17425

17426
17427
17428
17429
17430
17431
17432
  u8 scanstatsOn;        /* True to display scan stats before each finalize */
  u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
  u8 doXdgOpen;          /* Invoke start/open/xdg-open in output_reset() */
  u8 nEqpLevel;          /* Depth of the EQP output graph */
  u8 eTraceType;         /* SHELL_TRACE_* value for type of trace */
  u8 bSafeMode;          /* True to prohibit unsafe operations */
  u8 bSafeModePersist;   /* The long-term value of bSafeMode */

  ColModeOpts cmOpts;    /* Option values affecting columnar mode output */
  unsigned statsOn;      /* True to display memory stats before each finalize */
  unsigned mEqpLines;    /* Mask of vertical lines in the EQP output graph */
  int inputNesting;      /* Track nesting level of .read and other redirects */
  int outCount;          /* Revert to stdout when reaching zero */
  int cnt;               /* Number of records displayed so far */
  int lineno;            /* Line number of last line read from in */







>







19285
19286
19287
19288
19289
19290
19291
19292
19293
19294
19295
19296
19297
19298
19299
  u8 scanstatsOn;        /* True to display scan stats before each finalize */
  u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
  u8 doXdgOpen;          /* Invoke start/open/xdg-open in output_reset() */
  u8 nEqpLevel;          /* Depth of the EQP output graph */
  u8 eTraceType;         /* SHELL_TRACE_* value for type of trace */
  u8 bSafeMode;          /* True to prohibit unsafe operations */
  u8 bSafeModePersist;   /* The long-term value of bSafeMode */
  u8 eRestoreState;      /* See comments above doAutoDetectRestore() */
  ColModeOpts cmOpts;    /* Option values affecting columnar mode output */
  unsigned statsOn;      /* True to display memory stats before each finalize */
  unsigned mEqpLines;    /* Mask of vertical lines in the EQP output graph */
  int inputNesting;      /* Track nesting level of .read and other redirects */
  int outCount;          /* Revert to stdout when reaching zero */
  int cnt;               /* Number of records displayed so far */
  int lineno;            /* Line number of last line read from in */
17612
17613
17614
17615
17616
17617
17618
17619
17620
17621
17622
17623
17624
17625
17626
17627
17628
17629
17630
17631
17632
17633
17634
17635
17636
17637
17638
17639
17640
17641
17642
17643
17644
17645
17646
17647
17648
17649
17650
17651
17652
17653
17654
17655
17656
17657
17658
17659
17660
17661
17662
17663

/*
** A callback for the sqlite3_log() interface.
*/
static void shellLog(void *pArg, int iErrCode, const char *zMsg){
  ShellState *p = (ShellState*)pArg;
  if( p->pLog==0 ) return;
  utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
  fflush(p->pLog);
}

/*
** SQL function:  shell_putsnl(X)
**
** Write the text X to the screen (or whatever output is being directed)
** adding a newline at the end, and then return X.
*/
static void shellPutsFunc(
  sqlite3_context *pCtx,
  int nVal,
  sqlite3_value **apVal
){
  ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
  (void)nVal;
  utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
  sqlite3_result_value(pCtx, apVal[0]);
}

/*
** If in safe mode, print an error message described by the arguments
** and exit immediately.
*/
static void failIfSafeMode(
  ShellState *p,
  const char *zErrMsg,
  ...
){
  if( p->bSafeMode ){
    va_list ap;
    char *zMsg;
    va_start(ap, zErrMsg);
    zMsg = sqlite3_vmprintf(zErrMsg, ap);
    va_end(ap);
    raw_printf(stderr, "line %d: ", p->lineno);
    utf8_printf(stderr, "%s\n", zMsg);
    exit(1);
  }
}

/*
** SQL function:   edit(VALUE)
**                 edit(VALUE,EDITOR)







|














|

|


















|
<







19479
19480
19481
19482
19483
19484
19485
19486
19487
19488
19489
19490
19491
19492
19493
19494
19495
19496
19497
19498
19499
19500
19501
19502
19503
19504
19505
19506
19507
19508
19509
19510
19511
19512
19513
19514
19515
19516
19517
19518
19519
19520
19521
19522

19523
19524
19525
19526
19527
19528
19529

/*
** A callback for the sqlite3_log() interface.
*/
static void shellLog(void *pArg, int iErrCode, const char *zMsg){
  ShellState *p = (ShellState*)pArg;
  if( p->pLog==0 ) return;
  sputf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
  fflush(p->pLog);
}

/*
** SQL function:  shell_putsnl(X)
**
** Write the text X to the screen (or whatever output is being directed)
** adding a newline at the end, and then return X.
*/
static void shellPutsFunc(
  sqlite3_context *pCtx,
  int nVal,
  sqlite3_value **apVal
){
  /* Unused: (ShellState*)sqlite3_user_data(pCtx); */
  (void)nVal;
  oputf("%s\n", sqlite3_value_text(apVal[0]));
  sqlite3_result_value(pCtx, apVal[0]);
}

/*
** If in safe mode, print an error message described by the arguments
** and exit immediately.
*/
static void failIfSafeMode(
  ShellState *p,
  const char *zErrMsg,
  ...
){
  if( p->bSafeMode ){
    va_list ap;
    char *zMsg;
    va_start(ap, zErrMsg);
    zMsg = sqlite3_vmprintf(zErrMsg, ap);
    va_end(ap);
    eputf("line %d: %s\n", p->lineno, zMsg);

    exit(1);
  }
}

/*
** SQL function:   edit(VALUE)
**                 edit(VALUE,EDITOR)
17817
17818
17819
17820
17821
17822
17823
17824
17825
17826
17827
17828
17829
17830
17831
17832
17833
17834
17835
17836
17837
17838
17839
17840
17841
17842
17843
17844
17845
17846
17847
17848
  memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
  memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
}

/*
** Output the given string as a hex-encoded blob (eg. X'1234' )
*/
static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
  int i;
  unsigned char *aBlob = (unsigned char*)pBlob;

  char *zStr = sqlite3_malloc(nBlob*2 + 1);
  shell_check_oom(zStr);

  for(i=0; i<nBlob; i++){
    static const char aHex[] = {
        '0', '1', '2', '3', '4', '5', '6', '7',
        '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    };
    zStr[i*2] = aHex[ (aBlob[i] >> 4) ];
    zStr[i*2+1] = aHex[ (aBlob[i] & 0x0F) ];
  }
  zStr[i*2] = '\0';

  raw_printf(out,"X'%s'", zStr);
  sqlite3_free(zStr);
}

/*
** Find a string that is not found anywhere in z[].  Return a pointer
** to that string.
**







|
















|







19683
19684
19685
19686
19687
19688
19689
19690
19691
19692
19693
19694
19695
19696
19697
19698
19699
19700
19701
19702
19703
19704
19705
19706
19707
19708
19709
19710
19711
19712
19713
19714
  memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
  memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
}

/*
** Output the given string as a hex-encoded blob (eg. X'1234' )
*/
static void output_hex_blob(const void *pBlob, int nBlob){
  int i;
  unsigned char *aBlob = (unsigned char*)pBlob;

  char *zStr = sqlite3_malloc(nBlob*2 + 1);
  shell_check_oom(zStr);

  for(i=0; i<nBlob; i++){
    static const char aHex[] = {
        '0', '1', '2', '3', '4', '5', '6', '7',
        '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    };
    zStr[i*2] = aHex[ (aBlob[i] >> 4) ];
    zStr[i*2+1] = aHex[ (aBlob[i] & 0x0F) ];
  }
  zStr[i*2] = '\0';

  oputf("X'%s'", zStr);
  sqlite3_free(zStr);
}

/*
** Find a string that is not found anywhere in z[].  Return a pointer
** to that string.
**
17864
17865
17866
17867
17868
17869
17870
17871
17872
17873


17874

17875
17876
17877
17878
17879
17880
17881
17882
17883
17884
17885
17886
17887
17888
17889
17890
17891
17892
17893
17894
17895
17896
17897
17898

17899



17900
17901
17902
17903
17904
17905
17906
17907
17908
17909
17910
17911
17912
17913


17914

17915
17916
17917
17918
17919
17920
17921
17922
17923
17924
17925
17926
17927
17928
17929
17930
17931
17932
17933
17934
17935
17936
17937
17938
17939
17940
17941
17942
17943
17944
17945
17946
17947
17948
17949
17950
17951
17952
17953
17954
17955
17956
17957
17958
17959
17960
17961
17962
17963
17964
17965

17966



17967
17968

















17969
17970
17971
17972
17973





17974
17975



17976
17977
17978
17979
17980
17981

17982
17983


17984
17985
17986
17987




17988
17989

17990
17991
17992
17993

17994
17995

17996
17997
17998
17999
18000
18001
18002
18003







18004
18005
18006
18007
18008








18009
18010
18011











18012
18013
18014
18015
18016
18017
18018
18019
18020
18021
18022
18023
18024
18025
18026
18027
18028

18029
18030
18031
18032
18033
18034
18035
18036
18037
18038
18039
18040
18041
18042
18043
18044
18045
18046
18047
18048
18049
18050
18051
18052
18053
18054
18055
18056
18057
18058
18059
18060
18061
18062
18063
18064
18065
18066
18067
18068
18069
}

/*
** Output the given string as a quoted string using SQL quoting conventions.
**
** See also: output_quoted_escaped_string()
*/
static void output_quoted_string(FILE *out, const char *z){
  int i;
  char c;


  setBinaryMode(out, 1);

  if( z==0 ) return;
  for(i=0; (c = z[i])!=0 && c!='\''; i++){}
  if( c==0 ){
    utf8_printf(out,"'%s'",z);
  }else{
    raw_printf(out, "'");
    while( *z ){
      for(i=0; (c = z[i])!=0 && c!='\''; i++){}
      if( c=='\'' ) i++;
      if( i ){
        utf8_printf(out, "%.*s", i, z);
        z += i;
      }
      if( c=='\'' ){
        raw_printf(out, "'");
        continue;
      }
      if( c==0 ){
        break;
      }
      z++;
    }
    raw_printf(out, "'");
  }

  setTextMode(out, 1);



}

/*
** Output the given string as a quoted string using SQL quoting conventions.
** Additionallly , escape the "\n" and "\r" characters so that they do not
** get corrupted by end-of-line translation facilities in some operating
** systems.
**
** This is like output_quoted_string() but with the addition of the \r\n
** escape mechanism.
*/
static void output_quoted_escaped_string(FILE *out, const char *z){
  int i;
  char c;


  setBinaryMode(out, 1);

  for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
  if( c==0 ){
    utf8_printf(out,"'%s'",z);
  }else{
    const char *zNL = 0;
    const char *zCR = 0;
    int nNL = 0;
    int nCR = 0;
    char zBuf1[20], zBuf2[20];
    for(i=0; z[i]; i++){
      if( z[i]=='\n' ) nNL++;
      if( z[i]=='\r' ) nCR++;
    }
    if( nNL ){
      raw_printf(out, "replace(");
      zNL = unused_string(z, "\\n", "\\012", zBuf1);
    }
    if( nCR ){
      raw_printf(out, "replace(");
      zCR = unused_string(z, "\\r", "\\015", zBuf2);
    }
    raw_printf(out, "'");
    while( *z ){
      for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
      if( c=='\'' ) i++;
      if( i ){
        utf8_printf(out, "%.*s", i, z);
        z += i;
      }
      if( c=='\'' ){
        raw_printf(out, "'");
        continue;
      }
      if( c==0 ){
        break;
      }
      z++;
      if( c=='\n' ){
        raw_printf(out, "%s", zNL);
        continue;
      }
      raw_printf(out, "%s", zCR);
    }
    raw_printf(out, "'");
    if( nCR ){
      raw_printf(out, ",'%s',char(13))", zCR);
    }
    if( nNL ){
      raw_printf(out, ",'%s',char(10))", zNL);
    }
  }

  setTextMode(out, 1);



}


















/*
** Output the given string as a quoted according to C or TCL quoting rules.
*/
static void output_c_string(FILE *out, const char *z){
  unsigned int c;





  fputc('"', out);
  while( (c = *(z++))!=0 ){



    if( c=='\\' ){
      fputc(c, out);
      fputc(c, out);
    }else if( c=='"' ){
      fputc('\\', out);
      fputc('"', out);

    }else if( c=='\t' ){
      fputc('\\', out);


      fputc('t', out);
    }else if( c=='\n' ){
      fputc('\\', out);
      fputc('n', out);




    }else if( c=='\r' ){
      fputc('\\', out);

      fputc('r', out);
    }else if( !isprint(c&0xff) ){
      raw_printf(out, "\\%03o", c&0xff);
    }else{

      fputc(c, out);
    }

  }
  fputc('"', out);
}

/*
** Output the given string as a quoted according to JSON quoting rules.
*/
static void output_json_string(FILE *out, const char *z, i64 n){







  unsigned int c;
  if( z==0 ) z = "";
  if( n<0 ) n = strlen(z);
  fputc('"', out);
  while( n-- ){








    c = *(z++);
    if( c=='\\' || c=='"' ){
      fputc('\\', out);











      fputc(c, out);
    }else if( c<=0x1f ){
      fputc('\\', out);
      if( c=='\b' ){
        fputc('b', out);
      }else if( c=='\f' ){
        fputc('f', out);
      }else if( c=='\n' ){
        fputc('n', out);
      }else if( c=='\r' ){
        fputc('r', out);
      }else if( c=='\t' ){
        fputc('t', out);
      }else{
         raw_printf(out, "u%04x",c);
      }
    }else{

      fputc(c, out);
    }
  }
  fputc('"', out);
}

/*
** Output the given string with characters that are special to
** HTML escaped.
*/
static void output_html_string(FILE *out, const char *z){
  int i;
  if( z==0 ) z = "";
  while( *z ){
    for(i=0;   z[i]
            && z[i]!='<'
            && z[i]!='&'
            && z[i]!='>'
            && z[i]!='\"'
            && z[i]!='\'';
        i++){}
    if( i>0 ){
      utf8_printf(out,"%.*s",i,z);
    }
    if( z[i]=='<' ){
      raw_printf(out,"&lt;");
    }else if( z[i]=='&' ){
      raw_printf(out,"&amp;");
    }else if( z[i]=='>' ){
      raw_printf(out,"&gt;");
    }else if( z[i]=='\"' ){
      raw_printf(out,"&quot;");
    }else if( z[i]=='\'' ){
      raw_printf(out,"&#39;");
    }else{
      break;
    }
    z += i + 1;
  }
}








|


>
>
|
>



|

|




|



|







|

>
|
>
>
>











|


>
>
|
>


|











|



|


|




|



|







|


|

|

|


|


>
|
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
|
>
>
>
>
>
|
|
>
>
>
|
<
<
|
<
<
>
|
|
>
>
|
|
<
<
>
>
>
>
|
<
>
|

|

>
|

>

|





|
>
>
>
>
>
>
>
|

|
|
|
>
>
>
>
>
>
>
>

|
|
>
>
>
>
>
>
>
>
>
>
>
|

<
<
<
<
<
<
<
<
<
<
<
<
|
<

>
|


|






|











|


|

|

|

|

|







19730
19731
19732
19733
19734
19735
19736
19737
19738
19739
19740
19741
19742
19743
19744
19745
19746
19747
19748
19749
19750
19751
19752
19753
19754
19755
19756
19757
19758
19759
19760
19761
19762
19763
19764
19765
19766
19767
19768
19769
19770
19771
19772
19773
19774
19775
19776
19777
19778
19779
19780
19781
19782
19783
19784
19785
19786
19787
19788
19789
19790
19791
19792
19793
19794
19795
19796
19797
19798
19799
19800
19801
19802
19803
19804
19805
19806
19807
19808
19809
19810
19811
19812
19813
19814
19815
19816
19817
19818
19819
19820
19821
19822
19823
19824
19825
19826
19827
19828
19829
19830
19831
19832
19833
19834
19835
19836
19837
19838
19839
19840
19841
19842
19843
19844
19845
19846
19847
19848
19849
19850
19851
19852
19853
19854
19855
19856
19857
19858
19859
19860
19861
19862
19863
19864
19865
19866
19867
19868
19869
19870
19871
19872
19873
19874
19875
19876
19877
19878
19879
19880
19881


19882


19883
19884
19885
19886
19887
19888
19889


19890
19891
19892
19893
19894

19895
19896
19897
19898
19899
19900
19901
19902
19903
19904
19905
19906
19907
19908
19909
19910
19911
19912
19913
19914
19915
19916
19917
19918
19919
19920
19921
19922
19923
19924
19925
19926
19927
19928
19929
19930
19931
19932
19933
19934
19935
19936
19937
19938
19939
19940
19941
19942
19943
19944
19945
19946
19947












19948

19949
19950
19951
19952
19953
19954
19955
19956
19957
19958
19959
19960
19961
19962
19963
19964
19965
19966
19967
19968
19969
19970
19971
19972
19973
19974
19975
19976
19977
19978
19979
19980
19981
19982
19983
19984
19985
19986
19987
19988
19989
19990
19991
}

/*
** Output the given string as a quoted string using SQL quoting conventions.
**
** See also: output_quoted_escaped_string()
*/
static void output_quoted_string(const char *z){
  int i;
  char c;
#ifndef SQLITE_SHELL_FIDDLE
  FILE *pfO = setOutputStream(invalidFileStream);
  setBinaryMode(pfO, 1);
#endif
  if( z==0 ) return;
  for(i=0; (c = z[i])!=0 && c!='\''; i++){}
  if( c==0 ){
    oputf("'%s'",z);
  }else{
    oputz("'");
    while( *z ){
      for(i=0; (c = z[i])!=0 && c!='\''; i++){}
      if( c=='\'' ) i++;
      if( i ){
        oputf("%.*s", i, z);
        z += i;
      }
      if( c=='\'' ){
        oputz("'");
        continue;
      }
      if( c==0 ){
        break;
      }
      z++;
    }
    oputz("'");
  }
#ifndef SQLITE_SHELL_FIDDLE
  setTextMode(pfO, 1);
#else
  setTextMode(stdout, 1);
#endif
}

/*
** Output the given string as a quoted string using SQL quoting conventions.
** Additionallly , escape the "\n" and "\r" characters so that they do not
** get corrupted by end-of-line translation facilities in some operating
** systems.
**
** This is like output_quoted_string() but with the addition of the \r\n
** escape mechanism.
*/
static void output_quoted_escaped_string(const char *z){
  int i;
  char c;
#ifndef SQLITE_SHELL_FIDDLE
  FILE *pfO = setOutputStream(invalidFileStream);
  setBinaryMode(pfO, 1);
#endif
  for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
  if( c==0 ){
    oputf("'%s'",z);
  }else{
    const char *zNL = 0;
    const char *zCR = 0;
    int nNL = 0;
    int nCR = 0;
    char zBuf1[20], zBuf2[20];
    for(i=0; z[i]; i++){
      if( z[i]=='\n' ) nNL++;
      if( z[i]=='\r' ) nCR++;
    }
    if( nNL ){
      oputz("replace(");
      zNL = unused_string(z, "\\n", "\\012", zBuf1);
    }
    if( nCR ){
      oputz("replace(");
      zCR = unused_string(z, "\\r", "\\015", zBuf2);
    }
    oputz("'");
    while( *z ){
      for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
      if( c=='\'' ) i++;
      if( i ){
        oputf("%.*s", i, z);
        z += i;
      }
      if( c=='\'' ){
        oputz("'");
        continue;
      }
      if( c==0 ){
        break;
      }
      z++;
      if( c=='\n' ){
        oputz(zNL);
        continue;
      }
      oputz(zCR);
    }
    oputz("'");
    if( nCR ){
      oputf(",'%s',char(13))", zCR);
    }
    if( nNL ){
      oputf(",'%s',char(10))", zNL);
    }
  }
#ifndef SQLITE_SHELL_FIDDLE
  setTextMode(pfO, 1);
#else
  setTextMode(stdout, 1);
#endif
}

/*
** Find earliest of chars within s specified in zAny.
** With ns == ~0, is like strpbrk(s,zAny) and s must be 0-terminated.
*/
static const char *anyOfInStr(const char *s, const char *zAny, size_t ns){
  const char *pcFirst = 0;
  if( ns == ~(size_t)0 ) ns = strlen(s);
  while(*zAny){
    const char *pc = (const char*)memchr(s, *zAny&0xff, ns);
    if( pc ){
      pcFirst = pc;
      ns = pcFirst - s;
    }
    ++zAny;
  }
  return pcFirst;
}
/*
** Output the given string as a quoted according to C or TCL quoting rules.
*/
static void output_c_string(const char *z){
  char c;
  static const char *zq = "\"";
  static long ctrlMask = ~0L;
  static const char *zDQBSRO = "\"\\\x7f"; /* double-quote, backslash, rubout */
  char ace[3] = "\\?";
  char cbsSay;
  oputz(zq);
  while( *z!=0 ){
    const char *pcDQBSRO = anyOfInStr(z, zDQBSRO, ~(size_t)0);
    const char *pcPast = zSkipValidUtf8(z, INT_MAX, ctrlMask);
    const char *pcEnd = (pcDQBSRO && pcDQBSRO < pcPast)? pcDQBSRO : pcPast;
    if( pcEnd > z ) oputb(z, (int)(pcEnd-z));


    if( (c = *pcEnd)==0 ) break;


    ++pcEnd;
    switch( c ){
    case '\\': case '"':
      cbsSay = (char)c;
      break;
    case '\t': cbsSay = 't'; break;
    case '\n': cbsSay = 'n'; break;


    case '\r': cbsSay = 'r'; break;
    case '\f': cbsSay = 'f'; break;
    default: cbsSay = 0; break;
    }
    if( cbsSay ){

      ace[1] = cbsSay;
      oputz(ace);
    }else if( !isprint(c&0xff) ){
      oputf("\\%03o", c&0xff);
    }else{
      ace[1] = (char)c;
      oputz(ace+1);
    }
    z = pcEnd;
  }
  oputz(zq);
}

/*
** Output the given string as a quoted according to JSON quoting rules.
*/
static void output_json_string(const char *z, i64 n){
  char c;
  static const char *zq = "\"";
  static long ctrlMask = ~0L;
  static const char *zDQBS = "\"\\";
  const char *pcLimit;
  char ace[3] = "\\?";
  char cbsSay;

  if( z==0 ) z = "";
  pcLimit = z + ((n<0)? strlen(z) : (size_t)n);
  oputz(zq);
  while( z < pcLimit ){
    const char *pcDQBS = anyOfInStr(z, zDQBS, pcLimit-z);
    const char *pcPast = zSkipValidUtf8(z, (int)(pcLimit-z), ctrlMask);
    const char *pcEnd = (pcDQBS && pcDQBS < pcPast)? pcDQBS : pcPast;
    if( pcEnd > z ){
      oputb(z, (int)(pcEnd-z));
      z = pcEnd;
    }
    if( z >= pcLimit ) break;
    c = *(z++);
    switch( c ){
    case '"': case '\\':
      cbsSay = (char)c;
      break;
    case '\b': cbsSay = 'b'; break;
    case '\f': cbsSay = 'f'; break;
    case '\n': cbsSay = 'n'; break;
    case '\r': cbsSay = 'r'; break;
    case '\t': cbsSay = 't'; break;
    default: cbsSay = 0; break;
    }
    if( cbsSay ){
      ace[1] = cbsSay;
      oputz(ace);
    }else if( c<=0x1f ){












      oputf("u%04x", c);

    }else{
      ace[1] = (char)c;
      oputz(ace+1);
    }
  }
  oputz(zq);
}

/*
** Output the given string with characters that are special to
** HTML escaped.
*/
static void output_html_string(const char *z){
  int i;
  if( z==0 ) z = "";
  while( *z ){
    for(i=0;   z[i]
            && z[i]!='<'
            && z[i]!='&'
            && z[i]!='>'
            && z[i]!='\"'
            && z[i]!='\'';
        i++){}
    if( i>0 ){
      oputf("%.*s",i,z);
    }
    if( z[i]=='<' ){
      oputz("&lt;");
    }else if( z[i]=='&' ){
      oputz("&amp;");
    }else if( z[i]=='>' ){
      oputz("&gt;");
    }else if( z[i]=='\"' ){
      oputz("&quot;");
    }else if( z[i]=='\'' ){
      oputz("&#39;");
    }else{
      break;
    }
    z += i + 1;
  }
}

18093
18094
18095
18096
18097
18098
18099
18100
18101
18102
18103
18104
18105
18106
18107
18108
18109
18110
18111
18112
18113
18114
18115
18116
18117
18118
18119
18120
18121
18122
18123
18124
18125
18126
18127
18128
/*
** Output a single term of CSV.  Actually, p->colSeparator is used for
** the separator, which may or may not be a comma.  p->nullValue is
** the null value.  Strings are quoted if necessary.  The separator
** is only issued if bSep is true.
*/
static void output_csv(ShellState *p, const char *z, int bSep){
  FILE *out = p->out;
  if( z==0 ){
    utf8_printf(out,"%s",p->nullValue);
  }else{
    unsigned i;
    for(i=0; z[i]; i++){
      if( needCsvQuote[((unsigned char*)z)[i]] ){
        i = 0;
        break;
      }
    }
    if( i==0 || strstr(z, p->colSeparator)!=0 ){
      char *zQuoted = sqlite3_mprintf("\"%w\"", z);
      shell_check_oom(zQuoted);
      utf8_printf(out, "%s", zQuoted);
      sqlite3_free(zQuoted);
    }else{
      utf8_printf(out, "%s", z);
    }
  }
  if( bSep ){
    utf8_printf(p->out, "%s", p->colSeparator);
  }
}

/*
** This routine runs when the user presses Ctrl-C
*/
static void interrupt_handler(int NotUsed){







<

|











|


|



|







20015
20016
20017
20018
20019
20020
20021

20022
20023
20024
20025
20026
20027
20028
20029
20030
20031
20032
20033
20034
20035
20036
20037
20038
20039
20040
20041
20042
20043
20044
20045
20046
20047
20048
20049
/*
** Output a single term of CSV.  Actually, p->colSeparator is used for
** the separator, which may or may not be a comma.  p->nullValue is
** the null value.  Strings are quoted if necessary.  The separator
** is only issued if bSep is true.
*/
static void output_csv(ShellState *p, const char *z, int bSep){

  if( z==0 ){
    oputf("%s",p->nullValue);
  }else{
    unsigned i;
    for(i=0; z[i]; i++){
      if( needCsvQuote[((unsigned char*)z)[i]] ){
        i = 0;
        break;
      }
    }
    if( i==0 || strstr(z, p->colSeparator)!=0 ){
      char *zQuoted = sqlite3_mprintf("\"%w\"", z);
      shell_check_oom(zQuoted);
      oputz(zQuoted);
      sqlite3_free(zQuoted);
    }else{
      oputz(z);
    }
  }
  if( bSep ){
    oputz(p->colSeparator);
  }
}

/*
** This routine runs when the user presses Ctrl-C
*/
static void interrupt_handler(int NotUsed){
18222
18223
18224
18225
18226
18227
18228
18229
18230
18231
18232
18233
18234
18235
18236
18237
18238
18239
18240
18241
18242
18243
18244
18245
18246
18247
18248
18249
18250
18251
18252
18253
18254
18255
18256
18257
18258
18259
18260
18261
  };
  int i;
  const char *az[4];
  az[0] = zA1;
  az[1] = zA2;
  az[2] = zA3;
  az[3] = zA4;
  utf8_printf(p->out, "authorizer: %s", azAction[op]);
  for(i=0; i<4; i++){
    raw_printf(p->out, " ");
    if( az[i] ){
      output_c_string(p->out, az[i]);
    }else{
      raw_printf(p->out, "NULL");
    }
  }
  raw_printf(p->out, "\n");
  if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
  return SQLITE_OK;
}
#endif

/*
** Print a schema statement.  Part of MODE_Semi and MODE_Pretty output.
**
** This routine converts some CREATE TABLE statements for shadow tables
** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
**
** If the schema statement in z[] contains a start-of-comment and if
** sqlite3_complete() returns false, try to terminate the comment before
** printing the result.  https://sqlite.org/forum/forumpost/d7be961c5c
*/
static void printSchemaLine(FILE *out, const char *z, const char *zTail){
  char *zToFree = 0;
  if( z==0 ) return;
  if( zTail==0 ) return;
  if( zTail[0]==';' && (strstr(z, "/*")!=0 || strstr(z,"--")!=0) ){
    const char *zOrig = z;
    static const char *azTerm[] = { "", "*/", "\n" };
    int i;







|

|

|

|


|















|







20143
20144
20145
20146
20147
20148
20149
20150
20151
20152
20153
20154
20155
20156
20157
20158
20159
20160
20161
20162
20163
20164
20165
20166
20167
20168
20169
20170
20171
20172
20173
20174
20175
20176
20177
20178
20179
20180
20181
20182
  };
  int i;
  const char *az[4];
  az[0] = zA1;
  az[1] = zA2;
  az[2] = zA3;
  az[3] = zA4;
  oputf("authorizer: %s", azAction[op]);
  for(i=0; i<4; i++){
    oputz(" ");
    if( az[i] ){
      output_c_string(az[i]);
    }else{
      oputz("NULL");
    }
  }
  oputz("\n");
  if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
  return SQLITE_OK;
}
#endif

/*
** Print a schema statement.  Part of MODE_Semi and MODE_Pretty output.
**
** This routine converts some CREATE TABLE statements for shadow tables
** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
**
** If the schema statement in z[] contains a start-of-comment and if
** sqlite3_complete() returns false, try to terminate the comment before
** printing the result.  https://sqlite.org/forum/forumpost/d7be961c5c
*/
static void printSchemaLine(const char *z, const char *zTail){
  char *zToFree = 0;
  if( z==0 ) return;
  if( zTail==0 ) return;
  if( zTail[0]==';' && (strstr(z, "/*")!=0 || strstr(z,"--")!=0) ){
    const char *zOrig = z;
    static const char *azTerm[] = { "", "*/", "\n" };
    int i;
18269
18270
18271
18272
18273
18274
18275
18276
18277
18278
18279
18280
18281
18282
18283
18284
18285
18286
18287
18288
18289
18290
18291
18292
        z = zNew;
        break;
      }
      sqlite3_free(zNew);
    }
  }
  if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
    utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
  }else{
    utf8_printf(out, "%s%s", z, zTail);
  }
  sqlite3_free(zToFree);
}
static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
  char c = z[n];
  z[n] = 0;
  printSchemaLine(out, z, zTail);
  z[n] = c;
}

/*
** Return true if string z[] has nothing but whitespace and comments to the
** end of the first line.
*/







|

|



|


|







20190
20191
20192
20193
20194
20195
20196
20197
20198
20199
20200
20201
20202
20203
20204
20205
20206
20207
20208
20209
20210
20211
20212
20213
        z = zNew;
        break;
      }
      sqlite3_free(zNew);
    }
  }
  if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
    oputf("CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
  }else{
    oputf("%s%s", z, zTail);
  }
  sqlite3_free(zToFree);
}
static void printSchemaLineN(char *z, int n, const char *zTail){
  char c = z[n];
  z[n] = 0;
  printSchemaLine(z, zTail);
  z[n] = c;
}

/*
** Return true if string z[] has nothing but whitespace and comments to the
** end of the first line.
*/
18306
18307
18308
18309
18310
18311
18312
18313
18314
18315
18316
18317
18318
18319
18320
*/
static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
  EQPGraphRow *pNew;
  i64 nText;
  if( zText==0 ) return;
  nText = strlen(zText);
  if( p->autoEQPtest ){
    utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
  }
  pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
  shell_check_oom(pNew);
  pNew->iEqpId = iEqpId;
  pNew->iParentId = p2;
  memcpy(pNew->zText, zText, nText+1);
  pNew->pNext = 0;







|







20227
20228
20229
20230
20231
20232
20233
20234
20235
20236
20237
20238
20239
20240
20241
*/
static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
  EQPGraphRow *pNew;
  i64 nText;
  if( zText==0 ) return;
  nText = strlen(zText);
  if( p->autoEQPtest ){
    oputf("%d,%d,%s\n", iEqpId, p2, zText);
  }
  pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
  shell_check_oom(pNew);
  pNew->iEqpId = iEqpId;
  pNew->iParentId = p2;
  memcpy(pNew->zText, zText, nText+1);
  pNew->pNext = 0;
18354
18355
18356
18357
18358
18359
18360
18361
18362
18363
18364
18365
18366
18367
18368
18369
18370
18371
18372
18373
18374
18375
18376
18377
18378
18379
18380
18381
18382
18383
18384
18385
18386
18387
18388
18389
18390
18391
18392
18393
18394
18395
18396
18397
18398
18399
18400
18401
18402
18403
18404
18405
18406
18407
18408
18409
18410
18411
18412
18413
18414
18415
18416
18417
18418
18419
18420
18421
18422
18423
18424
18425
18426
18427
18428
18429
18430
18431
18432
18433
18434
18435
18436
18437
18438
18439
18440
18441
18442
18443
18444
18445
18446
18447
18448
18449
18450
18451
18452
18453
18454
static void eqp_render_level(ShellState *p, int iEqpId){
  EQPGraphRow *pRow, *pNext;
  i64 n = strlen(p->sGraph.zPrefix);
  char *z;
  for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
    pNext = eqp_next_row(p, iEqpId, pRow);
    z = pRow->zText;
    utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
                pNext ? "|--" : "`--", z);
    if( n<(i64)sizeof(p->sGraph.zPrefix)-7 ){
      memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);
      eqp_render_level(p, pRow->iEqpId);
      p->sGraph.zPrefix[n] = 0;
    }
  }
}

/*
** Display and reset the EXPLAIN QUERY PLAN data
*/
static void eqp_render(ShellState *p, i64 nCycle){
  EQPGraphRow *pRow = p->sGraph.pRow;
  if( pRow ){
    if( pRow->zText[0]=='-' ){
      if( pRow->pNext==0 ){
        eqp_reset(p);
        return;
      }
      utf8_printf(p->out, "%s\n", pRow->zText+3);
      p->sGraph.pRow = pRow->pNext;
      sqlite3_free(pRow);
    }else if( nCycle>0 ){
      utf8_printf(p->out, "QUERY PLAN (cycles=%lld [100%%])\n", nCycle);
    }else{
      utf8_printf(p->out, "QUERY PLAN\n");
    }
    p->sGraph.zPrefix[0] = 0;
    eqp_render_level(p, 0);
    eqp_reset(p);
  }
}

#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/*
** Progress handler callback.
*/
static int progress_handler(void *pClientData) {
  ShellState *p = (ShellState*)pClientData;
  p->nProgress++;
  if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
    raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
    if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
    if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
    return 1;
  }
  if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
    raw_printf(p->out, "Progress %u\n", p->nProgress);
  }
  return 0;
}
#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */

/*
** Print N dashes
*/
static void print_dashes(FILE *out, int N){
  const char zDash[] = "--------------------------------------------------";
  const int nDash = sizeof(zDash) - 1;
  while( N>nDash ){
    fputs(zDash, out);
    N -= nDash;
  }
  raw_printf(out, "%.*s", N, zDash);
}

/*
** Print a markdown or table-style row separator using ascii-art
*/
static void print_row_separator(
  ShellState *p,
  int nArg,
  const char *zSep
){
  int i;
  if( nArg>0 ){
    fputs(zSep, p->out);
    print_dashes(p->out, p->actualWidth[0]+2);
    for(i=1; i<nArg; i++){
      fputs(zSep, p->out);
      print_dashes(p->out, p->actualWidth[i]+2);
    }
    fputs(zSep, p->out);
  }
  fputs("\n", p->out);
}

/*
** This is the callback routine that the shell
** invokes for each row of a query result.
*/
static int shell_callback(







<
|



















|



|

|















|





|








|



|


|












|
|

|
|

|

|







20275
20276
20277
20278
20279
20280
20281

20282
20283
20284
20285
20286
20287
20288
20289
20290
20291
20292
20293
20294
20295
20296
20297
20298
20299
20300
20301
20302
20303
20304
20305
20306
20307
20308
20309
20310
20311
20312
20313
20314
20315
20316
20317
20318
20319
20320
20321
20322
20323
20324
20325
20326
20327
20328
20329
20330
20331
20332
20333
20334
20335
20336
20337
20338
20339
20340
20341
20342
20343
20344
20345
20346
20347
20348
20349
20350
20351
20352
20353
20354
20355
20356
20357
20358
20359
20360
20361
20362
20363
20364
20365
20366
20367
20368
20369
20370
20371
20372
20373
20374
static void eqp_render_level(ShellState *p, int iEqpId){
  EQPGraphRow *pRow, *pNext;
  i64 n = strlen(p->sGraph.zPrefix);
  char *z;
  for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
    pNext = eqp_next_row(p, iEqpId, pRow);
    z = pRow->zText;

    oputf("%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z);
    if( n<(i64)sizeof(p->sGraph.zPrefix)-7 ){
      memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);
      eqp_render_level(p, pRow->iEqpId);
      p->sGraph.zPrefix[n] = 0;
    }
  }
}

/*
** Display and reset the EXPLAIN QUERY PLAN data
*/
static void eqp_render(ShellState *p, i64 nCycle){
  EQPGraphRow *pRow = p->sGraph.pRow;
  if( pRow ){
    if( pRow->zText[0]=='-' ){
      if( pRow->pNext==0 ){
        eqp_reset(p);
        return;
      }
      oputf("%s\n", pRow->zText+3);
      p->sGraph.pRow = pRow->pNext;
      sqlite3_free(pRow);
    }else if( nCycle>0 ){
      oputf("QUERY PLAN (cycles=%lld [100%%])\n", nCycle);
    }else{
      oputz("QUERY PLAN\n");
    }
    p->sGraph.zPrefix[0] = 0;
    eqp_render_level(p, 0);
    eqp_reset(p);
  }
}

#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/*
** Progress handler callback.
*/
static int progress_handler(void *pClientData) {
  ShellState *p = (ShellState*)pClientData;
  p->nProgress++;
  if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
    oputf("Progress limit reached (%u)\n", p->nProgress);
    if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
    if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
    return 1;
  }
  if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
    oputf("Progress %u\n", p->nProgress);
  }
  return 0;
}
#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */

/*
** Print N dashes
*/
static void print_dashes(int N){
  const char zDash[] = "--------------------------------------------------";
  const int nDash = sizeof(zDash) - 1;
  while( N>nDash ){
    oputz(zDash);
    N -= nDash;
  }
  oputf("%.*s", N, zDash);
}

/*
** Print a markdown or table-style row separator using ascii-art
*/
static void print_row_separator(
  ShellState *p,
  int nArg,
  const char *zSep
){
  int i;
  if( nArg>0 ){
    oputz(zSep);
    print_dashes(p->actualWidth[0]+2);
    for(i=1; i<nArg; i++){
      oputz(zSep);
      print_dashes(p->actualWidth[i]+2);
    }
    oputz(zSep);
  }
  oputz("\n");
}

/*
** This is the callback routine that the shell
** invokes for each row of a query result.
*/
static int shell_callback(
18470
18471
18472
18473
18474
18475
18476
18477
18478
18479
18480
18481
18482
18483
18484
18485
18486
18487
    case MODE_Line: {
      int w = 5;
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        int len = strlen30(azCol[i] ? azCol[i] : "");
        if( len>w ) w = len;
      }
      if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
      for(i=0; i<nArg; i++){
        utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
                azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
      }
      break;
    }
    case MODE_ScanExp:
    case MODE_Explain: {
      static const int aExplainWidth[] = {4,       13, 4, 4, 4, 13, 2, 13};
      static const int aExplainMap[] =   {0,       1,  2, 3, 4, 5,  6, 7 };







|

|
|







20390
20391
20392
20393
20394
20395
20396
20397
20398
20399
20400
20401
20402
20403
20404
20405
20406
20407
    case MODE_Line: {
      int w = 5;
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        int len = strlen30(azCol[i] ? azCol[i] : "");
        if( len>w ) w = len;
      }
      if( p->cnt++>0 ) oputz(p->rowSeparator);
      for(i=0; i<nArg; i++){
        oputf("%*s = %s%s", w, azCol[i],
              azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
      }
      break;
    }
    case MODE_ScanExp:
    case MODE_Explain: {
      static const int aExplainWidth[] = {4,       13, 4, 4, 4, 13, 2, 13};
      static const int aExplainMap[] =   {0,       1,  2, 3, 4, 5,  6, 7 };
18500
18501
18502
18503
18504
18505
18506
18507
18508
18509
18510
18511
18512
18513
18514
18515
18516
18517
18518
18519
18520
18521
18522
18523
18524
18525
18526
18527
18528
18529
18530
18531
18532
18533
18534
18535
18536
18537
18538
18539
18540
18541
18542
18543
18544
18545
18546
18547
18548
18549
18550
18551
18552
18553
18554
18555
18556
18557
18558
18559
18560
18561
18562
        iIndent = 3;
      }
      if( nArg>nWidth ) nArg = nWidth;

      /* If this is the first row seen, print out the headers */
      if( p->cnt++==0 ){
        for(i=0; i<nArg; i++){
          utf8_width_print(p->out, aWidth[i], azCol[ aMap[i] ]);
          fputs(i==nArg-1 ? "\n" : "  ", p->out);
        }
        for(i=0; i<nArg; i++){
          print_dashes(p->out, aWidth[i]);
          fputs(i==nArg-1 ? "\n" : "  ", p->out);
        }
      }

      /* If there is no data, exit early. */
      if( azArg==0 ) break;

      for(i=0; i<nArg; i++){
        const char *zSep = "  ";
        int w = aWidth[i];
        const char *zVal = azArg[ aMap[i] ];
        if( i==nArg-1 ) w = 0;
        if( zVal && strlenChar(zVal)>w ){
          w = strlenChar(zVal);
          zSep = " ";
        }
        if( i==iIndent && p->aiIndent && p->pStmt ){
          if( p->iIndent<p->nIndent ){
            utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
          }
          p->iIndent++;
        }
        utf8_width_print(p->out, w, zVal ? zVal : p->nullValue);
        fputs(i==nArg-1 ? "\n" : zSep, p->out);
      }
      break;
    }
    case MODE_Semi: {   /* .schema and .fullschema output */
      printSchemaLine(p->out, azArg[0], ";\n");
      break;
    }
    case MODE_Pretty: {  /* .schema and .fullschema with --indent */
      char *z;
      int j;
      int nParen = 0;
      char cEnd = 0;
      char c;
      int nLine = 0;
      assert( nArg==1 );
      if( azArg[0]==0 ) break;
      if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
       || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
      ){
        utf8_printf(p->out, "%s;\n", azArg[0]);
        break;
      }
      z = sqlite3_mprintf("%s", azArg[0]);
      shell_check_oom(z);
      j = 0;
      for(i=0; IsSpace(z[i]); i++){}
      for(; (c = z[i])!=0; i++){







|
|


|
|

















|



|
|




|














|







20420
20421
20422
20423
20424
20425
20426
20427
20428
20429
20430
20431
20432
20433
20434
20435
20436
20437
20438
20439
20440
20441
20442
20443
20444
20445
20446
20447
20448
20449
20450
20451
20452
20453
20454
20455
20456
20457
20458
20459
20460
20461
20462
20463
20464
20465
20466
20467
20468
20469
20470
20471
20472
20473
20474
20475
20476
20477
20478
20479
20480
20481
20482
        iIndent = 3;
      }
      if( nArg>nWidth ) nArg = nWidth;

      /* If this is the first row seen, print out the headers */
      if( p->cnt++==0 ){
        for(i=0; i<nArg; i++){
          utf8_width_print(aWidth[i], azCol[ aMap[i] ]);
          oputz(i==nArg-1 ? "\n" : "  ");
        }
        for(i=0; i<nArg; i++){
          print_dashes(aWidth[i]);
          oputz(i==nArg-1 ? "\n" : "  ");
        }
      }

      /* If there is no data, exit early. */
      if( azArg==0 ) break;

      for(i=0; i<nArg; i++){
        const char *zSep = "  ";
        int w = aWidth[i];
        const char *zVal = azArg[ aMap[i] ];
        if( i==nArg-1 ) w = 0;
        if( zVal && strlenChar(zVal)>w ){
          w = strlenChar(zVal);
          zSep = " ";
        }
        if( i==iIndent && p->aiIndent && p->pStmt ){
          if( p->iIndent<p->nIndent ){
            oputf("%*.s", p->aiIndent[p->iIndent], "");
          }
          p->iIndent++;
        }
        utf8_width_print(w, zVal ? zVal : p->nullValue);
        oputz(i==nArg-1 ? "\n" : zSep);
      }
      break;
    }
    case MODE_Semi: {   /* .schema and .fullschema output */
      printSchemaLine(azArg[0], ";\n");
      break;
    }
    case MODE_Pretty: {  /* .schema and .fullschema with --indent */
      char *z;
      int j;
      int nParen = 0;
      char cEnd = 0;
      char c;
      int nLine = 0;
      assert( nArg==1 );
      if( azArg[0]==0 ) break;
      if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
       || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
      ){
        oputf("%s;\n", azArg[0]);
        break;
      }
      z = sqlite3_mprintf("%s", azArg[0]);
      shell_check_oom(z);
      j = 0;
      for(i=0; IsSpace(z[i]); i++){}
      for(; (c = z[i])!=0; i++){
18581
18582
18583
18584
18585
18586
18587
18588
18589
18590
18591
18592
18593
18594
18595
18596
18597
18598
18599
18600
18601
18602
18603
18604
18605
18606
18607
18608
18609
18610
18611
18612
18613
18614
18615
18616
18617
18618
18619
18620
18621
18622
18623
18624
18625
18626
18627
18628
18629
18630
18631
18632
18633
18634
18635
18636
18637
18638
18639
18640
18641
18642
18643
18644
18645
18646
18647
18648
18649
18650
18651
18652
18653
18654
18655
18656
18657
18658
18659
18660
18661
18662
18663
18664
18665
18666
18667
18668
18669
18670
18671
18672
18673
18674
18675
18676
18677
18678
18679
18680
18681
18682
18683
18684
18685
18686
18687
18688
18689
18690
18691
18692
18693
18694
18695
18696
18697
18698
18699
18700
18701
18702
18703
18704
18705
18706
18707
18708
18709
18710
18711
18712
18713
18714
18715
18716
18717
18718
18719
18720
18721
18722
18723
18724
18725
18726
18727
18728
18729
18730
18731
18732
18733
18734
18735
18736
18737
18738
18739
18740
18741
18742
18743
18744
18745
18746
18747
18748
18749
18750
18751
18752
18753
18754
18755
18756
18757
18758
18759
18760
18761
18762
18763
18764
18765
18766
18767
18768
18769
18770
18771
18772
18773
18774
18775
18776
18777
18778
18779
18780
18781
18782
18783
18784
18785
18786
18787
18788
18789
18790
18791
18792
18793
18794
18795
18796
18797
18798
18799
18800
18801
18802
18803
18804
18805
18806
18807
18808
18809
18810
18811
18812
18813
18814
18815
18816
18817
18818
18819
18820
18821
18822
18823
18824
18825
18826
18827
18828
18829
18830
18831
18832
18833
18834
18835
18836
18837
18838
18839
18840
18841
18842
18843
18844
          }else if( c=='-' && z[i+1]=='-' ){
            cEnd = '\n';
          }else if( c=='(' ){
            nParen++;
          }else if( c==')' ){
            nParen--;
            if( nLine>0 && nParen==0 && j>0 ){
              printSchemaLineN(p->out, z, j, "\n");
              j = 0;
            }
          }
          z[j++] = c;
          if( nParen==1 && cEnd==0
           && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
          ){
            if( c=='\n' ) j--;
            printSchemaLineN(p->out, z, j, "\n  ");
            j = 0;
            nLine++;
            while( IsSpace(z[i+1]) ){ i++; }
          }
        }
        z[j] = 0;
      }
      printSchemaLine(p->out, z, ";\n");
      sqlite3_free(z);
      break;
    }
    case MODE_List: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          utf8_printf(p->out,"%s%s",azCol[i],
                  i==nArg-1 ? p->rowSeparator : p->colSeparator);
        }
      }
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        char *z = azArg[i];
        if( z==0 ) z = p->nullValue;
        utf8_printf(p->out, "%s", z);
        if( i<nArg-1 ){
          utf8_printf(p->out, "%s", p->colSeparator);
        }else{
          utf8_printf(p->out, "%s", p->rowSeparator);
        }
      }
      break;
    }
    case MODE_Html: {
      if( p->cnt++==0 && p->showHeader ){
        raw_printf(p->out,"<TR>");
        for(i=0; i<nArg; i++){
          raw_printf(p->out,"<TH>");
          output_html_string(p->out, azCol[i]);
          raw_printf(p->out,"</TH>\n");
        }
        raw_printf(p->out,"</TR>\n");
      }
      if( azArg==0 ) break;
      raw_printf(p->out,"<TR>");
      for(i=0; i<nArg; i++){
        raw_printf(p->out,"<TD>");
        output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
        raw_printf(p->out,"</TD>\n");
      }
      raw_printf(p->out,"</TR>\n");
      break;
    }
    case MODE_Tcl: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          output_c_string(p->out,azCol[i] ? azCol[i] : "");
          if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
        }
        utf8_printf(p->out, "%s", p->rowSeparator);
      }
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
        if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
      }
      utf8_printf(p->out, "%s", p->rowSeparator);
      break;
    }
    case MODE_Csv: {
      setBinaryMode(p->out, 1);
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
        }
        utf8_printf(p->out, "%s", p->rowSeparator);
      }
      if( nArg>0 ){
        for(i=0; i<nArg; i++){
          output_csv(p, azArg[i], i<nArg-1);
        }
        utf8_printf(p->out, "%s", p->rowSeparator);
      }
      setTextMode(p->out, 1);
      break;
    }
    case MODE_Insert: {
      if( azArg==0 ) break;
      utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
      if( p->showHeader ){
        raw_printf(p->out,"(");
        for(i=0; i<nArg; i++){
          if( i>0 ) raw_printf(p->out, ",");
          if( quoteChar(azCol[i]) ){
            char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
            shell_check_oom(z);
            utf8_printf(p->out, "%s", z);
            sqlite3_free(z);
          }else{
            raw_printf(p->out, "%s", azCol[i]);
          }
        }
        raw_printf(p->out,")");
      }
      p->cnt++;
      for(i=0; i<nArg; i++){
        raw_printf(p->out, i>0 ? "," : " VALUES(");
        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
          utf8_printf(p->out,"NULL");
        }else if( aiType && aiType[i]==SQLITE_TEXT ){
          if( ShellHasFlag(p, SHFLG_Newlines) ){
            output_quoted_string(p->out, azArg[i]);
          }else{
            output_quoted_escaped_string(p->out, azArg[i]);
          }
        }else if( aiType && aiType[i]==SQLITE_INTEGER ){
          utf8_printf(p->out,"%s", azArg[i]);
        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
          char z[50];
          double r = sqlite3_column_double(p->pStmt, i);
          sqlite3_uint64 ur;
          memcpy(&ur,&r,sizeof(r));
          if( ur==0x7ff0000000000000LL ){
            raw_printf(p->out, "9.0e+999");
          }else if( ur==0xfff0000000000000LL ){
            raw_printf(p->out, "-9.0e+999");
          }else{
            sqlite3_int64 ir = (sqlite3_int64)r;
            if( r==(double)ir ){
              sqlite3_snprintf(50,z,"%lld.0", ir);
            }else{
              sqlite3_snprintf(50,z,"%!.20g", r);
            }
            raw_printf(p->out, "%s", z);
          }
        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
          int nBlob = sqlite3_column_bytes(p->pStmt, i);
          output_hex_blob(p->out, pBlob, nBlob);
        }else if( isNumber(azArg[i], 0) ){
          utf8_printf(p->out,"%s", azArg[i]);
        }else if( ShellHasFlag(p, SHFLG_Newlines) ){
          output_quoted_string(p->out, azArg[i]);
        }else{
          output_quoted_escaped_string(p->out, azArg[i]);
        }
      }
      raw_printf(p->out,");\n");
      break;
    }
    case MODE_Json: {
      if( azArg==0 ) break;
      if( p->cnt==0 ){
        fputs("[{", p->out);
      }else{
        fputs(",\n{", p->out);
      }
      p->cnt++;
      for(i=0; i<nArg; i++){
        output_json_string(p->out, azCol[i], -1);
        putc(':', p->out);
        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
          fputs("null",p->out);
        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
          char z[50];
          double r = sqlite3_column_double(p->pStmt, i);
          sqlite3_uint64 ur;
          memcpy(&ur,&r,sizeof(r));
          if( ur==0x7ff0000000000000LL ){
            raw_printf(p->out, "9.0e+999");
          }else if( ur==0xfff0000000000000LL ){
            raw_printf(p->out, "-9.0e+999");
          }else{
            sqlite3_snprintf(50,z,"%!.20g", r);
            raw_printf(p->out, "%s", z);
          }
        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
          int nBlob = sqlite3_column_bytes(p->pStmt, i);
          output_json_string(p->out, pBlob, nBlob);
        }else if( aiType && aiType[i]==SQLITE_TEXT ){
          output_json_string(p->out, azArg[i], -1);
        }else{
          utf8_printf(p->out,"%s", azArg[i]);
        }
        if( i<nArg-1 ){
          putc(',', p->out);
        }
      }
      putc('}', p->out);
      break;
    }
    case MODE_Quote: {
      if( azArg==0 ) break;
      if( p->cnt==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          if( i>0 ) fputs(p->colSeparator, p->out);
          output_quoted_string(p->out, azCol[i]);
        }
        fputs(p->rowSeparator, p->out);
      }
      p->cnt++;
      for(i=0; i<nArg; i++){
        if( i>0 ) fputs(p->colSeparator, p->out);
        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
          utf8_printf(p->out,"NULL");
        }else if( aiType && aiType[i]==SQLITE_TEXT ){
          output_quoted_string(p->out, azArg[i]);
        }else if( aiType && aiType[i]==SQLITE_INTEGER ){
          utf8_printf(p->out,"%s", azArg[i]);
        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
          char z[50];
          double r = sqlite3_column_double(p->pStmt, i);
          sqlite3_snprintf(50,z,"%!.20g", r);
          raw_printf(p->out, "%s", z);
        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
          int nBlob = sqlite3_column_bytes(p->pStmt, i);
          output_hex_blob(p->out, pBlob, nBlob);
        }else if( isNumber(azArg[i], 0) ){
          utf8_printf(p->out,"%s", azArg[i]);
        }else{
          output_quoted_string(p->out, azArg[i]);
        }
      }
      fputs(p->rowSeparator, p->out);
      break;
    }
    case MODE_Ascii: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
          utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
        }
        utf8_printf(p->out, "%s", p->rowSeparator);
      }
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
        utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
      }
      utf8_printf(p->out, "%s", p->rowSeparator);
      break;
    }
    case MODE_EQP: {
      eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
      break;
    }
  }







|








|







|






<
|






|
<
|
<
<
|
<




|

|
|
|

|


|

|
|
|

|





|
|

|



|
|

|








|





|






|

|

|



|


|


|



|

|


|

|


|






|

|







|




|

|

|

|


|











|
|

|






|

|


|




|

|

|


|


|







|







|

|

|




|



|

|

|








|
|

|



|
|

|







20501
20502
20503
20504
20505
20506
20507
20508
20509
20510
20511
20512
20513
20514
20515
20516
20517
20518
20519
20520
20521
20522
20523
20524
20525
20526
20527
20528
20529
20530
20531

20532
20533
20534
20535
20536
20537
20538
20539

20540


20541

20542
20543
20544
20545
20546
20547
20548
20549
20550
20551
20552
20553
20554
20555
20556
20557
20558
20559
20560
20561
20562
20563
20564
20565
20566
20567
20568
20569
20570
20571
20572
20573
20574
20575
20576
20577
20578
20579
20580
20581
20582
20583
20584
20585
20586
20587
20588
20589
20590
20591
20592
20593
20594
20595
20596
20597
20598
20599
20600
20601
20602
20603
20604
20605
20606
20607
20608
20609
20610
20611
20612
20613
20614
20615
20616
20617
20618
20619
20620
20621
20622
20623
20624
20625
20626
20627
20628
20629
20630
20631
20632
20633
20634
20635
20636
20637
20638
20639
20640
20641
20642
20643
20644
20645
20646
20647
20648
20649
20650
20651
20652
20653
20654
20655
20656
20657
20658
20659
20660
20661
20662
20663
20664
20665
20666
20667
20668
20669
20670
20671
20672
20673
20674
20675
20676
20677
20678
20679
20680
20681
20682
20683
20684
20685
20686
20687
20688
20689
20690
20691
20692
20693
20694
20695
20696
20697
20698
20699
20700
20701
20702
20703
20704
20705
20706
20707
20708
20709
20710
20711
20712
20713
20714
20715
20716
20717
20718
20719
20720
20721
20722
20723
20724
20725
20726
20727
20728
20729
20730
20731
20732
20733
20734
20735
20736
20737
20738
20739
20740
20741
20742
20743
20744
20745
20746
20747
20748
20749
20750
20751
20752
20753
20754
20755
20756
20757
20758
20759
          }else if( c=='-' && z[i+1]=='-' ){
            cEnd = '\n';
          }else if( c=='(' ){
            nParen++;
          }else if( c==')' ){
            nParen--;
            if( nLine>0 && nParen==0 && j>0 ){
              printSchemaLineN(z, j, "\n");
              j = 0;
            }
          }
          z[j++] = c;
          if( nParen==1 && cEnd==0
           && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
          ){
            if( c=='\n' ) j--;
            printSchemaLineN(z, j, "\n  ");
            j = 0;
            nLine++;
            while( IsSpace(z[i+1]) ){ i++; }
          }
        }
        z[j] = 0;
      }
      printSchemaLine(z, ";\n");
      sqlite3_free(z);
      break;
    }
    case MODE_List: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){

          oputf("%s%s",azCol[i], i==nArg-1 ? p->rowSeparator : p->colSeparator);
        }
      }
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        char *z = azArg[i];
        if( z==0 ) z = p->nullValue;
        oputz(z);

        oputz((i<nArg-1)? p->colSeparator : p->rowSeparator);


      }

      break;
    }
    case MODE_Html: {
      if( p->cnt++==0 && p->showHeader ){
        oputz("<TR>");
        for(i=0; i<nArg; i++){
          oputz("<TH>");
          output_html_string(azCol[i]);
          oputz("</TH>\n");
        }
        oputz("</TR>\n");
      }
      if( azArg==0 ) break;
      oputz("<TR>");
      for(i=0; i<nArg; i++){
        oputz("<TD>");
        output_html_string(azArg[i] ? azArg[i] : p->nullValue);
        oputz("</TD>\n");
      }
      oputz("</TR>\n");
      break;
    }
    case MODE_Tcl: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          output_c_string(azCol[i] ? azCol[i] : "");
          if(i<nArg-1) oputz(p->colSeparator);
        }
        oputz(p->rowSeparator);
      }
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        output_c_string(azArg[i] ? azArg[i] : p->nullValue);
        if(i<nArg-1) oputz(p->colSeparator);
      }
      oputz(p->rowSeparator);
      break;
    }
    case MODE_Csv: {
      setBinaryMode(p->out, 1);
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
        }
        oputz(p->rowSeparator);
      }
      if( nArg>0 ){
        for(i=0; i<nArg; i++){
          output_csv(p, azArg[i], i<nArg-1);
        }
        oputz(p->rowSeparator);
      }
      setTextMode(p->out, 1);
      break;
    }
    case MODE_Insert: {
      if( azArg==0 ) break;
      oputf("INSERT INTO %s",p->zDestTable);
      if( p->showHeader ){
        oputz("(");
        for(i=0; i<nArg; i++){
          if( i>0 ) oputz(",");
          if( quoteChar(azCol[i]) ){
            char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
            shell_check_oom(z);
            oputz(z);
            sqlite3_free(z);
          }else{
            oputf("%s", azCol[i]);
          }
        }
        oputz(")");
      }
      p->cnt++;
      for(i=0; i<nArg; i++){
        oputz(i>0 ? "," : " VALUES(");
        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
          oputz("NULL");
        }else if( aiType && aiType[i]==SQLITE_TEXT ){
          if( ShellHasFlag(p, SHFLG_Newlines) ){
            output_quoted_string(azArg[i]);
          }else{
            output_quoted_escaped_string(azArg[i]);
          }
        }else if( aiType && aiType[i]==SQLITE_INTEGER ){
          oputz(azArg[i]);
        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
          char z[50];
          double r = sqlite3_column_double(p->pStmt, i);
          sqlite3_uint64 ur;
          memcpy(&ur,&r,sizeof(r));
          if( ur==0x7ff0000000000000LL ){
            oputz("9.0e+999");
          }else if( ur==0xfff0000000000000LL ){
            oputz("-9.0e+999");
          }else{
            sqlite3_int64 ir = (sqlite3_int64)r;
            if( r==(double)ir ){
              sqlite3_snprintf(50,z,"%lld.0", ir);
            }else{
              sqlite3_snprintf(50,z,"%!.20g", r);
            }
            oputz(z);
          }
        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
          int nBlob = sqlite3_column_bytes(p->pStmt, i);
          output_hex_blob(pBlob, nBlob);
        }else if( isNumber(azArg[i], 0) ){
          oputz(azArg[i]);
        }else if( ShellHasFlag(p, SHFLG_Newlines) ){
          output_quoted_string(azArg[i]);
        }else{
          output_quoted_escaped_string(azArg[i]);
        }
      }
      oputz(");\n");
      break;
    }
    case MODE_Json: {
      if( azArg==0 ) break;
      if( p->cnt==0 ){
        fputs("[{", p->out);
      }else{
        fputs(",\n{", p->out);
      }
      p->cnt++;
      for(i=0; i<nArg; i++){
        output_json_string(azCol[i], -1);
        oputz(":");
        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
          oputz("null");
        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
          char z[50];
          double r = sqlite3_column_double(p->pStmt, i);
          sqlite3_uint64 ur;
          memcpy(&ur,&r,sizeof(r));
          if( ur==0x7ff0000000000000LL ){
            oputz("9.0e+999");
          }else if( ur==0xfff0000000000000LL ){
            oputz("-9.0e+999");
          }else{
            sqlite3_snprintf(50,z,"%!.20g", r);
            oputz(z);
          }
        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
          int nBlob = sqlite3_column_bytes(p->pStmt, i);
          output_json_string(pBlob, nBlob);
        }else if( aiType && aiType[i]==SQLITE_TEXT ){
          output_json_string(azArg[i], -1);
        }else{
          oputz(azArg[i]);
        }
        if( i<nArg-1 ){
          oputz(",");
        }
      }
      oputz("}");
      break;
    }
    case MODE_Quote: {
      if( azArg==0 ) break;
      if( p->cnt==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          if( i>0 ) fputs(p->colSeparator, p->out);
          output_quoted_string(azCol[i]);
        }
        fputs(p->rowSeparator, p->out);
      }
      p->cnt++;
      for(i=0; i<nArg; i++){
        if( i>0 ) fputs(p->colSeparator, p->out);
        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
          oputz("NULL");
        }else if( aiType && aiType[i]==SQLITE_TEXT ){
          output_quoted_string(azArg[i]);
        }else if( aiType && aiType[i]==SQLITE_INTEGER ){
          oputz(azArg[i]);
        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
          char z[50];
          double r = sqlite3_column_double(p->pStmt, i);
          sqlite3_snprintf(50,z,"%!.20g", r);
          oputz(z);
        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
          int nBlob = sqlite3_column_bytes(p->pStmt, i);
          output_hex_blob(pBlob, nBlob);
        }else if( isNumber(azArg[i], 0) ){
          oputz(azArg[i]);
        }else{
          output_quoted_string(azArg[i]);
        }
      }
      fputs(p->rowSeparator, p->out);
      break;
    }
    case MODE_Ascii: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          if( i>0 ) oputz(p->colSeparator);
          oputz(azCol[i] ? azCol[i] : "");
        }
        oputz(p->rowSeparator);
      }
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        if( i>0 ) oputz(p->colSeparator);
        oputz(azArg[i] ? azArg[i] : p->nullValue);
      }
      oputz(p->rowSeparator);
      break;
    }
    case MODE_EQP: {
      eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
      break;
    }
  }
18909
18910
18911
18912
18913
18914
18915
18916
18917
18918
18919
18920
18921
18922
18923
    "INSERT INTO [_shell$self]\n"
    "  VALUES('run','PRAGMA integrity_check','ok');\n"
    "INSERT INTO selftest(tno,op,cmd,ans)"
    "  SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
    "DROP TABLE [_shell$self];"
    ,0,0,&zErrMsg);
  if( zErrMsg ){
    utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
    sqlite3_free(zErrMsg);
  }
  sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
}


/*







|







20824
20825
20826
20827
20828
20829
20830
20831
20832
20833
20834
20835
20836
20837
20838
    "INSERT INTO [_shell$self]\n"
    "  VALUES('run','PRAGMA integrity_check','ok');\n"
    "INSERT INTO selftest(tno,op,cmd,ans)"
    "  SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
    "DROP TABLE [_shell$self];"
    ,0,0,&zErrMsg);
  if( zErrMsg ){
    eputf("SELFTEST initialization failure: %s\n", zErrMsg);
    sqlite3_free(zErrMsg);
  }
  sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
}


/*
19012
19013
19014
19015
19016
19017
19018
19019
19020
19021
19022
19023
19024
19025
19026
19027
19028
19029
19030
19031
19032
19033
19034
19035
19036
19037
19038
19039
19040
19041
19042
19043
19044
19045
19046
19047
19048
19049
19050
19051
19052
  int rc;
  int nResult;
  int i;
  const char *z;
  rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
  if( rc!=SQLITE_OK || !pSelect ){
    char *zContext = shell_error_context(zSelect, p->db);
    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
                sqlite3_errmsg(p->db), zContext);
    sqlite3_free(zContext);
    if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
    return rc;
  }
  rc = sqlite3_step(pSelect);
  nResult = sqlite3_column_count(pSelect);
  while( rc==SQLITE_ROW ){
    z = (const char*)sqlite3_column_text(pSelect, 0);
    utf8_printf(p->out, "%s", z);
    for(i=1; i<nResult; i++){
      utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
    }
    if( z==0 ) z = "";
    while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
    if( z[0] ){
      raw_printf(p->out, "\n;\n");
    }else{
      raw_printf(p->out, ";\n");
    }
    rc = sqlite3_step(pSelect);
  }
  rc = sqlite3_finalize(pSelect);
  if( rc!=SQLITE_OK ){
    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
                sqlite3_errmsg(p->db));
    if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
  }
  return rc;
}

/*
** Allocate space and save off string indicating current error.







|
|








|

|




|

|





|
<







20927
20928
20929
20930
20931
20932
20933
20934
20935
20936
20937
20938
20939
20940
20941
20942
20943
20944
20945
20946
20947
20948
20949
20950
20951
20952
20953
20954
20955
20956
20957
20958
20959

20960
20961
20962
20963
20964
20965
20966
  int rc;
  int nResult;
  int i;
  const char *z;
  rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
  if( rc!=SQLITE_OK || !pSelect ){
    char *zContext = shell_error_context(zSelect, p->db);
    oputf("/**** ERROR: (%d) %s *****/\n%s",
          rc, sqlite3_errmsg(p->db), zContext);
    sqlite3_free(zContext);
    if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
    return rc;
  }
  rc = sqlite3_step(pSelect);
  nResult = sqlite3_column_count(pSelect);
  while( rc==SQLITE_ROW ){
    z = (const char*)sqlite3_column_text(pSelect, 0);
    oputf("%s", z);
    for(i=1; i<nResult; i++){
      oputf(",%s", sqlite3_column_text(pSelect, i));
    }
    if( z==0 ) z = "";
    while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
    if( z[0] ){
      oputz("\n;\n");
    }else{
      oputz(";\n");
    }
    rc = sqlite3_step(pSelect);
  }
  rc = sqlite3_finalize(pSelect);
  if( rc!=SQLITE_OK ){
    oputf("/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));

    if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
  }
  return rc;
}

/*
** Allocate space and save off string indicating current error.
19074
19075
19076
19077
19078
19079
19080
19081
19082
19083
19084
19085
19086
19087
19088
  return zErr;
}

#ifdef __linux__
/*
** Attempt to display I/O stats on Linux using /proc/PID/io
*/
static void displayLinuxIoStats(FILE *out){
  FILE *in;
  char z[200];
  sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
  in = fopen(z, "rb");
  if( in==0 ) return;
  while( fgets(z, sizeof(z), in)!=0 ){
    static const struct {







|







20988
20989
20990
20991
20992
20993
20994
20995
20996
20997
20998
20999
21000
21001
21002
  return zErr;
}

#ifdef __linux__
/*
** Attempt to display I/O stats on Linux using /proc/PID/io
*/
static void displayLinuxIoStats(void){
  FILE *in;
  char z[200];
  sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
  in = fopen(z, "rb");
  if( in==0 ) return;
  while( fgets(z, sizeof(z), in)!=0 ){
    static const struct {
19097
19098
19099
19100
19101
19102
19103
19104
19105
19106
19107
19108
19109
19110
19111
19112
19113
19114
19115
19116
19117
19118
19119
19120
19121
19122
19123
19124
19125
19126
19127
19128
19129
19130
19131
19132
19133
19134
19135
19136
19137
19138
19139
19140
19141
19142
19143
19144
19145
19146
19147
19148
19149
19150
19151
19152
19153
19154
19155
19156
19157
19158
19159
19160
19161
19162
19163
19164
19165
19166
19167
19168
19169
19170
19171
19172
19173
19174
19175
19176
19177
19178
19179
19180
19181
19182
19183
19184
19185
19186
19187
19188
19189
19190
19191
19192
19193
19194
19195
19196
19197
19198
19199
19200
19201
19202
19203
19204
19205
19206
19207
19208
19209
19210
19211
19212
19213
19214
19215
19216
19217
19218
19219
19220
19221
19222
19223
19224
19225
19226
19227
19228
19229
19230
19231
19232
19233
19234
19235
19236
19237
19238
19239
19240
19241
19242
19243
19244
19245
19246
19247
19248
19249
19250
19251
19252
19253
19254
19255
19256
19257
19258
19259
19260
19261
19262
19263
19264
19265
19266
19267
19268
19269
19270
19271
19272
19273
19274
19275
19276
19277
19278
19279
19280
19281
19282
19283
19284
19285
19286
      { "write_bytes: ",            "Bytes written to storage:" },
      { "cancelled_write_bytes: ",  "Cancelled write bytes:"    },
    };
    int i;
    for(i=0; i<ArraySize(aTrans); i++){
      int n = strlen30(aTrans[i].zPattern);
      if( cli_strncmp(aTrans[i].zPattern, z, n)==0 ){
        utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
        break;
      }
    }
  }
  fclose(in);
}
#endif

/*
** Display a single line of status using 64-bit values.
*/
static void displayStatLine(
  ShellState *p,            /* The shell context */
  char *zLabel,             /* Label for this one line */
  char *zFormat,            /* Format for the result */
  int iStatusCtrl,          /* Which status to display */
  int bReset                /* True to reset the stats */
){
  sqlite3_int64 iCur = -1;
  sqlite3_int64 iHiwtr = -1;
  int i, nPercent;
  char zLine[200];
  sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
  for(i=0, nPercent=0; zFormat[i]; i++){
    if( zFormat[i]=='%' ) nPercent++;
  }
  if( nPercent>1 ){
    sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
  }else{
    sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
  }
  raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
}

/*
** Display memory stats.
*/
static int display_stats(
  sqlite3 *db,                /* Database to query */
  ShellState *pArg,           /* Pointer to ShellState */
  int bReset                  /* True to reset the stats */
){
  int iCur;
  int iHiwtr;
  FILE *out;
  if( pArg==0 || pArg->out==0 ) return 0;
  out = pArg->out;

  if( pArg->pStmt && pArg->statsOn==2 ){
    int nCol, i, x;
    sqlite3_stmt *pStmt = pArg->pStmt;
    char z[100];
    nCol = sqlite3_column_count(pStmt);
    raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
    for(i=0; i<nCol; i++){
      sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
#ifndef SQLITE_OMIT_DECLTYPE
      sqlite3_snprintf(30, z+x, "declared type:");
      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
#endif
#ifdef SQLITE_ENABLE_COLUMN_METADATA
      sqlite3_snprintf(30, z+x, "database name:");
      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
      sqlite3_snprintf(30, z+x, "table name:");
      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
      sqlite3_snprintf(30, z+x, "origin name:");
      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
#endif
    }
  }

  if( pArg->statsOn==3 ){
    if( pArg->pStmt ){
      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP,bReset);
      raw_printf(pArg->out, "VM-steps: %d\n", iCur);
    }
    return 0;
  }

  displayStatLine(pArg, "Memory Used:",
     "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
  displayStatLine(pArg, "Number of Outstanding Allocations:",
     "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
  if( pArg->shellFlgs & SHFLG_Pagecache ){
    displayStatLine(pArg, "Number of Pcache Pages Used:",
       "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
  }
  displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
     "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
  displayStatLine(pArg, "Largest Allocation:",
     "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
  displayStatLine(pArg, "Largest Pcache Allocation:",
     "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
#ifdef YYTRACKMAXSTACKDEPTH
  displayStatLine(pArg, "Deepest Parser Stack:",
     "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
#endif

  if( db ){
    if( pArg->shellFlgs & SHFLG_Lookaside ){
      iHiwtr = iCur = -1;
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
                        &iCur, &iHiwtr, bReset);
      raw_printf(pArg->out,
              "Lookaside Slots Used:                %d (max %d)\n",
              iCur, iHiwtr);
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
                        &iCur, &iHiwtr, bReset);
      raw_printf(pArg->out, "Successful lookaside attempts:       %d\n",
              iHiwtr);
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
                        &iCur, &iHiwtr, bReset);
      raw_printf(pArg->out, "Lookaside failures due to size:      %d\n",
              iHiwtr);
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
                        &iCur, &iHiwtr, bReset);
      raw_printf(pArg->out, "Lookaside failures due to OOM:       %d\n",
              iHiwtr);
    }
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
    raw_printf(pArg->out, "Pager Heap Usage:                    %d bytes\n",
            iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
    raw_printf(pArg->out, "Page cache hits:                     %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
    raw_printf(pArg->out, "Page cache misses:                   %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
    raw_printf(pArg->out, "Page cache writes:                   %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
    raw_printf(pArg->out, "Page cache spills:                   %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
    raw_printf(pArg->out, "Schema Heap Usage:                   %d bytes\n",
            iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
    raw_printf(pArg->out, "Statement Heap/Lookaside Usage:      %d bytes\n",
            iCur);
  }

  if( pArg->pStmt ){
    int iHit, iMiss;
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
                               bReset);
    raw_printf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
    raw_printf(pArg->out, "Sort Operations:                     %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
    raw_printf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
    iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT,
                               bReset);
    iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS,
                                bReset);
    if( iHit || iMiss ){
      raw_printf(pArg->out, "Bloom filter bypass taken:           %d/%d\n",
            iHit, iHit+iMiss);
    }
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
    raw_printf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
    raw_printf(pArg->out, "Reprepare operations:                %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
    raw_printf(pArg->out, "Number of times run:                 %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
    raw_printf(pArg->out, "Memory used by prepared stmt:        %d\n", iCur);
  }

#ifdef __linux__
  displayLinuxIoStats(pArg->out);
#endif

  /* Do not remove this machine readable comment: extra-stats-output-here */

  return 0;
}








|












<


















|












<

<






|


|


|



|

|

|







|




|

|


|


|

|

|


|








<
|
<


|
<


|
<


|
<



|
<


|


|


|


|


|
<


|
<






|

|

|





|
<


|

|

|

|



|







21011
21012
21013
21014
21015
21016
21017
21018
21019
21020
21021
21022
21023
21024
21025
21026
21027
21028
21029
21030

21031
21032
21033
21034
21035
21036
21037
21038
21039
21040
21041
21042
21043
21044
21045
21046
21047
21048
21049
21050
21051
21052
21053
21054
21055
21056
21057
21058
21059
21060
21061

21062

21063
21064
21065
21066
21067
21068
21069
21070
21071
21072
21073
21074
21075
21076
21077
21078
21079
21080
21081
21082
21083
21084
21085
21086
21087
21088
21089
21090
21091
21092
21093
21094
21095
21096
21097
21098
21099
21100
21101
21102
21103
21104
21105
21106
21107
21108
21109
21110
21111
21112
21113
21114
21115
21116
21117
21118
21119

21120

21121
21122
21123

21124
21125
21126

21127
21128
21129

21130
21131
21132
21133

21134
21135
21136
21137
21138
21139
21140
21141
21142
21143
21144
21145
21146
21147
21148

21149
21150
21151

21152
21153
21154
21155
21156
21157
21158
21159
21160
21161
21162
21163
21164
21165
21166
21167
21168

21169
21170
21171
21172
21173
21174
21175
21176
21177
21178
21179
21180
21181
21182
21183
21184
21185
21186
21187
21188
      { "write_bytes: ",            "Bytes written to storage:" },
      { "cancelled_write_bytes: ",  "Cancelled write bytes:"    },
    };
    int i;
    for(i=0; i<ArraySize(aTrans); i++){
      int n = strlen30(aTrans[i].zPattern);
      if( cli_strncmp(aTrans[i].zPattern, z, n)==0 ){
        oputf("%-36s %s", aTrans[i].zDesc, &z[n]);
        break;
      }
    }
  }
  fclose(in);
}
#endif

/*
** Display a single line of status using 64-bit values.
*/
static void displayStatLine(

  char *zLabel,             /* Label for this one line */
  char *zFormat,            /* Format for the result */
  int iStatusCtrl,          /* Which status to display */
  int bReset                /* True to reset the stats */
){
  sqlite3_int64 iCur = -1;
  sqlite3_int64 iHiwtr = -1;
  int i, nPercent;
  char zLine[200];
  sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
  for(i=0, nPercent=0; zFormat[i]; i++){
    if( zFormat[i]=='%' ) nPercent++;
  }
  if( nPercent>1 ){
    sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
  }else{
    sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
  }
  oputf("%-36s %s\n", zLabel, zLine);
}

/*
** Display memory stats.
*/
static int display_stats(
  sqlite3 *db,                /* Database to query */
  ShellState *pArg,           /* Pointer to ShellState */
  int bReset                  /* True to reset the stats */
){
  int iCur;
  int iHiwtr;

  if( pArg==0 || pArg->out==0 ) return 0;


  if( pArg->pStmt && pArg->statsOn==2 ){
    int nCol, i, x;
    sqlite3_stmt *pStmt = pArg->pStmt;
    char z[100];
    nCol = sqlite3_column_count(pStmt);
    oputf("%-36s %d\n", "Number of output columns:", nCol);
    for(i=0; i<nCol; i++){
      sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
      oputf("%-36s %s\n", z, sqlite3_column_name(pStmt,i));
#ifndef SQLITE_OMIT_DECLTYPE
      sqlite3_snprintf(30, z+x, "declared type:");
      oputf("%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
#endif
#ifdef SQLITE_ENABLE_COLUMN_METADATA
      sqlite3_snprintf(30, z+x, "database name:");
      oputf("%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
      sqlite3_snprintf(30, z+x, "table name:");
      oputf("%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
      sqlite3_snprintf(30, z+x, "origin name:");
      oputf("%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
#endif
    }
  }

  if( pArg->statsOn==3 ){
    if( pArg->pStmt ){
      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP,bReset);
      oputf("VM-steps: %d\n", iCur);
    }
    return 0;
  }

  displayStatLine("Memory Used:",
     "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
  displayStatLine("Number of Outstanding Allocations:",
     "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
  if( pArg->shellFlgs & SHFLG_Pagecache ){
    displayStatLine("Number of Pcache Pages Used:",
       "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
  }
  displayStatLine("Number of Pcache Overflow Bytes:",
     "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
  displayStatLine("Largest Allocation:",
     "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
  displayStatLine("Largest Pcache Allocation:",
     "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
#ifdef YYTRACKMAXSTACKDEPTH
  displayStatLine("Deepest Parser Stack:",
     "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
#endif

  if( db ){
    if( pArg->shellFlgs & SHFLG_Lookaside ){
      iHiwtr = iCur = -1;
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
                        &iCur, &iHiwtr, bReset);

      oputf("Lookaside Slots Used:                %d (max %d)\n", iCur, iHiwtr);

      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
                        &iCur, &iHiwtr, bReset);
      oputf("Successful lookaside attempts:       %d\n", iHiwtr);

      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
                        &iCur, &iHiwtr, bReset);
      oputf("Lookaside failures due to size:      %d\n", iHiwtr);

      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
                        &iCur, &iHiwtr, bReset);
      oputf("Lookaside failures due to OOM:       %d\n", iHiwtr);

    }
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
    oputf("Pager Heap Usage:                    %d bytes\n", iCur);

    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
    oputf("Page cache hits:                     %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
    oputf("Page cache misses:                   %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
    oputf("Page cache writes:                   %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
    oputf("Page cache spills:                   %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
    oputf("Schema Heap Usage:                   %d bytes\n", iCur);

    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
    oputf("Statement Heap/Lookaside Usage:      %d bytes\n", iCur);

  }

  if( pArg->pStmt ){
    int iHit, iMiss;
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
                               bReset);
    oputf("Fullscan Steps:                      %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
    oputf("Sort Operations:                     %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
    oputf("Autoindex Inserts:                   %d\n", iCur);
    iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT,
                               bReset);
    iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS,
                                bReset);
    if( iHit || iMiss ){
      oputf("Bloom filter bypass taken:           %d/%d\n", iHit, iHit+iMiss);

    }
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
    oputf("Virtual Machine Steps:               %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
    oputf("Reprepare operations:                %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
    oputf("Number of times run:                 %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
    oputf("Memory used by prepared stmt:        %d\n", iCur);
  }

#ifdef __linux__
  displayLinuxIoStats();
#endif

  /* Do not remove this machine readable comment: extra-stats-output-here */

  return 0;
}

19507
19508
19509
19510
19511
19512
19513
19514
19515
19516
19517
19518
19519
19520
19521
  ShellState *pArg                /* Pointer to ShellState */
){
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
  UNUSED_PARAMETER(db);
  UNUSED_PARAMETER(pArg);
#else
  if( pArg->scanstatsOn==3 ){
    const char *zSql = 
      "  SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec,"
      "   round(ncycle*100.0 / (sum(ncycle) OVER ()), 2)||'%' AS cycles"
      "   FROM bytecode(?)";

    int rc = SQLITE_OK;
    sqlite3_stmt *pStmt = 0;
    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);







|







21409
21410
21411
21412
21413
21414
21415
21416
21417
21418
21419
21420
21421
21422
21423
  ShellState *pArg                /* Pointer to ShellState */
){
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
  UNUSED_PARAMETER(db);
  UNUSED_PARAMETER(pArg);
#else
  if( pArg->scanstatsOn==3 ){
    const char *zSql =
      "  SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec,"
      "   round(ncycle*100.0 / (sum(ncycle) OVER ()), 2)||'%' AS cycles"
      "   FROM bytecode(?)";

    int rc = SQLITE_OK;
    sqlite3_stmt *pStmt = 0;
    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
19653
19654
19655
19656
19657
19658
19659
19660
19661
19662
19663
19664
19665
19666
19667
19668
19669
19670
19671
19672
19673
19674
19675
19676
19677
19678
19679
19680
19681
19682
19683
19684
19685
19686
19687
19688
19689
19690
19691
19692
19693
19694
19695
19696
19697
19698
19699
19700
#define BOX_234  "\342\224\254"  /* U+252c -,- */
#define BOX_124  "\342\224\264"  /* U+2534 -'- */
#define BOX_1234 "\342\224\274"  /* U+253c -|- */

/* Draw horizontal line N characters long using unicode box
** characters
*/
static void print_box_line(FILE *out, int N){
  const char zDash[] =
      BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
      BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
  const int nDash = sizeof(zDash) - 1;
  N *= 3;
  while( N>nDash ){
    utf8_printf(out, zDash);
    N -= nDash;
  }
  utf8_printf(out, "%.*s", N, zDash);
}

/*
** Draw a horizontal separator for a MODE_Box table.
*/
static void print_box_row_separator(
  ShellState *p,
  int nArg,
  const char *zSep1,
  const char *zSep2,
  const char *zSep3
){
  int i;
  if( nArg>0 ){
    utf8_printf(p->out, "%s", zSep1);
    print_box_line(p->out, p->actualWidth[0]+2);
    for(i=1; i<nArg; i++){
      utf8_printf(p->out, "%s", zSep2);
      print_box_line(p->out, p->actualWidth[i]+2);
    }
    utf8_printf(p->out, "%s", zSep3);
  }
  fputs("\n", p->out);
}

/*
** z[] is a line of text that is to be displayed the .mode box or table or
** similar tabular formats.  z[] might contain control characters such
** as \n, \t, \f, or \r.
**







|






|


|














|
|

|
|

|

|







21555
21556
21557
21558
21559
21560
21561
21562
21563
21564
21565
21566
21567
21568
21569
21570
21571
21572
21573
21574
21575
21576
21577
21578
21579
21580
21581
21582
21583
21584
21585
21586
21587
21588
21589
21590
21591
21592
21593
21594
21595
21596
21597
21598
21599
21600
21601
21602
#define BOX_234  "\342\224\254"  /* U+252c -,- */
#define BOX_124  "\342\224\264"  /* U+2534 -'- */
#define BOX_1234 "\342\224\274"  /* U+253c -|- */

/* Draw horizontal line N characters long using unicode box
** characters
*/
static void print_box_line(int N){
  const char zDash[] =
      BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
      BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
  const int nDash = sizeof(zDash) - 1;
  N *= 3;
  while( N>nDash ){
    oputz(zDash);
    N -= nDash;
  }
  oputf("%.*s", N, zDash);
}

/*
** Draw a horizontal separator for a MODE_Box table.
*/
static void print_box_row_separator(
  ShellState *p,
  int nArg,
  const char *zSep1,
  const char *zSep2,
  const char *zSep3
){
  int i;
  if( nArg>0 ){
    oputz(zSep1);
    print_box_line(p->actualWidth[0]+2);
    for(i=1; i<nArg; i++){
      oputz(zSep2);
      print_box_line(p->actualWidth[i]+2);
    }
    oputz(zSep3);
  }
  oputz("\n");
}

/*
** z[] is a line of text that is to be displayed the .mode box or table or
** similar tabular formats.  z[] might contain control characters such
** as \n, \t, \f, or \r.
**
19855
19856
19857
19858
19859
19860
19861

19862
19863
19864
19865
19866
19867
19868
  int bw = p->cmOpts.bWordWrap;
  const char *zEmpty = "";
  const char *zShowNull = p->nullValue;

  rc = sqlite3_step(pStmt);
  if( rc!=SQLITE_ROW ) return;
  nColumn = sqlite3_column_count(pStmt);

  nAlloc = nColumn*4;
  if( nAlloc<=0 ) nAlloc = 1;
  azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
  shell_check_oom(azData);
  azNextLine = sqlite3_malloc64( nColumn*sizeof(char*) );
  shell_check_oom(azNextLine);
  memset((void*)azNextLine, 0, nColumn*sizeof(char*) );







>







21757
21758
21759
21760
21761
21762
21763
21764
21765
21766
21767
21768
21769
21770
21771
  int bw = p->cmOpts.bWordWrap;
  const char *zEmpty = "";
  const char *zShowNull = p->nullValue;

  rc = sqlite3_step(pStmt);
  if( rc!=SQLITE_ROW ) return;
  nColumn = sqlite3_column_count(pStmt);
  if( nColumn==0 ) goto columnar_end;
  nAlloc = nColumn*4;
  if( nAlloc<=0 ) nAlloc = 1;
  azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
  shell_check_oom(azData);
  azNextLine = sqlite3_malloc64( nColumn*sizeof(char*) );
  shell_check_oom(azNextLine);
  memset((void*)azNextLine, 0, nColumn*sizeof(char*) );
19940
19941
19942
19943
19944
19945
19946
19947
19948
19949
19950
19951
19952
19953
19954
19955
19956
19957
19958
19959
19960
19961
19962
19963
19964
19965
19966
19967
19968
19969
19970
19971
19972
19973
19974
19975
19976
19977
19978
19979
19980
19981
19982
19983
19984
19985
19986
19987
19988
19989
19990
19991
19992
19993
19994
19995
19996
19997
19998
19999
20000
20001
20002
20003
20004
20005
20006
20007
20008
20009
20010
20011
20012
20013
20014
20015
20016
20017
20018
20019
20020
20021
20022
20023
20024
20025
20026
20027
20028
20029
20030
20031
20032
20033
20034
20035
20036
20037
20038
20039
20040
20041
20042
20043
20044
20045
20046
20047
20048
20049
    z = azData[i];
    if( z==0 ) z = (char*)zEmpty;
    n = strlenChar(z);
    j = i%nColumn;
    if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
  }
  if( seenInterrupt ) goto columnar_end;
  if( nColumn==0 ) goto columnar_end;
  switch( p->cMode ){
    case MODE_Column: {
      colSep = "  ";
      rowSep = "\n";
      if( p->showHeader ){
        for(i=0; i<nColumn; i++){
          w = p->actualWidth[i];
          if( p->colWidth[i]<0 ) w = -w;
          utf8_width_print(p->out, w, azData[i]);
          fputs(i==nColumn-1?"\n":"  ", p->out);
        }
        for(i=0; i<nColumn; i++){
          print_dashes(p->out, p->actualWidth[i]);
          fputs(i==nColumn-1?"\n":"  ", p->out);
        }
      }
      break;
    }
    case MODE_Table: {
      colSep = " | ";
      rowSep = " |\n";
      print_row_separator(p, nColumn, "+");
      fputs("| ", p->out);
      for(i=0; i<nColumn; i++){
        w = p->actualWidth[i];
        n = strlenChar(azData[i]);
        utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
        fputs(i==nColumn-1?" |\n":" | ", p->out);
      }
      print_row_separator(p, nColumn, "+");
      break;
    }
    case MODE_Markdown: {
      colSep = " | ";
      rowSep = " |\n";
      fputs("| ", p->out);
      for(i=0; i<nColumn; i++){
        w = p->actualWidth[i];
        n = strlenChar(azData[i]);
        utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
        fputs(i==nColumn-1?" |\n":" | ", p->out);
      }
      print_row_separator(p, nColumn, "|");
      break;
    }
    case MODE_Box: {
      colSep = " " BOX_13 " ";
      rowSep = " " BOX_13 "\n";
      print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
      utf8_printf(p->out, BOX_13 " ");
      for(i=0; i<nColumn; i++){
        w = p->actualWidth[i];
        n = strlenChar(azData[i]);
        utf8_printf(p->out, "%*s%s%*s%s",
            (w-n)/2, "", azData[i], (w-n+1)/2, "",
            i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
      }
      print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
      break;
    }
  }
  for(i=nColumn, j=0; i<nTotal; i++, j++){
    if( j==0 && p->cMode!=MODE_Column ){
      utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
    }
    z = azData[i];
    if( z==0 ) z = p->nullValue;
    w = p->actualWidth[j];
    if( p->colWidth[j]<0 ) w = -w;
    utf8_width_print(p->out, w, z);
    if( j==nColumn-1 ){
      utf8_printf(p->out, "%s", rowSep);
      if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1<nTotal ){
        if( p->cMode==MODE_Table ){
          print_row_separator(p, nColumn, "+");
        }else if( p->cMode==MODE_Box ){
          print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
        }else if( p->cMode==MODE_Column ){
          raw_printf(p->out, "\n");
        }
      }
      j = -1;
      if( seenInterrupt ) goto columnar_end;
    }else{
      utf8_printf(p->out, "%s", colSep);
    }
  }
  if( p->cMode==MODE_Table ){
    print_row_separator(p, nColumn, "+");
  }else if( p->cMode==MODE_Box ){
    print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
  }
columnar_end:
  if( seenInterrupt ){
    utf8_printf(p->out, "Interrupt\n");
  }
  nData = (nRow+1)*nColumn;
  for(i=0; i<nData; i++){
    z = azData[i];
    if( z!=zEmpty && z!=zShowNull ) free(azData[i]);
  }
  sqlite3_free(azData);







<








|



|













|
|











|
|








|



|
|
|







|





|

|






|





|









|







21843
21844
21845
21846
21847
21848
21849

21850
21851
21852
21853
21854
21855
21856
21857
21858
21859
21860
21861
21862
21863
21864
21865
21866
21867
21868
21869
21870
21871
21872
21873
21874
21875
21876
21877
21878
21879
21880
21881
21882
21883
21884
21885
21886
21887
21888
21889
21890
21891
21892
21893
21894
21895
21896
21897
21898
21899
21900
21901
21902
21903
21904
21905
21906
21907
21908
21909
21910
21911
21912
21913
21914
21915
21916
21917
21918
21919
21920
21921
21922
21923
21924
21925
21926
21927
21928
21929
21930
21931
21932
21933
21934
21935
21936
21937
21938
21939
21940
21941
21942
21943
21944
21945
21946
21947
21948
21949
21950
21951
    z = azData[i];
    if( z==0 ) z = (char*)zEmpty;
    n = strlenChar(z);
    j = i%nColumn;
    if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
  }
  if( seenInterrupt ) goto columnar_end;

  switch( p->cMode ){
    case MODE_Column: {
      colSep = "  ";
      rowSep = "\n";
      if( p->showHeader ){
        for(i=0; i<nColumn; i++){
          w = p->actualWidth[i];
          if( p->colWidth[i]<0 ) w = -w;
          utf8_width_print(w, azData[i]);
          fputs(i==nColumn-1?"\n":"  ", p->out);
        }
        for(i=0; i<nColumn; i++){
          print_dashes(p->actualWidth[i]);
          fputs(i==nColumn-1?"\n":"  ", p->out);
        }
      }
      break;
    }
    case MODE_Table: {
      colSep = " | ";
      rowSep = " |\n";
      print_row_separator(p, nColumn, "+");
      fputs("| ", p->out);
      for(i=0; i<nColumn; i++){
        w = p->actualWidth[i];
        n = strlenChar(azData[i]);
        oputf("%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
        oputz(i==nColumn-1?" |\n":" | ");
      }
      print_row_separator(p, nColumn, "+");
      break;
    }
    case MODE_Markdown: {
      colSep = " | ";
      rowSep = " |\n";
      fputs("| ", p->out);
      for(i=0; i<nColumn; i++){
        w = p->actualWidth[i];
        n = strlenChar(azData[i]);
        oputf("%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
        oputz(i==nColumn-1?" |\n":" | ");
      }
      print_row_separator(p, nColumn, "|");
      break;
    }
    case MODE_Box: {
      colSep = " " BOX_13 " ";
      rowSep = " " BOX_13 "\n";
      print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
      oputz(BOX_13 " ");
      for(i=0; i<nColumn; i++){
        w = p->actualWidth[i];
        n = strlenChar(azData[i]);
        oputf("%*s%s%*s%s",
              (w-n)/2, "", azData[i], (w-n+1)/2, "",
              i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
      }
      print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
      break;
    }
  }
  for(i=nColumn, j=0; i<nTotal; i++, j++){
    if( j==0 && p->cMode!=MODE_Column ){
      oputz(p->cMode==MODE_Box?BOX_13" ":"| ");
    }
    z = azData[i];
    if( z==0 ) z = p->nullValue;
    w = p->actualWidth[j];
    if( p->colWidth[j]<0 ) w = -w;
    utf8_width_print(w, z);
    if( j==nColumn-1 ){
      oputz(rowSep);
      if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1<nTotal ){
        if( p->cMode==MODE_Table ){
          print_row_separator(p, nColumn, "+");
        }else if( p->cMode==MODE_Box ){
          print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
        }else if( p->cMode==MODE_Column ){
          oputz("\n");
        }
      }
      j = -1;
      if( seenInterrupt ) goto columnar_end;
    }else{
      oputz(colSep);
    }
  }
  if( p->cMode==MODE_Table ){
    print_row_separator(p, nColumn, "+");
  }else if( p->cMode==MODE_Box ){
    print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
  }
columnar_end:
  if( seenInterrupt ){
    oputz("Interrupt\n");
  }
  nData = (nRow+1)*nColumn;
  for(i=0; i<nData; i++){
    z = azData[i];
    if( z!=zEmpty && z!=zShowNull ) free(azData[i]);
  }
  sqlite3_free(azData);
20174
20175
20176
20177
20178
20179
20180
20181
20182
20183
20184
20185
20186
20187
20188
20189
20190
20191
20192
20193
20194
20195
20196
20197
20198
20199
20200
20201
20202
20203
20204
20205
20206
20207
20208
20209
20210
20211
  char **pzErr
){
  int rc = SQLITE_OK;
  sqlite3expert *p = pState->expert.pExpert;
  assert( p );
  assert( bCancel || pzErr==0 || *pzErr==0 );
  if( bCancel==0 ){
    FILE *out = pState->out;
    int bVerbose = pState->expert.bVerbose;

    rc = sqlite3_expert_analyze(p, pzErr);
    if( rc==SQLITE_OK ){
      int nQuery = sqlite3_expert_count(p);
      int i;

      if( bVerbose ){
        const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
        raw_printf(out, "-- Candidates -----------------------------\n");
        raw_printf(out, "%s\n", zCand);
      }
      for(i=0; i<nQuery; i++){
        const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
        const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
        const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
        if( zIdx==0 ) zIdx = "(no new indexes)\n";
        if( bVerbose ){
          raw_printf(out, "-- Query %d --------------------------------\n",i+1);
          raw_printf(out, "%s\n\n", zSql);
        }
        raw_printf(out, "%s\n", zIdx);
        raw_printf(out, "%s\n", zEQP);
      }
    }
  }
  sqlite3_expert_destroy(p);
  pState->expert.pExpert = 0;
  return rc;
}







<









|
|







|
|

|
|







22076
22077
22078
22079
22080
22081
22082

22083
22084
22085
22086
22087
22088
22089
22090
22091
22092
22093
22094
22095
22096
22097
22098
22099
22100
22101
22102
22103
22104
22105
22106
22107
22108
22109
22110
22111
22112
  char **pzErr
){
  int rc = SQLITE_OK;
  sqlite3expert *p = pState->expert.pExpert;
  assert( p );
  assert( bCancel || pzErr==0 || *pzErr==0 );
  if( bCancel==0 ){

    int bVerbose = pState->expert.bVerbose;

    rc = sqlite3_expert_analyze(p, pzErr);
    if( rc==SQLITE_OK ){
      int nQuery = sqlite3_expert_count(p);
      int i;

      if( bVerbose ){
        const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
        oputz("-- Candidates -----------------------------\n");
        oputf("%s\n", zCand);
      }
      for(i=0; i<nQuery; i++){
        const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
        const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
        const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
        if( zIdx==0 ) zIdx = "(no new indexes)\n";
        if( bVerbose ){
          oputf("-- Query %d --------------------------------\n",i+1);
          oputf("%s\n\n", zSql);
        }
        oputf("%s\n", zIdx);
        oputf("%s\n", zEQP);
      }
    }
  }
  sqlite3_expert_destroy(p);
  pState->expert.pExpert = 0;
  return rc;
}
20232
20233
20234
20235
20236
20237
20238
20239
20240
20241
20242
20243
20244
20245
20246
20247
20248
20249
20250
20251
20252
20253
20254
20255
20256
20257
20258
20259
20260
20261
20262
20263
20264
20265
20266
    if( z[0]=='-' && z[1]=='-' ) z++;
    n = strlen30(z);
    if( n>=2 && 0==cli_strncmp(z, "-verbose", n) ){
      pState->expert.bVerbose = 1;
    }
    else if( n>=2 && 0==cli_strncmp(z, "-sample", n) ){
      if( i==(nArg-1) ){
        raw_printf(stderr, "option requires an argument: %s\n", z);
        rc = SQLITE_ERROR;
      }else{
        iSample = (int)integerValue(azArg[++i]);
        if( iSample<0 || iSample>100 ){
          raw_printf(stderr, "value out of range: %s\n", azArg[i]);
          rc = SQLITE_ERROR;
        }
      }
    }
    else{
      raw_printf(stderr, "unknown option: %s\n", z);
      rc = SQLITE_ERROR;
    }
  }

  if( rc==SQLITE_OK ){
    pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
    if( pState->expert.pExpert==0 ){
      raw_printf(stderr, "sqlite3_expert_new: %s\n",
                 zErr ? zErr : "out of memory");
      rc = SQLITE_ERROR;
    }else{
      sqlite3_expert_config(
          pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
      );
    }
  }







|




|





|







<
|







22133
22134
22135
22136
22137
22138
22139
22140
22141
22142
22143
22144
22145
22146
22147
22148
22149
22150
22151
22152
22153
22154
22155
22156
22157
22158

22159
22160
22161
22162
22163
22164
22165
22166
    if( z[0]=='-' && z[1]=='-' ) z++;
    n = strlen30(z);
    if( n>=2 && 0==cli_strncmp(z, "-verbose", n) ){
      pState->expert.bVerbose = 1;
    }
    else if( n>=2 && 0==cli_strncmp(z, "-sample", n) ){
      if( i==(nArg-1) ){
        eputf("option requires an argument: %s\n", z);
        rc = SQLITE_ERROR;
      }else{
        iSample = (int)integerValue(azArg[++i]);
        if( iSample<0 || iSample>100 ){
          eputf("value out of range: %s\n", azArg[i]);
          rc = SQLITE_ERROR;
        }
      }
    }
    else{
      eputf("unknown option: %s\n", z);
      rc = SQLITE_ERROR;
    }
  }

  if( rc==SQLITE_OK ){
    pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
    if( pState->expert.pExpert==0 ){

      eputf("sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory");
      rc = SQLITE_ERROR;
    }else{
      sqlite3_expert_config(
          pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
      );
    }
  }
20579
20580
20581
20582
20583
20584
20585
20586
20587
20588
20589
20590
20591
20592
20593
20594
20595
20596
20597
20598
20599
20600
20601
20602
20603
20604
20605
20606
20607
20608
20609
20610
20611
20612
20613
20614
20615
  zSql = azArg[2];
  if( zTable==0 ) return 0;
  if( zType==0 ) return 0;
  dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
  noSys    = (p->shellFlgs & SHFLG_DumpNoSys)!=0;

  if( cli_strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
    if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
  }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
    if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
  }else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){
    return 0;
  }else if( dataOnly ){
    /* no-op */
  }else if( cli_strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
    char *zIns;
    if( !p->writableSchema ){
      raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
      p->writableSchema = 1;
    }
    zIns = sqlite3_mprintf(
       "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
       "VALUES('table','%q','%q',0,'%q');",
       zTable, zTable, zSql);
    shell_check_oom(zIns);
    utf8_printf(p->out, "%s\n", zIns);
    sqlite3_free(zIns);
    return 0;
  }else{
    printSchemaLine(p->out, zSql, ";\n");
  }

  if( cli_strcmp(zType, "table")==0 ){
    ShellText sSelect;
    ShellText sTable;
    char **azCol;
    int i;







|

|







|







|



|







22479
22480
22481
22482
22483
22484
22485
22486
22487
22488
22489
22490
22491
22492
22493
22494
22495
22496
22497
22498
22499
22500
22501
22502
22503
22504
22505
22506
22507
22508
22509
22510
22511
22512
22513
22514
22515
  zSql = azArg[2];
  if( zTable==0 ) return 0;
  if( zType==0 ) return 0;
  dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
  noSys    = (p->shellFlgs & SHFLG_DumpNoSys)!=0;

  if( cli_strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
    if( !dataOnly ) oputz("DELETE FROM sqlite_sequence;\n");
  }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
    if( !dataOnly ) oputz("ANALYZE sqlite_schema;\n");
  }else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){
    return 0;
  }else if( dataOnly ){
    /* no-op */
  }else if( cli_strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
    char *zIns;
    if( !p->writableSchema ){
      oputz("PRAGMA writable_schema=ON;\n");
      p->writableSchema = 1;
    }
    zIns = sqlite3_mprintf(
       "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
       "VALUES('table','%q','%q',0,'%q');",
       zTable, zTable, zSql);
    shell_check_oom(zIns);
    oputf("%s\n", zIns);
    sqlite3_free(zIns);
    return 0;
  }else{
    printSchemaLine(zSql, ";\n");
  }

  if( cli_strcmp(zType, "table")==0 ){
    ShellText sSelect;
    ShellText sTable;
    char **azCol;
    int i;
20659
20660
20661
20662
20663
20664
20665
20666
20667
20668
20669
20670
20671
20672
20673

    savedDestTable = p->zDestTable;
    savedMode = p->mode;
    p->zDestTable = sTable.z;
    p->mode = p->cMode = MODE_Insert;
    rc = shell_exec(p, sSelect.z, 0);
    if( (rc&0xff)==SQLITE_CORRUPT ){
      raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
      toggleSelectOrder(p->db);
      shell_exec(p, sSelect.z, 0);
      toggleSelectOrder(p->db);
    }
    p->zDestTable = savedDestTable;
    p->mode = savedMode;
    freeText(&sTable);







|







22559
22560
22561
22562
22563
22564
22565
22566
22567
22568
22569
22570
22571
22572
22573

    savedDestTable = p->zDestTable;
    savedMode = p->mode;
    p->zDestTable = sTable.z;
    p->mode = p->cMode = MODE_Insert;
    rc = shell_exec(p, sSelect.z, 0);
    if( (rc&0xff)==SQLITE_CORRUPT ){
      oputz("/****** CORRUPTION ERROR *******/\n");
      toggleSelectOrder(p->db);
      shell_exec(p, sSelect.z, 0);
      toggleSelectOrder(p->db);
    }
    p->zDestTable = savedDestTable;
    p->mode = savedMode;
    freeText(&sTable);
20690
20691
20692
20693
20694
20695
20696
20697
20698
20699
20700
20701
20702
20703
20704
20705
20706
20707
20708
20709
20710
20711
20712
20713
20714
20715
){
  int rc;
  char *zErr = 0;
  rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
  if( rc==SQLITE_CORRUPT ){
    char *zQ2;
    int len = strlen30(zQuery);
    raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
    if( zErr ){
      utf8_printf(p->out, "/****** %s ******/\n", zErr);
      sqlite3_free(zErr);
      zErr = 0;
    }
    zQ2 = malloc( len+100 );
    if( zQ2==0 ) return rc;
    sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
    rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
    if( rc ){
      utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
    }else{
      rc = SQLITE_CORRUPT;
    }
    sqlite3_free(zErr);
    free(zQ2);
  }
  return rc;







|

|








|







22590
22591
22592
22593
22594
22595
22596
22597
22598
22599
22600
22601
22602
22603
22604
22605
22606
22607
22608
22609
22610
22611
22612
22613
22614
22615
){
  int rc;
  char *zErr = 0;
  rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
  if( rc==SQLITE_CORRUPT ){
    char *zQ2;
    int len = strlen30(zQuery);
    oputz("/****** CORRUPTION ERROR *******/\n");
    if( zErr ){
      oputf("/****** %s ******/\n", zErr);
      sqlite3_free(zErr);
      zErr = 0;
    }
    zQ2 = malloc( len+100 );
    if( zQ2==0 ) return rc;
    sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
    rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
    if( rc ){
      oputf("/****** ERROR: %s ******/\n", zErr);
    }else{
      rc = SQLITE_CORRUPT;
    }
    sqlite3_free(zErr);
    free(zQ2);
  }
  return rc;
20825
20826
20827
20828
20829
20830
20831

20832
20833
20834
20835
20836
20837
20838
#endif
#ifndef SQLITE_OMIT_TEST_CONTROL
  ",imposter INDEX TABLE    Create imposter table TABLE on index INDEX",
#endif
  ".indexes ?TABLE?         Show names of indexes",
  "                           If TABLE is specified, only show indexes for",
  "                           tables matching TABLE using the LIKE operator.",

#ifdef SQLITE_ENABLE_IOTRACE
  ",iotrace FILE            Enable I/O diagnostic logging to FILE",
#endif
  ".limit ?LIMIT? ?VAL?     Display or change the value of an SQLITE_LIMIT",
  ".lint OPTIONS            Report potential schema issues.",
  "     Options:",
  "        fkey-indexes     Find missing foreign key indexes",







>







22725
22726
22727
22728
22729
22730
22731
22732
22733
22734
22735
22736
22737
22738
22739
#endif
#ifndef SQLITE_OMIT_TEST_CONTROL
  ",imposter INDEX TABLE    Create imposter table TABLE on index INDEX",
#endif
  ".indexes ?TABLE?         Show names of indexes",
  "                           If TABLE is specified, only show indexes for",
  "                           tables matching TABLE using the LIKE operator.",
  ".intck ?STEPS_PER_UNLOCK?  Run an incremental integrity check on the db",
#ifdef SQLITE_ENABLE_IOTRACE
  ",iotrace FILE            Enable I/O diagnostic logging to FILE",
#endif
  ".limit ?LIMIT? ?VAL?     Display or change the value of an SQLITE_LIMIT",
  ".lint OPTIONS            Report potential schema issues.",
  "     Options:",
  "        fkey-indexes     Find missing foreign key indexes",
21057
21058
21059
21060
21061
21062
21063
21064
21065
21066
21067
21068
21069
21070
21071
21072
21073
21074
21075
21076
21077
21078
21079
21080
21081
21082
21083
21084
21085
21086
21087
21088
21089
21090
21091
21092
21093
21094
21095
21096
21097
21098
21099
21100
21101
21102
21103
21104
21105
21106
21107
21108
21109
21110
21111
21112
21113
21114
21115
        break;
      default:
        hh &= ~HH_Summary;
        break;
      }
      if( ((hw^hh)&HH_Undoc)==0 ){
        if( (hh&HH_Summary)!=0 ){
          utf8_printf(out, ".%s\n", azHelp[i]+1);
          ++n;
        }else if( (hw&HW_SummaryOnly)==0 ){
          utf8_printf(out, "%s\n", azHelp[i]);
        }
      }
    }
  }else{
    /* Seek documented commands for which zPattern is an exact prefix */
    zPat = sqlite3_mprintf(".%s*", zPattern);
    shell_check_oom(zPat);
    for(i=0; i<ArraySize(azHelp); i++){
      if( sqlite3_strglob(zPat, azHelp[i])==0 ){
        utf8_printf(out, "%s\n", azHelp[i]);
        j = i+1;
        n++;
      }
    }
    sqlite3_free(zPat);
    if( n ){
      if( n==1 ){
        /* when zPattern is a prefix of exactly one command, then include
        ** the details of that command, which should begin at offset j */
        while( j<ArraySize(azHelp)-1 && azHelp[j][0]==' ' ){
          utf8_printf(out, "%s\n", azHelp[j]);
          j++;
        }
      }
      return n;
    }
    /* Look for documented commands that contain zPattern anywhere.
    ** Show complete text of all documented commands that match. */
    zPat = sqlite3_mprintf("%%%s%%", zPattern);
    shell_check_oom(zPat);
    for(i=0; i<ArraySize(azHelp); i++){
      if( azHelp[i][0]==',' ){
        while( i<ArraySize(azHelp)-1 && azHelp[i+1][0]==' ' ) ++i;
        continue;
      }
      if( azHelp[i][0]=='.' ) j = i;
      if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
        utf8_printf(out, "%s\n", azHelp[j]);
        while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]==' ' ){
          j++;
          utf8_printf(out, "%s\n", azHelp[j]);
        }
        i = j;
        n++;
      }
    }
    sqlite3_free(zPat);
  }







|


|









|










|
















|


|







22958
22959
22960
22961
22962
22963
22964
22965
22966
22967
22968
22969
22970
22971
22972
22973
22974
22975
22976
22977
22978
22979
22980
22981
22982
22983
22984
22985
22986
22987
22988
22989
22990
22991
22992
22993
22994
22995
22996
22997
22998
22999
23000
23001
23002
23003
23004
23005
23006
23007
23008
23009
23010
23011
23012
23013
23014
23015
23016
        break;
      default:
        hh &= ~HH_Summary;
        break;
      }
      if( ((hw^hh)&HH_Undoc)==0 ){
        if( (hh&HH_Summary)!=0 ){
          sputf(out, ".%s\n", azHelp[i]+1);
          ++n;
        }else if( (hw&HW_SummaryOnly)==0 ){
          sputf(out, "%s\n", azHelp[i]);
        }
      }
    }
  }else{
    /* Seek documented commands for which zPattern is an exact prefix */
    zPat = sqlite3_mprintf(".%s*", zPattern);
    shell_check_oom(zPat);
    for(i=0; i<ArraySize(azHelp); i++){
      if( sqlite3_strglob(zPat, azHelp[i])==0 ){
        sputf(out, "%s\n", azHelp[i]);
        j = i+1;
        n++;
      }
    }
    sqlite3_free(zPat);
    if( n ){
      if( n==1 ){
        /* when zPattern is a prefix of exactly one command, then include
        ** the details of that command, which should begin at offset j */
        while( j<ArraySize(azHelp)-1 && azHelp[j][0]==' ' ){
          sputf(out, "%s\n", azHelp[j]);
          j++;
        }
      }
      return n;
    }
    /* Look for documented commands that contain zPattern anywhere.
    ** Show complete text of all documented commands that match. */
    zPat = sqlite3_mprintf("%%%s%%", zPattern);
    shell_check_oom(zPat);
    for(i=0; i<ArraySize(azHelp); i++){
      if( azHelp[i][0]==',' ){
        while( i<ArraySize(azHelp)-1 && azHelp[i+1][0]==' ' ) ++i;
        continue;
      }
      if( azHelp[i][0]=='.' ) j = i;
      if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
        sputf(out, "%s\n", azHelp[j]);
        while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]==' ' ){
          j++;
          sputf(out, "%s\n", azHelp[j]);
        }
        i = j;
        n++;
      }
    }
    sqlite3_free(zPat);
  }
21139
21140
21141
21142
21143
21144
21145
21146
21147
21148
21149
21150
21151
21152
21153
21154
21155
21156
21157
21158
21159
21160
21161
21162
21163
21164
21165
21166
21167
21168
21169
  long nIn;
  size_t nRead;
  char *pBuf;
  int rc;
  if( in==0 ) return 0;
  rc = fseek(in, 0, SEEK_END);
  if( rc!=0 ){
    raw_printf(stderr, "Error: '%s' not seekable\n", zName);
    fclose(in);
    return 0;
  }
  nIn = ftell(in);
  rewind(in);
  pBuf = sqlite3_malloc64( nIn+1 );
  if( pBuf==0 ){
    raw_printf(stderr, "Error: out of memory\n");
    fclose(in);
    return 0;
  }
  nRead = fread(pBuf, nIn, 1, in);
  fclose(in);
  if( nRead!=1 ){
    sqlite3_free(pBuf);
    raw_printf(stderr, "Error: cannot read '%s'\n", zName);
    return 0;
  }
  pBuf[nIn] = 0;
  if( pnByte ) *pnByte = nIn;
  return pBuf;
}








|







|







|







23040
23041
23042
23043
23044
23045
23046
23047
23048
23049
23050
23051
23052
23053
23054
23055
23056
23057
23058
23059
23060
23061
23062
23063
23064
23065
23066
23067
23068
23069
23070
  long nIn;
  size_t nRead;
  char *pBuf;
  int rc;
  if( in==0 ) return 0;
  rc = fseek(in, 0, SEEK_END);
  if( rc!=0 ){
    eputf("Error: '%s' not seekable\n", zName);
    fclose(in);
    return 0;
  }
  nIn = ftell(in);
  rewind(in);
  pBuf = sqlite3_malloc64( nIn+1 );
  if( pBuf==0 ){
    eputz("Error: out of memory\n");
    fclose(in);
    return 0;
  }
  nRead = fread(pBuf, nIn, 1, in);
  fclose(in);
  if( nRead!=1 ){
    sqlite3_free(pBuf);
    eputf("Error: cannot read '%s'\n", zName);
    return 0;
  }
  pBuf[nIn] = 0;
  if( pnByte ) *pnByte = nIn;
  return pBuf;
}

21276
21277
21278
21279
21280
21281
21282
21283
21284
21285
21286
21287
21288
21289
21290
21291
21292
21293
21294
21295
21296
21297
21298
21299
21300
21301
21302
21303
21304
21305
21306
21307
21308
21309
21310
21311
  FILE *in;
  const char *zDbFilename = p->pAuxDb->zDbFilename;
  unsigned int x[16];
  char zLine[1000];
  if( zDbFilename ){
    in = fopen(zDbFilename, "r");
    if( in==0 ){
      utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
      return 0;
    }
    nLine = 0;
  }else{
    in = p->in;
    nLine = p->lineno;
    if( in==0 ) in = stdin;
  }
  *pnData = 0;
  nLine++;
  if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
  rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
  if( rc!=2 ) goto readHexDb_error;
  if( n<0 ) goto readHexDb_error;
  if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
  n = (n+pgsz-1)&~(pgsz-1);  /* Round n up to the next multiple of pgsz */
  a = sqlite3_malloc( n ? n : 1 );
  shell_check_oom(a);
  memset(a, 0, n);
  if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
    utf8_printf(stderr, "invalid pagesize\n");
    goto readHexDb_error;
  }
  for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
    rc = sscanf(zLine, "| page %d offset %d", &j, &k);
    if( rc==2 ){
      iOffset = k;
      continue;







|




















|







23177
23178
23179
23180
23181
23182
23183
23184
23185
23186
23187
23188
23189
23190
23191
23192
23193
23194
23195
23196
23197
23198
23199
23200
23201
23202
23203
23204
23205
23206
23207
23208
23209
23210
23211
23212
  FILE *in;
  const char *zDbFilename = p->pAuxDb->zDbFilename;
  unsigned int x[16];
  char zLine[1000];
  if( zDbFilename ){
    in = fopen(zDbFilename, "r");
    if( in==0 ){
      eputf("cannot open \"%s\" for reading\n", zDbFilename);
      return 0;
    }
    nLine = 0;
  }else{
    in = p->in;
    nLine = p->lineno;
    if( in==0 ) in = stdin;
  }
  *pnData = 0;
  nLine++;
  if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
  rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
  if( rc!=2 ) goto readHexDb_error;
  if( n<0 ) goto readHexDb_error;
  if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
  n = (n+pgsz-1)&~(pgsz-1);  /* Round n up to the next multiple of pgsz */
  a = sqlite3_malloc( n ? n : 1 );
  shell_check_oom(a);
  memset(a, 0, n);
  if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
    eputz("invalid pagesize\n");
    goto readHexDb_error;
  }
  for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
    rc = sscanf(zLine, "| page %d offset %d", &j, &k);
    if( rc==2 ){
      iOffset = k;
      continue;
21339
21340
21341
21342
21343
21344
21345
21346
21347
21348
21349
21350
21351
21352
21353
    while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
      nLine++;
      if(cli_strncmp(zLine, "| end ", 6)==0 ) break;
    }
    p->lineno = nLine;
  }
  sqlite3_free(a);
  utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
  return 0;
}
#endif /* SQLITE_OMIT_DESERIALIZE */

/*
** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
*/







|







23240
23241
23242
23243
23244
23245
23246
23247
23248
23249
23250
23251
23252
23253
23254
    while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
      nLine++;
      if(cli_strncmp(zLine, "| end ", 6)==0 ) break;
    }
    p->lineno = nLine;
  }
  sqlite3_free(a);
  eputf("Error on line %d of --hexdb input\n", nLine);
  return 0;
}
#endif /* SQLITE_OMIT_DESERIALIZE */

/*
** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
*/
21413
21414
21415
21416
21417
21418
21419
21420
21421
21422
21423
21424
21425
21426
21427
21428
21429
21430
21431
21432
21433
21434
21435
21436
21437
21438
21439

21440
21441
21442
21443
21444
21445
21446
      case SHELL_OPEN_UNSPEC:
      case SHELL_OPEN_NORMAL: {
        sqlite3_open_v2(zDbFilename, &p->db,
           SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
        break;
      }
    }
    globalDb = p->db;
    if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
      utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
          zDbFilename, sqlite3_errmsg(p->db));
      if( (openFlags & OPEN_DB_KEEPALIVE)==0 ){
        exit(1);
      }
      sqlite3_close(p->db);
      sqlite3_open(":memory:", &p->db);
      if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
        utf8_printf(stderr,
          "Also: unable to open substitute in-memory database.\n"
        );
        exit(1);
      }else{
        utf8_printf(stderr,
          "Notice: using substitute in-memory database instead of \"%s\"\n",
          zDbFilename);
      }
    }

    sqlite3_db_config(p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, (int)0, (int*)0);

    /* Reflect the use or absence of --unsafe-testing invocation. */
    {
      int testmode_on = ShellHasFlag(p,SHFLG_TestingMode);
      sqlite3_db_config(p->db, SQLITE_DBCONFIG_TRUSTED_SCHEMA, testmode_on,0);
      sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, !testmode_on,0);







<

|
|






<
|
<


<
|
|


>







23314
23315
23316
23317
23318
23319
23320

23321
23322
23323
23324
23325
23326
23327
23328
23329

23330

23331
23332

23333
23334
23335
23336
23337
23338
23339
23340
23341
23342
23343
23344
      case SHELL_OPEN_UNSPEC:
      case SHELL_OPEN_NORMAL: {
        sqlite3_open_v2(zDbFilename, &p->db,
           SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
        break;
      }
    }

    if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
      eputf("Error: unable to open database \"%s\": %s\n",
            zDbFilename, sqlite3_errmsg(p->db));
      if( (openFlags & OPEN_DB_KEEPALIVE)==0 ){
        exit(1);
      }
      sqlite3_close(p->db);
      sqlite3_open(":memory:", &p->db);
      if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){

        eputz("Also: unable to open substitute in-memory database.\n");

        exit(1);
      }else{

        eputf("Notice: using substitute in-memory database instead of \"%s\"\n",
              zDbFilename);
      }
    }
    globalDb = p->db;
    sqlite3_db_config(p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, (int)0, (int*)0);

    /* Reflect the use or absence of --unsafe-testing invocation. */
    {
      int testmode_on = ShellHasFlag(p,SHFLG_TestingMode);
      sqlite3_db_config(p->db, SQLITE_DBCONFIG_TRUSTED_SCHEMA, testmode_on,0);
      sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, !testmode_on,0);
21537
21538
21539
21540
21541
21542
21543
21544
21545
21546
21547
21548
21549
21550
21551
      if( aData==0 ){
        return;
      }
      rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
                   SQLITE_DESERIALIZE_RESIZEABLE |
                   SQLITE_DESERIALIZE_FREEONCLOSE);
      if( rc ){
        utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
      }
      if( p->szMax>0 ){
        sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
      }
    }
#endif
  }







|







23435
23436
23437
23438
23439
23440
23441
23442
23443
23444
23445
23446
23447
23448
23449
      if( aData==0 ){
        return;
      }
      rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
                   SQLITE_DESERIALIZE_RESIZEABLE |
                   SQLITE_DESERIALIZE_FREEONCLOSE);
      if( rc ){
        eputf("Error: sqlite3_deserialize() returns %d\n", rc);
      }
      if( p->szMax>0 ){
        sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
      }
    }
#endif
  }
21561
21562
21563
21564
21565
21566
21567
21568
21569
21570
21571
21572
21573
21574
21575
21576

/*
** Attempt to close the database connection.  Report errors.
*/
void close_db(sqlite3 *db){
  int rc = sqlite3_close(db);
  if( rc ){
    utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
        rc, sqlite3_errmsg(db));
  }
}

#if HAVE_READLINE || HAVE_EDITLINE
/*
** Readline completion callbacks
*/







|
<







23459
23460
23461
23462
23463
23464
23465
23466

23467
23468
23469
23470
23471
23472
23473

/*
** Attempt to close the database connection.  Report errors.
*/
void close_db(sqlite3 *db){
  int rc = sqlite3_close(db);
  if( rc ){
    eputf("Error: sqlite3_close() returns %d: %s\n", rc, sqlite3_errmsg(db));

  }
}

#if HAVE_READLINE || HAVE_EDITLINE
/*
** Readline completion callbacks
*/
21723
21724
21725
21726
21727
21728
21729
21730
21731
21732
21733
21734
21735
21736
21737
21738
  if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
  if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
    return 1;
  }
  if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
    return 0;
  }
  utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
          zArg);
  return 0;
}

/*
** Set or clear a shell flag according to a boolean value.
*/
static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){







|
<







23620
23621
23622
23623
23624
23625
23626
23627

23628
23629
23630
23631
23632
23633
23634
  if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
  if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
    return 1;
  }
  if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
    return 0;
  }
  eputf("ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", zArg);

  return 0;
}

/*
** Set or clear a shell flag according to a boolean value.
*/
static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
21762
21763
21764
21765
21766
21767
21768
21769
21770
21771
21772
21773
21774
21775
21776
  }else if( cli_strcmp(zFile, "stderr")==0 ){
    f = stderr;
  }else if( cli_strcmp(zFile, "off")==0 ){
    f = 0;
  }else{
    f = fopen(zFile, bTextMode ? "w" : "wb");
    if( f==0 ){
      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
    }
  }
  return f;
}

#ifndef SQLITE_OMIT_TRACE
/*







|







23658
23659
23660
23661
23662
23663
23664
23665
23666
23667
23668
23669
23670
23671
23672
  }else if( cli_strcmp(zFile, "stderr")==0 ){
    f = stderr;
  }else if( cli_strcmp(zFile, "off")==0 ){
    f = 0;
  }else{
    f = fopen(zFile, bTextMode ? "w" : "wb");
    if( f==0 ){
      eputf("Error: cannot open \"%s\"\n", zFile);
    }
  }
  return f;
}

#ifndef SQLITE_OMIT_TRACE
/*
21784
21785
21786
21787
21788
21789
21790
21791
21792
21793
21794
21795
21796
21797
21798
){
  ShellState *p = (ShellState*)pArg;
  sqlite3_stmt *pStmt;
  const char *zSql;
  i64 nSql;
  if( p->traceOut==0 ) return 0;
  if( mType==SQLITE_TRACE_CLOSE ){
    utf8_printf(p->traceOut, "-- closing database connection\n");
    return 0;
  }
  if( mType!=SQLITE_TRACE_ROW && pX!=0 && ((const char*)pX)[0]=='-' ){
    zSql = (const char*)pX;
  }else{
    pStmt = (sqlite3_stmt*)pP;
    switch( p->eTraceType ){







|







23680
23681
23682
23683
23684
23685
23686
23687
23688
23689
23690
23691
23692
23693
23694
){
  ShellState *p = (ShellState*)pArg;
  sqlite3_stmt *pStmt;
  const char *zSql;
  i64 nSql;
  if( p->traceOut==0 ) return 0;
  if( mType==SQLITE_TRACE_CLOSE ){
    sputz(p->traceOut, "-- closing database connection\n");
    return 0;
  }
  if( mType!=SQLITE_TRACE_ROW && pX!=0 && ((const char*)pX)[0]=='-' ){
    zSql = (const char*)pX;
  }else{
    pStmt = (sqlite3_stmt*)pP;
    switch( p->eTraceType ){
21815
21816
21817
21818
21819
21820
21821
21822
21823
21824
21825
21826
21827
21828
21829
21830
21831
21832
21833
21834
  if( zSql==0 ) return 0;
  nSql = strlen(zSql);
  if( nSql>1000000000 ) nSql = 1000000000;
  while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
  switch( mType ){
    case SQLITE_TRACE_ROW:
    case SQLITE_TRACE_STMT: {
      utf8_printf(p->traceOut, "%.*s;\n", (int)nSql, zSql);
      break;
    }
    case SQLITE_TRACE_PROFILE: {
      sqlite3_int64 nNanosec = pX ? *(sqlite3_int64*)pX : 0;
      utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec);
      break;
    }
  }
  return 0;
}
#endif








|




|







23711
23712
23713
23714
23715
23716
23717
23718
23719
23720
23721
23722
23723
23724
23725
23726
23727
23728
23729
23730
  if( zSql==0 ) return 0;
  nSql = strlen(zSql);
  if( nSql>1000000000 ) nSql = 1000000000;
  while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
  switch( mType ){
    case SQLITE_TRACE_ROW:
    case SQLITE_TRACE_STMT: {
      sputf(p->traceOut, "%.*s;\n", (int)nSql, zSql);
      break;
    }
    case SQLITE_TRACE_PROFILE: {
      sqlite3_int64 nNanosec = pX ? *(sqlite3_int64*)pX : 0;
      sputf(p->traceOut, "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec);
      break;
    }
  }
  return 0;
}
#endif

21927
21928
21929
21930
21931
21932
21933
21934
21935
21936
21937
21938
21939
21940
21941
21942
21943
21944
21945
21946
       || (c==EOF && pc==cQuote)
      ){
        do{ p->n--; }while( p->z[p->n]!=cQuote );
        p->cTerm = c;
        break;
      }
      if( pc==cQuote && c!='\r' ){
        utf8_printf(stderr, "%s:%d: unescaped %c character\n",
                p->zFile, p->nLine, cQuote);
      }
      if( c==EOF ){
        utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
                p->zFile, startLine, cQuote);
        p->cTerm = c;
        break;
      }
      import_append_char(p, c);
      ppc = pc;
      pc = c;
    }







<
|


|
|







23823
23824
23825
23826
23827
23828
23829

23830
23831
23832
23833
23834
23835
23836
23837
23838
23839
23840
23841
       || (c==EOF && pc==cQuote)
      ){
        do{ p->n--; }while( p->z[p->n]!=cQuote );
        p->cTerm = c;
        break;
      }
      if( pc==cQuote && c!='\r' ){

        eputf("%s:%d: unescaped %c character\n", p->zFile, p->nLine, cQuote);
      }
      if( c==EOF ){
        eputf("%s:%d: unterminated %c-quoted field\n",
              p->zFile, startLine, cQuote);
        p->cTerm = c;
        break;
      }
      import_append_char(p, c);
      ppc = pc;
      pc = c;
    }
22030
22031
22032
22033
22034
22035
22036
22037
22038
22039
22040
22041
22042
22043
22044
22045
22046
22047
22048
22049
22050
22051
22052
22053
22054
22055
22056
22057
22058
22059
22060
22061
22062
22063
22064
  int cnt = 0;
  const int spinRate = 10000;

  zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
  shell_check_oom(zQuery);
  rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
  if( rc ){
    utf8_printf(stderr, "Error %d: %s on [%s]\n",
            sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
            zQuery);
    goto end_data_xfer;
  }
  n = sqlite3_column_count(pQuery);
  zInsert = sqlite3_malloc64(200 + nTable + n*3);
  shell_check_oom(zInsert);
  sqlite3_snprintf(200+nTable,zInsert,
                   "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
  i = strlen30(zInsert);
  for(j=1; j<n; j++){
    memcpy(zInsert+i, ",?", 2);
    i += 2;
  }
  memcpy(zInsert+i, ");", 3);
  rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
  if( rc ){
    utf8_printf(stderr, "Error %d: %s on [%s]\n",
            sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
            zInsert);
    goto end_data_xfer;
  }
  for(k=0; k<2; k++){
    while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
      for(i=0; i<n; i++){
        switch( sqlite3_column_type(pQuery, i) ){
          case SQLITE_NULL: {







|
|
<















|
|
<







23925
23926
23927
23928
23929
23930
23931
23932
23933

23934
23935
23936
23937
23938
23939
23940
23941
23942
23943
23944
23945
23946
23947
23948
23949
23950

23951
23952
23953
23954
23955
23956
23957
  int cnt = 0;
  const int spinRate = 10000;

  zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
  shell_check_oom(zQuery);
  rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
  if( rc ){
    eputf("Error %d: %s on [%s]\n",
          sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), zQuery);

    goto end_data_xfer;
  }
  n = sqlite3_column_count(pQuery);
  zInsert = sqlite3_malloc64(200 + nTable + n*3);
  shell_check_oom(zInsert);
  sqlite3_snprintf(200+nTable,zInsert,
                   "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
  i = strlen30(zInsert);
  for(j=1; j<n; j++){
    memcpy(zInsert+i, ",?", 2);
    i += 2;
  }
  memcpy(zInsert+i, ");", 3);
  rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
  if( rc ){
    eputf("Error %d: %s on [%s]\n",
          sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb), zInsert);

    goto end_data_xfer;
  }
  for(k=0; k<2; k++){
    while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
      for(i=0; i<n; i++){
        switch( sqlite3_column_type(pQuery, i) ){
          case SQLITE_NULL: {
22085
22086
22087
22088
22089
22090
22091
22092
22093
22094
22095
22096
22097
22098
22099
22100
22101
22102
22103
22104
22105
22106
22107
22108
22109
22110
22111
22112
22113
22114
22115
22116
22117
                                            SQLITE_STATIC);
            break;
          }
        }
      } /* End for */
      rc = sqlite3_step(pInsert);
      if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
        utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
                        sqlite3_errmsg(newDb));
      }
      sqlite3_reset(pInsert);
      cnt++;
      if( (cnt%spinRate)==0 ){
        printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
        fflush(stdout);
      }
    } /* End while */
    if( rc==SQLITE_DONE ) break;
    sqlite3_finalize(pQuery);
    sqlite3_free(zQuery);
    zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
                             zTable);
    shell_check_oom(zQuery);
    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
    if( rc ){
      utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
      break;
    }
  } /* End for(k=0...) */

end_data_xfer:
  sqlite3_finalize(pQuery);
  sqlite3_finalize(pInsert);







|
|
















|







23978
23979
23980
23981
23982
23983
23984
23985
23986
23987
23988
23989
23990
23991
23992
23993
23994
23995
23996
23997
23998
23999
24000
24001
24002
24003
24004
24005
24006
24007
24008
24009
24010
                                            SQLITE_STATIC);
            break;
          }
        }
      } /* End for */
      rc = sqlite3_step(pInsert);
      if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
        eputf("Error %d: %s\n",
              sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb));
      }
      sqlite3_reset(pInsert);
      cnt++;
      if( (cnt%spinRate)==0 ){
        printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
        fflush(stdout);
      }
    } /* End while */
    if( rc==SQLITE_DONE ) break;
    sqlite3_finalize(pQuery);
    sqlite3_free(zQuery);
    zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
                             zTable);
    shell_check_oom(zQuery);
    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
    if( rc ){
      eputf("Warning: cannot step \"%s\" backwards", zTable);
      break;
    }
  } /* End for(k=0...) */

end_data_xfer:
  sqlite3_finalize(pQuery);
  sqlite3_finalize(pInsert);
22140
22141
22142
22143
22144
22145
22146
22147
22148
22149
22150
22151
22152
22153
22154
22155
22156
22157
22158
22159
22160
22161
22162
22163
22164
22165
22166
22167
22168
22169
22170
22171
22172
22173
22174
22175
22176
22177
22178
22179
22180
22181
22182
22183
22184
22185
22186
22187
22188
22189
22190
22191
22192
22193
22194
22195
22196
22197
22198
22199
22200
22201
22202
22203
22204
22205
22206
22207
22208
22209
22210
22211
22212
22213
22214
22215
22216
22217
22218
22219
22220
22221
22222
22223
22224
22225
22226
22227
22228
22229
22230
22231












22232
22233
22234
22235
22236
22237
22238
  char *zErrMsg = 0;

  zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
                           " WHERE %s ORDER BY rowid ASC", zWhere);
  shell_check_oom(zQuery);
  rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
  if( rc ){
    utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
                    sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
                    zQuery);
    goto end_schema_xfer;
  }
  while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
    zName = sqlite3_column_text(pQuery, 0);
    zSql = sqlite3_column_text(pQuery, 1);
    if( zName==0 || zSql==0 ) continue;
    if( sqlite3_stricmp((char*)zName, "sqlite_sequence")!=0 ){
      printf("%s... ", zName); fflush(stdout);
      sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
      if( zErrMsg ){
        utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
        sqlite3_free(zErrMsg);
        zErrMsg = 0;
      }
    }
    if( xForEach ){
      xForEach(p, newDb, (const char*)zName);
    }
    printf("done\n");
  }
  if( rc!=SQLITE_DONE ){
    sqlite3_finalize(pQuery);
    sqlite3_free(zQuery);
    zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
                             " WHERE %s ORDER BY rowid DESC", zWhere);
    shell_check_oom(zQuery);
    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
    if( rc ){
      utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
                      sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
                      zQuery);
      goto end_schema_xfer;
    }
    while( sqlite3_step(pQuery)==SQLITE_ROW ){
      zName = sqlite3_column_text(pQuery, 0);
      zSql = sqlite3_column_text(pQuery, 1);
      if( zName==0 || zSql==0 ) continue;
      if( sqlite3_stricmp((char*)zName, "sqlite_sequence")==0 ) continue;
      printf("%s... ", zName); fflush(stdout);
      sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
      if( zErrMsg ){
        utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
        sqlite3_free(zErrMsg);
        zErrMsg = 0;
      }
      if( xForEach ){
        xForEach(p, newDb, (const char*)zName);
      }
      printf("done\n");
    }
  }
end_schema_xfer:
  sqlite3_finalize(pQuery);
  sqlite3_free(zQuery);
}

/*
** Open a new database file named "zNewDb".  Try to recover as much information
** as possible out of the main database (which might be corrupt) and write it
** into zNewDb.
*/
static void tryToClone(ShellState *p, const char *zNewDb){
  int rc;
  sqlite3 *newDb = 0;
  if( access(zNewDb,0)==0 ){
    utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
    return;
  }
  rc = sqlite3_open(zNewDb, &newDb);
  if( rc ){
    utf8_printf(stderr, "Cannot create output database: %s\n",
            sqlite3_errmsg(newDb));
  }else{
    sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
    sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
    tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
    tryToCloneSchema(p, newDb, "type!='table'", 0);
    sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
    sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
  }
  close_db(newDb);
}













/*
** Change the output file back to stdout.
**
** If the p->doXdgOpen flag is set, that means the output was being
** redirected to a temporary file named by p->zTempFile.  In that case,
** launch start/open/xdg-open on that temporary file.







|
|
<







|


|







|









|
|
<







|


|






|
















|




|
<










>
>
>
>
>
>
>
>
>
>
>
>







24033
24034
24035
24036
24037
24038
24039
24040
24041

24042
24043
24044
24045
24046
24047
24048
24049
24050
24051
24052
24053
24054
24055
24056
24057
24058
24059
24060
24061
24062
24063
24064
24065
24066
24067
24068
24069
24070
24071

24072
24073
24074
24075
24076
24077
24078
24079
24080
24081
24082
24083
24084
24085
24086
24087
24088
24089
24090
24091
24092
24093
24094
24095
24096
24097
24098
24099
24100
24101
24102
24103
24104
24105
24106
24107
24108
24109
24110
24111

24112
24113
24114
24115
24116
24117
24118
24119
24120
24121
24122
24123
24124
24125
24126
24127
24128
24129
24130
24131
24132
24133
24134
24135
24136
24137
24138
24139
24140
  char *zErrMsg = 0;

  zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
                           " WHERE %s ORDER BY rowid ASC", zWhere);
  shell_check_oom(zQuery);
  rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
  if( rc ){
    eputf("Error: (%d) %s on [%s]\n", sqlite3_extended_errcode(p->db),
          sqlite3_errmsg(p->db), zQuery);

    goto end_schema_xfer;
  }
  while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
    zName = sqlite3_column_text(pQuery, 0);
    zSql = sqlite3_column_text(pQuery, 1);
    if( zName==0 || zSql==0 ) continue;
    if( sqlite3_stricmp((char*)zName, "sqlite_sequence")!=0 ){
      sputf(stdout, "%s... ", zName); fflush(stdout);
      sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
      if( zErrMsg ){
        eputf("Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
        sqlite3_free(zErrMsg);
        zErrMsg = 0;
      }
    }
    if( xForEach ){
      xForEach(p, newDb, (const char*)zName);
    }
    sputz(stdout, "done\n");
  }
  if( rc!=SQLITE_DONE ){
    sqlite3_finalize(pQuery);
    sqlite3_free(zQuery);
    zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
                             " WHERE %s ORDER BY rowid DESC", zWhere);
    shell_check_oom(zQuery);
    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
    if( rc ){
      eputf("Error: (%d) %s on [%s]\n",
            sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), zQuery);

      goto end_schema_xfer;
    }
    while( sqlite3_step(pQuery)==SQLITE_ROW ){
      zName = sqlite3_column_text(pQuery, 0);
      zSql = sqlite3_column_text(pQuery, 1);
      if( zName==0 || zSql==0 ) continue;
      if( sqlite3_stricmp((char*)zName, "sqlite_sequence")==0 ) continue;
      sputf(stdout, "%s... ", zName); fflush(stdout);
      sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
      if( zErrMsg ){
        eputf("Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
        sqlite3_free(zErrMsg);
        zErrMsg = 0;
      }
      if( xForEach ){
        xForEach(p, newDb, (const char*)zName);
      }
      sputz(stdout, "done\n");
    }
  }
end_schema_xfer:
  sqlite3_finalize(pQuery);
  sqlite3_free(zQuery);
}

/*
** Open a new database file named "zNewDb".  Try to recover as much information
** as possible out of the main database (which might be corrupt) and write it
** into zNewDb.
*/
static void tryToClone(ShellState *p, const char *zNewDb){
  int rc;
  sqlite3 *newDb = 0;
  if( access(zNewDb,0)==0 ){
    eputf("File \"%s\" already exists.\n", zNewDb);
    return;
  }
  rc = sqlite3_open(zNewDb, &newDb);
  if( rc ){
    eputf("Cannot create output database: %s\n", sqlite3_errmsg(newDb));

  }else{
    sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
    sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
    tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
    tryToCloneSchema(p, newDb, "type!='table'", 0);
    sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
    sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
  }
  close_db(newDb);
}

#ifndef SQLITE_SHELL_FIDDLE
/*
** Change the output stream (file or pipe or console) to something else.
*/
static void output_redir(ShellState *p, FILE *pfNew){
  if( p->out != stdout ) eputz("Output already redirected.\n");
  else{
    p->out = pfNew;
    setOutputStream(pfNew);
  }
}

/*
** Change the output file back to stdout.
**
** If the p->doXdgOpen flag is set, that means the output was being
** redirected to a temporary file named by p->zTempFile.  In that case,
** launch start/open/xdg-open on that temporary file.
22253
22254
22255
22256
22257
22258
22259
22260
22261
22262
22263
22264
22265
22266
22267
22268
22269
22270
22271
22272
22273
22274

22275




22276
22277
22278
22279
22280
22281
22282
      "open";
#else
      "xdg-open";
#endif
      char *zCmd;
      zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
      if( system(zCmd) ){
        utf8_printf(stderr, "Failed: [%s]\n", zCmd);
      }else{
        /* Give the start/open/xdg-open command some time to get
        ** going before we continue, and potential delete the
        ** p->zTempFile data file out from under it */
        sqlite3_sleep(2000);
      }
      sqlite3_free(zCmd);
      outputModePop(p);
      p->doXdgOpen = 0;
    }
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
  }
  p->outfile[0] = 0;
  p->out = stdout;

}





/*
** Run an SQL command and return the single integer result.
*/
static int db_int(sqlite3 *db, const char *zSql){
  sqlite3_stmt *pStmt;
  int res = 0;







|














>

>
>
>
>







24155
24156
24157
24158
24159
24160
24161
24162
24163
24164
24165
24166
24167
24168
24169
24170
24171
24172
24173
24174
24175
24176
24177
24178
24179
24180
24181
24182
24183
24184
24185
24186
24187
24188
24189
      "open";
#else
      "xdg-open";
#endif
      char *zCmd;
      zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
      if( system(zCmd) ){
        eputf("Failed: [%s]\n", zCmd);
      }else{
        /* Give the start/open/xdg-open command some time to get
        ** going before we continue, and potential delete the
        ** p->zTempFile data file out from under it */
        sqlite3_sleep(2000);
      }
      sqlite3_free(zCmd);
      outputModePop(p);
      p->doXdgOpen = 0;
    }
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
  }
  p->outfile[0] = 0;
  p->out = stdout;
  setOutputStream(stdout);
}
#else
# define output_redir(SS,pfO)
# define output_reset(SS)
#endif

/*
** Run an SQL command and return the single integer result.
*/
static int db_int(sqlite3 *db, const char *zSql){
  sqlite3_stmt *pStmt;
  int res = 0;
22339
22340
22341
22342
22343
22344
22345
22346
22347
22348
22349
22350
22351
22352
22353
22354
22355
22356
22357
22358
22359
22360
22361
22362
22363
22364
22365
22366
22367
22368
22369
22370
22371
22372
22373
22374
22375
22376
22377
22378
22379
22380
22381
22382
22383
22384
22385
22386
22387
22388
22389
22390
22391
22392
22393
22394
22395
22396
22397
22398
22399
22400
22401
22402
22403
22404
22405
22406
22407
22408
22409
22410
22411
22412
22413
22414
  unsigned char aHdr[100];
  open_db(p, 0);
  if( p->db==0 ) return 1;
  rc = sqlite3_prepare_v2(p->db,
             "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
             -1, &pStmt, 0);
  if( rc ){
    utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
    sqlite3_finalize(pStmt);
    return 1;
  }
  sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
  if( sqlite3_step(pStmt)==SQLITE_ROW
   && sqlite3_column_bytes(pStmt,0)>100
  ){
    const u8 *pb = sqlite3_column_blob(pStmt,0);
    shell_check_oom(pb);
    memcpy(aHdr, pb, 100);
    sqlite3_finalize(pStmt);
  }else{
    raw_printf(stderr, "unable to read database header\n");
    sqlite3_finalize(pStmt);
    return 1;
  }
  i = get2byteInt(aHdr+16);
  if( i==1 ) i = 65536;
  utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
  utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
  utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
  utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
  for(i=0; i<ArraySize(aField); i++){
    int ofst = aField[i].ofst;
    unsigned int val = get4byteInt(aHdr + ofst);
    utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
    switch( ofst ){
      case 56: {
        if( val==1 ) raw_printf(p->out, " (utf8)");
        if( val==2 ) raw_printf(p->out, " (utf16le)");
        if( val==3 ) raw_printf(p->out, " (utf16be)");
      }
    }
    raw_printf(p->out, "\n");
  }
  if( zDb==0 ){
    zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
  }else if( cli_strcmp(zDb,"temp")==0 ){
    zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
  }else{
    zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
  }
  for(i=0; i<ArraySize(aQuery); i++){
    char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
    int val = db_int(p->db, zSql);
    sqlite3_free(zSql);
    utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
  }
  sqlite3_free(zSchemaTab);
  sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
  utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
  return 0;
}
#endif /* SQLITE_SHELL_HAVE_RECOVER */

/*
** Print the current sqlite3_errmsg() value to stderr and return 1.
*/
static int shellDatabaseError(sqlite3 *db){
  const char *zErr = sqlite3_errmsg(db);
  utf8_printf(stderr, "Error: %s\n", zErr);
  return 1;
}

/*
** Compare the pattern in zGlob[] against the text in z[].  Return TRUE
** if they match and FALSE (0) if they do not match.
**







|












|





|
|
|
|



|


|
|
|


|












|



|









|







24246
24247
24248
24249
24250
24251
24252
24253
24254
24255
24256
24257
24258
24259
24260
24261
24262
24263
24264
24265
24266
24267
24268
24269
24270
24271
24272
24273
24274
24275
24276
24277
24278
24279
24280
24281
24282
24283
24284
24285
24286
24287
24288
24289
24290
24291
24292
24293
24294
24295
24296
24297
24298
24299
24300
24301
24302
24303
24304
24305
24306
24307
24308
24309
24310
24311
24312
24313
24314
24315
24316
24317
24318
24319
24320
24321
  unsigned char aHdr[100];
  open_db(p, 0);
  if( p->db==0 ) return 1;
  rc = sqlite3_prepare_v2(p->db,
             "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
             -1, &pStmt, 0);
  if( rc ){
    eputf("error: %s\n", sqlite3_errmsg(p->db));
    sqlite3_finalize(pStmt);
    return 1;
  }
  sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
  if( sqlite3_step(pStmt)==SQLITE_ROW
   && sqlite3_column_bytes(pStmt,0)>100
  ){
    const u8 *pb = sqlite3_column_blob(pStmt,0);
    shell_check_oom(pb);
    memcpy(aHdr, pb, 100);
    sqlite3_finalize(pStmt);
  }else{
    eputz("unable to read database header\n");
    sqlite3_finalize(pStmt);
    return 1;
  }
  i = get2byteInt(aHdr+16);
  if( i==1 ) i = 65536;
  oputf("%-20s %d\n", "database page size:", i);
  oputf("%-20s %d\n", "write format:", aHdr[18]);
  oputf("%-20s %d\n", "read format:", aHdr[19]);
  oputf("%-20s %d\n", "reserved bytes:", aHdr[20]);
  for(i=0; i<ArraySize(aField); i++){
    int ofst = aField[i].ofst;
    unsigned int val = get4byteInt(aHdr + ofst);
    oputf("%-20s %u", aField[i].zName, val);
    switch( ofst ){
      case 56: {
        if( val==1 ) oputz(" (utf8)");
        if( val==2 ) oputz(" (utf16le)");
        if( val==3 ) oputz(" (utf16be)");
      }
    }
    oputz("\n");
  }
  if( zDb==0 ){
    zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
  }else if( cli_strcmp(zDb,"temp")==0 ){
    zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
  }else{
    zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
  }
  for(i=0; i<ArraySize(aQuery); i++){
    char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
    int val = db_int(p->db, zSql);
    sqlite3_free(zSql);
    oputf("%-20s %d\n", aQuery[i].zName, val);
  }
  sqlite3_free(zSchemaTab);
  sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
  oputf("%-20s %u\n", "data version", iDataVersion);
  return 0;
}
#endif /* SQLITE_SHELL_HAVE_RECOVER */

/*
** Print the current sqlite3_errmsg() value to stderr and return 1.
*/
static int shellDatabaseError(sqlite3 *db){
  const char *zErr = sqlite3_errmsg(db);
  eputf("Error: %s\n", zErr);
  return 1;
}

/*
** Compare the pattern in zGlob[] against the text in z[].  Return TRUE
** if they match and FALSE (0) if they do not match.
**
22635
22636
22637
22638
22639
22640
22641
22642
22643
22644
22645
22646
22647
22648
22649
*/
static int lintFkeyIndexes(
  ShellState *pState,             /* Current shell tool state */
  char **azArg,                   /* Array of arguments passed to dot command */
  int nArg                        /* Number of entries in azArg[] */
){
  sqlite3 *db = pState->db;       /* Database handle to query "main" db of */
  FILE *out = pState->out;        /* Stream to write non-error output to */
  int bVerbose = 0;               /* If -verbose is present */
  int bGroupByParent = 0;         /* If -groupbyparent is present */
  int i;                          /* To iterate through azArg[] */
  const char *zIndent = "";       /* How much to indent CREATE INDEX by */
  int rc;                         /* Return code */
  sqlite3_stmt *pSql = 0;         /* Compiled version of SQL statement below */








<







24542
24543
24544
24545
24546
24547
24548

24549
24550
24551
24552
24553
24554
24555
*/
static int lintFkeyIndexes(
  ShellState *pState,             /* Current shell tool state */
  char **azArg,                   /* Array of arguments passed to dot command */
  int nArg                        /* Number of entries in azArg[] */
){
  sqlite3 *db = pState->db;       /* Database handle to query "main" db of */

  int bVerbose = 0;               /* If -verbose is present */
  int bGroupByParent = 0;         /* If -groupbyparent is present */
  int i;                          /* To iterate through azArg[] */
  const char *zIndent = "";       /* How much to indent CREATE INDEX by */
  int rc;                         /* Return code */
  sqlite3_stmt *pSql = 0;         /* Compiled version of SQL statement below */

22717
22718
22719
22720
22721
22722
22723
22724
22725
22726
22727
22728
22729
22730
22731
22732
22733
      bVerbose = 1;
    }
    else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
      bGroupByParent = 1;
      zIndent = "    ";
    }
    else{
      raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
          azArg[0], azArg[1]
      );
      return SQLITE_ERROR;
    }
  }

  /* Register the fkey_collate_clause() SQL function */
  rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
      0, shellFkeyCollateClause, 0, 0







|
<
<







24623
24624
24625
24626
24627
24628
24629
24630


24631
24632
24633
24634
24635
24636
24637
      bVerbose = 1;
    }
    else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
      bGroupByParent = 1;
      zIndent = "    ";
    }
    else{
      eputf("Usage: %s %s ?-verbose? ?-groupbyparent?\n", azArg[0], azArg[1]);


      return SQLITE_ERROR;
    }
  }

  /* Register the fkey_collate_clause() SQL function */
  rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
      0, shellFkeyCollateClause, 0, 0
22763
22764
22765
22766
22767
22768
22769
22770
22771
22772
22773
22774
22775
22776
22777
22778
22779
22780
22781
22782
22783
22784
22785
22786
22787
22788
22789
22790
22791
22792
22793
22794
22795
22796
22797
22798
22799
22800
22801
22802
22803
22804
22805
22806
22807
22808
22809
22810
22811
22812
22813
22814
22815
22816
22817
22818
22819
22820
22821
22822
22823
22824
22825
22826
22827
22828
22829
22830
22831
22832
22833
22834
22835
22836
22837
22838
22839
22840
22841
22842
22843
22844
22845
22846
22847
22848
22849
22850
22851
22852
22853
22854
22855
22856
22857
22858
22859
22860
22861
22862
        res = zPlan!=0 && (  0==sqlite3_strglob(zGlob, zPlan)
                          || 0==sqlite3_strglob(zGlobIPK, zPlan));
      }
      rc = sqlite3_finalize(pExplain);
      if( rc!=SQLITE_OK ) break;

      if( res<0 ){
        raw_printf(stderr, "Error: internal error");
        break;
      }else{
        if( bGroupByParent
        && (bVerbose || res==0)
        && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
        ){
          raw_printf(out, "-- Parent table %s\n", zParent);
          sqlite3_free(zPrev);
          zPrev = sqlite3_mprintf("%s", zParent);
        }

        if( res==0 ){
          raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
        }else if( bVerbose ){
          raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
              zIndent, zFrom, zTarget
          );
        }
      }
    }
    sqlite3_free(zPrev);

    if( rc!=SQLITE_OK ){
      raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
    }

    rc2 = sqlite3_finalize(pSql);
    if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
      rc = rc2;
      raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
    }
  }else{
    raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
  }

  return rc;
}

/*
** Implementation of ".lint" dot command.
*/
static int lintDotCommand(
  ShellState *pState,             /* Current shell tool state */
  char **azArg,                   /* Array of arguments passed to dot command */
  int nArg                        /* Number of entries in azArg[] */
){
  int n;
  n = (nArg>=2 ? strlen30(azArg[1]) : 0);
  if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
  return lintFkeyIndexes(pState, azArg, nArg);

 usage:
  raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
  raw_printf(stderr, "Where sub-commands are:\n");
  raw_printf(stderr, "    fkey-indexes\n");
  return SQLITE_ERROR;
}

#if !defined SQLITE_OMIT_VIRTUALTABLE
static void shellPrepare(
  sqlite3 *db,
  int *pRc,
  const char *zSql,
  sqlite3_stmt **ppStmt
){
  *ppStmt = 0;
  if( *pRc==SQLITE_OK ){
    int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
    if( rc!=SQLITE_OK ){
      raw_printf(stderr, "sql error: %s (%d)\n",
          sqlite3_errmsg(db), sqlite3_errcode(db)
      );
      *pRc = rc;
    }
  }
}

/*
** Create a prepared statement using printf-style arguments for the SQL.
**
** This routine is could be marked "static".  But it is not always used,
** depending on compile-time options.  By omitting the "static", we avoid
** nuisance compiler warnings about "defined but not used".
*/
void shellPreparePrintf(
  sqlite3 *db,
  int *pRc,
  sqlite3_stmt **ppStmt,
  const char *zFmt,
  ...
){
  *ppStmt = 0;







|






|





|

|
|







|





|


|



















|
|
|



<










<
|
<







<
<
<
<

|







24667
24668
24669
24670
24671
24672
24673
24674
24675
24676
24677
24678
24679
24680
24681
24682
24683
24684
24685
24686
24687
24688
24689
24690
24691
24692
24693
24694
24695
24696
24697
24698
24699
24700
24701
24702
24703
24704
24705
24706
24707
24708
24709
24710
24711
24712
24713
24714
24715
24716
24717
24718
24719
24720
24721
24722
24723
24724
24725
24726
24727
24728
24729
24730
24731
24732

24733
24734
24735
24736
24737
24738
24739
24740
24741
24742

24743

24744
24745
24746
24747
24748
24749
24750




24751
24752
24753
24754
24755
24756
24757
24758
24759
        res = zPlan!=0 && (  0==sqlite3_strglob(zGlob, zPlan)
                          || 0==sqlite3_strglob(zGlobIPK, zPlan));
      }
      rc = sqlite3_finalize(pExplain);
      if( rc!=SQLITE_OK ) break;

      if( res<0 ){
        eputz("Error: internal error");
        break;
      }else{
        if( bGroupByParent
        && (bVerbose || res==0)
        && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
        ){
          oputf("-- Parent table %s\n", zParent);
          sqlite3_free(zPrev);
          zPrev = sqlite3_mprintf("%s", zParent);
        }

        if( res==0 ){
          oputf("%s%s --> %s\n", zIndent, zCI, zTarget);
        }else if( bVerbose ){
          oputf("%s/* no extra indexes required for %s -> %s */\n",
                zIndent, zFrom, zTarget
          );
        }
      }
    }
    sqlite3_free(zPrev);

    if( rc!=SQLITE_OK ){
      eputf("%s\n", sqlite3_errmsg(db));
    }

    rc2 = sqlite3_finalize(pSql);
    if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
      rc = rc2;
      eputf("%s\n", sqlite3_errmsg(db));
    }
  }else{
    eputf("%s\n", sqlite3_errmsg(db));
  }

  return rc;
}

/*
** Implementation of ".lint" dot command.
*/
static int lintDotCommand(
  ShellState *pState,             /* Current shell tool state */
  char **azArg,                   /* Array of arguments passed to dot command */
  int nArg                        /* Number of entries in azArg[] */
){
  int n;
  n = (nArg>=2 ? strlen30(azArg[1]) : 0);
  if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
  return lintFkeyIndexes(pState, azArg, nArg);

 usage:
  eputf("Usage %s sub-command ?switches...?\n", azArg[0]);
  eputz("Where sub-commands are:\n");
  eputz("    fkey-indexes\n");
  return SQLITE_ERROR;
}


static void shellPrepare(
  sqlite3 *db,
  int *pRc,
  const char *zSql,
  sqlite3_stmt **ppStmt
){
  *ppStmt = 0;
  if( *pRc==SQLITE_OK ){
    int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
    if( rc!=SQLITE_OK ){

      eputf("sql error: %s (%d)\n", sqlite3_errmsg(db), sqlite3_errcode(db));

      *pRc = rc;
    }
  }
}

/*
** Create a prepared statement using printf-style arguments for the SQL.




*/
static void shellPreparePrintf(
  sqlite3 *db,
  int *pRc,
  sqlite3_stmt **ppStmt,
  const char *zFmt,
  ...
){
  *ppStmt = 0;
22871
22872
22873
22874
22875
22876
22877

22878
22879
22880
22881
22882
22883
22884
22885
22886
22887
22888
22889
22890
22891
22892
22893
22894
22895
22896
22897
22898
22899

22900
22901
22902
22903
22904
22905
22906
22907
22908
22909
22910
22911
22912
22913
22914
22915
22916
22917
22918
22919
22920
22921
    }else{
      shellPrepare(db, pRc, z, ppStmt);
      sqlite3_free(z);
    }
  }
}


/* Finalize the prepared statement created using shellPreparePrintf().
**
** This routine is could be marked "static".  But it is not always used,
** depending on compile-time options.  By omitting the "static", we avoid
** nuisance compiler warnings about "defined but not used".
*/
void shellFinalize(
  int *pRc,
  sqlite3_stmt *pStmt
){
  if( pStmt ){
    sqlite3 *db = sqlite3_db_handle(pStmt);
    int rc = sqlite3_finalize(pStmt);
    if( *pRc==SQLITE_OK ){
      if( rc!=SQLITE_OK ){
        raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
      }
      *pRc = rc;
    }
  }
}


/* Reset the prepared statement created using shellPreparePrintf().
**
** This routine is could be marked "static".  But it is not always used,
** depending on compile-time options.  By omitting the "static", we avoid
** nuisance compiler warnings about "defined but not used".
*/
void shellReset(
  int *pRc,
  sqlite3_stmt *pStmt
){
  int rc = sqlite3_reset(pStmt);
  if( *pRc==SQLITE_OK ){
    if( rc!=SQLITE_OK ){
      sqlite3 *db = sqlite3_db_handle(pStmt);
      raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
    }
    *pRc = rc;
  }
}
#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)







>
|
<
<
<
<

|








|






>














|







24768
24769
24770
24771
24772
24773
24774
24775
24776




24777
24778
24779
24780
24781
24782
24783
24784
24785
24786
24787
24788
24789
24790
24791
24792
24793
24794
24795
24796
24797
24798
24799
24800
24801
24802
24803
24804
24805
24806
24807
24808
24809
24810
24811
24812
24813
24814
24815
24816
    }else{
      shellPrepare(db, pRc, z, ppStmt);
      sqlite3_free(z);
    }
  }
}

/* 
** Finalize the prepared statement created using shellPreparePrintf().




*/
static void shellFinalize(
  int *pRc,
  sqlite3_stmt *pStmt
){
  if( pStmt ){
    sqlite3 *db = sqlite3_db_handle(pStmt);
    int rc = sqlite3_finalize(pStmt);
    if( *pRc==SQLITE_OK ){
      if( rc!=SQLITE_OK ){
        eputf("SQL error: %s\n", sqlite3_errmsg(db));
      }
      *pRc = rc;
    }
  }
}

#if !defined SQLITE_OMIT_VIRTUALTABLE
/* Reset the prepared statement created using shellPreparePrintf().
**
** This routine is could be marked "static".  But it is not always used,
** depending on compile-time options.  By omitting the "static", we avoid
** nuisance compiler warnings about "defined but not used".
*/
void shellReset(
  int *pRc,
  sqlite3_stmt *pStmt
){
  int rc = sqlite3_reset(pStmt);
  if( *pRc==SQLITE_OK ){
    if( rc!=SQLITE_OK ){
      sqlite3 *db = sqlite3_db_handle(pStmt);
      eputf("SQL error: %s\n", sqlite3_errmsg(db));
    }
    *pRc = rc;
  }
}
#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
22957
22958
22959
22960
22961
22962
22963
22964
22965
22966
22967
22968
22969
22970
22971
22972
22973
22974
22975
*/
static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
  va_list ap;
  char *z;
  va_start(ap, zFmt);
  z = sqlite3_vmprintf(zFmt, ap);
  va_end(ap);
  utf8_printf(stderr, "Error: %s\n", z);
  if( pAr->fromCmdLine ){
    utf8_printf(stderr, "Use \"-A\" for more help\n");
  }else{
    utf8_printf(stderr, "Use \".archive --help\" for more help\n");
  }
  sqlite3_free(z);
  return SQLITE_ERROR;
}

/*
** Values for ArCommand.eCmd.







|

|

|







24852
24853
24854
24855
24856
24857
24858
24859
24860
24861
24862
24863
24864
24865
24866
24867
24868
24869
24870
*/
static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
  va_list ap;
  char *z;
  va_start(ap, zFmt);
  z = sqlite3_vmprintf(zFmt, ap);
  va_end(ap);
  eputf("Error: %s\n", z);
  if( pAr->fromCmdLine ){
    eputz("Use \"-A\" for more help\n");
  }else{
    eputz("Use \".archive --help\" for more help\n");
  }
  sqlite3_free(z);
  return SQLITE_ERROR;
}

/*
** Values for ArCommand.eCmd.
23061
23062
23063
23064
23065
23066
23067
23068
23069
23070
23071
23072
23073
23074
23075
    { "dryrun",    'n', AR_SWITCH_DRYRUN,    0 },
    { "glob",      'g', AR_SWITCH_GLOB,      0 },
  };
  int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
  struct ArSwitch *pEnd = &aSwitch[nSwitch];

  if( nArg<=1 ){
    utf8_printf(stderr, "Wrong number of arguments.  Usage:\n");
    return arUsage(stderr);
  }else{
    char *z = azArg[1];
    if( z[0]!='-' ){
      /* Traditional style [tar] invocation */
      int i;
      int iArg = 2;







|







24956
24957
24958
24959
24960
24961
24962
24963
24964
24965
24966
24967
24968
24969
24970
    { "dryrun",    'n', AR_SWITCH_DRYRUN,    0 },
    { "glob",      'g', AR_SWITCH_GLOB,      0 },
  };
  int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
  struct ArSwitch *pEnd = &aSwitch[nSwitch];

  if( nArg<=1 ){
    eputz("Wrong number of arguments.  Usage:\n");
    return arUsage(stderr);
  }else{
    char *z = azArg[1];
    if( z[0]!='-' ){
      /* Traditional style [tar] invocation */
      int i;
      int iArg = 2;
23167
23168
23169
23170
23171
23172
23173
23174
23175
23176
23177
23178
23179
23180
23181
          }
          if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
        }
      }
    }
  }
  if( pAr->eCmd==0 ){
    utf8_printf(stderr, "Required argument missing.  Usage:\n");
    return arUsage(stderr);
  }
  return SQLITE_OK;
}

/*
** This function assumes that all arguments within the ArCommand.azArg[]







|







25062
25063
25064
25065
25066
25067
25068
25069
25070
25071
25072
25073
25074
25075
25076
          }
          if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
        }
      }
    }
  }
  if( pAr->eCmd==0 ){
    eputz("Required argument missing.  Usage:\n");
    return arUsage(stderr);
  }
  return SQLITE_OK;
}

/*
** This function assumes that all arguments within the ArCommand.azArg[]
23210
23211
23212
23213
23214
23215
23216
23217
23218
23219
23220
23221
23222
23223
23224
      z[n] = '\0';
      sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
      if( SQLITE_ROW==sqlite3_step(pTest) ){
        bOk = 1;
      }
      shellReset(&rc, pTest);
      if( rc==SQLITE_OK && bOk==0 ){
        utf8_printf(stderr, "not found in archive: %s\n", z);
        rc = SQLITE_ERROR;
      }
    }
    shellFinalize(&rc, pTest);
  }
  return rc;
}







|







25105
25106
25107
25108
25109
25110
25111
25112
25113
25114
25115
25116
25117
25118
25119
      z[n] = '\0';
      sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
      if( SQLITE_ROW==sqlite3_step(pTest) ){
        bOk = 1;
      }
      shellReset(&rc, pTest);
      if( rc==SQLITE_OK && bOk==0 ){
        eputf("not found in archive: %s\n", z);
        rc = SQLITE_ERROR;
      }
    }
    shellFinalize(&rc, pTest);
  }
  return rc;
}
23277
23278
23279
23280
23281
23282
23283
23284
23285
23286
23287
23288
23289
23290
23291
23292
23293
23294
23295
23296
23297
23298
23299
23300
23301
23302
23303
23304
23305
23306
23307
23308
23309
23310
23311
23312
23313
23314
23315
23316
23317
23318
23319
23320
23321
23322
23323
23324
23325
23326
23327
23328
23329
23330
23331
23332
23333
23334
23335
23336
23337
23338
23339
23340
23341
23342
23343

  rc = arCheckEntries(pAr);
  arWhereClause(&rc, pAr, &zWhere);

  shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
                     pAr->zSrcTable, zWhere);
  if( pAr->bDryRun ){
    utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
  }else{
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
      if( pAr->bVerbose ){
        utf8_printf(pAr->p->out, "%s % 10d  %s  %s\n",
            sqlite3_column_text(pSql, 0),
            sqlite3_column_int(pSql, 1),
            sqlite3_column_text(pSql, 2),
            sqlite3_column_text(pSql, 3)
        );
      }else{
        utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
      }
    }
  }
  shellFinalize(&rc, pSql);
  sqlite3_free(zWhere);
  return rc;
}


/*
** Implementation of .ar "Remove" command.
*/
static int arRemoveCommand(ArCommand *pAr){
  int rc = 0;
  char *zSql = 0;
  char *zWhere = 0;

  if( pAr->nArg ){
    /* Verify that args actually exist within the archive before proceeding.
    ** And formulate a WHERE clause to match them.  */
    rc = arCheckEntries(pAr);
    arWhereClause(&rc, pAr, &zWhere);
  }
  if( rc==SQLITE_OK ){
    zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
                           pAr->zSrcTable, zWhere);
    if( pAr->bDryRun ){
      utf8_printf(pAr->p->out, "%s\n", zSql);
    }else{
      char *zErr = 0;
      rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
      if( rc==SQLITE_OK ){
        rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
        if( rc!=SQLITE_OK ){
          sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
        }else{
          rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
        }
      }
      if( zErr ){
        utf8_printf(stdout, "ERROR: %s\n", zErr);
        sqlite3_free(zErr);
      }
    }
  }
  sqlite3_free(zWhere);
  sqlite3_free(zSql);
  return rc;







|



|
|
<
|
<
<

|







<



















|












|







25172
25173
25174
25175
25176
25177
25178
25179
25180
25181
25182
25183
25184

25185


25186
25187
25188
25189
25190
25191
25192
25193
25194

25195
25196
25197
25198
25199
25200
25201
25202
25203
25204
25205
25206
25207
25208
25209
25210
25211
25212
25213
25214
25215
25216
25217
25218
25219
25220
25221
25222
25223
25224
25225
25226
25227
25228
25229
25230
25231
25232
25233
25234

  rc = arCheckEntries(pAr);
  arWhereClause(&rc, pAr, &zWhere);

  shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
                     pAr->zSrcTable, zWhere);
  if( pAr->bDryRun ){
    oputf("%s\n", sqlite3_sql(pSql));
  }else{
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
      if( pAr->bVerbose ){
        oputf("%s % 10d  %s  %s\n",
              sqlite3_column_text(pSql, 0), sqlite3_column_int(pSql, 1),

              sqlite3_column_text(pSql, 2),sqlite3_column_text(pSql, 3));


      }else{
        oputf("%s\n", sqlite3_column_text(pSql, 0));
      }
    }
  }
  shellFinalize(&rc, pSql);
  sqlite3_free(zWhere);
  return rc;
}


/*
** Implementation of .ar "Remove" command.
*/
static int arRemoveCommand(ArCommand *pAr){
  int rc = 0;
  char *zSql = 0;
  char *zWhere = 0;

  if( pAr->nArg ){
    /* Verify that args actually exist within the archive before proceeding.
    ** And formulate a WHERE clause to match them.  */
    rc = arCheckEntries(pAr);
    arWhereClause(&rc, pAr, &zWhere);
  }
  if( rc==SQLITE_OK ){
    zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
                           pAr->zSrcTable, zWhere);
    if( pAr->bDryRun ){
      oputf("%s\n", zSql);
    }else{
      char *zErr = 0;
      rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
      if( rc==SQLITE_OK ){
        rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
        if( rc!=SQLITE_OK ){
          sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
        }else{
          rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
        }
      }
      if( zErr ){
        sputf(stdout, "ERROR: %s\n", zErr); /* stdout? */
        sqlite3_free(zErr);
      }
    }
  }
  sqlite3_free(zWhere);
  sqlite3_free(zSql);
  return rc;
23393
23394
23395
23396
23397
23398
23399
23400
23401
23402
23403
23404
23405
23406
23407
23408
23409
23410
23411
23412
23413
23414
23415
23416
23417
23418
23419
23420
23421
23422
23423
23424
23425
23426
23427
23428
23429
23430
23431
23432
23433
23434
23435
23436
23437
    ** only for the directories. This is because the timestamps for
    ** extracted directories must be reset after they are populated (as
    ** populating them changes the timestamp).  */
    for(i=0; i<2; i++){
      j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
      sqlite3_bind_int(pSql, j, i);
      if( pAr->bDryRun ){
        utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
      }else{
        while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
          if( i==0 && pAr->bVerbose ){
            utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
          }
        }
      }
      shellReset(&rc, pSql);
    }
    shellFinalize(&rc, pSql);
  }

  sqlite3_free(zDir);
  sqlite3_free(zWhere);
  return rc;
}

/*
** Run the SQL statement in zSql.  Or if doing a --dryrun, merely print it out.
*/
static int arExecSql(ArCommand *pAr, const char *zSql){
  int rc;
  if( pAr->bDryRun ){
    utf8_printf(pAr->p->out, "%s\n", zSql);
    rc = SQLITE_OK;
  }else{
    char *zErr = 0;
    rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
    if( zErr ){
      utf8_printf(stdout, "ERROR: %s\n", zErr);
      sqlite3_free(zErr);
    }
  }
  return rc;
}









|



|



















|





|







25284
25285
25286
25287
25288
25289
25290
25291
25292
25293
25294
25295
25296
25297
25298
25299
25300
25301
25302
25303
25304
25305
25306
25307
25308
25309
25310
25311
25312
25313
25314
25315
25316
25317
25318
25319
25320
25321
25322
25323
25324
25325
25326
25327
25328
    ** only for the directories. This is because the timestamps for
    ** extracted directories must be reset after they are populated (as
    ** populating them changes the timestamp).  */
    for(i=0; i<2; i++){
      j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
      sqlite3_bind_int(pSql, j, i);
      if( pAr->bDryRun ){
        oputf("%s\n", sqlite3_sql(pSql));
      }else{
        while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
          if( i==0 && pAr->bVerbose ){
            oputf("%s\n", sqlite3_column_text(pSql, 0));
          }
        }
      }
      shellReset(&rc, pSql);
    }
    shellFinalize(&rc, pSql);
  }

  sqlite3_free(zDir);
  sqlite3_free(zWhere);
  return rc;
}

/*
** Run the SQL statement in zSql.  Or if doing a --dryrun, merely print it out.
*/
static int arExecSql(ArCommand *pAr, const char *zSql){
  int rc;
  if( pAr->bDryRun ){
    oputf("%s\n", zSql);
    rc = SQLITE_OK;
  }else{
    char *zErr = 0;
    rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
    if( zErr ){
      sputf(stdout, "ERROR: %s\n", zErr);
      sqlite3_free(zErr);
    }
  }
  return rc;
}


23598
23599
23600
23601
23602
23603
23604
23605
23606
23607
23608
23609
23610
23611
23612
23613
23614
23615
23616
23617
23618
23619
23620
23621
23622
23623
23624
23625
23626
23627
23628
23629
23630
23631
23632
23633
           || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
        flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
      }else{
        flags = SQLITE_OPEN_READONLY;
      }
      cmd.db = 0;
      if( cmd.bDryRun ){
        utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
             eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
      }
      rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
             eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
      if( rc!=SQLITE_OK ){
        utf8_printf(stderr, "cannot open file: %s (%s)\n",
            cmd.zFile, sqlite3_errmsg(cmd.db)
        );
        goto end_ar_command;
      }
      sqlite3_fileio_init(cmd.db, 0, 0);
      sqlite3_sqlar_init(cmd.db, 0, 0);
      sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
                              shellPutsFunc, 0, 0);

    }
    if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
      if( cmd.eCmd!=AR_CMD_CREATE
       && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
      ){
        utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
        rc = SQLITE_ERROR;
        goto end_ar_command;
      }
      cmd.zSrcTable = sqlite3_mprintf("sqlar");
    }

    switch( cmd.eCmd ){







|
|




<
|
<












|







25489
25490
25491
25492
25493
25494
25495
25496
25497
25498
25499
25500
25501

25502

25503
25504
25505
25506
25507
25508
25509
25510
25511
25512
25513
25514
25515
25516
25517
25518
25519
25520
25521
25522
           || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
        flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
      }else{
        flags = SQLITE_OPEN_READONLY;
      }
      cmd.db = 0;
      if( cmd.bDryRun ){
        oputf("-- open database '%s'%s\n", cmd.zFile,
              eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
      }
      rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
             eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
      if( rc!=SQLITE_OK ){

        eputf("cannot open file: %s (%s)\n", cmd.zFile, sqlite3_errmsg(cmd.db));

        goto end_ar_command;
      }
      sqlite3_fileio_init(cmd.db, 0, 0);
      sqlite3_sqlar_init(cmd.db, 0, 0);
      sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
                              shellPutsFunc, 0, 0);

    }
    if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
      if( cmd.eCmd!=AR_CMD_CREATE
       && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
      ){
        eputz("database does not contain an 'sqlar' table\n");
        rc = SQLITE_ERROR;
        goto end_ar_command;
      }
      cmd.zSrcTable = sqlite3_mprintf("sqlar");
    }

    switch( cmd.eCmd ){
23677
23678
23679
23680
23681
23682
23683
23684
23685
23686
23687
23688
23689
23690
23691

/*
** This function is used as a callback by the recover extension. Simply
** print the supplied SQL statement to stdout.
*/
static int recoverSqlCb(void *pCtx, const char *zSql){
  ShellState *pState = (ShellState*)pCtx;
  utf8_printf(pState->out, "%s;\n", zSql);
  return SQLITE_OK;
}

/*
** This function is called to recover data from the database. A script
** to construct a new database containing all recovered data is output
** on stream pState->out.







|







25566
25567
25568
25569
25570
25571
25572
25573
25574
25575
25576
25577
25578
25579
25580

/*
** This function is used as a callback by the recover extension. Simply
** print the supplied SQL statement to stdout.
*/
static int recoverSqlCb(void *pCtx, const char *zSql){
  ShellState *pState = (ShellState*)pCtx;
  sputf(pState->out, "%s;\n", zSql);
  return SQLITE_OK;
}

/*
** This function is called to recover data from the database. A script
** to construct a new database containing all recovered data is output
** on stream pState->out.
23720
23721
23722
23723
23724
23725
23726
23727
23728
23729
23730
23731
23732
23733
23734
23735
23736
23737
23738
23739
23740
23741
23742
23743
23744
23745
23746
23747
23748
23749
23750
23751
23752


































23753
23754
23755
23756
23757
23758
23759
23760
23761
23762
23763
23764
23765
23766
23767
23768
23769
23770
23771
23772
23773
23774
23775
23776
23777
23778
      i++;
      zLAF = azArg[i];
    }else
    if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
      bRowids = 0;
    }
    else{
      utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
      showHelp(pState->out, azArg[0]);
      return 1;
    }
  }

  p = sqlite3_recover_init_sql(
      pState->db, "main", recoverSqlCb, (void*)pState
  );

  sqlite3_recover_config(p, 789, (void*)zRecoveryDb);  /* Debug use only */
  sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF);
  sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
  sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);

  sqlite3_recover_run(p);
  if( sqlite3_recover_errcode(p)!=SQLITE_OK ){
    const char *zErr = sqlite3_recover_errmsg(p);
    int errCode = sqlite3_recover_errcode(p);
    raw_printf(stderr, "sql error: %s (%d)\n", zErr, errCode);
  }
  rc = sqlite3_recover_finish(p);
  return rc;
}
#endif /* SQLITE_SHELL_HAVE_RECOVER */




































/*
 * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it.
 * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE,
 *   close db and set it to 0, and return the columns spec, to later
 *   be sqlite3_free()'ed by the caller.
 * The return is 0 when either:
 *   (a) The db was not initialized and zCol==0 (There are no columns.)
 *   (b) zCol!=0  (Column was added, db initialized as needed.)
 * The 3rd argument, pRenamed, references an out parameter. If the
 * pointer is non-zero, its referent will be set to a summary of renames
 * done if renaming was necessary, or set to 0 if none was done. The out
 * string (if any) must be sqlite3_free()'ed by the caller.
 */
#ifdef SHELL_DEBUG
#define rc_err_oom_die(rc) \
  if( rc==SQLITE_NOMEM ) shell_check_oom(0); \
  else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \
    fprintf(stderr,"E:%d\n",rc), assert(0)
#else
static void rc_err_oom_die(int rc){
  if( rc==SQLITE_NOMEM ) shell_check_oom(0);
  assert(rc==SQLITE_OK||rc==SQLITE_DONE);
}
#endif








|


















|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


















|







25609
25610
25611
25612
25613
25614
25615
25616
25617
25618
25619
25620
25621
25622
25623
25624
25625
25626
25627
25628
25629
25630
25631
25632
25633
25634
25635
25636
25637
25638
25639
25640
25641
25642
25643
25644
25645
25646
25647
25648
25649
25650
25651
25652
25653
25654
25655
25656
25657
25658
25659
25660
25661
25662
25663
25664
25665
25666
25667
25668
25669
25670
25671
25672
25673
25674
25675
25676
25677
25678
25679
25680
25681
25682
25683
25684
25685
25686
25687
25688
25689
25690
25691
25692
25693
25694
25695
25696
25697
25698
25699
25700
25701
      i++;
      zLAF = azArg[i];
    }else
    if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
      bRowids = 0;
    }
    else{
      eputf("unexpected option: %s\n", azArg[i]);
      showHelp(pState->out, azArg[0]);
      return 1;
    }
  }

  p = sqlite3_recover_init_sql(
      pState->db, "main", recoverSqlCb, (void*)pState
  );

  sqlite3_recover_config(p, 789, (void*)zRecoveryDb);  /* Debug use only */
  sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF);
  sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
  sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);

  sqlite3_recover_run(p);
  if( sqlite3_recover_errcode(p)!=SQLITE_OK ){
    const char *zErr = sqlite3_recover_errmsg(p);
    int errCode = sqlite3_recover_errcode(p);
    eputf("sql error: %s (%d)\n", zErr, errCode);
  }
  rc = sqlite3_recover_finish(p);
  return rc;
}
#endif /* SQLITE_SHELL_HAVE_RECOVER */

/*
** Implementation of ".intck STEPS_PER_UNLOCK" command.
*/
static int intckDatabaseCmd(ShellState *pState, i64 nStepPerUnlock){
  sqlite3_intck *p = 0;
  int rc = SQLITE_OK;

  rc = sqlite3_intck_open(pState->db, "main", &p);
  if( rc==SQLITE_OK ){
    i64 nStep = 0;
    i64 nError = 0;
    const char *zErr = 0;
    while( SQLITE_OK==sqlite3_intck_step(p) ){
      const char *zMsg = sqlite3_intck_message(p);
      if( zMsg ){
        oputf("%s\n", zMsg);
        nError++;
      }
      nStep++;
      if( nStepPerUnlock && (nStep % nStepPerUnlock)==0 ){
        sqlite3_intck_unlock(p);
      }
    }
    rc = sqlite3_intck_error(p, &zErr);
    if( zErr ){
      eputf("%s\n", zErr);
    }
    sqlite3_intck_close(p);

    oputf("%lld steps, %lld errors\n", nStep, nError);
  }

  return rc;
}

/*
 * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it.
 * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE,
 *   close db and set it to 0, and return the columns spec, to later
 *   be sqlite3_free()'ed by the caller.
 * The return is 0 when either:
 *   (a) The db was not initialized and zCol==0 (There are no columns.)
 *   (b) zCol!=0  (Column was added, db initialized as needed.)
 * The 3rd argument, pRenamed, references an out parameter. If the
 * pointer is non-zero, its referent will be set to a summary of renames
 * done if renaming was necessary, or set to 0 if none was done. The out
 * string (if any) must be sqlite3_free()'ed by the caller.
 */
#ifdef SHELL_DEBUG
#define rc_err_oom_die(rc) \
  if( rc==SQLITE_NOMEM ) shell_check_oom(0); \
  else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \
    eputf("E:%d\n",rc), assert(0)
#else
static void rc_err_oom_die(int rc){
  if( rc==SQLITE_NOMEM ) shell_check_oom(0);
  assert(rc==SQLITE_OK||rc==SQLITE_DONE);
}
#endif

23904
23905
23906
23907
23908
23909
23910

23911
23912
23913
23914
23915
23916
23917
    if( *pDb==0 ){
      if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0;
#ifdef SHELL_COLFIX_DB
      if(*zCOL_DB!=':')
        sqlite3_exec(*pDb,"drop table if exists ColNames;"
                     "drop view if exists RepeatedNames;",0,0,0);
#endif

      rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0);
      rc_err_oom_die(rc);
    }
    assert(*pDb!=0);
    rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0);
    rc_err_oom_die(rc);
    rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0);







>







25827
25828
25829
25830
25831
25832
25833
25834
25835
25836
25837
25838
25839
25840
25841
    if( *pDb==0 ){
      if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0;
#ifdef SHELL_COLFIX_DB
      if(*zCOL_DB!=':')
        sqlite3_exec(*pDb,"drop table if exists ColNames;"
                     "drop view if exists RepeatedNames;",0,0,0);
#endif
#undef SHELL_COLFIX_DB
      rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0);
      rc_err_oom_die(rc);
    }
    assert(*pDb!=0);
    rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0);
    rc_err_oom_die(rc);
    rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0);
23963
23964
23965
23966
23967
23968
23969
























































23970
23971
23972
23973
23974
23975
23976
    }
    sqlite3_finalize(pStmt);
    sqlite3_close(*pDb);
    *pDb = 0;
    return zColsSpec;
  }
}

























































/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
** Return 1 on error, 2 to exit, and 0 otherwise.
*/







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







25887
25888
25889
25890
25891
25892
25893
25894
25895
25896
25897
25898
25899
25900
25901
25902
25903
25904
25905
25906
25907
25908
25909
25910
25911
25912
25913
25914
25915
25916
25917
25918
25919
25920
25921
25922
25923
25924
25925
25926
25927
25928
25929
25930
25931
25932
25933
25934
25935
25936
25937
25938
25939
25940
25941
25942
25943
25944
25945
25946
25947
25948
25949
25950
25951
25952
25953
25954
25955
25956
    }
    sqlite3_finalize(pStmt);
    sqlite3_close(*pDb);
    *pDb = 0;
    return zColsSpec;
  }
}

/*
** Check if the sqlite_schema table contains one or more virtual tables. If
** parameter zLike is not NULL, then it is an SQL expression that the
** sqlite_schema row must also match. If one or more such rows are found,
** print the following warning to the output:
**
** WARNING: Script requires that SQLITE_DBCONFIG_DEFENSIVE be disabled
*/
static int outputDumpWarning(ShellState *p, const char *zLike){
  int rc = SQLITE_OK;
  sqlite3_stmt *pStmt = 0;
  shellPreparePrintf(p->db, &rc, &pStmt,
    "SELECT 1 FROM sqlite_schema o WHERE "
    "sql LIKE 'CREATE VIRTUAL TABLE%%' AND %s", zLike ? zLike : "true"
  );
  if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
    oputz("/* WARNING: "
          "Script requires that SQLITE_DBCONFIG_DEFENSIVE be disabled */\n"
    );
  }
  shellFinalize(&rc, pStmt);
  return rc;
}

/*
** Fault-Simulator state and logic.
*/
static struct {
  int iId;           /* ID that triggers a simulated fault.  -1 means "any" */
  int iErr;          /* The error code to return on a fault */
  int iCnt;          /* Trigger the fault only if iCnt is already zero */
  int iInterval;     /* Reset iCnt to this value after each fault */
  int eVerbose;      /* When to print output */
} faultsim_state = {-1, 0, 0, 0, 0};

/*
** This is the fault-sim callback
*/
static int faultsim_callback(int iArg){
  if( faultsim_state.iId>0 && faultsim_state.iId!=iArg ){
    return SQLITE_OK;
  }
  if( faultsim_state.iCnt>0 ){
    faultsim_state.iCnt--;
    if( faultsim_state.eVerbose>=2 ){
      oputf("FAULT-SIM id=%d no-fault (cnt=%d)\n", iArg, faultsim_state.iCnt);
    }
    return SQLITE_OK;
  }
  if( faultsim_state.eVerbose>=1 ){
    oputf("FAULT-SIM id=%d returns %d\n", iArg, faultsim_state.iErr);
  }
  faultsim_state.iCnt = faultsim_state.iInterval;
  return faultsim_state.iErr;
}

/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
24017
24018
24019
24020
24021
24022
24023
24024
24025
24026
24027
24028
24029
24030
24031
  n = strlen30(azArg[0]);
  c = azArg[0][0];
  clearTempFile(p);

#ifndef SQLITE_OMIT_AUTHORIZATION
  if( c=='a' && cli_strncmp(azArg[0], "auth", n)==0 ){
    if( nArg!=2 ){
      raw_printf(stderr, "Usage: .auth ON|OFF\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    if( booleanValue(azArg[1]) ){
      sqlite3_set_authorizer(p->db, shellAuth, p);
    }else if( p->bSafeModePersist ){







|







25997
25998
25999
26000
26001
26002
26003
26004
26005
26006
26007
26008
26009
26010
26011
  n = strlen30(azArg[0]);
  c = azArg[0][0];
  clearTempFile(p);

#ifndef SQLITE_OMIT_AUTHORIZATION
  if( c=='a' && cli_strncmp(azArg[0], "auth", n)==0 ){
    if( nArg!=2 ){
      eputz("Usage: .auth ON|OFF\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    if( booleanValue(azArg[1]) ){
      sqlite3_set_authorizer(p->db, shellAuth, p);
    }else if( p->bSafeModePersist ){
24064
24065
24066
24067
24068
24069
24070
24071
24072
24073
24074
24075
24076
24077
24078
24079
24080
24081
24082
24083
24084
24085
24086
24087
24088
24089
24090
24091
24092
24093
24094
24095
24096
24097
24098
24099
24100
24101
24102
24103
24104
24105
24106
24107
24108
24109
24110
24111
24112
24113
24114
24115
24116
24117
24118
24119
24120
24121
24122
24123
24124
24125
24126
24127
24128
24129
24130
24131
24132
24133
24134
24135
24136
24137
24138
24139
24140
24141
24142
24143
24144
24145
24146
        if( cli_strcmp(z, "-append")==0 ){
          zVfs = "apndvfs";
        }else
        if( cli_strcmp(z, "-async")==0 ){
          bAsync = 1;
        }else
        {
          utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
          return 1;
        }
      }else if( zDestFile==0 ){
        zDestFile = azArg[j];
      }else if( zDb==0 ){
        zDb = zDestFile;
        zDestFile = azArg[j];
      }else{
        raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
        return 1;
      }
    }
    if( zDestFile==0 ){
      raw_printf(stderr, "missing FILENAME argument on .backup\n");
      return 1;
    }
    if( zDb==0 ) zDb = "main";
    rc = sqlite3_open_v2(zDestFile, &pDest,
                  SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
    if( rc!=SQLITE_OK ){
      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
      close_db(pDest);
      return 1;
    }
    if( bAsync ){
      sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
                   0, 0, 0);
    }
    open_db(p, 0);
    pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
    if( pBackup==0 ){
      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
      close_db(pDest);
      return 1;
    }
    while(  (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
    sqlite3_backup_finish(pBackup);
    if( rc==SQLITE_DONE ){
      rc = 0;
    }else{
      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
      rc = 1;
    }
    close_db(pDest);
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='b' && n>=3 && cli_strncmp(azArg[0], "bail", n)==0 ){
    if( nArg==2 ){
      bail_on_error = booleanValue(azArg[1]);
    }else{
      raw_printf(stderr, "Usage: .bail on|off\n");
      rc = 1;
    }
  }else

  /* Undocumented.  Legacy only.  See "crnl" below */
  if( c=='b' && n>=3 && cli_strncmp(azArg[0], "binary", n)==0 ){
    if( nArg==2 ){
      if( booleanValue(azArg[1]) ){
        setBinaryMode(p->out, 1);
      }else{
        setTextMode(p->out, 1);
      }
    }else{
      raw_printf(stderr, "The \".binary\" command is deprecated."
                         " Use \".crnl\" instead.\n");
      raw_printf(stderr, "Usage: .binary on|off\n");
      rc = 1;
    }
  }else

  /* The undocumented ".breakpoint" command causes a call to the no-op
  ** routine named test_breakpoint().
  */







|








|




|






|










|








|










|













|
<
|







26044
26045
26046
26047
26048
26049
26050
26051
26052
26053
26054
26055
26056
26057
26058
26059
26060
26061
26062
26063
26064
26065
26066
26067
26068
26069
26070
26071
26072
26073
26074
26075
26076
26077
26078
26079
26080
26081
26082
26083
26084
26085
26086
26087
26088
26089
26090
26091
26092
26093
26094
26095
26096
26097
26098
26099
26100
26101
26102
26103
26104
26105
26106
26107
26108
26109
26110
26111
26112
26113
26114
26115
26116
26117

26118
26119
26120
26121
26122
26123
26124
26125
        if( cli_strcmp(z, "-append")==0 ){
          zVfs = "apndvfs";
        }else
        if( cli_strcmp(z, "-async")==0 ){
          bAsync = 1;
        }else
        {
          eputf("unknown option: %s\n", azArg[j]);
          return 1;
        }
      }else if( zDestFile==0 ){
        zDestFile = azArg[j];
      }else if( zDb==0 ){
        zDb = zDestFile;
        zDestFile = azArg[j];
      }else{
        eputz("Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
        return 1;
      }
    }
    if( zDestFile==0 ){
      eputz("missing FILENAME argument on .backup\n");
      return 1;
    }
    if( zDb==0 ) zDb = "main";
    rc = sqlite3_open_v2(zDestFile, &pDest,
                  SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
    if( rc!=SQLITE_OK ){
      eputf("Error: cannot open \"%s\"\n", zDestFile);
      close_db(pDest);
      return 1;
    }
    if( bAsync ){
      sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
                   0, 0, 0);
    }
    open_db(p, 0);
    pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
    if( pBackup==0 ){
      eputf("Error: %s\n", sqlite3_errmsg(pDest));
      close_db(pDest);
      return 1;
    }
    while(  (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
    sqlite3_backup_finish(pBackup);
    if( rc==SQLITE_DONE ){
      rc = 0;
    }else{
      eputf("Error: %s\n", sqlite3_errmsg(pDest));
      rc = 1;
    }
    close_db(pDest);
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='b' && n>=3 && cli_strncmp(azArg[0], "bail", n)==0 ){
    if( nArg==2 ){
      bail_on_error = booleanValue(azArg[1]);
    }else{
      eputz("Usage: .bail on|off\n");
      rc = 1;
    }
  }else

  /* Undocumented.  Legacy only.  See "crnl" below */
  if( c=='b' && n>=3 && cli_strncmp(azArg[0], "binary", n)==0 ){
    if( nArg==2 ){
      if( booleanValue(azArg[1]) ){
        setBinaryMode(p->out, 1);
      }else{
        setTextMode(p->out, 1);
      }
    }else{
      eputz("The \".binary\" command is deprecated. Use \".crnl\" instead.\n"

            "Usage: .binary on|off\n");
      rc = 1;
    }
  }else

  /* The undocumented ".breakpoint" command causes a call to the no-op
  ** routine named test_breakpoint().
  */
24156
24157
24158
24159
24160
24161
24162
24163
24164
24165
24166
24167
24168
24169
24170
24171
24172
24173
24174
24175
24176
24177
24178
24179
24180
24181
24182
24183
24184
24185
24186
24187
24188
24189
24190
24191
24192
24193
24194
24195
24196
24197
24198
24199
24200
24201
24202
24203
24204
24205
24206
24207
24208
24209
24210
24211
24212
24213
24214
24215
24216
24217
24218
24219
24220
24221
24222
24223
24224
24225
24226
24227
24228
24229
24230
24231
24232
24233
24234
24235
24236
24237
24238
24239
24240
24241
24242
24243
24244
24245
24246
24247
24248
24249
24250
24251
24252
24253
24254
24255
24256
24257
24258
24259
24260
24261
24262
24263
24264
24265
24266
24267
24268
24269
24270
24271
24272
24273
24274
24275
24276
24277
24278
24279
24280
24281
24282
24283
24284
24285
24286
24287
24288
24289
24290
24291
24292
24293
24294
24295
24296
24297
24298
24299
24300
24301
24302
24303
24304
24305
24306
24307
24308
24309
24310
24311
24312
24313
24314
24315
24316
24317
24318
24319
24320
      wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
      rc = !SetCurrentDirectoryW(z);
      sqlite3_free(z);
#else
      rc = chdir(azArg[1]);
#endif
      if( rc ){
        utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
        rc = 1;
      }
    }else{
      raw_printf(stderr, "Usage: .cd DIRECTORY\n");
      rc = 1;
    }
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='c' && n>=3 && cli_strncmp(azArg[0], "changes", n)==0 ){
    if( nArg==2 ){
      setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
    }else{
      raw_printf(stderr, "Usage: .changes on|off\n");
      rc = 1;
    }
  }else

#ifndef SQLITE_SHELL_FIDDLE
  /* Cancel output redirection, if it is currently set (by .testcase)
  ** Then read the content of the testcase-out.txt file and compare against
  ** azArg[1].  If there are differences, report an error and exit.
  */
  if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){
    char *zRes = 0;
    output_reset(p);
    if( nArg!=2 ){
      raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
      rc = 2;
    }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
      rc = 2;
    }else if( testcase_glob(azArg[1],zRes)==0 ){
      utf8_printf(stderr,
                 "testcase-%s FAILED\n Expected: [%s]\n      Got: [%s]\n",
                 p->zTestcase, azArg[1], zRes);
      rc = 1;
    }else{
      utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
      p->nCheck++;
    }
    sqlite3_free(zRes);
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){
    failIfSafeMode(p, "cannot run .clone in safe mode");
    if( nArg==2 ){
      tryToClone(p, azArg[1]);
    }else{
      raw_printf(stderr, "Usage: .clone FILENAME\n");
      rc = 1;
    }
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='c' && cli_strncmp(azArg[0], "connection", n)==0 ){
    if( nArg==1 ){
      /* List available connections */
      int i;
      for(i=0; i<ArraySize(p->aAuxDb); i++){
        const char *zFile = p->aAuxDb[i].zDbFilename;
        if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
          zFile = "(not open)";
        }else if( zFile==0 ){
          zFile = "(memory)";
        }else if( zFile[0]==0 ){
          zFile = "(temporary-file)";
        }
        if( p->pAuxDb == &p->aAuxDb[i] ){
          utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
        }else if( p->aAuxDb[i].db!=0 ){
          utf8_printf(stdout, "       %d: %s\n", i, zFile);
        }
      }
    }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
      int i = azArg[1][0] - '0';
      if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
        p->pAuxDb->db = p->db;
        p->pAuxDb = &p->aAuxDb[i];
        globalDb = p->db = p->pAuxDb->db;
        p->pAuxDb->db = 0;
      }
    }else if( nArg==3 && cli_strcmp(azArg[1], "close")==0
           && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
      int i = azArg[2][0] - '0';
      if( i<0 || i>=ArraySize(p->aAuxDb) ){
        /* No-op */
      }else if( p->pAuxDb == &p->aAuxDb[i] ){
        raw_printf(stderr, "cannot close the active database connection\n");
        rc = 1;
      }else if( p->aAuxDb[i].db ){
        session_close_all(p, i);
        close_db(p->aAuxDb[i].db);
        p->aAuxDb[i].db = 0;
      }
    }else{
      raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
      rc = 1;
    }
  }else

  if( c=='c' && n==4 && cli_strncmp(azArg[0], "crnl", n)==0 ){
    if( nArg==2 ){
      if( booleanValue(azArg[1]) ){
        setTextMode(p->out, 1);
      }else{
        setBinaryMode(p->out, 1);
      }
    }else{
#if !defined(_WIN32) && !defined(WIN32)
      raw_printf(stderr, "The \".crnl\" is a no-op on non-Windows machines.\n");
#endif
      raw_printf(stderr, "Usage: .crnl on|off\n");
      rc = 1;
    }
  }else

  if( c=='d' && n>1 && cli_strncmp(azArg[0], "databases", n)==0 ){
    char **azName = 0;
    int nName = 0;
    sqlite3_stmt *pStmt;
    int i;
    open_db(p, 0);
    rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
    if( rc ){
      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
      rc = 1;
    }else{
      while( sqlite3_step(pStmt)==SQLITE_ROW ){
        const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
        const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
        if( zSchema==0 || zFile==0 ) continue;
        azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
        shell_check_oom(azName);
        azName[nName*2] = strdup(zSchema);
        azName[nName*2+1] = strdup(zFile);
        nName++;
      }
    }
    sqlite3_finalize(pStmt);
    for(i=0; i<nName; i++){
      int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
      int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
      const char *z = azName[i*2+1];
      utf8_printf(p->out, "%s: %s %s%s\n",
         azName[i*2],
         z && z[0] ? z : "\"\"",
         bRdonly ? "r/o" : "r/w",
         eTxn==SQLITE_TXN_NONE ? "" :
            eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
      free(azName[i*2]);
      free(azName[i*2+1]);
    }
    sqlite3_free(azName);
  }else








|



|









|













|




<
|
|


|












|



















|

|
















|







|













|

|












|


















|
<
<
|
|







26135
26136
26137
26138
26139
26140
26141
26142
26143
26144
26145
26146
26147
26148
26149
26150
26151
26152
26153
26154
26155
26156
26157
26158
26159
26160
26161
26162
26163
26164
26165
26166
26167
26168
26169
26170
26171
26172
26173
26174

26175
26176
26177
26178
26179
26180
26181
26182
26183
26184
26185
26186
26187
26188
26189
26190
26191
26192
26193
26194
26195
26196
26197
26198
26199
26200
26201
26202
26203
26204
26205
26206
26207
26208
26209
26210
26211
26212
26213
26214
26215
26216
26217
26218
26219
26220
26221
26222
26223
26224
26225
26226
26227
26228
26229
26230
26231
26232
26233
26234
26235
26236
26237
26238
26239
26240
26241
26242
26243
26244
26245
26246
26247
26248
26249
26250
26251
26252
26253
26254
26255
26256
26257
26258
26259
26260
26261
26262
26263
26264
26265
26266
26267
26268
26269
26270
26271
26272
26273
26274
26275
26276
26277
26278
26279
26280
26281
26282
26283
26284
26285
26286
26287


26288
26289
26290
26291
26292
26293
26294
26295
26296
      wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
      rc = !SetCurrentDirectoryW(z);
      sqlite3_free(z);
#else
      rc = chdir(azArg[1]);
#endif
      if( rc ){
        eputf("Cannot change to directory \"%s\"\n", azArg[1]);
        rc = 1;
      }
    }else{
      eputz("Usage: .cd DIRECTORY\n");
      rc = 1;
    }
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='c' && n>=3 && cli_strncmp(azArg[0], "changes", n)==0 ){
    if( nArg==2 ){
      setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
    }else{
      eputz("Usage: .changes on|off\n");
      rc = 1;
    }
  }else

#ifndef SQLITE_SHELL_FIDDLE
  /* Cancel output redirection, if it is currently set (by .testcase)
  ** Then read the content of the testcase-out.txt file and compare against
  ** azArg[1].  If there are differences, report an error and exit.
  */
  if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){
    char *zRes = 0;
    output_reset(p);
    if( nArg!=2 ){
      eputz("Usage: .check GLOB-PATTERN\n");
      rc = 2;
    }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
      rc = 2;
    }else if( testcase_glob(azArg[1],zRes)==0 ){

      eputf("testcase-%s FAILED\n Expected: [%s]\n      Got: [%s]\n",
            p->zTestcase, azArg[1], zRes);
      rc = 1;
    }else{
      oputf("testcase-%s ok\n", p->zTestcase);
      p->nCheck++;
    }
    sqlite3_free(zRes);
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){
    failIfSafeMode(p, "cannot run .clone in safe mode");
    if( nArg==2 ){
      tryToClone(p, azArg[1]);
    }else{
      eputz("Usage: .clone FILENAME\n");
      rc = 1;
    }
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='c' && cli_strncmp(azArg[0], "connection", n)==0 ){
    if( nArg==1 ){
      /* List available connections */
      int i;
      for(i=0; i<ArraySize(p->aAuxDb); i++){
        const char *zFile = p->aAuxDb[i].zDbFilename;
        if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
          zFile = "(not open)";
        }else if( zFile==0 ){
          zFile = "(memory)";
        }else if( zFile[0]==0 ){
          zFile = "(temporary-file)";
        }
        if( p->pAuxDb == &p->aAuxDb[i] ){
          sputf(stdout, "ACTIVE %d: %s\n", i, zFile);
        }else if( p->aAuxDb[i].db!=0 ){
          sputf(stdout, "       %d: %s\n", i, zFile);
        }
      }
    }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
      int i = azArg[1][0] - '0';
      if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
        p->pAuxDb->db = p->db;
        p->pAuxDb = &p->aAuxDb[i];
        globalDb = p->db = p->pAuxDb->db;
        p->pAuxDb->db = 0;
      }
    }else if( nArg==3 && cli_strcmp(azArg[1], "close")==0
           && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
      int i = azArg[2][0] - '0';
      if( i<0 || i>=ArraySize(p->aAuxDb) ){
        /* No-op */
      }else if( p->pAuxDb == &p->aAuxDb[i] ){
        eputz("cannot close the active database connection\n");
        rc = 1;
      }else if( p->aAuxDb[i].db ){
        session_close_all(p, i);
        close_db(p->aAuxDb[i].db);
        p->aAuxDb[i].db = 0;
      }
    }else{
      eputz("Usage: .connection [close] [CONNECTION-NUMBER]\n");
      rc = 1;
    }
  }else

  if( c=='c' && n==4 && cli_strncmp(azArg[0], "crnl", n)==0 ){
    if( nArg==2 ){
      if( booleanValue(azArg[1]) ){
        setTextMode(p->out, 1);
      }else{
        setBinaryMode(p->out, 1);
      }
    }else{
#if !defined(_WIN32) && !defined(WIN32)
      eputz("The \".crnl\" is a no-op on non-Windows machines.\n");
#endif
      eputz("Usage: .crnl on|off\n");
      rc = 1;
    }
  }else

  if( c=='d' && n>1 && cli_strncmp(azArg[0], "databases", n)==0 ){
    char **azName = 0;
    int nName = 0;
    sqlite3_stmt *pStmt;
    int i;
    open_db(p, 0);
    rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
    if( rc ){
      eputf("Error: %s\n", sqlite3_errmsg(p->db));
      rc = 1;
    }else{
      while( sqlite3_step(pStmt)==SQLITE_ROW ){
        const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
        const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
        if( zSchema==0 || zFile==0 ) continue;
        azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
        shell_check_oom(azName);
        azName[nName*2] = strdup(zSchema);
        azName[nName*2+1] = strdup(zFile);
        nName++;
      }
    }
    sqlite3_finalize(pStmt);
    for(i=0; i<nName; i++){
      int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
      int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
      const char *z = azName[i*2+1];
      oputf("%s: %s %s%s\n",


            azName[i*2], z && z[0] ? z : "\"\"", bRdonly ? "r/o" : "r/w",
            eTxn==SQLITE_TXN_NONE ? "" :
            eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
      free(azName[i*2]);
      free(azName[i*2+1]);
    }
    sqlite3_free(azName);
  }else

24346
24347
24348
24349
24350
24351
24352
24353
24354
24355
24356
24357
24358
24359
24360
24361
24362
24363
24364
24365
    open_db(p, 0);
    for(ii=0; ii<ArraySize(aDbConfig); ii++){
      if( nArg>1 && cli_strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
      if( nArg>=3 ){
        sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
      }
      sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
      utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
      if( nArg>1 ) break;
    }
    if( nArg>1 && ii==ArraySize(aDbConfig) ){
      utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
      utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
    }
  }else

#if SQLITE_SHELL_HAVE_RECOVER
  if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
    rc = shell_dbinfo_command(p, nArg, azArg);
  }else







|



|
|







26322
26323
26324
26325
26326
26327
26328
26329
26330
26331
26332
26333
26334
26335
26336
26337
26338
26339
26340
26341
    open_db(p, 0);
    for(ii=0; ii<ArraySize(aDbConfig); ii++){
      if( nArg>1 && cli_strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
      if( nArg>=3 ){
        sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
      }
      sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
      oputf("%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
      if( nArg>1 ) break;
    }
    if( nArg>1 && ii==ArraySize(aDbConfig) ){
      eputf("Error: unknown dbconfig \"%s\"\n", azArg[1]);
      eputz("Enter \".dbconfig\" with no arguments for a list\n");
    }
  }else

#if SQLITE_SHELL_HAVE_RECOVER
  if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
    rc = shell_dbinfo_command(p, nArg, azArg);
  }else
24381
24382
24383
24384
24385
24386
24387
24388
24389
24390
24391
24392
24393
24394
24395
24396
24397
24398
24399
24400
24401
24402
24403
24404
24405
24406
24407
24408
24409
24410
24411
24412
24413
24414
       |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
    for(i=1; i<nArg; i++){
      if( azArg[i][0]=='-' ){
        const char *z = azArg[i]+1;
        if( z[0]=='-' ) z++;
        if( cli_strcmp(z,"preserve-rowids")==0 ){
#ifdef SQLITE_OMIT_VIRTUALTABLE
          raw_printf(stderr, "The --preserve-rowids option is not compatible"
                             " with SQLITE_OMIT_VIRTUALTABLE\n");
          rc = 1;
          sqlite3_free(zLike);
          goto meta_command_exit;
#else
          ShellSetFlag(p, SHFLG_PreserveRowid);
#endif
        }else
        if( cli_strcmp(z,"newlines")==0 ){
          ShellSetFlag(p, SHFLG_Newlines);
        }else
        if( cli_strcmp(z,"data-only")==0 ){
          ShellSetFlag(p, SHFLG_DumpDataOnly);
        }else
        if( cli_strcmp(z,"nosys")==0 ){
          ShellSetFlag(p, SHFLG_DumpNoSys);
        }else
        {
          raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
          rc = 1;
          sqlite3_free(zLike);
          goto meta_command_exit;
        }
      }else{
        /* azArg[i] contains a LIKE pattern. This ".dump" request should
        ** only dump data for tables for which either the table name matches







|
|

















|







26357
26358
26359
26360
26361
26362
26363
26364
26365
26366
26367
26368
26369
26370
26371
26372
26373
26374
26375
26376
26377
26378
26379
26380
26381
26382
26383
26384
26385
26386
26387
26388
26389
26390
       |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
    for(i=1; i<nArg; i++){
      if( azArg[i][0]=='-' ){
        const char *z = azArg[i]+1;
        if( z[0]=='-' ) z++;
        if( cli_strcmp(z,"preserve-rowids")==0 ){
#ifdef SQLITE_OMIT_VIRTUALTABLE
          eputz("The --preserve-rowids option is not compatible"
                " with SQLITE_OMIT_VIRTUALTABLE\n");
          rc = 1;
          sqlite3_free(zLike);
          goto meta_command_exit;
#else
          ShellSetFlag(p, SHFLG_PreserveRowid);
#endif
        }else
        if( cli_strcmp(z,"newlines")==0 ){
          ShellSetFlag(p, SHFLG_Newlines);
        }else
        if( cli_strcmp(z,"data-only")==0 ){
          ShellSetFlag(p, SHFLG_DumpDataOnly);
        }else
        if( cli_strcmp(z,"nosys")==0 ){
          ShellSetFlag(p, SHFLG_DumpNoSys);
        }else
        {
          eputf("Unknown option \"%s\" on \".dump\"\n", azArg[i]);
          rc = 1;
          sqlite3_free(zLike);
          goto meta_command_exit;
        }
      }else{
        /* azArg[i] contains a LIKE pattern. This ".dump" request should
        ** only dump data for tables for which either the table name matches
24430
24431
24432
24433
24434
24435
24436

24437
24438
24439
24440
24441
24442
24443
24444
24445
24446
24447
24448
24449
          zLike = zExpr;
        }
      }
    }

    open_db(p, 0);


    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
      /* When playing back a "dump", the content might appear in an order
      ** which causes immediate foreign key constraints to be violated.
      ** So disable foreign-key constraint enforcement to prevent problems. */
      raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
      raw_printf(p->out, "BEGIN TRANSACTION;\n");
    }
    p->writableSchema = 0;
    p->showHeader = 0;
    /* Set writable_schema=ON since doing so forces SQLite to initialize
    ** as much of the schema as it can even if the sqlite_schema table is
    ** corrupt. */
    sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);







>




|
|







26406
26407
26408
26409
26410
26411
26412
26413
26414
26415
26416
26417
26418
26419
26420
26421
26422
26423
26424
26425
26426
          zLike = zExpr;
        }
      }
    }

    open_db(p, 0);

    outputDumpWarning(p, zLike);
    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
      /* When playing back a "dump", the content might appear in an order
      ** which causes immediate foreign key constraints to be violated.
      ** So disable foreign-key constraint enforcement to prevent problems. */
      oputz("PRAGMA foreign_keys=OFF;\n");
      oputz("BEGIN TRANSACTION;\n");
    }
    p->writableSchema = 0;
    p->showHeader = 0;
    /* Set writable_schema=ON since doing so forces SQLite to initialize
    ** as much of the schema as it can even if the sqlite_schema table is
    ** corrupt. */
    sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
24458
24459
24460
24461
24462
24463
24464
24465

24466
24467
24468
24469
24470
24471
24472
24473
24474
24475
24476
24477
24478
24479
24480
24481
24482
24483
24484
24485
24486
24487
24488
24489
24490
24491
24492
24493
24494
24495
24496
    );
    run_schema_dump_query(p,zSql);
    sqlite3_free(zSql);
    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
      zSql = sqlite3_mprintf(
        "SELECT sql FROM sqlite_schema AS o "
        "WHERE (%s) AND sql NOT NULL"
        "  AND type IN ('index','trigger','view')",

        zLike
      );
      run_table_dump_query(p, zSql);
      sqlite3_free(zSql);
    }
    sqlite3_free(zLike);
    if( p->writableSchema ){
      raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
      p->writableSchema = 0;
    }
    sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
    sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
      raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
    }
    p->showHeader = savedShowHeader;
    p->shellFlgs = savedShellFlags;
  }else

  if( c=='e' && cli_strncmp(azArg[0], "echo", n)==0 ){
    if( nArg==2 ){
      setOrClearFlag(p, SHFLG_Echo, azArg[1]);
    }else{
      raw_printf(stderr, "Usage: .echo on|off\n");
      rc = 1;
    }
  }else

  if( c=='e' && cli_strncmp(azArg[0], "eqp", n)==0 ){
    if( nArg==2 ){
      p->autoEQPtest = 0;







|
>







|





|









|







26435
26436
26437
26438
26439
26440
26441
26442
26443
26444
26445
26446
26447
26448
26449
26450
26451
26452
26453
26454
26455
26456
26457
26458
26459
26460
26461
26462
26463
26464
26465
26466
26467
26468
26469
26470
26471
26472
26473
26474
    );
    run_schema_dump_query(p,zSql);
    sqlite3_free(zSql);
    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
      zSql = sqlite3_mprintf(
        "SELECT sql FROM sqlite_schema AS o "
        "WHERE (%s) AND sql NOT NULL"
        "  AND type IN ('index','trigger','view') "
        "ORDER BY type COLLATE NOCASE DESC",
        zLike
      );
      run_table_dump_query(p, zSql);
      sqlite3_free(zSql);
    }
    sqlite3_free(zLike);
    if( p->writableSchema ){
      oputz("PRAGMA writable_schema=OFF;\n");
      p->writableSchema = 0;
    }
    sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
    sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
      oputz(p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
    }
    p->showHeader = savedShowHeader;
    p->shellFlgs = savedShellFlags;
  }else

  if( c=='e' && cli_strncmp(azArg[0], "echo", n)==0 ){
    if( nArg==2 ){
      setOrClearFlag(p, SHFLG_Echo, azArg[1]);
    }else{
      eputz("Usage: .echo on|off\n");
      rc = 1;
    }
  }else

  if( c=='e' && cli_strncmp(azArg[0], "eqp", n)==0 ){
    if( nArg==2 ){
      p->autoEQPtest = 0;
24513
24514
24515
24516
24517
24518
24519
24520
24521
24522
24523
24524
24525
24526
24527
        sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
        sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
#endif
      }else{
        p->autoEQP = (u8)booleanValue(azArg[1]);
      }
    }else{
      raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
      rc = 1;
    }
  }else

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='e' && cli_strncmp(azArg[0], "exit", n)==0 ){
    if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);







|







26491
26492
26493
26494
26495
26496
26497
26498
26499
26500
26501
26502
26503
26504
26505
        sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
        sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
#endif
      }else{
        p->autoEQP = (u8)booleanValue(azArg[1]);
      }
    }else{
      eputz("Usage: .eqp off|on|trace|trigger|full\n");
      rc = 1;
    }
  }else

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='e' && cli_strncmp(azArg[0], "exit", n)==0 ){
    if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
24552
24553
24554
24555
24556
24557
24558
24559
24560
24561
24562
24563
24564
24565
24566
24567
24568
      p->autoExplain = 1;
    }
  }else

#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( c=='e' && cli_strncmp(azArg[0], "expert", n)==0 ){
    if( p->bSafeMode ){
      raw_printf(stderr,
        "Cannot run experimental commands such as \"%s\" in safe mode\n",
        azArg[0]);
      rc = 1;
    }else{
      open_db(p, 0);
      expertDotCommand(p, azArg, nArg);
    }
  }else
#endif







<
|
|







26530
26531
26532
26533
26534
26535
26536

26537
26538
26539
26540
26541
26542
26543
26544
26545
      p->autoExplain = 1;
    }
  }else

#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( c=='e' && cli_strncmp(azArg[0], "expert", n)==0 ){
    if( p->bSafeMode ){

      eputf("Cannot run experimental commands such as \"%s\" in safe mode\n",
            azArg[0]);
      rc = 1;
    }else{
      open_db(p, 0);
      expertDotCommand(p, azArg, nArg);
    }
  }else
#endif
24610
24611
24612
24613
24614
24615
24616
24617
24618
24619
24620
24621
24622
24623
24624
24625
24626
24627
24628
24629
24630
24631
24632
24633
24634
24635
24636
24637
24638
24639
24640
24641
24642
24643
24644
24645
24646
24647
24648
24649
24650
24651
    if( zCmd[0]=='-' && zCmd[1] ){
      zCmd++;
      if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
    }

    /* --help lists all file-controls */
    if( cli_strcmp(zCmd,"help")==0 ){
      utf8_printf(p->out, "Available file-controls:\n");
      for(i=0; i<ArraySize(aCtrl); i++){
        utf8_printf(p->out, "  .filectrl %s %s\n",
                    aCtrl[i].zCtrlName, aCtrl[i].zUsage);
      }
      rc = 1;
      goto meta_command_exit;
    }

    /* convert filectrl text option to value. allow any unique prefix
    ** of the option name, or a numerical value. */
    n2 = strlen30(zCmd);
    for(i=0; i<ArraySize(aCtrl); i++){
      if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
        if( filectrl<0 ){
          filectrl = aCtrl[i].ctrlCode;
          iCtrl = i;
        }else{
          utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
                              "Use \".filectrl --help\" for help\n", zCmd);
          rc = 1;
          goto meta_command_exit;
        }
      }
    }
    if( filectrl<0 ){
      utf8_printf(stderr,"Error: unknown file-control: %s\n"
                         "Use \".filectrl --help\" for help\n", zCmd);
    }else{
      switch(filectrl){
        case SQLITE_FCNTL_SIZE_LIMIT: {
          if( nArg!=2 && nArg!=3 ) break;
          iRes = nArg==3 ? integerValue(azArg[2]) : -1;
          sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
          isOk = 1;







|

<
|














|
|






|
|







26587
26588
26589
26590
26591
26592
26593
26594
26595

26596
26597
26598
26599
26600
26601
26602
26603
26604
26605
26606
26607
26608
26609
26610
26611
26612
26613
26614
26615
26616
26617
26618
26619
26620
26621
26622
26623
26624
26625
26626
26627
    if( zCmd[0]=='-' && zCmd[1] ){
      zCmd++;
      if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
    }

    /* --help lists all file-controls */
    if( cli_strcmp(zCmd,"help")==0 ){
      oputz("Available file-controls:\n");
      for(i=0; i<ArraySize(aCtrl); i++){

        oputf("  .filectrl %s %s\n", aCtrl[i].zCtrlName, aCtrl[i].zUsage);
      }
      rc = 1;
      goto meta_command_exit;
    }

    /* convert filectrl text option to value. allow any unique prefix
    ** of the option name, or a numerical value. */
    n2 = strlen30(zCmd);
    for(i=0; i<ArraySize(aCtrl); i++){
      if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
        if( filectrl<0 ){
          filectrl = aCtrl[i].ctrlCode;
          iCtrl = i;
        }else{
          eputf("Error: ambiguous file-control: \"%s\"\n"
                "Use \".filectrl --help\" for help\n", zCmd);
          rc = 1;
          goto meta_command_exit;
        }
      }
    }
    if( filectrl<0 ){
      eputf("Error: unknown file-control: %s\n"
            "Use \".filectrl --help\" for help\n", zCmd);
    }else{
      switch(filectrl){
        case SQLITE_FCNTL_SIZE_LIMIT: {
          if( nArg!=2 && nArg!=3 ) break;
          iRes = nArg==3 ? integerValue(azArg[2]) : -1;
          sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
          isOk = 1;
24680
24681
24682
24683
24684
24685
24686
24687
24688
24689
24690
24691
24692
24693
24694
24695
24696
24697
24698
24699
24700
24701
24702
24703
24704
24705
24706
24707
24708
24709
24710
24711
24712
24713
24714
24715
24716
24717
24718
24719
24720
24721
24722
24723
24724
24725
24726
24727
24728
24729
24730
24731
24732
24733
24734
24735
          break;
        }
        case SQLITE_FCNTL_TEMPFILENAME: {
          char *z = 0;
          if( nArg!=2 ) break;
          sqlite3_file_control(p->db, zSchema, filectrl, &z);
          if( z ){
            utf8_printf(p->out, "%s\n", z);
            sqlite3_free(z);
          }
          isOk = 2;
          break;
        }
        case SQLITE_FCNTL_RESERVE_BYTES: {
          int x;
          if( nArg>=3 ){
            x = atoi(azArg[2]);
            sqlite3_file_control(p->db, zSchema, filectrl, &x);
          }
          x = -1;
          sqlite3_file_control(p->db, zSchema, filectrl, &x);
          utf8_printf(p->out,"%d\n", x);
          isOk = 2;
          break;
        }
      }
    }
    if( isOk==0 && iCtrl>=0 ){
      utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
      rc = 1;
    }else if( isOk==1 ){
      char zBuf[100];
      sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
      raw_printf(p->out, "%s\n", zBuf);
    }
  }else

  if( c=='f' && cli_strncmp(azArg[0], "fullschema", n)==0 ){
    ShellState data;
    int doStats = 0;
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.cMode = data.mode = MODE_Semi;
    if( nArg==2 && optionMatch(azArg[1], "indent") ){
      data.cMode = data.mode = MODE_Pretty;
      nArg = 1;
    }
    if( nArg!=1 ){
      raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    rc = sqlite3_exec(p->db,
       "SELECT sql FROM"
       "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"







|













|






|




|














|







26656
26657
26658
26659
26660
26661
26662
26663
26664
26665
26666
26667
26668
26669
26670
26671
26672
26673
26674
26675
26676
26677
26678
26679
26680
26681
26682
26683
26684
26685
26686
26687
26688
26689
26690
26691
26692
26693
26694
26695
26696
26697
26698
26699
26700
26701
26702
26703
26704
26705
26706
26707
26708
26709
26710
26711
          break;
        }
        case SQLITE_FCNTL_TEMPFILENAME: {
          char *z = 0;
          if( nArg!=2 ) break;
          sqlite3_file_control(p->db, zSchema, filectrl, &z);
          if( z ){
            oputf("%s\n", z);
            sqlite3_free(z);
          }
          isOk = 2;
          break;
        }
        case SQLITE_FCNTL_RESERVE_BYTES: {
          int x;
          if( nArg>=3 ){
            x = atoi(azArg[2]);
            sqlite3_file_control(p->db, zSchema, filectrl, &x);
          }
          x = -1;
          sqlite3_file_control(p->db, zSchema, filectrl, &x);
          oputf("%d\n", x);
          isOk = 2;
          break;
        }
      }
    }
    if( isOk==0 && iCtrl>=0 ){
      oputf("Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
      rc = 1;
    }else if( isOk==1 ){
      char zBuf[100];
      sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
      oputf("%s\n", zBuf);
    }
  }else

  if( c=='f' && cli_strncmp(azArg[0], "fullschema", n)==0 ){
    ShellState data;
    int doStats = 0;
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.cMode = data.mode = MODE_Semi;
    if( nArg==2 && optionMatch(azArg[1], "indent") ){
      data.cMode = data.mode = MODE_Pretty;
      nArg = 1;
    }
    if( nArg!=1 ){
      eputz("Usage: .fullschema ?--indent?\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    rc = sqlite3_exec(p->db,
       "SELECT sql FROM"
       "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
24747
24748
24749
24750
24751
24752
24753
24754
24755
24756
24757
24758
24759
24760
24761
24762
24763
24764
24765
24766
24767
24768
24769
24770
24771
24772
24773
24774
24775
24776
24777
24778
24779
24780
24781
24782
24783
24784
24785
24786
24787
24788
24789
24790
24791
24792
24793
24794
24795
24796
24797
24798
24799
24800
24801
24802
24803
24804
24805
24806
               -1, &pStmt, 0);
      if( rc==SQLITE_OK ){
        doStats = sqlite3_step(pStmt)==SQLITE_ROW;
        sqlite3_finalize(pStmt);
      }
    }
    if( doStats==0 ){
      raw_printf(p->out, "/* No STAT tables available */\n");
    }else{
      raw_printf(p->out, "ANALYZE sqlite_schema;\n");
      data.cMode = data.mode = MODE_Insert;
      data.zDestTable = "sqlite_stat1";
      shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
      data.zDestTable = "sqlite_stat4";
      shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
      raw_printf(p->out, "ANALYZE sqlite_schema;\n");
    }
  }else

  if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){
    if( nArg==2 ){
      p->showHeader = booleanValue(azArg[1]);
      p->shellFlgs |= SHFLG_HeaderSet;
    }else{
      raw_printf(stderr, "Usage: .headers on|off\n");
      rc = 1;
    }
  }else

  if( c=='h' && cli_strncmp(azArg[0], "help", n)==0 ){
    if( nArg>=2 ){
      n = showHelp(p->out, azArg[1]);
      if( n==0 ){
        utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
      }
    }else{
      showHelp(p->out, 0);
    }
  }else

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){
    char *zTable = 0;           /* Insert data into this table */
    char *zSchema = 0;          /* within this schema (may default to "main") */
    char *zFile = 0;            /* Name of file to extra content from */
    sqlite3_stmt *pStmt = NULL; /* A statement */
    int nCol;                   /* Number of columns in the table */
    int nByte;                  /* Number of bytes in an SQL string */
    int i, j;                   /* Loop counters */
    int needCommit;             /* True to COMMIT or ROLLBACK at end */
    int nSep;                   /* Number of bytes in p->colSeparator[] */
    char *zSql;                 /* An SQL statement */
    char *zFullTabName;         /* Table name with schema if applicable */
    ImportCtx sCtx;             /* Reader context */
    char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
    int eVerbose = 0;           /* Larger for more console output */
    int nSkip = 0;              /* Initial lines to skip */
    int useOutputMode = 1;      /* Use output mode to determine separators */
    char *zCreate = 0;          /* CREATE TABLE statement text */








|

|





|








|








|









|



|



|
<







26723
26724
26725
26726
26727
26728
26729
26730
26731
26732
26733
26734
26735
26736
26737
26738
26739
26740
26741
26742
26743
26744
26745
26746
26747
26748
26749
26750
26751
26752
26753
26754
26755
26756
26757
26758
26759
26760
26761
26762
26763
26764
26765
26766
26767
26768
26769
26770
26771
26772
26773
26774

26775
26776
26777
26778
26779
26780
26781
               -1, &pStmt, 0);
      if( rc==SQLITE_OK ){
        doStats = sqlite3_step(pStmt)==SQLITE_ROW;
        sqlite3_finalize(pStmt);
      }
    }
    if( doStats==0 ){
      oputz("/* No STAT tables available */\n");
    }else{
      oputz("ANALYZE sqlite_schema;\n");
      data.cMode = data.mode = MODE_Insert;
      data.zDestTable = "sqlite_stat1";
      shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
      data.zDestTable = "sqlite_stat4";
      shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
      oputz("ANALYZE sqlite_schema;\n");
    }
  }else

  if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){
    if( nArg==2 ){
      p->showHeader = booleanValue(azArg[1]);
      p->shellFlgs |= SHFLG_HeaderSet;
    }else{
      eputz("Usage: .headers on|off\n");
      rc = 1;
    }
  }else

  if( c=='h' && cli_strncmp(azArg[0], "help", n)==0 ){
    if( nArg>=2 ){
      n = showHelp(p->out, azArg[1]);
      if( n==0 ){
        oputf("Nothing matches '%s'\n", azArg[1]);
      }
    }else{
      showHelp(p->out, 0);
    }
  }else

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){
    char *zTable = 0;           /* Insert data into this table */
    char *zSchema = 0;          /* Schema of zTable */
    char *zFile = 0;            /* Name of file to extra content from */
    sqlite3_stmt *pStmt = NULL; /* A statement */
    int nCol;                   /* Number of columns in the table */
    i64 nByte;                  /* Number of bytes in an SQL string */
    int i, j;                   /* Loop counters */
    int needCommit;             /* True to COMMIT or ROLLBACK at end */
    int nSep;                   /* Number of bytes in p->colSeparator[] */
    char *zSql = 0;             /* An SQL statement */

    ImportCtx sCtx;             /* Reader context */
    char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
    int eVerbose = 0;           /* Larger for more console output */
    int nSkip = 0;              /* Initial lines to skip */
    int useOutputMode = 1;      /* Use output mode to determine separators */
    char *zCreate = 0;          /* CREATE TABLE statement text */

24817
24818
24819
24820
24821
24822
24823
24824
24825
24826
24827
24828
24829
24830
24831
24832
24833
24834
24835
24836
24837
24838
24839
24840
24841
24842
24843
24844
24845
24846
24847
24848
24849
24850
24851
24852
24853
24854
24855
24856
24857
24858
24859
24860
24861
24862
24863
24864
24865
24866
24867
24868
24869
24870
24871
24872
24873
24874
24875
24876
24877
24878
24879
24880
24881
24882
24883
24884
24885
24886
24887
24888
24889
24890
24891
24892
24893
24894
24895
24896
24897
24898
24899
24900
24901
24902
24903
24904
24905
24906
24907
24908
24909
24910
24911
24912
24913
24914
24915
24916
24917
24918
24919
24920
24921
24922
24923
24924
24925
24926
24927
24928
24929
24930
24931
24932
24933
24934
24935
24936
24937
24938
24939
24940
24941
24942
24943
24944
24945
24946
24947
24948
24949

24950
24951
24952
24953

24954
24955
24956
24957
24958
24959
24960
24961
24962
24963
24964
24965
24966
24967
24968
24969
24970
24971
24972
24973
24974
24975
24976




24977
24978
24979
24980


24981
24982
24983


24984









24985
24986
24987
24988
24989
24990
24991
24992


24993
24994
24995



24996
24997
24998
24999
25000
25001
25002
25003

25004




25005
25006
25007
25008
25009
25010
25011
25012
25013
25014
25015


25016
25017
25018
25019


25020
25021
25022
25023
25024
25025
25026
25027
25028
25029
      if( z[0]=='-' && z[1]=='-' ) z++;
      if( z[0]!='-' ){
        if( zFile==0 ){
          zFile = z;
        }else if( zTable==0 ){
          zTable = z;
        }else{
          utf8_printf(p->out, "ERROR: extra argument: \"%s\".  Usage:\n", z);
          showHelp(p->out, "import");
          goto meta_command_exit;
        }
      }else if( cli_strcmp(z,"-v")==0 ){
        eVerbose++;
      }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){
        zSchema = azArg[++i];
      }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
        nSkip = integerValue(azArg[++i]);
      }else if( cli_strcmp(z,"-ascii")==0 ){
        sCtx.cColSep = SEP_Unit[0];
        sCtx.cRowSep = SEP_Record[0];
        xRead = ascii_read_one_field;
        useOutputMode = 0;
      }else if( cli_strcmp(z,"-csv")==0 ){
        sCtx.cColSep = ',';
        sCtx.cRowSep = '\n';
        xRead = csv_read_one_field;
        useOutputMode = 0;
      }else{
        utf8_printf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n", z);
        showHelp(p->out, "import");
        goto meta_command_exit;
      }
    }
    if( zTable==0 ){
      utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
                  zFile==0 ? "FILE" : "TABLE");
      showHelp(p->out, "import");
      goto meta_command_exit;
    }
    seenInterrupt = 0;
    open_db(p, 0);
    if( useOutputMode ){
      /* If neither the --csv or --ascii options are specified, then set
      ** the column and row separator characters from the output mode. */
      nSep = strlen30(p->colSeparator);
      if( nSep==0 ){
        raw_printf(stderr,
                   "Error: non-null column separator required for import\n");
        goto meta_command_exit;
      }
      if( nSep>1 ){
        raw_printf(stderr,
              "Error: multi-character column separators not allowed"
              " for import\n");
        goto meta_command_exit;
      }
      nSep = strlen30(p->rowSeparator);
      if( nSep==0 ){
        raw_printf(stderr,
            "Error: non-null row separator required for import\n");
        goto meta_command_exit;
      }
      if( nSep==2 && p->mode==MODE_Csv
       && cli_strcmp(p->rowSeparator,SEP_CrLf)==0
      ){
        /* When importing CSV (only), if the row separator is set to the
        ** default output row separator, change it to the default input
        ** row separator.  This avoids having to maintain different input
        ** and output row separators. */
        sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
        nSep = strlen30(p->rowSeparator);
      }
      if( nSep>1 ){
        raw_printf(stderr, "Error: multi-character row separators not allowed"
                           " for import\n");
        goto meta_command_exit;
      }
      sCtx.cColSep = (u8)p->colSeparator[0];
      sCtx.cRowSep = (u8)p->rowSeparator[0];
    }
    sCtx.zFile = zFile;
    sCtx.nLine = 1;
    if( sCtx.zFile[0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
      goto meta_command_exit;
#else
      sCtx.in = popen(sCtx.zFile+1, "r");
      sCtx.zFile = "<pipe>";
      sCtx.xCloser = pclose;
#endif
    }else{
      sCtx.in = fopen(sCtx.zFile, "rb");
      sCtx.xCloser = fclose;
    }
    if( sCtx.in==0 ){
      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
      goto meta_command_exit;
    }
    if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
      char zSep[2];
      zSep[1] = 0;
      zSep[0] = sCtx.cColSep;
      utf8_printf(p->out, "Column separator ");
      output_c_string(p->out, zSep);
      utf8_printf(p->out, ", row separator ");
      zSep[0] = sCtx.cRowSep;
      output_c_string(p->out, zSep);
      utf8_printf(p->out, "\n");
    }
    sCtx.z = sqlite3_malloc64(120);
    if( sCtx.z==0 ){
      import_cleanup(&sCtx);
      shell_out_of_memory();
    }
    /* Below, resources must be freed before exit. */
    while( (nSkip--)>0 ){
      while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
    }
    if( zSchema!=0 ){
      zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable);
    }else{
      zFullTabName = sqlite3_mprintf("\"%w\"", zTable);
    }
    zSql = sqlite3_mprintf("SELECT * FROM %s", zFullTabName);
    if( zSql==0 || zFullTabName==0 ){
      import_cleanup(&sCtx);
      shell_out_of_memory();
    }
    nByte = strlen30(zSql);
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    import_append_char(&sCtx, 0);    /* To ensure sCtx.z is allocated */
    if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){

      sqlite3 *dbCols = 0;
      char *zRenames = 0;
      char *zColDefs;
      zCreate = sqlite3_mprintf("CREATE TABLE %s", zFullTabName);

      while( xRead(&sCtx) ){
        zAutoColumn(sCtx.z, &dbCols, 0);
        if( sCtx.cTerm!=sCtx.cColSep ) break;
      }
      zColDefs = zAutoColumn(0, &dbCols, &zRenames);
      if( zRenames!=0 ){
        utf8_printf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
                    "Columns renamed during .import %s due to duplicates:\n"
                    "%s\n", sCtx.zFile, zRenames);
        sqlite3_free(zRenames);
      }
      assert(dbCols==0);
      if( zColDefs==0 ){
        utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
      import_fail:
        sqlite3_free(zCreate);
        sqlite3_free(zSql);
        sqlite3_free(zFullTabName);
        import_cleanup(&sCtx);
        rc = 1;
        goto meta_command_exit;
      }
      zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);




      if( eVerbose>=1 ){
        utf8_printf(p->out, "%s\n", zCreate);
      }
      rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);


      if( rc ){
        utf8_printf(stderr, "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
        goto import_fail;


      }









      sqlite3_free(zCreate);
      zCreate = 0;
      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    }
    if( rc ){
      if (pStmt) sqlite3_finalize(pStmt);
      utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
      goto import_fail;


    }
    sqlite3_free(zSql);
    nCol = sqlite3_column_count(pStmt);



    sqlite3_finalize(pStmt);
    pStmt = 0;
    if( nCol==0 ) return 0; /* no columns, no error */
    zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
    if( zSql==0 ){
      import_cleanup(&sCtx);
      shell_out_of_memory();
    }

    sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName);




    j = strlen30(zSql);
    for(i=1; i<nCol; i++){
      zSql[j++] = ',';
      zSql[j++] = '?';
    }
    zSql[j++] = ')';
    zSql[j] = 0;
    if( eVerbose>=2 ){
      utf8_printf(p->out, "Insert using: %s\n", zSql);
    }
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);


    if( rc ){
      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
      if (pStmt) sqlite3_finalize(pStmt);
      goto import_fail;


    }
    sqlite3_free(zSql);
    sqlite3_free(zFullTabName);
    needCommit = sqlite3_get_autocommit(p->db);
    if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
    do{
      int startLine = sCtx.nLine;
      for(i=0; i<nCol; i++){
        char *z = xRead(&sCtx);
        /*







|




















|





|
|










<
|



<
|





<
|













|
|









|











|






|
|
|

|
|










<
<
<
<
<
<
<
<
<
<
<
<

|
>



|
>






|
|
|




|
<
<
<
<





>
>
>
>

|


>
>

|
|
>
>

>
>
>
>
>
>
>
>
>
|
|
<
<


|
|
>
>

|
|
>
>
>








>
|
>
>
>
>








|


>
>

|

|
>
>

<
<







26792
26793
26794
26795
26796
26797
26798
26799
26800
26801
26802
26803
26804
26805
26806
26807
26808
26809
26810
26811
26812
26813
26814
26815
26816
26817
26818
26819
26820
26821
26822
26823
26824
26825
26826
26827
26828
26829
26830
26831
26832
26833
26834
26835
26836
26837

26838
26839
26840
26841

26842
26843
26844
26845
26846
26847

26848
26849
26850
26851
26852
26853
26854
26855
26856
26857
26858
26859
26860
26861
26862
26863
26864
26865
26866
26867
26868
26869
26870
26871
26872
26873
26874
26875
26876
26877
26878
26879
26880
26881
26882
26883
26884
26885
26886
26887
26888
26889
26890
26891
26892
26893
26894
26895
26896
26897
26898
26899
26900
26901
26902
26903
26904
26905
26906
26907












26908
26909
26910
26911
26912
26913
26914
26915
26916
26917
26918
26919
26920
26921
26922
26923
26924
26925
26926
26927
26928
26929




26930
26931
26932
26933
26934
26935
26936
26937
26938
26939
26940
26941
26942
26943
26944
26945
26946
26947
26948
26949
26950
26951
26952
26953
26954
26955
26956
26957
26958
26959
26960
26961


26962
26963
26964
26965
26966
26967
26968
26969
26970
26971
26972
26973
26974
26975
26976
26977
26978
26979
26980
26981
26982
26983
26984
26985
26986
26987
26988
26989
26990
26991
26992
26993
26994
26995
26996
26997
26998
26999
27000
27001
27002
27003
27004
27005
27006
27007


27008
27009
27010
27011
27012
27013
27014
      if( z[0]=='-' && z[1]=='-' ) z++;
      if( z[0]!='-' ){
        if( zFile==0 ){
          zFile = z;
        }else if( zTable==0 ){
          zTable = z;
        }else{
          oputf("ERROR: extra argument: \"%s\".  Usage:\n", z);
          showHelp(p->out, "import");
          goto meta_command_exit;
        }
      }else if( cli_strcmp(z,"-v")==0 ){
        eVerbose++;
      }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){
        zSchema = azArg[++i];
      }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
        nSkip = integerValue(azArg[++i]);
      }else if( cli_strcmp(z,"-ascii")==0 ){
        sCtx.cColSep = SEP_Unit[0];
        sCtx.cRowSep = SEP_Record[0];
        xRead = ascii_read_one_field;
        useOutputMode = 0;
      }else if( cli_strcmp(z,"-csv")==0 ){
        sCtx.cColSep = ',';
        sCtx.cRowSep = '\n';
        xRead = csv_read_one_field;
        useOutputMode = 0;
      }else{
        oputf("ERROR: unknown option: \"%s\".  Usage:\n", z);
        showHelp(p->out, "import");
        goto meta_command_exit;
      }
    }
    if( zTable==0 ){
      oputf("ERROR: missing %s argument. Usage:\n",
            zFile==0 ? "FILE" : "TABLE");
      showHelp(p->out, "import");
      goto meta_command_exit;
    }
    seenInterrupt = 0;
    open_db(p, 0);
    if( useOutputMode ){
      /* If neither the --csv or --ascii options are specified, then set
      ** the column and row separator characters from the output mode. */
      nSep = strlen30(p->colSeparator);
      if( nSep==0 ){

        eputz("Error: non-null column separator required for import\n");
        goto meta_command_exit;
      }
      if( nSep>1 ){

        eputz("Error: multi-character column separators not allowed"
              " for import\n");
        goto meta_command_exit;
      }
      nSep = strlen30(p->rowSeparator);
      if( nSep==0 ){

        eputz("Error: non-null row separator required for import\n");
        goto meta_command_exit;
      }
      if( nSep==2 && p->mode==MODE_Csv
       && cli_strcmp(p->rowSeparator,SEP_CrLf)==0
      ){
        /* When importing CSV (only), if the row separator is set to the
        ** default output row separator, change it to the default input
        ** row separator.  This avoids having to maintain different input
        ** and output row separators. */
        sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
        nSep = strlen30(p->rowSeparator);
      }
      if( nSep>1 ){
        eputz("Error: multi-character row separators not allowed"
              " for import\n");
        goto meta_command_exit;
      }
      sCtx.cColSep = (u8)p->colSeparator[0];
      sCtx.cRowSep = (u8)p->rowSeparator[0];
    }
    sCtx.zFile = zFile;
    sCtx.nLine = 1;
    if( sCtx.zFile[0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
      eputz("Error: pipes are not supported in this OS\n");
      goto meta_command_exit;
#else
      sCtx.in = popen(sCtx.zFile+1, "r");
      sCtx.zFile = "<pipe>";
      sCtx.xCloser = pclose;
#endif
    }else{
      sCtx.in = fopen(sCtx.zFile, "rb");
      sCtx.xCloser = fclose;
    }
    if( sCtx.in==0 ){
      eputf("Error: cannot open \"%s\"\n", zFile);
      goto meta_command_exit;
    }
    if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
      char zSep[2];
      zSep[1] = 0;
      zSep[0] = sCtx.cColSep;
      oputz("Column separator ");
      output_c_string(zSep);
      oputz(", row separator ");
      zSep[0] = sCtx.cRowSep;
      output_c_string(zSep);
      oputz("\n");
    }
    sCtx.z = sqlite3_malloc64(120);
    if( sCtx.z==0 ){
      import_cleanup(&sCtx);
      shell_out_of_memory();
    }
    /* Below, resources must be freed before exit. */
    while( (nSkip--)>0 ){
      while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
    }












    import_append_char(&sCtx, 0);    /* To ensure sCtx.z is allocated */
    if( sqlite3_table_column_metadata(p->db, zSchema, zTable,0,0,0,0,0,0) ){
      /* Table does not exist.  Create it. */
      sqlite3 *dbCols = 0;
      char *zRenames = 0;
      char *zColDefs;
      zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"", 
                    zSchema ? zSchema : "main", zTable);
      while( xRead(&sCtx) ){
        zAutoColumn(sCtx.z, &dbCols, 0);
        if( sCtx.cTerm!=sCtx.cColSep ) break;
      }
      zColDefs = zAutoColumn(0, &dbCols, &zRenames);
      if( zRenames!=0 ){
        sputf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
              "Columns renamed during .import %s due to duplicates:\n"
              "%s\n", sCtx.zFile, zRenames);
        sqlite3_free(zRenames);
      }
      assert(dbCols==0);
      if( zColDefs==0 ){
        eputf("%s: empty file\n", sCtx.zFile);




        import_cleanup(&sCtx);
        rc = 1;
        goto meta_command_exit;
      }
      zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
      if( zCreate==0 ){
        import_cleanup(&sCtx);
        shell_out_of_memory();
      }
      if( eVerbose>=1 ){
        oputf("%s\n", zCreate);
      }
      rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
      sqlite3_free(zCreate);
      zCreate = 0;
      if( rc ){
        eputf("%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
        import_cleanup(&sCtx);
        rc = 1;
        goto meta_command_exit;
      }
    }
    zSql = sqlite3_mprintf("SELECT count(*) FROM pragma_table_info(%Q,%Q);",
                           zTable, zSchema);
    if( zSql==0 ){
      import_cleanup(&sCtx);
      shell_out_of_memory();
    }
    nByte = strlen(zSql);    
    rc =  sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
    zSql = 0;


    if( rc ){
      if (pStmt) sqlite3_finalize(pStmt);
      eputf("Error: %s\n", sqlite3_errmsg(p->db));
      import_cleanup(&sCtx);
      rc = 1;
      goto meta_command_exit;
    }
    if( sqlite3_step(pStmt)==SQLITE_ROW ){
      nCol = sqlite3_column_int(pStmt, 0);
    }else{
      nCol = 0;
    }
    sqlite3_finalize(pStmt);
    pStmt = 0;
    if( nCol==0 ) return 0; /* no columns, no error */
    zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
    if( zSql==0 ){
      import_cleanup(&sCtx);
      shell_out_of_memory();
    }
    if( zSchema ){
      sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?", 
                       zSchema, zTable);
    }else{
      sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
    }
    j = strlen30(zSql);
    for(i=1; i<nCol; i++){
      zSql[j++] = ',';
      zSql[j++] = '?';
    }
    zSql[j++] = ')';
    zSql[j] = 0;
    if( eVerbose>=2 ){
      oputf("Insert using: %s\n", zSql);
    }
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
    zSql = 0;
    if( rc ){
      eputf("Error: %s\n", sqlite3_errmsg(p->db));
      if (pStmt) sqlite3_finalize(pStmt);
      import_cleanup(&sCtx);
      rc = 1;
      goto meta_command_exit;
    }


    needCommit = sqlite3_get_autocommit(p->db);
    if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
    do{
      int startLine = sCtx.nLine;
      for(i=0; i<nCol; i++){
        char *z = xRead(&sCtx);
        /*
25043
25044
25045
25046
25047
25048
25049
25050
25051
25052
25053
25054
25055
25056
25057
25058
25059
25060
25061
25062
25063
25064
25065
25066
25067
25068
25069
25070
25071
25072
25073
25074
25075
25076
25077
25078
25079
25080
25081
25082
25083
25084
25085
25086
25087
25088
25089
25090
25091
25092
25093
25094
25095
25096
25097
25098
25099
25100
25101
25102
25103
25104
25105
25106
25107
25108
25109
25110
25111
25112
25113
25114
        ** (If there are too few fields, it's not valid CSV anyway.)
        */
        if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){
          z = "";
        }
        sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
        if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
          utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
                          "filling the rest with NULL\n",
                          sCtx.zFile, startLine, nCol, i+1);
          i += 2;
          while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
        }
      }
      if( sCtx.cTerm==sCtx.cColSep ){
        do{
          xRead(&sCtx);
          i++;
        }while( sCtx.cTerm==sCtx.cColSep );
        utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
                        "extras ignored\n",
                        sCtx.zFile, startLine, nCol, i);
      }
      if( i>=nCol ){
        sqlite3_step(pStmt);
        rc = sqlite3_reset(pStmt);
        if( rc!=SQLITE_OK ){
          utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
                      startLine, sqlite3_errmsg(p->db));
          sCtx.nErr++;
        }else{
          sCtx.nRow++;
        }
      }
    }while( sCtx.cTerm!=EOF );

    import_cleanup(&sCtx);
    sqlite3_finalize(pStmt);
    if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
    if( eVerbose>0 ){
      utf8_printf(p->out,
          "Added %d rows with %d errors using %d lines of input\n",
          sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
    }
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

#ifndef SQLITE_UNTESTABLE
  if( c=='i' && cli_strncmp(azArg[0], "imposter", n)==0 ){
    char *zSql;
    char *zCollist = 0;
    sqlite3_stmt *pStmt;
    int tnum = 0;
    int isWO = 0;  /* True if making an imposter of a WITHOUT ROWID table */
    int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
    int i;
    if( !ShellHasFlag(p,SHFLG_TestingMode) ){
      utf8_printf(stderr, ".%s unavailable without --unsafe-testing\n",
                  "imposter");
      rc = 1;
      goto meta_command_exit;
    }
    if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
      utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
                          "       .imposter off\n");
      /* Also allowed, but not documented:
      **
      **    .imposter TABLE IMPOSTER
      **
      ** where TABLE is a WITHOUT ROWID table.  In that case, the
      ** imposter is another WITHOUT ROWID table with the columns in
      ** storage order. */







|
|
|









|
<
|





|
|











<
|
|














|
|




|
|







27028
27029
27030
27031
27032
27033
27034
27035
27036
27037
27038
27039
27040
27041
27042
27043
27044
27045
27046
27047

27048
27049
27050
27051
27052
27053
27054
27055
27056
27057
27058
27059
27060
27061
27062
27063
27064
27065
27066

27067
27068
27069
27070
27071
27072
27073
27074
27075
27076
27077
27078
27079
27080
27081
27082
27083
27084
27085
27086
27087
27088
27089
27090
27091
27092
27093
27094
27095
27096
27097
        ** (If there are too few fields, it's not valid CSV anyway.)
        */
        if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){
          z = "";
        }
        sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
        if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
          eputf("%s:%d: expected %d columns but found %d"
                " - filling the rest with NULL\n",
                sCtx.zFile, startLine, nCol, i+1);
          i += 2;
          while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
        }
      }
      if( sCtx.cTerm==sCtx.cColSep ){
        do{
          xRead(&sCtx);
          i++;
        }while( sCtx.cTerm==sCtx.cColSep );
        eputf("%s:%d: expected %d columns but found %d - extras ignored\n",

              sCtx.zFile, startLine, nCol, i);
      }
      if( i>=nCol ){
        sqlite3_step(pStmt);
        rc = sqlite3_reset(pStmt);
        if( rc!=SQLITE_OK ){
          eputf("%s:%d: INSERT failed: %s\n",
                sCtx.zFile, startLine, sqlite3_errmsg(p->db));
          sCtx.nErr++;
        }else{
          sCtx.nRow++;
        }
      }
    }while( sCtx.cTerm!=EOF );

    import_cleanup(&sCtx);
    sqlite3_finalize(pStmt);
    if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
    if( eVerbose>0 ){

      oputf("Added %d rows with %d errors using %d lines of input\n",
            sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
    }
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

#ifndef SQLITE_UNTESTABLE
  if( c=='i' && cli_strncmp(azArg[0], "imposter", n)==0 ){
    char *zSql;
    char *zCollist = 0;
    sqlite3_stmt *pStmt;
    int tnum = 0;
    int isWO = 0;  /* True if making an imposter of a WITHOUT ROWID table */
    int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
    int i;
    if( !ShellHasFlag(p,SHFLG_TestingMode) ){
      eputf(".%s unavailable without --unsafe-testing\n",
            "imposter");
      rc = 1;
      goto meta_command_exit;
    }
    if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
      eputz("Usage: .imposter INDEX IMPOSTER\n"
            "       .imposter off\n");
      /* Also allowed, but not documented:
      **
      **    .imposter TABLE IMPOSTER
      **
      ** where TABLE is a WITHOUT ROWID table.  In that case, the
      ** imposter is another WITHOUT ROWID table with the columns in
      ** storage order. */
25159
25160
25161
25162
25163
25164
25165
25166
25167
25168
25169
25170
25171
25172
25173
25174
25175
25176
25177
25178
25179
25180
25181
25182
25183
25184
25185
25186
25187
25188
25189
25190
25191
25192
25193
25194
25195















25196
25197
25198
25199
25200
25201
25202
25203
25204
25205
25206
25207
25208
25209
25210
25211
25212
25213
25214
25215
25216
25217
        zCollist = sqlite3_mprintf("\"%w\"", zCol);
      }else{
        zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
      }
    }
    sqlite3_finalize(pStmt);
    if( i==0 || tnum==0 ){
      utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
      rc = 1;
      sqlite3_free(zCollist);
      goto meta_command_exit;
    }
    if( lenPK==0 ) lenPK = 100000;
    zSql = sqlite3_mprintf(
          "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
          azArg[2], zCollist, lenPK, zCollist);
    sqlite3_free(zCollist);
    rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
    if( rc==SQLITE_OK ){
      rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
      if( rc ){
        utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
      }else{
        utf8_printf(stdout, "%s;\n", zSql);
        raw_printf(stdout,
          "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
          azArg[1], isWO ? "table" : "index"
        );
      }
    }else{
      raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
      rc = 1;
    }
    sqlite3_free(zSql);
  }else
#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
















#ifdef SQLITE_ENABLE_IOTRACE
  if( c=='i' && cli_strncmp(azArg[0], "iotrace", n)==0 ){
    SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
    if( iotrace && iotrace!=stdout ) fclose(iotrace);
    iotrace = 0;
    if( nArg<2 ){
      sqlite3IoTrace = 0;
    }else if( cli_strcmp(azArg[1], "-")==0 ){
      sqlite3IoTrace = iotracePrintf;
      iotrace = stdout;
    }else{
      iotrace = fopen(azArg[1], "w");
      if( iotrace==0 ){
        utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
        sqlite3IoTrace = 0;
        rc = 1;
      }else{
        sqlite3IoTrace = iotracePrintf;
      }
    }
  }else







|














|

|
<
|
|
<


|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














|







27142
27143
27144
27145
27146
27147
27148
27149
27150
27151
27152
27153
27154
27155
27156
27157
27158
27159
27160
27161
27162
27163
27164
27165
27166

27167
27168

27169
27170
27171
27172
27173
27174
27175
27176
27177
27178
27179
27180
27181
27182
27183
27184
27185
27186
27187
27188
27189
27190
27191
27192
27193
27194
27195
27196
27197
27198
27199
27200
27201
27202
27203
27204
27205
27206
27207
27208
27209
27210
27211
27212
27213
        zCollist = sqlite3_mprintf("\"%w\"", zCol);
      }else{
        zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
      }
    }
    sqlite3_finalize(pStmt);
    if( i==0 || tnum==0 ){
      eputf("no such index: \"%s\"\n", azArg[1]);
      rc = 1;
      sqlite3_free(zCollist);
      goto meta_command_exit;
    }
    if( lenPK==0 ) lenPK = 100000;
    zSql = sqlite3_mprintf(
          "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
          azArg[2], zCollist, lenPK, zCollist);
    sqlite3_free(zCollist);
    rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
    if( rc==SQLITE_OK ){
      rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
      if( rc ){
        eputf("Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
      }else{
        sputf(stdout, "%s;\n", zSql);

        sputf(stdout, "WARNING: writing to an imposter table will corrupt"
              " the \"%s\" %s!\n", azArg[1], isWO ? "table" : "index");

      }
    }else{
      eputf("SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
      rc = 1;
    }
    sqlite3_free(zSql);
  }else
#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */

  if( c=='i' && cli_strncmp(azArg[0], "intck", n)==0 ){
    i64 iArg = 0;
    if( nArg==2 ){
      iArg = integerValue(azArg[1]);
      if( iArg==0 ) iArg = -1;
    }
    if( (nArg!=1 && nArg!=2) || iArg<0 ){
      eputf("%s","Usage: .intck STEPS_PER_UNLOCK\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    rc = intckDatabaseCmd(p, iArg);
  }else

#ifdef SQLITE_ENABLE_IOTRACE
  if( c=='i' && cli_strncmp(azArg[0], "iotrace", n)==0 ){
    SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
    if( iotrace && iotrace!=stdout ) fclose(iotrace);
    iotrace = 0;
    if( nArg<2 ){
      sqlite3IoTrace = 0;
    }else if( cli_strcmp(azArg[1], "-")==0 ){
      sqlite3IoTrace = iotracePrintf;
      iotrace = stdout;
    }else{
      iotrace = fopen(azArg[1], "w");
      if( iotrace==0 ){
        eputf("Error: cannot open \"%s\"\n", azArg[1]);
        sqlite3IoTrace = 0;
        rc = 1;
      }else{
        sqlite3IoTrace = iotracePrintf;
      }
    }
  }else
25235
25236
25237
25238
25239
25240
25241
25242
25243
25244
25245
25246
25247
25248
25249
25250
25251
25252
25253
25254
25255
25256
25257
25258
25259
25260
25261
25262
25263
25264
25265
25266
25267
25268
25269
25270
25271
25272
25273
25274
25275
25276
25277
25278
25279
25280
25281
25282
25283
25284
25285
25286
25287
25288
25289
25290
25291
25292
25293
25294
25295
25296
25297
25298
25299
25300
25301
25302
25303
25304
25305
25306
25307
25308
25309
25310
25311
25312
25313
25314
25315
25316
25317
25318
25319
25320
25321
25322
25323
25324
25325
      { "trigger_depth",         SQLITE_LIMIT_TRIGGER_DEPTH             },
      { "worker_threads",        SQLITE_LIMIT_WORKER_THREADS            },
    };
    int i, n2;
    open_db(p, 0);
    if( nArg==1 ){
      for(i=0; i<ArraySize(aLimit); i++){
        printf("%20s %d\n", aLimit[i].zLimitName,
               sqlite3_limit(p->db, aLimit[i].limitCode, -1));
      }
    }else if( nArg>3 ){
      raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
      rc = 1;
      goto meta_command_exit;
    }else{
      int iLimit = -1;
      n2 = strlen30(azArg[1]);
      for(i=0; i<ArraySize(aLimit); i++){
        if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
          if( iLimit<0 ){
            iLimit = i;
          }else{
            utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
            rc = 1;
            goto meta_command_exit;
          }
        }
      }
      if( iLimit<0 ){
        utf8_printf(stderr, "unknown limit: \"%s\"\n"
                        "enter \".limits\" with no arguments for a list.\n",
                         azArg[1]);
        rc = 1;
        goto meta_command_exit;
      }
      if( nArg==3 ){
        sqlite3_limit(p->db, aLimit[iLimit].limitCode,
                      (int)integerValue(azArg[2]));
      }
      printf("%20s %d\n", aLimit[iLimit].zLimitName,
             sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
    }
  }else

  if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){
    open_db(p, 0);
    lintDotCommand(p, azArg, nArg);
  }else

#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE)
  if( c=='l' && cli_strncmp(azArg[0], "load", n)==0 ){
    const char *zFile, *zProc;
    char *zErrMsg = 0;
    failIfSafeMode(p, "cannot run .load in safe mode");
    if( nArg<2 || azArg[1][0]==0 ){
      /* Must have a non-empty FILE. (Will not load self.) */
      raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
      rc = 1;
      goto meta_command_exit;
    }
    zFile = azArg[1];
    zProc = nArg>=3 ? azArg[2] : 0;
    open_db(p, 0);
    rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
    if( rc!=SQLITE_OK ){
      utf8_printf(stderr, "Error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
      rc = 1;
    }
  }else
#endif

  if( c=='l' && cli_strncmp(azArg[0], "log", n)==0 ){
    if( nArg!=2 ){
      raw_printf(stderr, "Usage: .log FILENAME\n");
      rc = 1;
    }else{
      const char *zFile = azArg[1];
      if( p->bSafeMode
       && cli_strcmp(zFile,"on")!=0
       && cli_strcmp(zFile,"off")!=0
      ){
        raw_printf(stdout, "cannot set .log to anything other "
                   "than \"on\" or \"off\"\n");
        zFile = "off";
      }
      output_file_close(p->pLog);
      if( cli_strcmp(zFile,"on")==0 ) zFile = "stdout";
      p->pLog = output_file_open(zFile, 0);
    }
  }else







|
|


|










|






|
|
|







|
|















|








|








|







|
|







27231
27232
27233
27234
27235
27236
27237
27238
27239
27240
27241
27242
27243
27244
27245
27246
27247
27248
27249
27250
27251
27252
27253
27254
27255
27256
27257
27258
27259
27260
27261
27262
27263
27264
27265
27266
27267
27268
27269
27270
27271
27272
27273
27274
27275
27276
27277
27278
27279
27280
27281
27282
27283
27284
27285
27286
27287
27288
27289
27290
27291
27292
27293
27294
27295
27296
27297
27298
27299
27300
27301
27302
27303
27304
27305
27306
27307
27308
27309
27310
27311
27312
27313
27314
27315
27316
27317
27318
27319
27320
27321
      { "trigger_depth",         SQLITE_LIMIT_TRIGGER_DEPTH             },
      { "worker_threads",        SQLITE_LIMIT_WORKER_THREADS            },
    };
    int i, n2;
    open_db(p, 0);
    if( nArg==1 ){
      for(i=0; i<ArraySize(aLimit); i++){
        sputf(stdout, "%20s %d\n", aLimit[i].zLimitName,
              sqlite3_limit(p->db, aLimit[i].limitCode, -1));
      }
    }else if( nArg>3 ){
      eputz("Usage: .limit NAME ?NEW-VALUE?\n");
      rc = 1;
      goto meta_command_exit;
    }else{
      int iLimit = -1;
      n2 = strlen30(azArg[1]);
      for(i=0; i<ArraySize(aLimit); i++){
        if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
          if( iLimit<0 ){
            iLimit = i;
          }else{
            eputf("ambiguous limit: \"%s\"\n", azArg[1]);
            rc = 1;
            goto meta_command_exit;
          }
        }
      }
      if( iLimit<0 ){
        eputf("unknown limit: \"%s\"\n"
              "enter \".limits\" with no arguments for a list.\n",
              azArg[1]);
        rc = 1;
        goto meta_command_exit;
      }
      if( nArg==3 ){
        sqlite3_limit(p->db, aLimit[iLimit].limitCode,
                      (int)integerValue(azArg[2]));
      }
      sputf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName,
            sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
    }
  }else

  if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){
    open_db(p, 0);
    lintDotCommand(p, azArg, nArg);
  }else

#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE)
  if( c=='l' && cli_strncmp(azArg[0], "load", n)==0 ){
    const char *zFile, *zProc;
    char *zErrMsg = 0;
    failIfSafeMode(p, "cannot run .load in safe mode");
    if( nArg<2 || azArg[1][0]==0 ){
      /* Must have a non-empty FILE. (Will not load self.) */
      eputz("Usage: .load FILE ?ENTRYPOINT?\n");
      rc = 1;
      goto meta_command_exit;
    }
    zFile = azArg[1];
    zProc = nArg>=3 ? azArg[2] : 0;
    open_db(p, 0);
    rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
    if( rc!=SQLITE_OK ){
      eputf("Error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
      rc = 1;
    }
  }else
#endif

  if( c=='l' && cli_strncmp(azArg[0], "log", n)==0 ){
    if( nArg!=2 ){
      eputz("Usage: .log FILENAME\n");
      rc = 1;
    }else{
      const char *zFile = azArg[1];
      if( p->bSafeMode
       && cli_strcmp(zFile,"on")!=0
       && cli_strcmp(zFile,"off")!=0
      ){
        sputz(stdout, "cannot set .log to anything other"
              " than \"on\" or \"off\"\n");
        zFile = "off";
      }
      output_file_close(p->pLog);
      if( cli_strcmp(zFile,"on")==0 ) zFile = "stdout";
      p->pLog = output_file_open(zFile, 0);
    }
  }else
25350
25351
25352
25353
25354
25355
25356
25357
25358
25359
25360
25361
25362
25363
25364
25365
25366
25367
25368
25369
25370
25371
25372
25373
25374
25375
25376
25377
25378
25379
25380
25381
25382
25383
25384
25385
25386
25387
25388
25389
25390
          ColModeOpts cmo = ColModeOpts_default_qbox;
          zMode = "box";
          cmOpts = cmo;
        }
      }else if( zTabname==0 ){
        zTabname = z;
      }else if( z[0]=='-' ){
        utf8_printf(stderr, "unknown option: %s\n", z);
        utf8_printf(stderr, "options:\n"
                            "  --noquote\n"
                            "  --quote\n"
                            "  --wordwrap on/off\n"
                            "  --wrap N\n"
                            "  --ww\n");
        rc = 1;
        goto meta_command_exit;
      }else{
        utf8_printf(stderr, "extra argument: \"%s\"\n", z);
        rc = 1;
        goto meta_command_exit;
      }
    }
    if( zMode==0 ){
      if( p->mode==MODE_Column
       || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
      ){
        raw_printf
          (p->out,
           "current output mode: %s --wrap %d --wordwrap %s --%squote\n",
           modeDescr[p->mode], p->cmOpts.iWrap,
           p->cmOpts.bWordWrap ? "on" : "off",
           p->cmOpts.bQuote ? "" : "no");
      }else{
        raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
      }
      zMode = modeDescr[p->mode];
    }
    n2 = strlen30(zMode);
    if( cli_strncmp(zMode,"lines",n2)==0 ){
      p->mode = MODE_Line;
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);







|
|
|
|
|
|
|



|








<
<
|
|
|
|

|







27346
27347
27348
27349
27350
27351
27352
27353
27354
27355
27356
27357
27358
27359
27360
27361
27362
27363
27364
27365
27366
27367
27368
27369
27370
27371


27372
27373
27374
27375
27376
27377
27378
27379
27380
27381
27382
27383
27384
          ColModeOpts cmo = ColModeOpts_default_qbox;
          zMode = "box";
          cmOpts = cmo;
        }
      }else if( zTabname==0 ){
        zTabname = z;
      }else if( z[0]=='-' ){
        eputf("unknown option: %s\n", z);
        eputz("options:\n"
              "  --noquote\n"
              "  --quote\n"
              "  --wordwrap on/off\n"
              "  --wrap N\n"
              "  --ww\n");
        rc = 1;
        goto meta_command_exit;
      }else{
        eputf("extra argument: \"%s\"\n", z);
        rc = 1;
        goto meta_command_exit;
      }
    }
    if( zMode==0 ){
      if( p->mode==MODE_Column
       || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
      ){


        oputf("current output mode: %s --wrap %d --wordwrap %s --%squote\n",
              modeDescr[p->mode], p->cmOpts.iWrap,
              p->cmOpts.bWordWrap ? "on" : "off",
              p->cmOpts.bQuote ? "" : "no");
      }else{
        oputf("current output mode: %s\n", modeDescr[p->mode]);
      }
      zMode = modeDescr[p->mode];
    }
    n2 = strlen30(zMode);
    if( cli_strncmp(zMode,"lines",n2)==0 ){
      p->mode = MODE_Line;
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
25435
25436
25437
25438
25439
25440
25441
25442
25443
25444
25445
25446
25447
25448
25449
25450
25451
25452
25453
25454
25455
25456
25457
25458
25459
25460
25461
25462
25463
25464
25465
25466
25467
25468
25469
25470
25471
25472
25473
25474
25475
25476
25477
25478
25479
    }else if( cli_strncmp(zMode,"count",n2)==0 ){
      p->mode = MODE_Count;
    }else if( cli_strncmp(zMode,"off",n2)==0 ){
      p->mode = MODE_Off;
    }else if( cli_strncmp(zMode,"json",n2)==0 ){
      p->mode = MODE_Json;
    }else{
      raw_printf(stderr, "Error: mode should be one of: "
         "ascii box column csv html insert json line list markdown "
         "qbox quote table tabs tcl\n");
      rc = 1;
    }
    p->cMode = p->mode;
  }else

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='n' && cli_strcmp(azArg[0], "nonce")==0 ){
    if( nArg!=2 ){
      raw_printf(stderr, "Usage: .nonce NONCE\n");
      rc = 1;
    }else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){
      raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
                 p->lineno, azArg[1]);
      exit(1);
    }else{
      p->bSafeMode = 0;
      return 0;  /* Return immediately to bypass the safe mode reset
                 ** at the end of this procedure */
    }
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='n' && cli_strncmp(azArg[0], "nullvalue", n)==0 ){
    if( nArg==2 ){
      sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
                       "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
    }else{
      raw_printf(stderr, "Usage: .nullvalue STRING\n");
      rc = 1;
    }
  }else

  if( c=='o' && cli_strncmp(azArg[0], "open", n)==0 && n>=2 ){
    const char *zFN = 0;     /* Pointer to constant filename */
    char *zNewFilename = 0;  /* Name of the database file to open */







|
|
|








|


|
|














|







27429
27430
27431
27432
27433
27434
27435
27436
27437
27438
27439
27440
27441
27442
27443
27444
27445
27446
27447
27448
27449
27450
27451
27452
27453
27454
27455
27456
27457
27458
27459
27460
27461
27462
27463
27464
27465
27466
27467
27468
27469
27470
27471
27472
27473
    }else if( cli_strncmp(zMode,"count",n2)==0 ){
      p->mode = MODE_Count;
    }else if( cli_strncmp(zMode,"off",n2)==0 ){
      p->mode = MODE_Off;
    }else if( cli_strncmp(zMode,"json",n2)==0 ){
      p->mode = MODE_Json;
    }else{
      eputz("Error: mode should be one of: "
            "ascii box column csv html insert json line list markdown "
            "qbox quote table tabs tcl\n");
      rc = 1;
    }
    p->cMode = p->mode;
  }else

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='n' && cli_strcmp(azArg[0], "nonce")==0 ){
    if( nArg!=2 ){
      eputz("Usage: .nonce NONCE\n");
      rc = 1;
    }else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){
      eputf("line %d: incorrect nonce: \"%s\"\n",
            p->lineno, azArg[1]);
      exit(1);
    }else{
      p->bSafeMode = 0;
      return 0;  /* Return immediately to bypass the safe mode reset
                 ** at the end of this procedure */
    }
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='n' && cli_strncmp(azArg[0], "nullvalue", n)==0 ){
    if( nArg==2 ){
      sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
                       "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
    }else{
      eputz("Usage: .nullvalue STRING\n");
      rc = 1;
    }
  }else

  if( c=='o' && cli_strncmp(azArg[0], "open", n)==0 && n>=2 ){
    const char *zFN = 0;     /* Pointer to constant filename */
    char *zNewFilename = 0;  /* Name of the database file to open */
25504
25505
25506
25507
25508
25509
25510
25511
25512
25513
25514
25515
25516
25517
25518
25519
25520
25521
25522
        openMode = SHELL_OPEN_HEXDB;
      }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
        p->szMax = integerValue(azArg[++iName]);
#endif /* SQLITE_OMIT_DESERIALIZE */
      }else
#endif /* !SQLITE_SHELL_FIDDLE */
      if( z[0]=='-' ){
        utf8_printf(stderr, "unknown option: %s\n", z);
        rc = 1;
        goto meta_command_exit;
      }else if( zFN ){
        utf8_printf(stderr, "extra argument: \"%s\"\n", z);
        rc = 1;
        goto meta_command_exit;
      }else{
        zFN = z;
      }
    }








|



|







27498
27499
27500
27501
27502
27503
27504
27505
27506
27507
27508
27509
27510
27511
27512
27513
27514
27515
27516
        openMode = SHELL_OPEN_HEXDB;
      }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
        p->szMax = integerValue(azArg[++iName]);
#endif /* SQLITE_OMIT_DESERIALIZE */
      }else
#endif /* !SQLITE_SHELL_FIDDLE */
      if( z[0]=='-' ){
        eputf("unknown option: %s\n", z);
        rc = 1;
        goto meta_command_exit;
      }else if( zFN ){
        eputf("extra argument: \"%s\"\n", z);
        rc = 1;
        goto meta_command_exit;
      }else{
        zFN = z;
      }
    }

25550
25551
25552
25553
25554
25555
25556
25557
25558
25559
25560
25561
25562
25563
25564
        shell_check_oom(zNewFilename);
      }else{
        zNewFilename = 0;
      }
      p->pAuxDb->zDbFilename = zNewFilename;
      open_db(p, OPEN_DB_KEEPALIVE);
      if( p->db==0 ){
        utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
        sqlite3_free(zNewFilename);
      }else{
        p->pAuxDb->zFreeOnClose = zNewFilename;
      }
    }
    if( p->db==0 ){
      /* As a fall-back open a TEMP database */







|







27544
27545
27546
27547
27548
27549
27550
27551
27552
27553
27554
27555
27556
27557
27558
        shell_check_oom(zNewFilename);
      }else{
        zNewFilename = 0;
      }
      p->pAuxDb->zDbFilename = zNewFilename;
      open_db(p, OPEN_DB_KEEPALIVE);
      if( p->db==0 ){
        eputf("Error: cannot open '%s'\n", zNewFilename);
        sqlite3_free(zNewFilename);
      }else{
        p->pAuxDb->zFreeOnClose = zNewFilename;
      }
    }
    if( p->db==0 ){
      /* As a fall-back open a TEMP database */
25574
25575
25576
25577
25578
25579
25580

25581
25582
25583
25584
25585
25586
25587
25588
25589
25590
25591
25592
25593
25594
25595
25596
25597
25598
25599
25600
25601
25602
25603
25604
25605
25606
25607
25608
25609
25610
25611
25612
25613
25614
25615
25616
25617
25618
25619
25620
25621
25622
25623
25624
25625
25626
   || (c=='e' && n==5 && cli_strcmp(azArg[0],"excel")==0)
  ){
    char *zFile = 0;
    int bTxtMode = 0;
    int i;
    int eMode = 0;
    int bOnce = 0;            /* 0: .output, 1: .once, 2: .excel */

    unsigned char zBOM[4];    /* Byte-order mark to using if --bom is present */

    zBOM[0] = 0;
    failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
    if( c=='e' ){
      eMode = 'x';
      bOnce = 2;
    }else if( cli_strncmp(azArg[0],"once",n)==0 ){
      bOnce = 1;
    }
    for(i=1; i<nArg; i++){
      char *z = azArg[i];
      if( z[0]=='-' ){
        if( z[1]=='-' ) z++;
        if( cli_strcmp(z,"-bom")==0 ){
          zBOM[0] = 0xef;
          zBOM[1] = 0xbb;
          zBOM[2] = 0xbf;
          zBOM[3] = 0;
        }else if( c!='e' && cli_strcmp(z,"-x")==0 ){
          eMode = 'x';  /* spreadsheet */
        }else if( c!='e' && cli_strcmp(z,"-e")==0 ){
          eMode = 'e';  /* text editor */
        }else{
          utf8_printf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n",
                      azArg[i]);
          showHelp(p->out, azArg[0]);
          rc = 1;
          goto meta_command_exit;
        }
      }else if( zFile==0 && eMode!='e' && eMode!='x' ){
        zFile = sqlite3_mprintf("%s", z);
        if( zFile && zFile[0]=='|' ){
          while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
          break;
        }
      }else{
        utf8_printf(p->out,"ERROR: extra parameter: \"%s\".  Usage:\n",
                    azArg[i]);
        showHelp(p->out, azArg[0]);
        rc = 1;
        sqlite3_free(zFile);
        goto meta_command_exit;
      }
    }
    if( zFile==0 ){







>
|

<












<
<
<
|





|
<











|
<







27568
27569
27570
27571
27572
27573
27574
27575
27576
27577

27578
27579
27580
27581
27582
27583
27584
27585
27586
27587
27588
27589



27590
27591
27592
27593
27594
27595
27596

27597
27598
27599
27600
27601
27602
27603
27604
27605
27606
27607
27608

27609
27610
27611
27612
27613
27614
27615
   || (c=='e' && n==5 && cli_strcmp(azArg[0],"excel")==0)
  ){
    char *zFile = 0;
    int bTxtMode = 0;
    int i;
    int eMode = 0;
    int bOnce = 0;            /* 0: .output, 1: .once, 2: .excel */
    static const char *zBomUtf8 = "\xef\xbb\xbf";
    const char *zBom = 0;


    failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
    if( c=='e' ){
      eMode = 'x';
      bOnce = 2;
    }else if( cli_strncmp(azArg[0],"once",n)==0 ){
      bOnce = 1;
    }
    for(i=1; i<nArg; i++){
      char *z = azArg[i];
      if( z[0]=='-' ){
        if( z[1]=='-' ) z++;
        if( cli_strcmp(z,"-bom")==0 ){



          zBom = zBomUtf8;
        }else if( c!='e' && cli_strcmp(z,"-x")==0 ){
          eMode = 'x';  /* spreadsheet */
        }else if( c!='e' && cli_strcmp(z,"-e")==0 ){
          eMode = 'e';  /* text editor */
        }else{
          oputf("ERROR: unknown option: \"%s\".  Usage:\n", azArg[i]);

          showHelp(p->out, azArg[0]);
          rc = 1;
          goto meta_command_exit;
        }
      }else if( zFile==0 && eMode!='e' && eMode!='x' ){
        zFile = sqlite3_mprintf("%s", z);
        if( zFile && zFile[0]=='|' ){
          while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
          break;
        }
      }else{
        oputf("ERROR: extra parameter: \"%s\".  Usage:\n", azArg[i]);

        showHelp(p->out, azArg[0]);
        rc = 1;
        sqlite3_free(zFile);
        goto meta_command_exit;
      }
    }
    if( zFile==0 ){
25651
25652
25653
25654
25655
25656
25657
25658
25659
25660
25661
25662
25663
25664
25665
25666
25667

25668
25669
25670
25671
25672
25673
25674
25675
25676
25677
25678
25679
25680

25681
25682
25683
25684
25685
25686
25687
25688
      sqlite3_free(zFile);
      zFile = sqlite3_mprintf("%s", p->zTempFile);
    }
#endif /* SQLITE_NOHAVE_SYSTEM */
    shell_check_oom(zFile);
    if( zFile[0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
      rc = 1;
      p->out = stdout;
#else
      p->out = popen(zFile + 1, "w");
      if( p->out==0 ){
        utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
        p->out = stdout;
        rc = 1;
      }else{

        if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
      }
#endif
    }else{
      p->out = output_file_open(zFile, bTxtMode);
      if( p->out==0 ){
        if( cli_strcmp(zFile,"off")!=0 ){
          utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
        }
        p->out = stdout;
        rc = 1;
      } else {

        if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
      }
    }
    sqlite3_free(zFile);
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */








|

|

|
|
|
<


>
|




|
|

|

<


>
|







27640
27641
27642
27643
27644
27645
27646
27647
27648
27649
27650
27651
27652
27653

27654
27655
27656
27657
27658
27659
27660
27661
27662
27663
27664
27665
27666

27667
27668
27669
27670
27671
27672
27673
27674
27675
27676
27677
      sqlite3_free(zFile);
      zFile = sqlite3_mprintf("%s", p->zTempFile);
    }
#endif /* SQLITE_NOHAVE_SYSTEM */
    shell_check_oom(zFile);
    if( zFile[0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
      eputz("Error: pipes are not supported in this OS\n");
      rc = 1;
      output_redir(p, stdout);
#else
      FILE *pfPipe = popen(zFile + 1, "w");
      if( pfPipe==0 ){
        eputf("Error: cannot open pipe \"%s\"\n", zFile + 1);

        rc = 1;
      }else{
        output_redir(p, pfPipe);
        if( zBom ) oputz(zBom);
        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
      }
#endif
    }else{
      FILE *pfFile = output_file_open(zFile, bTxtMode);
      if( pfFile==0 ){
        if( cli_strcmp(zFile,"off")!=0 ){
          eputf("Error: cannot write to \"%s\"\n", zFile);
        }

        rc = 1;
      } else {
        output_redir(p, pfFile);
        if( zBom ) oputz(zBom);
        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
      }
    }
    sqlite3_free(zFile);
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

25715
25716
25717
25718
25719
25720
25721
25722
25723
25724
25725
25726
25727
25728
25729
25730
      sqlite3_finalize(pStmt);
      pStmt = 0;
      if( len ){
        rx = sqlite3_prepare_v2(p->db,
             "SELECT key, quote(value) "
             "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
        while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
          utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
                      sqlite3_column_text(pStmt,1));
        }
        sqlite3_finalize(pStmt);
      }
    }else

    /* .parameter init
    ** Make sure the TEMP table used to hold bind parameters exists.







|
|







27704
27705
27706
27707
27708
27709
27710
27711
27712
27713
27714
27715
27716
27717
27718
27719
      sqlite3_finalize(pStmt);
      pStmt = 0;
      if( len ){
        rx = sqlite3_prepare_v2(p->db,
             "SELECT key, quote(value) "
             "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
        while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
          oputf("%-*s %s\n", len, sqlite3_column_text(pStmt,0),
                sqlite3_column_text(pStmt,1));
        }
        sqlite3_finalize(pStmt);
      }
    }else

    /* .parameter init
    ** Make sure the TEMP table used to hold bind parameters exists.
25760
25761
25762
25763
25764
25765
25766
25767
25768
25769
25770
25771
25772
25773
25774
        zSql = sqlite3_mprintf(
                   "REPLACE INTO temp.sqlite_parameters(key,value)"
                   "VALUES(%Q,%Q);", zKey, zValue);
        shell_check_oom(zSql);
        rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
        sqlite3_free(zSql);
        if( rx!=SQLITE_OK ){
          utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
          sqlite3_finalize(pStmt);
          pStmt = 0;
          rc = 1;
        }
      }
      sqlite3_step(pStmt);
      sqlite3_finalize(pStmt);







|







27749
27750
27751
27752
27753
27754
27755
27756
27757
27758
27759
27760
27761
27762
27763
        zSql = sqlite3_mprintf(
                   "REPLACE INTO temp.sqlite_parameters(key,value)"
                   "VALUES(%Q,%Q);", zKey, zValue);
        shell_check_oom(zSql);
        rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
        sqlite3_free(zSql);
        if( rx!=SQLITE_OK ){
          oputf("Error: %s\n", sqlite3_errmsg(p->db));
          sqlite3_finalize(pStmt);
          pStmt = 0;
          rc = 1;
        }
      }
      sqlite3_step(pStmt);
      sqlite3_finalize(pStmt);
25789
25790
25791
25792
25793
25794
25795
25796
25797
25798
25799
25800
25801
25802
25803
25804
25805
25806
    parameter_syntax_error:
    showHelp(p->out, "parameter");
  }else

  if( c=='p' && n>=3 && cli_strncmp(azArg[0], "print", n)==0 ){
    int i;
    for(i=1; i<nArg; i++){
      if( i>1 ) raw_printf(p->out, " ");
      utf8_printf(p->out, "%s", azArg[i]);
    }
    raw_printf(p->out, "\n");
  }else

#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  if( c=='p' && n>=3 && cli_strncmp(azArg[0], "progress", n)==0 ){
    int i;
    int nn = 0;
    p->flgProgress = 0;







|
|

|







27778
27779
27780
27781
27782
27783
27784
27785
27786
27787
27788
27789
27790
27791
27792
27793
27794
27795
    parameter_syntax_error:
    showHelp(p->out, "parameter");
  }else

  if( c=='p' && n>=3 && cli_strncmp(azArg[0], "print", n)==0 ){
    int i;
    for(i=1; i<nArg; i++){
      if( i>1 ) oputz(" ");
      oputz(azArg[i]);
    }
    oputz("\n");
  }else

#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  if( c=='p' && n>=3 && cli_strncmp(azArg[0], "progress", n)==0 ){
    int i;
    int nn = 0;
    p->flgProgress = 0;
25821
25822
25823
25824
25825
25826
25827
25828
25829
25830
25831
25832
25833
25834
25835
25836
25837
25838
25839
25840
25841
25842
25843
        }
        if( cli_strcmp(z,"once")==0 ){
          p->flgProgress |= SHELL_PROGRESS_ONCE;
          continue;
        }
        if( cli_strcmp(z,"limit")==0 ){
          if( i+1>=nArg ){
            utf8_printf(stderr, "Error: missing argument on --limit\n");
            rc = 1;
            goto meta_command_exit;
          }else{
            p->mxProgress = (int)integerValue(azArg[++i]);
          }
          continue;
        }
        utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
        rc = 1;
        goto meta_command_exit;
      }else{
        nn = (int)integerValue(z);
      }
    }
    open_db(p, 0);







|







|







27810
27811
27812
27813
27814
27815
27816
27817
27818
27819
27820
27821
27822
27823
27824
27825
27826
27827
27828
27829
27830
27831
27832
        }
        if( cli_strcmp(z,"once")==0 ){
          p->flgProgress |= SHELL_PROGRESS_ONCE;
          continue;
        }
        if( cli_strcmp(z,"limit")==0 ){
          if( i+1>=nArg ){
            eputz("Error: missing argument on --limit\n");
            rc = 1;
            goto meta_command_exit;
          }else{
            p->mxProgress = (int)integerValue(azArg[++i]);
          }
          continue;
        }
        eputf("Error: unknown option: \"%s\"\n", azArg[i]);
        rc = 1;
        goto meta_command_exit;
      }else{
        nn = (int)integerValue(z);
      }
    }
    open_db(p, 0);
25862
25863
25864
25865
25866
25867
25868
25869
25870
25871
25872
25873
25874
25875
25876
25877
25878
25879
25880
25881
25882
25883
25884
25885
25886
25887
25888
25889
25890
25891
25892
25893
25894
25895
25896

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='r' && n>=3 && cli_strncmp(azArg[0], "read", n)==0 ){
    FILE *inSaved = p->in;
    int savedLineno = p->lineno;
    failIfSafeMode(p, "cannot run .read in safe mode");
    if( nArg!=2 ){
      raw_printf(stderr, "Usage: .read FILE\n");
      rc = 1;
      goto meta_command_exit;
    }
    if( azArg[1][0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
      rc = 1;
      p->out = stdout;
#else
      p->in = popen(azArg[1]+1, "r");
      if( p->in==0 ){
        utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
        rc = 1;
      }else{
        rc = process_input(p);
        pclose(p->in);
      }
#endif
    }else if( (p->in = openChrSource(azArg[1]))==0 ){
      utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
      rc = 1;
    }else{
      rc = process_input(p);
      fclose(p->in);
    }
    p->in = inSaved;
    p->lineno = savedLineno;







|





|





|







|







27851
27852
27853
27854
27855
27856
27857
27858
27859
27860
27861
27862
27863
27864
27865
27866
27867
27868
27869
27870
27871
27872
27873
27874
27875
27876
27877
27878
27879
27880
27881
27882
27883
27884
27885

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='r' && n>=3 && cli_strncmp(azArg[0], "read", n)==0 ){
    FILE *inSaved = p->in;
    int savedLineno = p->lineno;
    failIfSafeMode(p, "cannot run .read in safe mode");
    if( nArg!=2 ){
      eputz("Usage: .read FILE\n");
      rc = 1;
      goto meta_command_exit;
    }
    if( azArg[1][0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
      eputz("Error: pipes are not supported in this OS\n");
      rc = 1;
      p->out = stdout;
#else
      p->in = popen(azArg[1]+1, "r");
      if( p->in==0 ){
        eputf("Error: cannot open \"%s\"\n", azArg[1]);
        rc = 1;
      }else{
        rc = process_input(p);
        pclose(p->in);
      }
#endif
    }else if( (p->in = openChrSource(azArg[1]))==0 ){
      eputf("Error: cannot open \"%s\"\n", azArg[1]);
      rc = 1;
    }else{
      rc = process_input(p);
      fclose(p->in);
    }
    p->in = inSaved;
    p->lineno = savedLineno;
25909
25910
25911
25912
25913
25914
25915
25916
25917
25918
25919
25920
25921
25922
25923
25924
25925
25926
25927
25928
25929
25930
25931
25932
25933
25934
25935
25936
25937
25938
25939
25940
25941
25942
25943
25944
25945
25946
25947
25948
25949
25950
25951
25952
25953
25954
25955
25956
25957
25958
25959
25960
25961
25962
25963
25964
25965
25966
25967
25968
25969




25970
25971
25972
25973
25974
25975
25976
25977
25978
25979
    if( nArg==2 ){
      zSrcFile = azArg[1];
      zDb = "main";
    }else if( nArg==3 ){
      zSrcFile = azArg[2];
      zDb = azArg[1];
    }else{
      raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
      rc = 1;
      goto meta_command_exit;
    }
    rc = sqlite3_open(zSrcFile, &pSrc);
    if( rc!=SQLITE_OK ){
      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
      close_db(pSrc);
      return 1;
    }
    open_db(p, 0);
    pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
    if( pBackup==0 ){
      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
      close_db(pSrc);
      return 1;
    }
    while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
          || rc==SQLITE_BUSY  ){
      if( rc==SQLITE_BUSY ){
        if( nTimeout++ >= 3 ) break;
        sqlite3_sleep(100);
      }
    }
    sqlite3_backup_finish(pBackup);
    if( rc==SQLITE_DONE ){
      rc = 0;
    }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
      raw_printf(stderr, "Error: source database is busy\n");
      rc = 1;
    }else{
      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
      rc = 1;
    }
    close_db(pSrc);
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='s' && cli_strncmp(azArg[0], "scanstats", n)==0 ){
    if( nArg==2 ){
      if( cli_strcmp(azArg[1], "vm")==0 ){
        p->scanstatsOn = 3;
      }else
      if( cli_strcmp(azArg[1], "est")==0 ){
        p->scanstatsOn = 2;
      }else{
        p->scanstatsOn = (u8)booleanValue(azArg[1]);
      }
      open_db(p, 0);
      sqlite3_db_config(
          p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, p->scanstatsOn, (int*)0
      );
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
      raw_printf(stderr, "Warning: .scanstats not available in this build.\n");




#endif
    }else{
      raw_printf(stderr, "Usage: .scanstats on|off|est\n");
      rc = 1;
    }
  }else

  if( c=='s' && cli_strncmp(azArg[0], "schema", n)==0 ){
    ShellText sSelect;
    ShellState data;







|





|






|














|


|




















|
|
>
>
>
>


|







27898
27899
27900
27901
27902
27903
27904
27905
27906
27907
27908
27909
27910
27911
27912
27913
27914
27915
27916
27917
27918
27919
27920
27921
27922
27923
27924
27925
27926
27927
27928
27929
27930
27931
27932
27933
27934
27935
27936
27937
27938
27939
27940
27941
27942
27943
27944
27945
27946
27947
27948
27949
27950
27951
27952
27953
27954
27955
27956
27957
27958
27959
27960
27961
27962
27963
27964
27965
27966
27967
27968
27969
27970
27971
27972
    if( nArg==2 ){
      zSrcFile = azArg[1];
      zDb = "main";
    }else if( nArg==3 ){
      zSrcFile = azArg[2];
      zDb = azArg[1];
    }else{
      eputz("Usage: .restore ?DB? FILE\n");
      rc = 1;
      goto meta_command_exit;
    }
    rc = sqlite3_open(zSrcFile, &pSrc);
    if( rc!=SQLITE_OK ){
      eputf("Error: cannot open \"%s\"\n", zSrcFile);
      close_db(pSrc);
      return 1;
    }
    open_db(p, 0);
    pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
    if( pBackup==0 ){
      eputf("Error: %s\n", sqlite3_errmsg(p->db));
      close_db(pSrc);
      return 1;
    }
    while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
          || rc==SQLITE_BUSY  ){
      if( rc==SQLITE_BUSY ){
        if( nTimeout++ >= 3 ) break;
        sqlite3_sleep(100);
      }
    }
    sqlite3_backup_finish(pBackup);
    if( rc==SQLITE_DONE ){
      rc = 0;
    }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
      eputz("Error: source database is busy\n");
      rc = 1;
    }else{
      eputf("Error: %s\n", sqlite3_errmsg(p->db));
      rc = 1;
    }
    close_db(pSrc);
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='s' && cli_strncmp(azArg[0], "scanstats", n)==0 ){
    if( nArg==2 ){
      if( cli_strcmp(azArg[1], "vm")==0 ){
        p->scanstatsOn = 3;
      }else
      if( cli_strcmp(azArg[1], "est")==0 ){
        p->scanstatsOn = 2;
      }else{
        p->scanstatsOn = (u8)booleanValue(azArg[1]);
      }
      open_db(p, 0);
      sqlite3_db_config(
          p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, p->scanstatsOn, (int*)0
      );
#if !defined(SQLITE_ENABLE_STMT_SCANSTATUS)
      eputz("Warning: .scanstats not available in this build.\n");
#elif !defined(SQLITE_ENABLE_BYTECODE_VTAB)
      if( p->scanstatsOn==3 ){
        eputz("Warning: \".scanstats vm\" not available in this build.\n");
      }
#endif
    }else{
      eputz("Usage: .scanstats on|off|est\n");
      rc = 1;
    }
  }else

  if( c=='s' && cli_strncmp(azArg[0], "schema", n)==0 ){
    ShellText sSelect;
    ShellState data;
25994
25995
25996
25997
25998
25999
26000
26001
26002
26003
26004
26005
26006
26007
26008
26009
26010
26011
26012
26013
26014
26015
      if( optionMatch(azArg[ii],"indent") ){
        data.cMode = data.mode = MODE_Pretty;
      }else if( optionMatch(azArg[ii],"debug") ){
        bDebug = 1;
      }else if( optionMatch(azArg[ii],"nosys") ){
        bNoSystemTabs = 1;
      }else if( azArg[ii][0]=='-' ){
        utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
        rc = 1;
        goto meta_command_exit;
      }else if( zName==0 ){
        zName = azArg[ii];
      }else{
        raw_printf(stderr,
                   "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
        rc = 1;
        goto meta_command_exit;
      }
    }
    if( zName!=0 ){
      int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
                  || sqlite3_strlike(zName, "sqlite_schema", '\\')==0







|





<
|







27987
27988
27989
27990
27991
27992
27993
27994
27995
27996
27997
27998
27999

28000
28001
28002
28003
28004
28005
28006
28007
      if( optionMatch(azArg[ii],"indent") ){
        data.cMode = data.mode = MODE_Pretty;
      }else if( optionMatch(azArg[ii],"debug") ){
        bDebug = 1;
      }else if( optionMatch(azArg[ii],"nosys") ){
        bNoSystemTabs = 1;
      }else if( azArg[ii][0]=='-' ){
        eputf("Unknown option: \"%s\"\n", azArg[ii]);
        rc = 1;
        goto meta_command_exit;
      }else if( zName==0 ){
        zName = azArg[ii];
      }else{

        eputz("Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
        rc = 1;
        goto meta_command_exit;
      }
    }
    if( zName!=0 ){
      int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
                  || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
26034
26035
26036
26037
26038
26039
26040
26041
26042
26043
26044
26045
26046
26047
26048
      }
    }
    if( zDiv ){
      sqlite3_stmt *pStmt = 0;
      rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
                              -1, &pStmt, 0);
      if( rc ){
        utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
        sqlite3_finalize(pStmt);
        rc = 1;
        goto meta_command_exit;
      }
      appendText(&sSelect, "SELECT sql FROM", 0);
      iSchema = 0;
      while( sqlite3_step(pStmt)==SQLITE_ROW ){







|







28026
28027
28028
28029
28030
28031
28032
28033
28034
28035
28036
28037
28038
28039
28040
      }
    }
    if( zDiv ){
      sqlite3_stmt *pStmt = 0;
      rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
                              -1, &pStmt, 0);
      if( rc ){
        eputf("Error: %s\n", sqlite3_errmsg(p->db));
        sqlite3_finalize(pStmt);
        rc = 1;
        goto meta_command_exit;
      }
      appendText(&sSelect, "SELECT sql FROM", 0);
      iSchema = 0;
      while( sqlite3_step(pStmt)==SQLITE_ROW ){
26096
26097
26098
26099
26100
26101
26102
26103
26104
26105
26106
26107
26108
26109
26110
26111
26112
26113
26114
26115
26116
26117
26118
26119
26120
26121
      }
      if( bNoSystemTabs ){
        appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
      }
      appendText(&sSelect, "sql IS NOT NULL"
                           " ORDER BY snum, rowid", 0);
      if( bDebug ){
        utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
      }else{
        rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
      }
      freeText(&sSelect);
    }
    if( zErrMsg ){
      utf8_printf(stderr,"Error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
      rc = 1;
    }else if( rc != SQLITE_OK ){
      raw_printf(stderr,"Error: querying schema information\n");
      rc = 1;
    }else{
      rc = 0;
    }
  }else

  if( (c=='s' && n==11 && cli_strncmp(azArg[0], "selecttrace", n)==0)







|






|



|







28088
28089
28090
28091
28092
28093
28094
28095
28096
28097
28098
28099
28100
28101
28102
28103
28104
28105
28106
28107
28108
28109
28110
28111
28112
28113
      }
      if( bNoSystemTabs ){
        appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
      }
      appendText(&sSelect, "sql IS NOT NULL"
                           " ORDER BY snum, rowid", 0);
      if( bDebug ){
        oputf("SQL: %s;\n", sSelect.z);
      }else{
        rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
      }
      freeText(&sSelect);
    }
    if( zErrMsg ){
      eputf("Error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
      rc = 1;
    }else if( rc != SQLITE_OK ){
      eputz("Error: querying schema information\n");
      rc = 1;
    }else{
      rc = 0;
    }
  }else

  if( (c=='s' && n==11 && cli_strncmp(azArg[0], "selecttrace", n)==0)
26153
26154
26155
26156
26157
26158
26159
26160
26161
26162
26163
26164
26165
26166
26167
26168
26169
26170
26171
26172
26173
26174
26175
26176
26177
26178
26179
26180
26181
26182
26183
26184
26185
26186
26187
26188
26189
26190
26191
26192
26193
26194
26195
26196
26197
26198
26199
26200
26201
26202
26203
26204
26205
26206
26207
    ** Invoke the sqlite3session_attach() interface to attach a particular
    ** table so that it is never filtered.
    */
    if( cli_strcmp(azCmd[0],"attach")==0 ){
      if( nCmd!=2 ) goto session_syntax_error;
      if( pSession->p==0 ){
        session_not_open:
        raw_printf(stderr, "ERROR: No sessions are open\n");
      }else{
        rc = sqlite3session_attach(pSession->p, azCmd[1]);
        if( rc ){
          raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
          rc = 0;
        }
      }
    }else

    /* .session changeset FILE
    ** .session patchset FILE
    ** Write a changeset or patchset into a file.  The file is overwritten.
    */
    if( cli_strcmp(azCmd[0],"changeset")==0
     || cli_strcmp(azCmd[0],"patchset")==0
    ){
      FILE *out = 0;
      failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
      if( nCmd!=2 ) goto session_syntax_error;
      if( pSession->p==0 ) goto session_not_open;
      out = fopen(azCmd[1], "wb");
      if( out==0 ){
        utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
                    azCmd[1]);
      }else{
        int szChng;
        void *pChng;
        if( azCmd[0][0]=='c' ){
          rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
        }else{
          rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
        }
        if( rc ){
          printf("Error: error code %d\n", rc);
          rc = 0;
        }
        if( pChng
          && fwrite(pChng, szChng, 1, out)!=1 ){
          raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
                  szChng);
        }
        sqlite3_free(pChng);
        fclose(out);
      }
    }else

    /* .session close







|



|


















|
|









|




|
<







28145
28146
28147
28148
28149
28150
28151
28152
28153
28154
28155
28156
28157
28158
28159
28160
28161
28162
28163
28164
28165
28166
28167
28168
28169
28170
28171
28172
28173
28174
28175
28176
28177
28178
28179
28180
28181
28182
28183
28184
28185
28186
28187
28188
28189
28190
28191

28192
28193
28194
28195
28196
28197
28198
    ** Invoke the sqlite3session_attach() interface to attach a particular
    ** table so that it is never filtered.
    */
    if( cli_strcmp(azCmd[0],"attach")==0 ){
      if( nCmd!=2 ) goto session_syntax_error;
      if( pSession->p==0 ){
        session_not_open:
        eputz("ERROR: No sessions are open\n");
      }else{
        rc = sqlite3session_attach(pSession->p, azCmd[1]);
        if( rc ){
          eputf("ERROR: sqlite3session_attach() returns %d\n",rc);
          rc = 0;
        }
      }
    }else

    /* .session changeset FILE
    ** .session patchset FILE
    ** Write a changeset or patchset into a file.  The file is overwritten.
    */
    if( cli_strcmp(azCmd[0],"changeset")==0
     || cli_strcmp(azCmd[0],"patchset")==0
    ){
      FILE *out = 0;
      failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
      if( nCmd!=2 ) goto session_syntax_error;
      if( pSession->p==0 ) goto session_not_open;
      out = fopen(azCmd[1], "wb");
      if( out==0 ){
        eputf("ERROR: cannot open \"%s\" for writing\n",
              azCmd[1]);
      }else{
        int szChng;
        void *pChng;
        if( azCmd[0][0]=='c' ){
          rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
        }else{
          rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
        }
        if( rc ){
          sputf(stdout, "Error: error code %d\n", rc);
          rc = 0;
        }
        if( pChng
          && fwrite(pChng, szChng, 1, out)!=1 ){
          eputf("ERROR: Failed to write entire %d-byte output\n", szChng);

        }
        sqlite3_free(pChng);
        fclose(out);
      }
    }else

    /* .session close
26220
26221
26222
26223
26224
26225
26226
26227
26228
26229
26230
26231
26232
26233
26234
26235
26236
26237
26238
26239
26240
26241
26242
26243
26244
26245
26246
26247
26248
26249
26250
26251
26252
26253
26254
26255
26256
26257
26258
26259
26260
26261
26262
26263
26264
26265
26266
26267
26268
26269
26270
26271
26272
26273
26274
26275
26276
26277
26278
26279
26280
26281
26282
26283
26284
26285
26286
26287
26288
26289
26290
26291
26292
26293
26294
26295
26296
26297
26298
26299
26300
26301
26302
26303
26304
26305
26306
26307
26308
26309
26310
26311
26312
26313
26314
26315
26316
26317
26318
26319
26320
26321
26322
26323
    */
    if( cli_strcmp(azCmd[0], "enable")==0 ){
      int ii;
      if( nCmd>2 ) goto session_syntax_error;
      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
      if( pAuxDb->nSession ){
        ii = sqlite3session_enable(pSession->p, ii);
        utf8_printf(p->out, "session %s enable flag = %d\n",
                    pSession->zName, ii);
      }
    }else

    /* .session filter GLOB ....
    ** Set a list of GLOB patterns of table names to be excluded.
    */
    if( cli_strcmp(azCmd[0], "filter")==0 ){
      int ii, nByte;
      if( nCmd<2 ) goto session_syntax_error;
      if( pAuxDb->nSession ){
        for(ii=0; ii<pSession->nFilter; ii++){
          sqlite3_free(pSession->azFilter[ii]);
        }
        sqlite3_free(pSession->azFilter);
        nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
        pSession->azFilter = sqlite3_malloc( nByte );
        if( pSession->azFilter==0 ){
          raw_printf(stderr, "Error: out or memory\n");
          exit(1);
        }
        for(ii=1; ii<nCmd; ii++){
          char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
          shell_check_oom(x);
        }
        pSession->nFilter = ii-1;
      }
    }else

    /* .session indirect ?BOOLEAN?
    ** Query or set the indirect flag
    */
    if( cli_strcmp(azCmd[0], "indirect")==0 ){
      int ii;
      if( nCmd>2 ) goto session_syntax_error;
      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
      if( pAuxDb->nSession ){
        ii = sqlite3session_indirect(pSession->p, ii);
        utf8_printf(p->out, "session %s indirect flag = %d\n",
                    pSession->zName, ii);
      }
    }else

    /* .session isempty
    ** Determine if the session is empty
    */
    if( cli_strcmp(azCmd[0], "isempty")==0 ){
      int ii;
      if( nCmd!=1 ) goto session_syntax_error;
      if( pAuxDb->nSession ){
        ii = sqlite3session_isempty(pSession->p);
        utf8_printf(p->out, "session %s isempty flag = %d\n",
                    pSession->zName, ii);
      }
    }else

    /* .session list
    ** List all currently open sessions
    */
    if( cli_strcmp(azCmd[0],"list")==0 ){
      for(i=0; i<pAuxDb->nSession; i++){
        utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
      }
    }else

    /* .session open DB NAME
    ** Open a new session called NAME on the attached database DB.
    ** DB is normally "main".
    */
    if( cli_strcmp(azCmd[0],"open")==0 ){
      char *zName;
      if( nCmd!=3 ) goto session_syntax_error;
      zName = azCmd[2];
      if( zName[0]==0 ) goto session_syntax_error;
      for(i=0; i<pAuxDb->nSession; i++){
        if( cli_strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
          utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
          goto meta_command_exit;
        }
      }
      if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
        raw_printf(stderr,
                   "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
        goto meta_command_exit;
      }
      pSession = &pAuxDb->aSession[pAuxDb->nSession];
      rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
      if( rc ){
        raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
        rc = 0;
        goto meta_command_exit;
      }
      pSession->nFilter = 0;
      sqlite3session_table_filter(pSession->p, session_filter, pSession);
      pAuxDb->nSession++;
      pSession->zName = sqlite3_mprintf("%s", zName);







|
<
















|
<
<
<

















|
<











|
<








|














|




<
|





|







28211
28212
28213
28214
28215
28216
28217
28218

28219
28220
28221
28222
28223
28224
28225
28226
28227
28228
28229
28230
28231
28232
28233
28234
28235



28236
28237
28238
28239
28240
28241
28242
28243
28244
28245
28246
28247
28248
28249
28250
28251
28252
28253

28254
28255
28256
28257
28258
28259
28260
28261
28262
28263
28264
28265

28266
28267
28268
28269
28270
28271
28272
28273
28274
28275
28276
28277
28278
28279
28280
28281
28282
28283
28284
28285
28286
28287
28288
28289
28290
28291
28292
28293

28294
28295
28296
28297
28298
28299
28300
28301
28302
28303
28304
28305
28306
28307
    */
    if( cli_strcmp(azCmd[0], "enable")==0 ){
      int ii;
      if( nCmd>2 ) goto session_syntax_error;
      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
      if( pAuxDb->nSession ){
        ii = sqlite3session_enable(pSession->p, ii);
        oputf("session %s enable flag = %d\n", pSession->zName, ii);

      }
    }else

    /* .session filter GLOB ....
    ** Set a list of GLOB patterns of table names to be excluded.
    */
    if( cli_strcmp(azCmd[0], "filter")==0 ){
      int ii, nByte;
      if( nCmd<2 ) goto session_syntax_error;
      if( pAuxDb->nSession ){
        for(ii=0; ii<pSession->nFilter; ii++){
          sqlite3_free(pSession->azFilter[ii]);
        }
        sqlite3_free(pSession->azFilter);
        nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
        pSession->azFilter = sqlite3_malloc( nByte );
        shell_check_oom( pSession->azFilter );



        for(ii=1; ii<nCmd; ii++){
          char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
          shell_check_oom(x);
        }
        pSession->nFilter = ii-1;
      }
    }else

    /* .session indirect ?BOOLEAN?
    ** Query or set the indirect flag
    */
    if( cli_strcmp(azCmd[0], "indirect")==0 ){
      int ii;
      if( nCmd>2 ) goto session_syntax_error;
      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
      if( pAuxDb->nSession ){
        ii = sqlite3session_indirect(pSession->p, ii);
        oputf("session %s indirect flag = %d\n", pSession->zName, ii);

      }
    }else

    /* .session isempty
    ** Determine if the session is empty
    */
    if( cli_strcmp(azCmd[0], "isempty")==0 ){
      int ii;
      if( nCmd!=1 ) goto session_syntax_error;
      if( pAuxDb->nSession ){
        ii = sqlite3session_isempty(pSession->p);
        oputf("session %s isempty flag = %d\n", pSession->zName, ii);

      }
    }else

    /* .session list
    ** List all currently open sessions
    */
    if( cli_strcmp(azCmd[0],"list")==0 ){
      for(i=0; i<pAuxDb->nSession; i++){
        oputf("%d %s\n", i, pAuxDb->aSession[i].zName);
      }
    }else

    /* .session open DB NAME
    ** Open a new session called NAME on the attached database DB.
    ** DB is normally "main".
    */
    if( cli_strcmp(azCmd[0],"open")==0 ){
      char *zName;
      if( nCmd!=3 ) goto session_syntax_error;
      zName = azCmd[2];
      if( zName[0]==0 ) goto session_syntax_error;
      for(i=0; i<pAuxDb->nSession; i++){
        if( cli_strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
          eputf("Session \"%s\" already exists\n", zName);
          goto meta_command_exit;
        }
      }
      if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){

        eputf("Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
        goto meta_command_exit;
      }
      pSession = &pAuxDb->aSession[pAuxDb->nSession];
      rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
      if( rc ){
        eputf("Cannot open session: error code=%d\n", rc);
        rc = 0;
        goto meta_command_exit;
      }
      pSession->nFilter = 0;
      sqlite3session_table_filter(pSession->p, session_filter, pSession);
      pAuxDb->nSession++;
      pSession->zName = sqlite3_mprintf("%s", zName);
26333
26334
26335
26336
26337
26338
26339
26340
26341
26342
26343
26344
26345
26346
26347
26348
26349
26350
26351
26352
26353
26354
26355
26356
  /* Undocumented commands for internal testing.  Subject to change
  ** without notice. */
  if( c=='s' && n>=10 && cli_strncmp(azArg[0], "selftest-", 9)==0 ){
    if( cli_strncmp(azArg[0]+9, "boolean", n-9)==0 ){
      int i, v;
      for(i=1; i<nArg; i++){
        v = booleanValue(azArg[i]);
        utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
      }
    }
    if( cli_strncmp(azArg[0]+9, "integer", n-9)==0 ){
      int i; sqlite3_int64 v;
      for(i=1; i<nArg; i++){
        char zBuf[200];
        v = integerValue(azArg[i]);
        sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
        utf8_printf(p->out, "%s", zBuf);
      }
    }
  }else
#endif

  if( c=='s' && n>=4 && cli_strncmp(azArg[0],"selftest",n)==0 ){
    int bIsInit = 0;         /* True to initialize the SELFTEST table */







|








|







28317
28318
28319
28320
28321
28322
28323
28324
28325
28326
28327
28328
28329
28330
28331
28332
28333
28334
28335
28336
28337
28338
28339
28340
  /* Undocumented commands for internal testing.  Subject to change
  ** without notice. */
  if( c=='s' && n>=10 && cli_strncmp(azArg[0], "selftest-", 9)==0 ){
    if( cli_strncmp(azArg[0]+9, "boolean", n-9)==0 ){
      int i, v;
      for(i=1; i<nArg; i++){
        v = booleanValue(azArg[i]);
        oputf("%s: %d 0x%x\n", azArg[i], v, v);
      }
    }
    if( cli_strncmp(azArg[0]+9, "integer", n-9)==0 ){
      int i; sqlite3_int64 v;
      for(i=1; i<nArg; i++){
        char zBuf[200];
        v = integerValue(azArg[i]);
        sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
        oputz(zBuf);
      }
    }
  }else
#endif

  if( c=='s' && n>=4 && cli_strncmp(azArg[0],"selftest",n)==0 ){
    int bIsInit = 0;         /* True to initialize the SELFTEST table */
26369
26370
26371
26372
26373
26374
26375
26376
26377
26378
26379
26380
26381
26382
26383
26384
26385
      if( cli_strcmp(z,"-init")==0 ){
        bIsInit = 1;
      }else
      if( cli_strcmp(z,"-v")==0 ){
        bVerbose++;
      }else
      {
        utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
                    azArg[i], azArg[0]);
        raw_printf(stderr, "Should be one of: --init -v\n");
        rc = 1;
        goto meta_command_exit;
      }
    }
    if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
           != SQLITE_OK ){
      bSelftestExists = 0;







|
<
|







28353
28354
28355
28356
28357
28358
28359
28360

28361
28362
28363
28364
28365
28366
28367
28368
      if( cli_strcmp(z,"-init")==0 ){
        bIsInit = 1;
      }else
      if( cli_strcmp(z,"-v")==0 ){
        bVerbose++;
      }else
      {
        eputf("Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]);

        eputz("Should be one of: --init -v\n");
        rc = 1;
        goto meta_command_exit;
      }
    }
    if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
           != SQLITE_OK ){
      bSelftestExists = 0;
26400
26401
26402
26403
26404
26405
26406
26407
26408
26409
26410
26411
26412
26413
26414
26415
26416
26417
26418
26419
26420
26421
26422
26423
26424
26425
26426
26427
26428
26429
26430
26431
26432
26433
26434
26435
26436
26437
26438
26439
26440
26441
26442
26443
26444
26445
26446
26447

26448
26449
26450
26451
26452
26453
26454
26455
26456
26457
26458
26459
26460
26461
26462
26463
26464
26465
26466
26467
26468
26469
26470
26471
      }else{
        rc = sqlite3_prepare_v2(p->db,
          "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
          "      (1,'run','PRAGMA integrity_check','ok')",
          -1, &pStmt, 0);
      }
      if( rc ){
        raw_printf(stderr, "Error querying the selftest table\n");
        rc = 1;
        sqlite3_finalize(pStmt);
        goto meta_command_exit;
      }
      for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
        int tno = sqlite3_column_int(pStmt, 0);
        const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
        const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
        const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);

        if( zOp==0 ) continue;
        if( zSql==0 ) continue;
        if( zAns==0 ) continue;
        k = 0;
        if( bVerbose>0 ){
          printf("%d: %s %s\n", tno, zOp, zSql);
        }
        if( cli_strcmp(zOp,"memo")==0 ){
          utf8_printf(p->out, "%s\n", zSql);
        }else
        if( cli_strcmp(zOp,"run")==0 ){
          char *zErrMsg = 0;
          str.n = 0;
          str.z[0] = 0;
          rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
          nTest++;
          if( bVerbose ){
            utf8_printf(p->out, "Result: %s\n", str.z);
          }
          if( rc || zErrMsg ){
            nErr++;
            rc = 1;
            utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
            sqlite3_free(zErrMsg);
          }else if( cli_strcmp(zAns,str.z)!=0 ){
            nErr++;
            rc = 1;
            utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
            utf8_printf(p->out, "%d:      Got: [%s]\n", tno, str.z);
          }

        }else
        {
          utf8_printf(stderr,
            "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
          rc = 1;
          break;
        }
      } /* End loop over rows of content from SELFTEST */
      sqlite3_finalize(pStmt);
    } /* End loop over k */
    freeText(&str);
    utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
  }else

  if( c=='s' && cli_strncmp(azArg[0], "separator", n)==0 ){
    if( nArg<2 || nArg>3 ){
      raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
      rc = 1;
    }
    if( nArg>=2 ){
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
                       "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
    }
    if( nArg>=3 ){







|















|


|








|




|




|
|

>
|
<
<
|







|




|







28383
28384
28385
28386
28387
28388
28389
28390
28391
28392
28393
28394
28395
28396
28397
28398
28399
28400
28401
28402
28403
28404
28405
28406
28407
28408
28409
28410
28411
28412
28413
28414
28415
28416
28417
28418
28419
28420
28421
28422
28423
28424
28425
28426
28427
28428
28429
28430
28431
28432


28433
28434
28435
28436
28437
28438
28439
28440
28441
28442
28443
28444
28445
28446
28447
28448
28449
28450
28451
28452
28453
      }else{
        rc = sqlite3_prepare_v2(p->db,
          "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
          "      (1,'run','PRAGMA integrity_check','ok')",
          -1, &pStmt, 0);
      }
      if( rc ){
        eputz("Error querying the selftest table\n");
        rc = 1;
        sqlite3_finalize(pStmt);
        goto meta_command_exit;
      }
      for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
        int tno = sqlite3_column_int(pStmt, 0);
        const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
        const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
        const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);

        if( zOp==0 ) continue;
        if( zSql==0 ) continue;
        if( zAns==0 ) continue;
        k = 0;
        if( bVerbose>0 ){
          sputf(stdout, "%d: %s %s\n", tno, zOp, zSql);
        }
        if( cli_strcmp(zOp,"memo")==0 ){
          oputf("%s\n", zSql);
        }else
        if( cli_strcmp(zOp,"run")==0 ){
          char *zErrMsg = 0;
          str.n = 0;
          str.z[0] = 0;
          rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
          nTest++;
          if( bVerbose ){
            oputf("Result: %s\n", str.z);
          }
          if( rc || zErrMsg ){
            nErr++;
            rc = 1;
            oputf("%d: error-code-%d: %s\n", tno, rc, zErrMsg);
            sqlite3_free(zErrMsg);
          }else if( cli_strcmp(zAns,str.z)!=0 ){
            nErr++;
            rc = 1;
            oputf("%d: Expected: [%s]\n", tno, zAns);
            oputf("%d:      Got: [%s]\n", tno, str.z);
          }
        }
        else{


          eputf("Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
          rc = 1;
          break;
        }
      } /* End loop over rows of content from SELFTEST */
      sqlite3_finalize(pStmt);
    } /* End loop over k */
    freeText(&str);
    oputf("%d errors out of %d tests\n", nErr, nTest);
  }else

  if( c=='s' && cli_strncmp(azArg[0], "separator", n)==0 ){
    if( nArg<2 || nArg>3 ){
      eputz("Usage: .separator COL ?ROW?\n");
      rc = 1;
    }
    if( nArg>=2 ){
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
                       "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
    }
    if( nArg>=3 ){
26500
26501
26502
26503
26504
26505
26506
26507
26508
26509
26510
26511
26512
26513
26514
26515
26516
26517
26518
26519
26520
26521
        ){
          iSize = atoi(&z[5]);
        }else
        if( cli_strcmp(z,"debug")==0 ){
          bDebug = 1;
        }else
        {
          utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
                      azArg[i], azArg[0]);
          showHelp(p->out, azArg[0]);
          rc = 1;
          goto meta_command_exit;
        }
      }else if( zLike ){
        raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
        rc = 1;
        goto meta_command_exit;
      }else{
        zLike = z;
        bSeparate = 1;
        if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
      }







|
<





|







28482
28483
28484
28485
28486
28487
28488
28489

28490
28491
28492
28493
28494
28495
28496
28497
28498
28499
28500
28501
28502
        ){
          iSize = atoi(&z[5]);
        }else
        if( cli_strcmp(z,"debug")==0 ){
          bDebug = 1;
        }else
        {
          eputf("Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]);

          showHelp(p->out, azArg[0]);
          rc = 1;
          goto meta_command_exit;
        }
      }else if( zLike ){
        eputz("Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
        rc = 1;
        goto meta_command_exit;
      }else{
        zLike = z;
        bSeparate = 1;
        if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
      }
26579
26580
26581
26582
26583
26584
26585
26586
26587
26588
26589
26590
26591
26592
26593
          "   FROM [sha3sum$query]",
          sSql.z, iSize);
    }
    shell_check_oom(zSql);
    freeText(&sQuery);
    freeText(&sSql);
    if( bDebug ){
      utf8_printf(p->out, "%s\n", zSql);
    }else{
      shell_exec(p, zSql, 0);
    }
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && !defined(SQLITE_OMIT_VIRTUALTABLE)
    {
      int lrc;
      char *zRevText = /* Query for reversible to-blob-to-text check */







|







28560
28561
28562
28563
28564
28565
28566
28567
28568
28569
28570
28571
28572
28573
28574
          "   FROM [sha3sum$query]",
          sSql.z, iSize);
    }
    shell_check_oom(zSql);
    freeText(&sQuery);
    freeText(&sSql);
    if( bDebug ){
      oputf("%s\n", zSql);
    }else{
      shell_exec(p, zSql, 0);
    }
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && !defined(SQLITE_OMIT_VIRTUALTABLE)
    {
      int lrc;
      char *zRevText = /* Query for reversible to-blob-to-text check */
26609
26610
26611
26612
26613
26614
26615
26616
26617
26618
26619
26620
26621
26622
26623
26624
26625
26626
26627
26628
26629
26630
26631
26632
26633
26634
26635
26636
26637
26638
26639
26640
26641
26642
26643
26644
26645
26646
26647
26648
26649
26650
26651
26652
26653
26654
26655
26656
26657
26658
26659
26660
26661
26662
26663
26664
26665
26666
26667
26668
26669
26670
26671

26672

26673
26674
26675
26676
26677
26678
26679
26680
26681
26682
26683
26684
26685
26686
26687
26688
26689
26690
26691
26692
26693
26694
26695
26696
26697
26698
26699
26700
26701
26702
26703
26704
26705
26706
26707
26708
26709
26710
26711
26712
26713
26714
26715
26716
26717
26718
26719
26720
26721
26722
26723
26724
26725
26726
26727
26728
26729
26730
26731
26732
26733
26734
26735
26736
26737
26738
26739
26740
26741
26742
26743
26744
26745
26746
26747
26748
26749
26750
          " from (select 'SELECT COUNT(*) AS bad_text_count\n"
          "FROM '||tname||' WHERE '\n"
          "||group_concat('CAST(CAST('||cname||' AS BLOB) AS TEXT)<>'||cname\n"
          "|| ' AND typeof('||cname||')=''text'' ',\n"
          "' OR ') as query, tname from tabcols group by tname)"
          , zRevText);
      shell_check_oom(zRevText);
      if( bDebug ) utf8_printf(p->out, "%s\n", zRevText);
      lrc = sqlite3_prepare_v2(p->db, zRevText, -1, &pStmt, 0);
      if( lrc!=SQLITE_OK ){
        /* assert(lrc==SQLITE_NOMEM); // might also be SQLITE_ERROR if the
        ** user does cruel and unnatural things like ".limit expr_depth 0". */
        rc = 1;
      }else{
        if( zLike ) sqlite3_bind_text(pStmt,1,zLike,-1,SQLITE_STATIC);
        lrc = SQLITE_ROW==sqlite3_step(pStmt);
        if( lrc ){
          const char *zGenQuery = (char*)sqlite3_column_text(pStmt,0);
          sqlite3_stmt *pCheckStmt;
          lrc = sqlite3_prepare_v2(p->db, zGenQuery, -1, &pCheckStmt, 0);
          if( bDebug ) utf8_printf(p->out, "%s\n", zGenQuery);
          if( lrc!=SQLITE_OK ){
            rc = 1;
          }else{
            if( SQLITE_ROW==sqlite3_step(pCheckStmt) ){
              double countIrreversible = sqlite3_column_double(pCheckStmt, 0);
              if( countIrreversible>0 ){
                int sz = (int)(countIrreversible + 0.5);
                utf8_printf(stderr,
                     "Digest includes %d invalidly encoded text field%s.\n",
                            sz, (sz>1)? "s": "");
              }
            }
            sqlite3_finalize(pCheckStmt);
          }
          sqlite3_finalize(pStmt);
        }
      }
      if( rc ) utf8_printf(stderr, ".sha3sum failed.\n");
      sqlite3_free(zRevText);
    }
#endif /* !defined(*_OMIT_SCHEMA_PRAGMAS) && !defined(*_OMIT_VIRTUALTABLE) */
    sqlite3_free(zSql);
  }else

#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
  if( c=='s'
   && (cli_strncmp(azArg[0], "shell", n)==0
       || cli_strncmp(azArg[0],"system",n)==0)
  ){
    char *zCmd;
    int i, x;
    failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
    if( nArg<2 ){
      raw_printf(stderr, "Usage: .system COMMAND\n");
      rc = 1;
      goto meta_command_exit;
    }
    zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
    for(i=2; i<nArg && zCmd!=0; i++){
      zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
                             zCmd, azArg[i]);
    }

    x = zCmd!=0 ? system(zCmd) : 1;

    sqlite3_free(zCmd);
    if( x ) raw_printf(stderr, "System command returns %d\n", x);
  }else
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='s' && cli_strncmp(azArg[0], "show", n)==0 ){
    static const char *azBool[] = { "off", "on", "trigger", "full"};
    const char *zOut;
    int i;
    if( nArg!=1 ){
      raw_printf(stderr, "Usage: .show\n");
      rc = 1;
      goto meta_command_exit;
    }
    utf8_printf(p->out, "%12.12s: %s\n","echo",
                azBool[ShellHasFlag(p, SHFLG_Echo)]);
    utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
    utf8_printf(p->out, "%12.12s: %s\n","explain",
         p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
    utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
    if( p->mode==MODE_Column
     || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
    ){
      utf8_printf
        (p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode",
         modeDescr[p->mode], p->cmOpts.iWrap,
         p->cmOpts.bWordWrap ? "on" : "off",
         p->cmOpts.bQuote ? "" : "no");
    }else{
      utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
    }
    utf8_printf(p->out, "%12.12s: ", "nullvalue");
      output_c_string(p->out, p->nullValue);
      raw_printf(p->out, "\n");
    utf8_printf(p->out,"%12.12s: %s\n","output",
            strlen30(p->outfile) ? p->outfile : "stdout");
    utf8_printf(p->out,"%12.12s: ", "colseparator");
      output_c_string(p->out, p->colSeparator);
      raw_printf(p->out, "\n");
    utf8_printf(p->out,"%12.12s: ", "rowseparator");
      output_c_string(p->out, p->rowSeparator);
      raw_printf(p->out, "\n");
    switch( p->statsOn ){
      case 0:  zOut = "off";     break;
      default: zOut = "on";      break;
      case 2:  zOut = "stmt";    break;
      case 3:  zOut = "vmstep";  break;
    }
    utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
    utf8_printf(p->out, "%12.12s: ", "width");
    for (i=0;i<p->nWidth;i++) {
      raw_printf(p->out, "%d ", p->colWidth[i]);
    }
    raw_printf(p->out, "\n");
    utf8_printf(p->out, "%12.12s: %s\n", "filename",
                p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
  }else

  if( c=='s' && cli_strncmp(azArg[0], "stats", n)==0 ){
    if( nArg==2 ){
      if( cli_strcmp(azArg[1],"stmt")==0 ){
        p->statsOn = 2;
      }else if( cli_strcmp(azArg[1],"vmstep")==0 ){
        p->statsOn = 3;
      }else{
        p->statsOn = (u8)booleanValue(azArg[1]);
      }
    }else if( nArg==1 ){
      display_stats(p->db, p, 0);
    }else{
      raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
      rc = 1;
    }
  }else

  if( (c=='t' && n>1 && cli_strncmp(azArg[0], "tables", n)==0)
   || (c=='i' && (cli_strncmp(azArg[0], "indices", n)==0
                 || cli_strncmp(azArg[0], "indexes", n)==0) )







|












|







<
|
|







|















|








>

>

|








|



|
|
|
|
|
|



<
|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|






|
|

|

|
|
|














|







28590
28591
28592
28593
28594
28595
28596
28597
28598
28599
28600
28601
28602
28603
28604
28605
28606
28607
28608
28609
28610
28611
28612
28613
28614
28615
28616
28617

28618
28619
28620
28621
28622
28623
28624
28625
28626
28627
28628
28629
28630
28631
28632
28633
28634
28635
28636
28637
28638
28639
28640
28641
28642
28643
28644
28645
28646
28647
28648
28649
28650
28651
28652
28653
28654
28655
28656
28657
28658
28659
28660
28661
28662
28663
28664
28665
28666
28667
28668
28669
28670
28671
28672
28673
28674
28675
28676
28677

28678
28679
28680
28681
28682
28683
28684
28685
28686
28687
28688
28689
28690
28691
28692
28693
28694
28695
28696
28697
28698
28699
28700
28701
28702
28703
28704
28705
28706
28707
28708
28709
28710
28711
28712
28713
28714
28715
28716
28717
28718
28719
28720
28721
28722
28723
28724
28725
28726
28727
28728
28729
28730
28731
          " from (select 'SELECT COUNT(*) AS bad_text_count\n"
          "FROM '||tname||' WHERE '\n"
          "||group_concat('CAST(CAST('||cname||' AS BLOB) AS TEXT)<>'||cname\n"
          "|| ' AND typeof('||cname||')=''text'' ',\n"
          "' OR ') as query, tname from tabcols group by tname)"
          , zRevText);
      shell_check_oom(zRevText);
      if( bDebug ) oputf("%s\n", zRevText);
      lrc = sqlite3_prepare_v2(p->db, zRevText, -1, &pStmt, 0);
      if( lrc!=SQLITE_OK ){
        /* assert(lrc==SQLITE_NOMEM); // might also be SQLITE_ERROR if the
        ** user does cruel and unnatural things like ".limit expr_depth 0". */
        rc = 1;
      }else{
        if( zLike ) sqlite3_bind_text(pStmt,1,zLike,-1,SQLITE_STATIC);
        lrc = SQLITE_ROW==sqlite3_step(pStmt);
        if( lrc ){
          const char *zGenQuery = (char*)sqlite3_column_text(pStmt,0);
          sqlite3_stmt *pCheckStmt;
          lrc = sqlite3_prepare_v2(p->db, zGenQuery, -1, &pCheckStmt, 0);
          if( bDebug ) oputf("%s\n", zGenQuery);
          if( lrc!=SQLITE_OK ){
            rc = 1;
          }else{
            if( SQLITE_ROW==sqlite3_step(pCheckStmt) ){
              double countIrreversible = sqlite3_column_double(pCheckStmt, 0);
              if( countIrreversible>0 ){
                int sz = (int)(countIrreversible + 0.5);

                eputf("Digest includes %d invalidly encoded text field%s.\n",
                      sz, (sz>1)? "s": "");
              }
            }
            sqlite3_finalize(pCheckStmt);
          }
          sqlite3_finalize(pStmt);
        }
      }
      if( rc ) eputz(".sha3sum failed.\n");
      sqlite3_free(zRevText);
    }
#endif /* !defined(*_OMIT_SCHEMA_PRAGMAS) && !defined(*_OMIT_VIRTUALTABLE) */
    sqlite3_free(zSql);
  }else

#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
  if( c=='s'
   && (cli_strncmp(azArg[0], "shell", n)==0
       || cli_strncmp(azArg[0],"system",n)==0)
  ){
    char *zCmd;
    int i, x;
    failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
    if( nArg<2 ){
      eputz("Usage: .system COMMAND\n");
      rc = 1;
      goto meta_command_exit;
    }
    zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
    for(i=2; i<nArg && zCmd!=0; i++){
      zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
                             zCmd, azArg[i]);
    }
    consoleRestore();
    x = zCmd!=0 ? system(zCmd) : 1;
    consoleRenewSetup();
    sqlite3_free(zCmd);
    if( x ) eputf("System command returns %d\n", x);
  }else
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='s' && cli_strncmp(azArg[0], "show", n)==0 ){
    static const char *azBool[] = { "off", "on", "trigger", "full"};
    const char *zOut;
    int i;
    if( nArg!=1 ){
      eputz("Usage: .show\n");
      rc = 1;
      goto meta_command_exit;
    }
    oputf("%12.12s: %s\n","echo",
          azBool[ShellHasFlag(p, SHFLG_Echo)]);
    oputf("%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
    oputf("%12.12s: %s\n","explain",
          p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
    oputf("%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
    if( p->mode==MODE_Column
     || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
    ){

      oputf("%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode",
            modeDescr[p->mode], p->cmOpts.iWrap,
            p->cmOpts.bWordWrap ? "on" : "off",
            p->cmOpts.bQuote ? "" : "no");
    }else{
      oputf("%12.12s: %s\n","mode", modeDescr[p->mode]);
    }
    oputf("%12.12s: ", "nullvalue");
    output_c_string(p->nullValue);
    oputz("\n");
    oputf("%12.12s: %s\n","output",
          strlen30(p->outfile) ? p->outfile : "stdout");
    oputf("%12.12s: ", "colseparator");
     output_c_string(p->colSeparator);
     oputz("\n");
    oputf("%12.12s: ", "rowseparator");
     output_c_string(p->rowSeparator);
     oputz("\n");
    switch( p->statsOn ){
      case 0:  zOut = "off";     break;
      default: zOut = "on";      break;
      case 2:  zOut = "stmt";    break;
      case 3:  zOut = "vmstep";  break;
    }
    oputf("%12.12s: %s\n","stats", zOut);
    oputf("%12.12s: ", "width");
    for (i=0;i<p->nWidth;i++) {
      oputf("%d ", p->colWidth[i]);
    }
    oputz("\n");
    oputf("%12.12s: %s\n", "filename",
          p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
  }else

  if( c=='s' && cli_strncmp(azArg[0], "stats", n)==0 ){
    if( nArg==2 ){
      if( cli_strcmp(azArg[1],"stmt")==0 ){
        p->statsOn = 2;
      }else if( cli_strcmp(azArg[1],"vmstep")==0 ){
        p->statsOn = 3;
      }else{
        p->statsOn = (u8)booleanValue(azArg[1]);
      }
    }else if( nArg==1 ){
      display_stats(p->db, p, 0);
    }else{
      eputz("Usage: .stats ?on|off|stmt|vmstep?\n");
      rc = 1;
    }
  }else

  if( (c=='t' && n>1 && cli_strncmp(azArg[0], "tables", n)==0)
   || (c=='i' && (cli_strncmp(azArg[0], "indices", n)==0
                 || cli_strncmp(azArg[0], "indexes", n)==0) )
26762
26763
26764
26765
26766
26767
26768
26769
26770
26771
26772
26773
26774
26775
26776
      return shellDatabaseError(p->db);
    }

    if( nArg>2 && c=='i' ){
      /* It is an historical accident that the .indexes command shows an error
      ** when called with the wrong number of arguments whereas the .tables
      ** command does not. */
      raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
      rc = 1;
      sqlite3_finalize(pStmt);
      goto meta_command_exit;
    }
    for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
      const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
      if( zDbName==0 ) continue;







|







28743
28744
28745
28746
28747
28748
28749
28750
28751
28752
28753
28754
28755
28756
28757
      return shellDatabaseError(p->db);
    }

    if( nArg>2 && c=='i' ){
      /* It is an historical accident that the .indexes command shows an error
      ** when called with the wrong number of arguments whereas the .tables
      ** command does not. */
      eputz("Usage: .indexes ?LIKE-PATTERN?\n");
      rc = 1;
      sqlite3_finalize(pStmt);
      goto meta_command_exit;
    }
    for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
      const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
      if( zDbName==0 ) continue;
26838
26839
26840
26841
26842
26843
26844
26845
26846
26847
26848
26849
26850
26851
26852
26853
26854
26855
26856
26857
26858
26859
26860
26861
26862
26863
26864
26865
26866
26867
26868
26869
      }
      nPrintCol = 80/(maxlen+2);
      if( nPrintCol<1 ) nPrintCol = 1;
      nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
      for(i=0; i<nPrintRow; i++){
        for(j=i; j<nRow; j+=nPrintRow){
          char *zSp = j<nPrintRow ? "" : "  ";
          utf8_printf(p->out, "%s%-*s", zSp, maxlen,
                      azResult[j] ? azResult[j]:"");
        }
        raw_printf(p->out, "\n");
      }
    }

    for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
    sqlite3_free(azResult);
  }else

#ifndef SQLITE_SHELL_FIDDLE
  /* Begin redirecting output to the file "testcase-out.txt" */
  if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
    output_reset(p);
    p->out = output_file_open("testcase-out.txt", 0);
    if( p->out==0 ){
      raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
    }
    if( nArg>=2 ){
      sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
    }else{
      sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
    }
  }else







<
|

|













|







28819
28820
28821
28822
28823
28824
28825

28826
28827
28828
28829
28830
28831
28832
28833
28834
28835
28836
28837
28838
28839
28840
28841
28842
28843
28844
28845
28846
28847
28848
28849
      }
      nPrintCol = 80/(maxlen+2);
      if( nPrintCol<1 ) nPrintCol = 1;
      nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
      for(i=0; i<nPrintRow; i++){
        for(j=i; j<nRow; j+=nPrintRow){
          char *zSp = j<nPrintRow ? "" : "  ";

          oputf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:"");
        }
        oputz("\n");
      }
    }

    for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
    sqlite3_free(azResult);
  }else

#ifndef SQLITE_SHELL_FIDDLE
  /* Begin redirecting output to the file "testcase-out.txt" */
  if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
    output_reset(p);
    p->out = output_file_open("testcase-out.txt", 0);
    if( p->out==0 ){
      eputz("Error: cannot open 'testcase-out.txt'\n");
    }
    if( nArg>=2 ){
      sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
    }else{
      sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
    }
  }else
26879
26880
26881
26882
26883
26884
26885
26886
26887
26888
26889

26890
26891
26892
26893
26894
26895
26896
26897
26898
26899
26900
26901
26902
26903
26904
26905
26906
26907
26908
26909
26910
26911
26912
26913
26914
26915
26916
26917
26918
26919
26920
26921
26922
26923
26924
26925
26926
26927
26928
26929
26930
26931
26932
26933
26934
26935
26936
26937
26938
26939
26940
26941
26942
26943
26944
26945
26946
26947
26948
26949
26950
26951
26952
26953
26954
26955
26956
26957
26958
26959
    } aCtrl[] = {
    {"always",             SQLITE_TESTCTRL_ALWAYS, 1,     "BOOLEAN"         },
    {"assert",             SQLITE_TESTCTRL_ASSERT, 1,     "BOOLEAN"         },
  /*{"benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, ""        },*/
  /*{"bitvec_test",        SQLITE_TESTCTRL_BITVEC_TEST, 1,  ""              },*/
    {"byteorder",          SQLITE_TESTCTRL_BYTEORDER, 0,  ""                },
    {"extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN"  },
  /*{"fault_install",      SQLITE_TESTCTRL_FAULT_INSTALL, 1,""              },*/
    {"fk_no_action",       SQLITE_TESTCTRL_FK_NO_ACTION, 0, "BOOLEAN"       },
    {"imposter",         SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
    {"internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,""          },

    {"localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN"      },
    {"never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN"       },
    {"optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK"   },
#ifdef YYCOVERAGE
    {"parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE,0,""             },
#endif
    {"pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET  "       },
    {"prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,0, ""               },
    {"prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,   0, ""               },
    {"prng_seed",          SQLITE_TESTCTRL_PRNG_SEED,   0, "SEED ?db?"      },
    {"seek_count",         SQLITE_TESTCTRL_SEEK_COUNT,  0, ""               },
    {"sorter_mmap",        SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX"           },
    {"tune",               SQLITE_TESTCTRL_TUNE,        1, "ID VALUE"       },
    {"uselongdouble",    SQLITE_TESTCTRL_USELONGDOUBLE,0,"?BOOLEAN|\"default\"?"},
    };
    int testctrl = -1;
    int iCtrl = -1;
    int rc2 = 0;    /* 0: usage.  1: %d  2: %x  3: no-output */
    int isOk = 0;
    int i, n2;
    const char *zCmd = 0;

    open_db(p, 0);
    zCmd = nArg>=2 ? azArg[1] : "help";

    /* The argument can optionally begin with "-" or "--" */
    if( zCmd[0]=='-' && zCmd[1] ){
      zCmd++;
      if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
    }

    /* --help lists all test-controls */
    if( cli_strcmp(zCmd,"help")==0 ){
      utf8_printf(p->out, "Available test-controls:\n");
      for(i=0; i<ArraySize(aCtrl); i++){
        if( aCtrl[i].unSafe && !ShellHasFlag(p,SHFLG_TestingMode) ) continue;
        utf8_printf(p->out, "  .testctrl %s %s\n",
                    aCtrl[i].zCtrlName, aCtrl[i].zUsage);
      }
      rc = 1;
      goto meta_command_exit;
    }

    /* convert testctrl text option to value. allow any unique prefix
    ** of the option name, or a numerical value. */
    n2 = strlen30(zCmd);
    for(i=0; i<ArraySize(aCtrl); i++){
      if( aCtrl[i].unSafe && !ShellHasFlag(p,SHFLG_TestingMode) ) continue;
      if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
        if( testctrl<0 ){
          testctrl = aCtrl[i].ctrlCode;
          iCtrl = i;
        }else{
          utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
                              "Use \".testctrl --help\" for help\n", zCmd);
          rc = 1;
          goto meta_command_exit;
        }
      }
    }
    if( testctrl<0 ){
      utf8_printf(stderr,"Error: unknown test-control: %s\n"
                         "Use \".testctrl --help\" for help\n", zCmd);
    }else{
      switch(testctrl){

        /* sqlite3_test_control(int, db, int) */
        case SQLITE_TESTCTRL_OPTIMIZATIONS:
        case SQLITE_TESTCTRL_FK_NO_ACTION:
          if( nArg==3 ){







|



>













|



















|


|
|















|
|






|
|







28859
28860
28861
28862
28863
28864
28865
28866
28867
28868
28869
28870
28871
28872
28873
28874
28875
28876
28877
28878
28879
28880
28881
28882
28883
28884
28885
28886
28887
28888
28889
28890
28891
28892
28893
28894
28895
28896
28897
28898
28899
28900
28901
28902
28903
28904
28905
28906
28907
28908
28909
28910
28911
28912
28913
28914
28915
28916
28917
28918
28919
28920
28921
28922
28923
28924
28925
28926
28927
28928
28929
28930
28931
28932
28933
28934
28935
28936
28937
28938
28939
28940
    } aCtrl[] = {
    {"always",             SQLITE_TESTCTRL_ALWAYS, 1,     "BOOLEAN"         },
    {"assert",             SQLITE_TESTCTRL_ASSERT, 1,     "BOOLEAN"         },
  /*{"benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, ""        },*/
  /*{"bitvec_test",        SQLITE_TESTCTRL_BITVEC_TEST, 1,  ""              },*/
    {"byteorder",          SQLITE_TESTCTRL_BYTEORDER, 0,  ""                },
    {"extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN"  },
    {"fault_install",      SQLITE_TESTCTRL_FAULT_INSTALL, 1,"args..."       },
    {"fk_no_action",       SQLITE_TESTCTRL_FK_NO_ACTION, 0, "BOOLEAN"       },
    {"imposter",         SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
    {"internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,""          },
    {"json_selfcheck",     SQLITE_TESTCTRL_JSON_SELFCHECK ,0,"BOOLEAN"      },
    {"localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN"      },
    {"never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN"       },
    {"optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK"   },
#ifdef YYCOVERAGE
    {"parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE,0,""             },
#endif
    {"pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET  "       },
    {"prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,0, ""               },
    {"prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,   0, ""               },
    {"prng_seed",          SQLITE_TESTCTRL_PRNG_SEED,   0, "SEED ?db?"      },
    {"seek_count",         SQLITE_TESTCTRL_SEEK_COUNT,  0, ""               },
    {"sorter_mmap",        SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX"           },
    {"tune",               SQLITE_TESTCTRL_TUNE,        1, "ID VALUE"       },
    {"uselongdouble",  SQLITE_TESTCTRL_USELONGDOUBLE,0,"?BOOLEAN|\"default\"?"},
    };
    int testctrl = -1;
    int iCtrl = -1;
    int rc2 = 0;    /* 0: usage.  1: %d  2: %x  3: no-output */
    int isOk = 0;
    int i, n2;
    const char *zCmd = 0;

    open_db(p, 0);
    zCmd = nArg>=2 ? azArg[1] : "help";

    /* The argument can optionally begin with "-" or "--" */
    if( zCmd[0]=='-' && zCmd[1] ){
      zCmd++;
      if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
    }

    /* --help lists all test-controls */
    if( cli_strcmp(zCmd,"help")==0 ){
      oputz("Available test-controls:\n");
      for(i=0; i<ArraySize(aCtrl); i++){
        if( aCtrl[i].unSafe && !ShellHasFlag(p,SHFLG_TestingMode) ) continue;
        oputf("  .testctrl %s %s\n",
              aCtrl[i].zCtrlName, aCtrl[i].zUsage);
      }
      rc = 1;
      goto meta_command_exit;
    }

    /* convert testctrl text option to value. allow any unique prefix
    ** of the option name, or a numerical value. */
    n2 = strlen30(zCmd);
    for(i=0; i<ArraySize(aCtrl); i++){
      if( aCtrl[i].unSafe && !ShellHasFlag(p,SHFLG_TestingMode) ) continue;
      if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
        if( testctrl<0 ){
          testctrl = aCtrl[i].ctrlCode;
          iCtrl = i;
        }else{
          eputf("Error: ambiguous test-control: \"%s\"\n"
                "Use \".testctrl --help\" for help\n", zCmd);
          rc = 1;
          goto meta_command_exit;
        }
      }
    }
    if( testctrl<0 ){
      eputf("Error: unknown test-control: %s\n"
            "Use \".testctrl --help\" for help\n", zCmd);
    }else{
      switch(testctrl){

        /* sqlite3_test_control(int, db, int) */
        case SQLITE_TESTCTRL_OPTIMIZATIONS:
        case SQLITE_TESTCTRL_FK_NO_ACTION:
          if( nArg==3 ){
26985
26986
26987
26988
26989
26990
26991
26992
26993
26994
26995
26996
26997
26998
26999
        /* sqlite3_test_control(int, int, sqlite3*) */
        case SQLITE_TESTCTRL_PRNG_SEED:
          if( nArg==3 || nArg==4 ){
            int ii = (int)integerValue(azArg[2]);
            sqlite3 *db;
            if( ii==0 && cli_strcmp(azArg[2],"random")==0 ){
              sqlite3_randomness(sizeof(ii),&ii);
              printf("-- random seed: %d\n", ii);
            }
            if( nArg==3 ){
              db = 0;
            }else{
              db = p->db;
              /* Make sure the schema has been loaded */
              sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);







|







28966
28967
28968
28969
28970
28971
28972
28973
28974
28975
28976
28977
28978
28979
28980
        /* sqlite3_test_control(int, int, sqlite3*) */
        case SQLITE_TESTCTRL_PRNG_SEED:
          if( nArg==3 || nArg==4 ){
            int ii = (int)integerValue(azArg[2]);
            sqlite3 *db;
            if( ii==0 && cli_strcmp(azArg[2],"random")==0 ){
              sqlite3_randomness(sizeof(ii),&ii);
              sputf(stdout, "-- random seed: %d\n", ii);
            }
            if( nArg==3 ){
              db = 0;
            }else{
              db = p->db;
              /* Make sure the schema has been loaded */
              sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
27053
27054
27055
27056
27057
27058
27059
27060
27061
27062
27063
27064
27065
27066
27067
            isOk = 3;
          }
          break;

        case SQLITE_TESTCTRL_SEEK_COUNT: {
          u64 x = 0;
          rc2 = sqlite3_test_control(testctrl, p->db, &x);
          utf8_printf(p->out, "%llu\n", x);
          isOk = 3;
          break;
        }

#ifdef YYCOVERAGE
        case SQLITE_TESTCTRL_PARSER_COVERAGE: {
          if( nArg==2 ){







|







29034
29035
29036
29037
29038
29039
29040
29041
29042
29043
29044
29045
29046
29047
29048
            isOk = 3;
          }
          break;

        case SQLITE_TESTCTRL_SEEK_COUNT: {
          u64 x = 0;
          rc2 = sqlite3_test_control(testctrl, p->db, &x);
          oputf("%llu\n", x);
          isOk = 3;
          break;
        }

#ifdef YYCOVERAGE
        case SQLITE_TESTCTRL_PARSER_COVERAGE: {
          if( nArg==2 ){
27084
27085
27086
27087
27088
27089
27090
27091
27092
27093
27094
27095
27096
27097
27098
27099
27100
27101
27102
27103
27104
27105
27106
27107







27108









































27109




















27110
27111
27112
27113
27114
27115
27116
27117
27118
27119
27120
27121
27122
27123
27124
27125
27126
27127
27128
27129
27130
27131
27132
27133
27134
27135
27136
27137
27138
27139
27140
27141
            isOk = 1;
          }else if( nArg==2 ){
            int id = 1;
            while(1){
              int val = 0;
              rc2 = sqlite3_test_control(testctrl, -id, &val);
              if( rc2!=SQLITE_OK ) break;
              if( id>1 ) utf8_printf(p->out, "  ");
              utf8_printf(p->out, "%d: %d", id, val);
              id++;
            }
            if( id>1 ) utf8_printf(p->out, "\n");
            isOk = 3;
          }
          break;
        }
#endif
        case SQLITE_TESTCTRL_SORTER_MMAP:
          if( nArg==3 ){
            int opt = (unsigned int)integerValue(azArg[2]);
            rc2 = sqlite3_test_control(testctrl, p->db, opt);
            isOk = 3;
          }
          break;







      }









































    }




















    if( isOk==0 && iCtrl>=0 ){
      utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
      rc = 1;
    }else if( isOk==1 ){
      raw_printf(p->out, "%d\n", rc2);
    }else if( isOk==2 ){
      raw_printf(p->out, "0x%08x\n", rc2);
    }
  }else
#endif /* !defined(SQLITE_UNTESTABLE) */

  if( c=='t' && n>4 && cli_strncmp(azArg[0], "timeout", n)==0 ){
    open_db(p, 0);
    sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
  }else

  if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){
    if( nArg==2 ){
      enableTimer = booleanValue(azArg[1]);
      if( enableTimer && !HAS_TIMER ){
        raw_printf(stderr, "Error: timer not available on this system.\n");
        enableTimer = 0;
      }
    }else{
      raw_printf(stderr, "Usage: .timer on|off\n");
      rc = 1;
    }
  }else

#ifndef SQLITE_OMIT_TRACE
  if( c=='t' && cli_strncmp(azArg[0], "trace", n)==0 ){
    int mType = 0;







|
|


|












>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|


|

|













|



|







29065
29066
29067
29068
29069
29070
29071
29072
29073
29074
29075
29076
29077
29078
29079
29080
29081
29082
29083
29084
29085
29086
29087
29088
29089
29090
29091
29092
29093
29094
29095
29096
29097
29098
29099
29100
29101
29102
29103
29104
29105
29106
29107
29108
29109
29110
29111
29112
29113
29114
29115
29116
29117
29118
29119
29120
29121
29122
29123
29124
29125
29126
29127
29128
29129
29130
29131
29132
29133
29134
29135
29136
29137
29138
29139
29140
29141
29142
29143
29144
29145
29146
29147
29148
29149
29150
29151
29152
29153
29154
29155
29156
29157
29158
29159
29160
29161
29162
29163
29164
29165
29166
29167
29168
29169
29170
29171
29172
29173
29174
29175
29176
29177
29178
29179
29180
29181
29182
29183
29184
29185
29186
29187
29188
29189
29190
            isOk = 1;
          }else if( nArg==2 ){
            int id = 1;
            while(1){
              int val = 0;
              rc2 = sqlite3_test_control(testctrl, -id, &val);
              if( rc2!=SQLITE_OK ) break;
              if( id>1 ) oputz("  ");
              oputf("%d: %d", id, val);
              id++;
            }
            if( id>1 ) oputz("\n");
            isOk = 3;
          }
          break;
        }
#endif
        case SQLITE_TESTCTRL_SORTER_MMAP:
          if( nArg==3 ){
            int opt = (unsigned int)integerValue(azArg[2]);
            rc2 = sqlite3_test_control(testctrl, p->db, opt);
            isOk = 3;
          }
          break;
        case SQLITE_TESTCTRL_JSON_SELFCHECK:
          if( nArg==2 ){
            rc2 = -1;
            isOk = 1;
          }else{
            rc2 = booleanValue(azArg[2]);
            isOk = 3;
          }
          sqlite3_test_control(testctrl, &rc2);
          break;
        case SQLITE_TESTCTRL_FAULT_INSTALL: {
          int kk;
          int bShowHelp = nArg<=2;
          isOk = 3;
          for(kk=2; kk<nArg; kk++){
            const char *z = azArg[kk];
            if( z[0]=='-' && z[1]=='-' ) z++;
            if( cli_strcmp(z,"off")==0 ){
              sqlite3_test_control(testctrl, 0);
            }else if( cli_strcmp(z,"on")==0 ){
              faultsim_state.iCnt = faultsim_state.iInterval;
              if( faultsim_state.iErr==0 ) faultsim_state.iErr = 1;
              sqlite3_test_control(testctrl, faultsim_callback);
            }else if( cli_strcmp(z,"reset")==0 ){
              faultsim_state.iCnt = faultsim_state.iInterval;
            }else if( cli_strcmp(z,"status")==0 ){
              oputf("faultsim.iId:       %d\n", faultsim_state.iId);
              oputf("faultsim.iErr:      %d\n", faultsim_state.iErr);
              oputf("faultsim.iCnt:      %d\n", faultsim_state.iCnt);
              oputf("faultsim.iInterval: %d\n", faultsim_state.iInterval);
              oputf("faultsim.eVerbose:  %d\n", faultsim_state.eVerbose);
            }else if( cli_strcmp(z,"-v")==0 ){
              if( faultsim_state.eVerbose<2 ) faultsim_state.eVerbose++;
            }else if( cli_strcmp(z,"-q")==0 ){
              if( faultsim_state.eVerbose>0 ) faultsim_state.eVerbose--;
            }else if( cli_strcmp(z,"-id")==0 && kk+1<nArg ){
              faultsim_state.iId = atoi(azArg[++kk]);
            }else if( cli_strcmp(z,"-errcode")==0 && kk+1<nArg ){
              faultsim_state.iErr = atoi(azArg[++kk]);
            }else if( cli_strcmp(z,"-interval")==0 && kk+1<nArg ){
              faultsim_state.iInterval = atoi(azArg[++kk]);
            }else if( cli_strcmp(z,"-?")==0 || sqlite3_strglob("*help*",z)==0){
              bShowHelp = 1;
            }else{
              eputf("Unrecognized fault_install argument: \"%s\"\n",
                  azArg[kk]);
              rc = 1;
              bShowHelp = 1;
              break;
            }
          }
          if( bShowHelp ){
            oputz(
               "Usage: .testctrl fault_install ARGS\n"
               "Possible arguments:\n"
               "   off               Disable faultsim\n"
               "   on                Activate faultsim\n"
               "   reset             Reset the trigger counter\n"
               "   status            Show current status\n"
               "   -v                Increase verbosity\n"
               "   -q                Decrease verbosity\n"
               "   --errcode N       When triggered, return N as error code\n"
               "   --id ID           Trigger only for the ID specified\n"
               "   --interval N      Trigger only after every N-th call\n"
            );
          }
          break;
        }
      }
    }
    if( isOk==0 && iCtrl>=0 ){
      oputf("Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
      rc = 1;
    }else if( isOk==1 ){
      oputf("%d\n", rc2);
    }else if( isOk==2 ){
      oputf("0x%08x\n", rc2);
    }
  }else
#endif /* !defined(SQLITE_UNTESTABLE) */

  if( c=='t' && n>4 && cli_strncmp(azArg[0], "timeout", n)==0 ){
    open_db(p, 0);
    sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
  }else

  if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){
    if( nArg==2 ){
      enableTimer = booleanValue(azArg[1]);
      if( enableTimer && !HAS_TIMER ){
        eputz("Error: timer not available on this system.\n");
        enableTimer = 0;
      }
    }else{
      eputz("Usage: .timer on|off\n");
      rc = 1;
    }
  }else

#ifndef SQLITE_OMIT_TRACE
  if( c=='t' && cli_strncmp(azArg[0], "trace", n)==0 ){
    int mType = 0;
27164
27165
27166
27167
27168
27169
27170
27171
27172
27173
27174
27175
27176
27177
27178
        else if( optionMatch(z, "stmt") ){
          mType |= SQLITE_TRACE_STMT;
        }
        else if( optionMatch(z, "close") ){
          mType |= SQLITE_TRACE_CLOSE;
        }
        else {
          raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
          rc = 1;
          goto meta_command_exit;
        }
      }else{
        output_file_close(p->traceOut);
        p->traceOut = output_file_open(z, 0);
      }







|







29213
29214
29215
29216
29217
29218
29219
29220
29221
29222
29223
29224
29225
29226
29227
        else if( optionMatch(z, "stmt") ){
          mType |= SQLITE_TRACE_STMT;
        }
        else if( optionMatch(z, "close") ){
          mType |= SQLITE_TRACE_CLOSE;
        }
        else {
          eputf("Unknown option \"%s\" on \".trace\"\n", z);
          rc = 1;
          goto meta_command_exit;
        }
      }else{
        output_file_close(p->traceOut);
        p->traceOut = output_file_open(z, 0);
      }
27188
27189
27190
27191
27192
27193
27194
27195
27196
27197
27198
27199
27200
27201
27202

#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
  if( c=='u' && cli_strncmp(azArg[0], "unmodule", n)==0 ){
    int ii;
    int lenOpt;
    char *zOpt;
    if( nArg<2 ){
      raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    zOpt = azArg[1];
    if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
    lenOpt = (int)strlen(zOpt);







|







29237
29238
29239
29240
29241
29242
29243
29244
29245
29246
29247
29248
29249
29250
29251

#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
  if( c=='u' && cli_strncmp(azArg[0], "unmodule", n)==0 ){
    int ii;
    int lenOpt;
    char *zOpt;
    if( nArg<2 ){
      eputz("Usage: .unmodule [--allexcept] NAME ...\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    zOpt = azArg[1];
    if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
    lenOpt = (int)strlen(zOpt);
27210
27211
27212
27213
27214
27215
27216
27217
27218
27219
27220
27221
27222
27223
27224
27225
27226
27227
27228
27229
27230
27231
27232
27233
27234
27235
27236
27237
27238
27239
27240
27241
27242
27243
27244
27245
27246
27247
27248
27249
27250
27251
27252
27253
27254
27255
27256
27257
27258
27259
27260
27261
27262
27263
27264
27265
27266
27267
27268
27269
27270
27271
27272
27273
27274
27275
27276
27277
27278
27279
27280
27281
27282
27283
27284
27285
27286
27287
27288
27289
27290
27291
27292
27293
27294
27295
27296
27297
27298
27299
27300
27301
27302
27303
27304
27305
27306
27307
27308
27309
27310
27311
27312
27313
27314
27315
27316
27317
27318
27319
27320
27321
27322
27323
27324
27325
27326
27327
27328
27329
27330
27331
27332
27333
27334
27335
27336
27337
27338
27339
27340
27341
27342
    }
  }else
#endif

#if SQLITE_USER_AUTHENTICATION
  if( c=='u' && cli_strncmp(azArg[0], "user", n)==0 ){
    if( nArg<2 ){
      raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    if( cli_strcmp(azArg[1],"login")==0 ){
      if( nArg!=4 ){
        raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
                                     strlen30(azArg[3]));
      if( rc ){
        utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
        rc = 1;
      }
    }else if( cli_strcmp(azArg[1],"add")==0 ){
      if( nArg!=5 ){
        raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
                            booleanValue(azArg[4]));
      if( rc ){
        raw_printf(stderr, "User-Add failed: %d\n", rc);
        rc = 1;
      }
    }else if( cli_strcmp(azArg[1],"edit")==0 ){
      if( nArg!=5 ){
        raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
                              booleanValue(azArg[4]));
      if( rc ){
        raw_printf(stderr, "User-Edit failed: %d\n", rc);
        rc = 1;
      }
    }else if( cli_strcmp(azArg[1],"delete")==0 ){
      if( nArg!=3 ){
        raw_printf(stderr, "Usage: .user delete USER\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_delete(p->db, azArg[2]);
      if( rc ){
        raw_printf(stderr, "User-Delete failed: %d\n", rc);
        rc = 1;
      }
    }else{
      raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
      rc = 1;
      goto meta_command_exit;
    }
  }else
#endif /* SQLITE_USER_AUTHENTICATION */

  if( c=='v' && cli_strncmp(azArg[0], "version", n)==0 ){
    char *zPtrSz = sizeof(void*)==8 ? "64-bit" : "32-bit";
    utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
        sqlite3_libversion(), sqlite3_sourceid());
#if SQLITE_HAVE_ZLIB
    utf8_printf(p->out, "zlib version %s\n", zlibVersion());
#endif
#define CTIMEOPT_VAL_(opt) #opt
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
#if defined(__clang__) && defined(__clang_major__)
    utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
                    CTIMEOPT_VAL(__clang_minor__) "."
                    CTIMEOPT_VAL(__clang_patchlevel__) " (%s)\n", zPtrSz);
#elif defined(_MSC_VER)
    utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) " (%s)\n", zPtrSz);
#elif defined(__GNUC__) && defined(__VERSION__)
    utf8_printf(p->out, "gcc-" __VERSION__ " (%s)\n", zPtrSz);
#endif
  }else

  if( c=='v' && cli_strncmp(azArg[0], "vfsinfo", n)==0 ){
    const char *zDbName = nArg==2 ? azArg[1] : "main";
    sqlite3_vfs *pVfs = 0;
    if( p->db ){
      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
      if( pVfs ){
        utf8_printf(p->out, "vfs.zName      = \"%s\"\n", pVfs->zName);
        raw_printf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
        raw_printf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
        raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
      }
    }
  }else

  if( c=='v' && cli_strncmp(azArg[0], "vfslist", n)==0 ){
    sqlite3_vfs *pVfs;
    sqlite3_vfs *pCurrent = 0;
    if( p->db ){
      sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
    }
    for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
      utf8_printf(p->out, "vfs.zName      = \"%s\"%s\n", pVfs->zName,
           pVfs==pCurrent ? "  <--- CURRENT" : "");
      raw_printf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
      raw_printf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
      raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
      if( pVfs->pNext ){
        raw_printf(p->out, "-----------------------------------\n");
      }
    }
  }else

  if( c=='v' && cli_strncmp(azArg[0], "vfsname", n)==0 ){
    const char *zDbName = nArg==2 ? azArg[1] : "main";
    char *zVfsName = 0;
    if( p->db ){
      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
      if( zVfsName ){
        utf8_printf(p->out, "%s\n", zVfsName);
        sqlite3_free(zVfsName);
      }
    }
  }else

  if( c=='w' && cli_strncmp(azArg[0], "wheretrace", n)==0 ){
    unsigned int x = nArg>=2? (unsigned int)integerValue(azArg[1]) : 0xffffffff;







|






|






|




|






|




|






|




|





|



|








|
|

|




|
|
|

|

|









|
|
|
|











|
|
|
|
|

|










|







29259
29260
29261
29262
29263
29264
29265
29266
29267
29268
29269
29270
29271
29272
29273
29274
29275
29276
29277
29278
29279
29280
29281
29282
29283
29284
29285
29286
29287
29288
29289
29290
29291
29292
29293
29294
29295
29296
29297
29298
29299
29300
29301
29302
29303
29304
29305
29306
29307
29308
29309
29310
29311
29312
29313
29314
29315
29316
29317
29318
29319
29320
29321
29322
29323
29324
29325
29326
29327
29328
29329
29330
29331
29332
29333
29334
29335
29336
29337
29338
29339
29340
29341
29342
29343
29344
29345
29346
29347
29348
29349
29350
29351
29352
29353
29354
29355
29356
29357
29358
29359
29360
29361
29362
29363
29364
29365
29366
29367
29368
29369
29370
29371
29372
29373
29374
29375
29376
29377
29378
29379
29380
29381
29382
29383
29384
29385
29386
29387
29388
29389
29390
29391
    }
  }else
#endif

#if SQLITE_USER_AUTHENTICATION
  if( c=='u' && cli_strncmp(azArg[0], "user", n)==0 ){
    if( nArg<2 ){
      eputz("Usage: .user SUBCOMMAND ...\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    if( cli_strcmp(azArg[1],"login")==0 ){
      if( nArg!=4 ){
        eputz("Usage: .user login USER PASSWORD\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
                                     strlen30(azArg[3]));
      if( rc ){
        eputf("Authentication failed for user %s\n", azArg[2]);
        rc = 1;
      }
    }else if( cli_strcmp(azArg[1],"add")==0 ){
      if( nArg!=5 ){
        eputz("Usage: .user add USER PASSWORD ISADMIN\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
                            booleanValue(azArg[4]));
      if( rc ){
        eputf("User-Add failed: %d\n", rc);
        rc = 1;
      }
    }else if( cli_strcmp(azArg[1],"edit")==0 ){
      if( nArg!=5 ){
        eputz("Usage: .user edit USER PASSWORD ISADMIN\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
                              booleanValue(azArg[4]));
      if( rc ){
        eputf("User-Edit failed: %d\n", rc);
        rc = 1;
      }
    }else if( cli_strcmp(azArg[1],"delete")==0 ){
      if( nArg!=3 ){
        eputz("Usage: .user delete USER\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_delete(p->db, azArg[2]);
      if( rc ){
        eputf("User-Delete failed: %d\n", rc);
        rc = 1;
      }
    }else{
      eputz("Usage: .user login|add|edit|delete ...\n");
      rc = 1;
      goto meta_command_exit;
    }
  }else
#endif /* SQLITE_USER_AUTHENTICATION */

  if( c=='v' && cli_strncmp(azArg[0], "version", n)==0 ){
    char *zPtrSz = sizeof(void*)==8 ? "64-bit" : "32-bit";
    oputf("SQLite %s %s\n" /*extra-version-info*/,
          sqlite3_libversion(), sqlite3_sourceid());
#if SQLITE_HAVE_ZLIB
    oputf("zlib version %s\n", zlibVersion());
#endif
#define CTIMEOPT_VAL_(opt) #opt
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
#if defined(__clang__) && defined(__clang_major__)
    oputf("clang-" CTIMEOPT_VAL(__clang_major__) "."
          CTIMEOPT_VAL(__clang_minor__) "."
          CTIMEOPT_VAL(__clang_patchlevel__) " (%s)\n", zPtrSz);
#elif defined(_MSC_VER)
    oputf("msvc-" CTIMEOPT_VAL(_MSC_VER) " (%s)\n", zPtrSz);
#elif defined(__GNUC__) && defined(__VERSION__)
    oputf("gcc-" __VERSION__ " (%s)\n", zPtrSz);
#endif
  }else

  if( c=='v' && cli_strncmp(azArg[0], "vfsinfo", n)==0 ){
    const char *zDbName = nArg==2 ? azArg[1] : "main";
    sqlite3_vfs *pVfs = 0;
    if( p->db ){
      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
      if( pVfs ){
        oputf("vfs.zName      = \"%s\"\n", pVfs->zName);
        oputf("vfs.iVersion   = %d\n", pVfs->iVersion);
        oputf("vfs.szOsFile   = %d\n", pVfs->szOsFile);
        oputf("vfs.mxPathname = %d\n", pVfs->mxPathname);
      }
    }
  }else

  if( c=='v' && cli_strncmp(azArg[0], "vfslist", n)==0 ){
    sqlite3_vfs *pVfs;
    sqlite3_vfs *pCurrent = 0;
    if( p->db ){
      sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
    }
    for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
      oputf("vfs.zName      = \"%s\"%s\n", pVfs->zName,
            pVfs==pCurrent ? "  <--- CURRENT" : "");
      oputf("vfs.iVersion   = %d\n", pVfs->iVersion);
      oputf("vfs.szOsFile   = %d\n", pVfs->szOsFile);
      oputf("vfs.mxPathname = %d\n", pVfs->mxPathname);
      if( pVfs->pNext ){
        oputz("-----------------------------------\n");
      }
    }
  }else

  if( c=='v' && cli_strncmp(azArg[0], "vfsname", n)==0 ){
    const char *zDbName = nArg==2 ? azArg[1] : "main";
    char *zVfsName = 0;
    if( p->db ){
      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
      if( zVfsName ){
        oputf("%s\n", zVfsName);
        sqlite3_free(zVfsName);
      }
    }
  }else

  if( c=='w' && cli_strncmp(azArg[0], "wheretrace", n)==0 ){
    unsigned int x = nArg>=2? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
27352
27353
27354
27355
27356
27357
27358
27359
27360
27361
27362
27363
27364
27365
27366
27367
    if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
    for(j=1; j<nArg; j++){
      p->colWidth[j-1] = (int)integerValue(azArg[j]);
    }
  }else

  {
    utf8_printf(stderr, "Error: unknown command or invalid arguments: "
      " \"%s\". Enter \".help\" for help\n", azArg[0]);
    rc = 1;
  }

meta_command_exit:
  if( p->outCount ){
    p->outCount--;
    if( p->outCount==0 ) output_reset(p);







|
|







29401
29402
29403
29404
29405
29406
29407
29408
29409
29410
29411
29412
29413
29414
29415
29416
    if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
    for(j=1; j<nArg; j++){
      p->colWidth[j-1] = (int)integerValue(azArg[j]);
    }
  }else

  {
    eputf("Error: unknown command or invalid arguments: "
          " \"%s\". Enter \".help\" for help\n", azArg[0]);
    rc = 1;
  }

meta_command_exit:
  if( p->outCount ){
    p->outCount--;
    if( p->outCount==0 ) output_reset(p);
27506
27507
27508
27509
27510
27511
27512


















































































27513
27514
27515
27516
27517
27518
27519
  if( zSql==0 ) return 1;
  zSql[nSql] = ';';
  zSql[nSql+1] = 0;
  rc = sqlite3_complete(zSql);
  zSql[nSql] = 0;
  return rc;
}



















































































/*
** Run a single line of SQL.  Return the number of errors.
*/
static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
  int rc;
  char *zErrMsg = 0;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







29555
29556
29557
29558
29559
29560
29561
29562
29563
29564
29565
29566
29567
29568
29569
29570
29571
29572
29573
29574
29575
29576
29577
29578
29579
29580
29581
29582
29583
29584
29585
29586
29587
29588
29589
29590
29591
29592
29593
29594
29595
29596
29597
29598
29599
29600
29601
29602
29603
29604
29605
29606
29607
29608
29609
29610
29611
29612
29613
29614
29615
29616
29617
29618
29619
29620
29621
29622
29623
29624
29625
29626
29627
29628
29629
29630
29631
29632
29633
29634
29635
29636
29637
29638
29639
29640
29641
29642
29643
29644
29645
29646
29647
29648
29649
29650
  if( zSql==0 ) return 1;
  zSql[nSql] = ';';
  zSql[nSql+1] = 0;
  rc = sqlite3_complete(zSql);
  zSql[nSql] = 0;
  return rc;
}

/*
** This function is called after processing each line of SQL in the
** runOneSqlLine() function. Its purpose is to detect scenarios where
** defensive mode should be automatically turned off. Specifically, when
**
**   1. The first line of input is "PRAGMA foreign_keys=OFF;",
**   2. The second line of input is "BEGIN TRANSACTION;",
**   3. The database is empty, and
**   4. The shell is not running in --safe mode.
** 
** The implementation uses the ShellState.eRestoreState to maintain state:
**
**    0: Have not seen any SQL.
**    1: Have seen "PRAGMA foreign_keys=OFF;".
**    2-6: Currently running .dump transaction. If the "2" bit is set,
**         disable DEFENSIVE when done. If "4" is set, disable DQS_DDL.
**    7: Nothing left to do. This function becomes a no-op.
*/
static int doAutoDetectRestore(ShellState *p, const char *zSql){
  int rc = SQLITE_OK;

  if( p->eRestoreState<7 ){
    switch( p->eRestoreState ){
      case 0: {
        const char *zExpect = "PRAGMA foreign_keys=OFF;";
        assert( strlen(zExpect)==24 );
        if( p->bSafeMode==0 && memcmp(zSql, zExpect, 25)==0 ){
          p->eRestoreState = 1;
        }else{
          p->eRestoreState = 7;
        }
        break;
      };
  
      case 1: {
        int bIsDump = 0;
        const char *zExpect = "BEGIN TRANSACTION;";
        assert( strlen(zExpect)==18 );
        if( memcmp(zSql, zExpect, 19)==0 ){
          /* Now check if the database is empty. */
          const char *zQuery = "SELECT 1 FROM sqlite_schema LIMIT 1";
          sqlite3_stmt *pStmt = 0;
  
          bIsDump = 1;
          shellPrepare(p->db, &rc, zQuery, &pStmt);
          if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
            bIsDump = 0;
          }
          shellFinalize(&rc, pStmt);
        }
        if( bIsDump && rc==SQLITE_OK ){
          int bDefense = 0;
          int bDqsDdl = 0;
          sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &bDefense);
          sqlite3_db_config(p->db, SQLITE_DBCONFIG_DQS_DDL, -1, &bDqsDdl);
          sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
          sqlite3_db_config(p->db, SQLITE_DBCONFIG_DQS_DDL, 1, 0);
          p->eRestoreState = (bDefense ? 2 : 0) + (bDqsDdl ? 4 : 0);
        }else{
          p->eRestoreState = 7;
        }
        break;
      }
  
      default: {
        if( sqlite3_get_autocommit(p->db) ){
          if( (p->eRestoreState & 2) ){
            sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 1, 0);
          }
          if( (p->eRestoreState & 4) ){
            sqlite3_db_config(p->db, SQLITE_DBCONFIG_DQS_DDL, 0, 0);
          }
          p->eRestoreState = 7;
        }
        break;
      }
    }
  }

  return rc;
}

/*
** Run a single line of SQL.  Return the number of errors.
*/
static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
  int rc;
  char *zErrMsg = 0;
27543
27544
27545
27546
27547
27548
27549
27550
27551
27552
27553
27554
27555
27556
27557
27558
27559
27560


27561
27562
27563
27564
27565
27566
27567
27568
27569
27570
27571
27572
    }
    if( in!=0 || !stdin_is_interactive ){
      sqlite3_snprintf(sizeof(zPrefix), zPrefix,
                       "%s near line %d:", zErrorType, startline);
    }else{
      sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType);
    }
    utf8_printf(stderr, "%s %s\n", zPrefix, zErrorTail);
    sqlite3_free(zErrMsg);
    zErrMsg = 0;
    return 1;
  }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
    char zLineBuf[2000];
    sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
            "changes: %lld   total_changes: %lld",
            sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
    raw_printf(p->out, "%s\n", zLineBuf);
  }


  return 0;
}

static void echo_group_input(ShellState *p, const char *zDo){
  if( ShellHasFlag(p, SHFLG_Echo) ) utf8_printf(p->out, "%s\n", zDo);
}

#ifdef SQLITE_SHELL_FIDDLE
/*
** Alternate one_input_line() impl for wasm mode. This is not in the primary
** impl because we need the global shellState and cannot access it from that
** function without moving lots of code around (creating a larger/messier diff).







|








|

>
>




|







29674
29675
29676
29677
29678
29679
29680
29681
29682
29683
29684
29685
29686
29687
29688
29689
29690
29691
29692
29693
29694
29695
29696
29697
29698
29699
29700
29701
29702
29703
29704
29705
    }
    if( in!=0 || !stdin_is_interactive ){
      sqlite3_snprintf(sizeof(zPrefix), zPrefix,
                       "%s near line %d:", zErrorType, startline);
    }else{
      sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType);
    }
    eputf("%s %s\n", zPrefix, zErrorTail);
    sqlite3_free(zErrMsg);
    zErrMsg = 0;
    return 1;
  }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
    char zLineBuf[2000];
    sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
            "changes: %lld   total_changes: %lld",
            sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
    oputf("%s\n", zLineBuf);
  }

  if( doAutoDetectRestore(p, zSql) ) return 1;
  return 0;
}

static void echo_group_input(ShellState *p, const char *zDo){
  if( ShellHasFlag(p, SHFLG_Echo) ) oputf("%s\n", zDo);
}

#ifdef SQLITE_SHELL_FIDDLE
/*
** Alternate one_input_line() impl for wasm mode. This is not in the primary
** impl because we need the global shellState and cannot access it from that
** function without moving lots of code around (creating a larger/messier diff).
27616
27617
27618
27619
27620
27621
27622
27623
27624
27625
27626
27627
27628
27629
27630
27631
27632
27633
27634
27635
27636
27637
27638
27639
27640
27641
27642
  int rc;                   /* Error code */
  int errCnt = 0;           /* Number of errors seen */
  i64 startline = 0;        /* Line number for start of current input */
  QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */

  if( p->inputNesting==MAX_INPUT_NESTING ){
    /* This will be more informative in a later version. */
    utf8_printf(stderr,"Input nesting limit (%d) reached at line %d."
                " Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
    return 1;
  }
  ++p->inputNesting;
  p->lineno = 0;
  CONTINUE_PROMPT_RESET;
  while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
    fflush(p->out);
    zLine = one_input_line(p->in, zLine, nSql>0);
    if( zLine==0 ){
      /* End of input */
      if( p->in==0 && stdin_is_interactive ) printf("\n");
      break;
    }
    if( seenInterrupt ){
      if( p->in!=0 ) break;
      seenInterrupt = 0;
    }
    p->lineno++;







|
|










|







29749
29750
29751
29752
29753
29754
29755
29756
29757
29758
29759
29760
29761
29762
29763
29764
29765
29766
29767
29768
29769
29770
29771
29772
29773
29774
29775
  int rc;                   /* Error code */
  int errCnt = 0;           /* Number of errors seen */
  i64 startline = 0;        /* Line number for start of current input */
  QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */

  if( p->inputNesting==MAX_INPUT_NESTING ){
    /* This will be more informative in a later version. */
    eputf("Input nesting limit (%d) reached at line %d."
          " Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
    return 1;
  }
  ++p->inputNesting;
  p->lineno = 0;
  CONTINUE_PROMPT_RESET;
  while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
    fflush(p->out);
    zLine = one_input_line(p->in, zLine, nSql>0);
    if( zLine==0 ){
      /* End of input */
      if( p->in==0 && stdin_is_interactive ) oputz("\n");
      break;
    }
    if( seenInterrupt ){
      if( p->in!=0 ) break;
      seenInterrupt = 0;
    }
    p->lineno++;
27838
27839
27840
27841
27842
27843
27844
27845
27846
27847
27848
27849
27850
27851
27852
27853
27854
27855
27856
27857
27858
27859
27860
27861
27862
27863
27864
27865
27866
27867
27868

  if( sqliterc == NULL ){
    sqliterc = find_xdg_config();
  }
  if( sqliterc == NULL ){
    home_dir = find_home_dir(0);
    if( home_dir==0 ){
      raw_printf(stderr, "-- warning: cannot find home directory;"
                      " cannot read ~/.sqliterc\n");
      return;
    }
    zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
    shell_check_oom(zBuf);
    sqliterc = zBuf;
  }
  p->in = fopen(sqliterc,"rb");
  if( p->in ){
    if( stdin_is_interactive ){
      utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
    }
    if( process_input(p) && bail_on_error ) exit(1);
    fclose(p->in);
  }else if( sqliterc_override!=0 ){
    utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
    if( bail_on_error ) exit(1);
  }
  p->in = inSaved;
  p->lineno = savedLineno;
  sqlite3_free(zBuf);
}








|
|









|




|







29971
29972
29973
29974
29975
29976
29977
29978
29979
29980
29981
29982
29983
29984
29985
29986
29987
29988
29989
29990
29991
29992
29993
29994
29995
29996
29997
29998
29999
30000
30001

  if( sqliterc == NULL ){
    sqliterc = find_xdg_config();
  }
  if( sqliterc == NULL ){
    home_dir = find_home_dir(0);
    if( home_dir==0 ){
      eputz("-- warning: cannot find home directory;"
            " cannot read ~/.sqliterc\n");
      return;
    }
    zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
    shell_check_oom(zBuf);
    sqliterc = zBuf;
  }
  p->in = fopen(sqliterc,"rb");
  if( p->in ){
    if( stdin_is_interactive ){
      eputf("-- Loading resources from %s\n", sqliterc);
    }
    if( process_input(p) && bail_on_error ) exit(1);
    fclose(p->in);
  }else if( sqliterc_override!=0 ){
    eputf("cannot open: \"%s\"\n", sqliterc);
    if( bail_on_error ) exit(1);
  }
  p->in = inSaved;
  p->lineno = savedLineno;
  sqlite3_free(zBuf);
}

27904
27905
27906
27907
27908
27909
27910
27911
27912
27913
27914
27915

27916
27917
27918
27919
27920
27921
27922
27923
27924
27925
27926
27927
27928
27929
27930
27931
27932
27933
27934
27935
27936
27937
27938
27939
27940
27941
27942
27943
27944
27945
27946
27947
27948
27949
27950
27951
27952
27953
27954
27955
27956
27957
27958
27959
27960
27961
27962
27963
27964
27965
27966
27967
27968
27969
#endif
  "   -memtrace            trace all memory allocations and deallocations\n"
  "   -mmap N              default mmap size set to N\n"
#ifdef SQLITE_ENABLE_MULTIPLEX
  "   -multiplex           enable the multiplexor VFS\n"
#endif
  "   -newline SEP         set output row separator. Default: '\\n'\n"
#if SHELL_WIN_UTF8_OPT
  "   -no-utf8             do not try to set up UTF-8 output (for legacy)\n"
#endif
  "   -nofollow            refuse to open symbolic links to database files\n"
  "   -nonce STRING        set the safe-mode escape nonce\n"

  "   -nullvalue TEXT      set text string for NULL values. Default ''\n"
  "   -pagecache SIZE N    use N slots of SZ bytes each for page cache memory\n"
  "   -pcachetrace         trace all page cache operations\n"
  "   -quote               set output mode to 'quote'\n"
  "   -readonly            open the database read-only\n"
  "   -safe                enable safe-mode\n"
  "   -separator SEP       set output column separator. Default: '|'\n"
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
  "   -sorterref SIZE      sorter references threshold size\n"
#endif
  "   -stats               print memory stats before each finalize\n"
  "   -table               set output mode to 'table'\n"
  "   -tabs                set output mode to 'tabs'\n"
  "   -unsafe-testing      allow unsafe commands and modes for testing\n"
#if SHELL_WIN_UTF8_OPT && 0 /* Option is accepted, but is now the default. */
  "   -utf8                setup interactive console code page for UTF-8\n"
#endif
  "   -version             show SQLite version\n"
  "   -vfs NAME            use NAME as the default VFS\n"
#ifdef SQLITE_ENABLE_VFSTRACE
  "   -vfstrace            enable tracing of all VFS calls\n"
#endif
#ifdef SQLITE_HAVE_ZLIB
  "   -zip                 open the file as a ZIP Archive\n"
#endif
;
static void usage(int showDetail){
  utf8_printf(stderr,
      "Usage: %s [OPTIONS] [FILENAME [SQL]]\n"
      "FILENAME is the name of an SQLite database. A new database is created\n"
      "if the file does not previously exist. Defaults to :memory:.\n", Argv0);
  if( showDetail ){
    utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
  }else{
    raw_printf(stderr, "Use the -help option for additional information\n");
  }
  exit(1);
}

/*
** Internal check:  Verify that the SQLite is uninitialized.  Print a
** error message if it is initialized.
*/
static void verify_uninitialized(void){
  if( sqlite3_config(-1)==SQLITE_MISUSE ){
    utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
                        " initialization.\n");
  }
}

/*
** Initialize the state information in data
*/
static void main_init(ShellState *data) {







<
<
<


>














<
<
<










<
|
|
|

|

|

|








|
|







30037
30038
30039
30040
30041
30042
30043



30044
30045
30046
30047
30048
30049
30050
30051
30052
30053
30054
30055
30056
30057
30058
30059
30060



30061
30062
30063
30064
30065
30066
30067
30068
30069
30070

30071
30072
30073
30074
30075
30076
30077
30078
30079
30080
30081
30082
30083
30084
30085
30086
30087
30088
30089
30090
30091
30092
30093
30094
30095
30096
#endif
  "   -memtrace            trace all memory allocations and deallocations\n"
  "   -mmap N              default mmap size set to N\n"
#ifdef SQLITE_ENABLE_MULTIPLEX
  "   -multiplex           enable the multiplexor VFS\n"
#endif
  "   -newline SEP         set output row separator. Default: '\\n'\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"
  "   -nullvalue TEXT      set text string for NULL values. Default ''\n"
  "   -pagecache SIZE N    use N slots of SZ bytes each for page cache memory\n"
  "   -pcachetrace         trace all page cache operations\n"
  "   -quote               set output mode to 'quote'\n"
  "   -readonly            open the database read-only\n"
  "   -safe                enable safe-mode\n"
  "   -separator SEP       set output column separator. Default: '|'\n"
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
  "   -sorterref SIZE      sorter references threshold size\n"
#endif
  "   -stats               print memory stats before each finalize\n"
  "   -table               set output mode to 'table'\n"
  "   -tabs                set output mode to 'tabs'\n"
  "   -unsafe-testing      allow unsafe commands and modes for testing\n"



  "   -version             show SQLite version\n"
  "   -vfs NAME            use NAME as the default VFS\n"
#ifdef SQLITE_ENABLE_VFSTRACE
  "   -vfstrace            enable tracing of all VFS calls\n"
#endif
#ifdef SQLITE_HAVE_ZLIB
  "   -zip                 open the file as a ZIP Archive\n"
#endif
;
static void usage(int showDetail){

  eputf("Usage: %s [OPTIONS] [FILENAME [SQL]]\n"
       "FILENAME is the name of an SQLite database. A new database is created\n"
       "if the file does not previously exist. Defaults to :memory:.\n", Argv0);
  if( showDetail ){
    eputf("OPTIONS include:\n%s", zOptions);
  }else{
    eputz("Use the -help option for additional information\n");
  }
  exit(0);
}

/*
** Internal check:  Verify that the SQLite is uninitialized.  Print a
** error message if it is initialized.
*/
static void verify_uninitialized(void){
  if( sqlite3_config(-1)==SQLITE_MISUSE ){
    sputz(stdout, "WARNING: attempt to configure SQLite after"
          " initialization.\n");
  }
}

/*
** Initialize the state information in data
*/
static void main_init(ShellState *data) {
27984
27985
27986
27987
27988
27989
27990
27991
27992
27993
27994
27995
27996
27997
27998
27999
28000
28001
28002
28003
28004
28005
28006
28007
28008
28009
28010
28011
28012
28013
28014
28015
28016
28017
28018
28019
28020
28021
28022
28023
28024
28025
28026
28027
28028
28029
28030
28031
28032
28033
  sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
  sqlite3_snprintf(sizeof(continuePrompt), continuePrompt,"   ...> ");
}

/*
** Output text to the console in a font that attracts extra attention.
*/
#ifdef _WIN32
static void printBold(const char *zText){
#if !SQLITE_OS_WINRT
  HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
  CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
  GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
  SetConsoleTextAttribute(out,
         FOREGROUND_RED|FOREGROUND_INTENSITY
  );
#endif
  printf("%s", zText);
#if !SQLITE_OS_WINRT
  SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
#endif
}
#else
static void printBold(const char *zText){
  printf("\033[1m%s\033[0m", zText);
}
#endif

/*
** Get the argument to an --option.  Throw an error and die if no argument
** is available.
*/
static char *cmdline_option_value(int argc, char **argv, int i){
  if( i==argc ){
    utf8_printf(stderr, "%s: Error: missing argument to %s\n",
            argv[0], argv[argc-1]);
    exit(1);
  }
  return argv[i];
}

static void sayAbnormalExit(void){
  if( seenInterrupt ) fprintf(stderr, "Program interrupted.\n");
}

#ifndef SQLITE_SHELL_IS_UTF8
#  if (defined(_WIN32) || defined(WIN32)) \
   && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
#    define SQLITE_SHELL_IS_UTF8          (0)
#  else







|









|






|









|
<






|







30111
30112
30113
30114
30115
30116
30117
30118
30119
30120
30121
30122
30123
30124
30125
30126
30127
30128
30129
30130
30131
30132
30133
30134
30135
30136
30137
30138
30139
30140
30141
30142
30143
30144
30145

30146
30147
30148
30149
30150
30151
30152
30153
30154
30155
30156
30157
30158
30159
  sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
  sqlite3_snprintf(sizeof(continuePrompt), continuePrompt,"   ...> ");
}

/*
** Output text to the console in a font that attracts extra attention.
*/
#if defined(_WIN32) || defined(WIN32)
static void printBold(const char *zText){
#if !SQLITE_OS_WINRT
  HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
  CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
  GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
  SetConsoleTextAttribute(out,
         FOREGROUND_RED|FOREGROUND_INTENSITY
  );
#endif
  sputz(stdout, zText);
#if !SQLITE_OS_WINRT
  SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
#endif
}
#else
static void printBold(const char *zText){
  sputf(stdout, "\033[1m%s\033[0m", zText);
}
#endif

/*
** Get the argument to an --option.  Throw an error and die if no argument
** is available.
*/
static char *cmdline_option_value(int argc, char **argv, int i){
  if( i==argc ){
    eputf("%s: Error: missing argument to %s\n", argv[0], argv[argc-1]);

    exit(1);
  }
  return argv[i];
}

static void sayAbnormalExit(void){
  if( seenInterrupt ) eputz("Program interrupted.\n");
}

#ifndef SQLITE_SHELL_IS_UTF8
#  if (defined(_WIN32) || defined(WIN32)) \
   && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
#    define SQLITE_SHELL_IS_UTF8          (0)
#  else
28049
28050
28051
28052
28053
28054
28055

28056
28057
28058
28059
28060
28061
28062
  sqlite3_int64 mem_main_enter = 0;
#endif
  char *zErrMsg = 0;
#ifdef SQLITE_SHELL_FIDDLE
#  define data shellState
#else
  ShellState data;

#endif
  const char *zInitFile = 0;
  int i;
  int rc = 0;
  int warnInmemoryDb = 0;
  int readStdin = 1;
  int nCmd = 0;







>







30175
30176
30177
30178
30179
30180
30181
30182
30183
30184
30185
30186
30187
30188
30189
  sqlite3_int64 mem_main_enter = 0;
#endif
  char *zErrMsg = 0;
#ifdef SQLITE_SHELL_FIDDLE
#  define data shellState
#else
  ShellState data;
  StreamsAreConsole consStreams = SAC_NoConsole;
#endif
  const char *zInitFile = 0;
  int i;
  int rc = 0;
  int warnInmemoryDb = 0;
  int readStdin = 1;
  int nCmd = 0;
28070
28071
28072
28073
28074
28075
28076

28077
28078
28079
28080
28081
28082
28083
28084
28085
28086
28087
28088
28089
28090
28091
28092
28093
28094
28095
28096
28097
28098
28099
28100
28101
28102
28103
28104
28105
28106
28107
28108
28109
28110
28111
28112
28113
28114
28115
28116
28117
28118
28119
28120
28121
28122
28123
28124
28125
28126
28127
  setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */

#ifdef SQLITE_SHELL_FIDDLE
  stdin_is_interactive = 0;
  stdout_is_console = 1;
  data.wasm.zDefaultDbName = "/fiddle.sqlite3";
#else

  stdin_is_interactive = isatty(0);
  stdout_is_console = isatty(1);
#endif
#if SHELL_WIN_UTF8_OPT
  probe_console(); /* Check for console I/O and UTF-8 capability. */
  if( !mbcs_opted ) atexit(console_restore);
#endif
  atexit(sayAbnormalExit);
#ifdef SQLITE_DEBUG
  mem_main_enter = sqlite3_memory_used();
#endif
#if !defined(_WIN32_WCE)
  if( getenv("SQLITE_DEBUG_BREAK") ){
    if( isatty(0) && isatty(2) ){
      fprintf(stderr,
          "attach debugger to process %d and press any key to continue.\n",
          GETPID());
      fgetc(stdin);
    }else{
#if defined(_WIN32) || defined(WIN32)
#if SQLITE_OS_WINRT
      __debugbreak();
#else
      DebugBreak();
#endif
#elif defined(SIGTRAP)
      raise(SIGTRAP);
#endif
    }
  }
#endif
  /* Register a valid signal handler early, before much else is done. */
#ifdef SIGINT
  signal(SIGINT, interrupt_handler);
#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
  if( !SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE) ){
    fprintf(stderr, "No ^C handler.\n");
  }
#endif

#if USE_SYSTEM_SQLITE+0!=1
  if( cli_strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
    utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
            sqlite3_sourceid(), SQLITE_SOURCE_ID);
    exit(1);
  }
#endif
  main_init(&data);

  /* On Windows, we must translate command-line arguments into UTF-8.
  ** The SQLite memory allocator subsystem has to be enabled in order to







>
|
|
<
<
<
|








<
|
|



















|





|
|







30197
30198
30199
30200
30201
30202
30203
30204
30205
30206



30207
30208
30209
30210
30211
30212
30213
30214
30215

30216
30217
30218
30219
30220
30221
30222
30223
30224
30225
30226
30227
30228
30229
30230
30231
30232
30233
30234
30235
30236
30237
30238
30239
30240
30241
30242
30243
30244
30245
30246
30247
30248
30249
30250
30251
  setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */

#ifdef SQLITE_SHELL_FIDDLE
  stdin_is_interactive = 0;
  stdout_is_console = 1;
  data.wasm.zDefaultDbName = "/fiddle.sqlite3";
#else
  consStreams = consoleClassifySetup(stdin, stdout, stderr);
  stdin_is_interactive = (consStreams & SAC_InConsole)!=0;
  stdout_is_console = (consStreams & SAC_OutConsole)!=0;



  atexit(consoleRestore);
#endif
  atexit(sayAbnormalExit);
#ifdef SQLITE_DEBUG
  mem_main_enter = sqlite3_memory_used();
#endif
#if !defined(_WIN32_WCE)
  if( getenv("SQLITE_DEBUG_BREAK") ){
    if( isatty(0) && isatty(2) ){

      eputf("attach debugger to process %d and press any key to continue.\n",
            GETPID());
      fgetc(stdin);
    }else{
#if defined(_WIN32) || defined(WIN32)
#if SQLITE_OS_WINRT
      __debugbreak();
#else
      DebugBreak();
#endif
#elif defined(SIGTRAP)
      raise(SIGTRAP);
#endif
    }
  }
#endif
  /* Register a valid signal handler early, before much else is done. */
#ifdef SIGINT
  signal(SIGINT, interrupt_handler);
#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
  if( !SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE) ){
    eputz("No ^C handler.\n");
  }
#endif

#if USE_SYSTEM_SQLITE+0!=1
  if( cli_strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
    eputf("SQLite header and source version mismatch\n%s\n%s\n",
          sqlite3_sourceid(), SQLITE_SOURCE_ID);
    exit(1);
  }
#endif
  main_init(&data);

  /* On Windows, we must translate command-line arguments into UTF-8.
  ** The SQLite memory allocator subsystem has to be enabled in order to
28198
28199
28200
28201
28202
28203
28204
28205
28206
28207
28208
28209
28210
28211
28212
28213
28214
28215
28216
28217
28218
28219
28220
28221

28222
28223


28224
28225
28226
28227
28228
28229
28230
     || cli_strcmp(z,"-newline")==0
     || cli_strcmp(z,"-cmd")==0
    ){
      (void)cmdline_option_value(argc, argv, ++i);
    }else if( cli_strcmp(z,"-init")==0 ){
      zInitFile = cmdline_option_value(argc, argv, ++i);
    }else if( cli_strcmp(z,"-interactive")==0 ){
      /* Need to check for interactive override here to so that it can
      ** affect console setup (for Windows only) and testing thereof.
      */
      stdin_is_interactive = 1;
    }else if( cli_strcmp(z,"-batch")==0 ){
      /* Need to check for batch mode here to so we can avoid printing
      ** informational messages (like from process_sqliterc) before
      ** we do the actual processing of arguments later in a second pass.
      */
      stdin_is_interactive = 0;
    }else if( cli_strcmp(z,"-utf8")==0 ){
#if SHELL_WIN_UTF8_OPT
      /* Option accepted, but is ignored except for this diagnostic. */
      if( mbcs_opted ) fprintf(stderr, "Cannot do UTF-8 at this console.\n");
#endif /* SHELL_WIN_UTF8_OPT */
    }else if( cli_strcmp(z,"-no-utf8")==0 ){
#if SHELL_WIN_UTF8_OPT

      mbcs_opted = 1;
#endif /* SHELL_WIN_UTF8_OPT */


    }else if( cli_strcmp(z,"-heap")==0 ){
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
      const char *zSize;
      sqlite3_int64 szHeap;

      zSize = cmdline_option_value(argc, argv, ++i);
      szHeap = integerValue(zSize);







<
<
<
<







<
<
<
<

<
>
|
<
>
>







30322
30323
30324
30325
30326
30327
30328




30329
30330
30331
30332
30333
30334
30335




30336

30337
30338

30339
30340
30341
30342
30343
30344
30345
30346
30347
     || cli_strcmp(z,"-newline")==0
     || cli_strcmp(z,"-cmd")==0
    ){
      (void)cmdline_option_value(argc, argv, ++i);
    }else if( cli_strcmp(z,"-init")==0 ){
      zInitFile = cmdline_option_value(argc, argv, ++i);
    }else if( cli_strcmp(z,"-interactive")==0 ){




    }else if( cli_strcmp(z,"-batch")==0 ){
      /* Need to check for batch mode here to so we can avoid printing
      ** informational messages (like from process_sqliterc) before
      ** we do the actual processing of arguments later in a second pass.
      */
      stdin_is_interactive = 0;
    }else if( cli_strcmp(z,"-utf8")==0 ){




    }else if( cli_strcmp(z,"-no-utf8")==0 ){

    }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
      int val = 0;

      sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW, &val);
      assert( val==0 );
    }else if( cli_strcmp(z,"-heap")==0 ){
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
      const char *zSize;
      sqlite3_int64 szHeap;

      zSize = cmdline_option_value(argc, argv, ++i);
      szHeap = integerValue(zSize);
28351
28352
28353
28354
28355
28356
28357
28358
28359
28360
28361
28362
28363
28364
28365
28366
28367
28368
28369
28370
28371
28372
28373
28374
28375
28376
28377
28378
28379
28380
28381
28382
28383
28384
#endif

  if( zVfs ){
    sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
    if( pVfs ){
      sqlite3_vfs_register(pVfs, 1);
    }else{
      utf8_printf(stderr, "no such VFS: \"%s\"\n", zVfs);
      exit(1);
    }
  }
#if SHELL_WIN_UTF8_OPT
  /* Get indicated Windows console setup done before running invocation commands. */
  if( in_console || out_console ){
    console_prepare_utf8();
  }
  if( !in_console ){
    setBinaryMode(stdin, 0);
  }
#endif

  if( data.pAuxDb->zDbFilename==0 ){
#ifndef SQLITE_OMIT_MEMORYDB
    data.pAuxDb->zDbFilename = ":memory:";
    warnInmemoryDb = argc==1;
#else
    utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
    return 1;
#endif
  }
  data.out = stdout;
#ifndef SQLITE_SHELL_FIDDLE
  sqlite3_appendvfs_init(0,0,0);
#endif







|



<
<
<
<
<
<
<
<
<






|







30468
30469
30470
30471
30472
30473
30474
30475
30476
30477
30478









30479
30480
30481
30482
30483
30484
30485
30486
30487
30488
30489
30490
30491
30492
#endif

  if( zVfs ){
    sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
    if( pVfs ){
      sqlite3_vfs_register(pVfs, 1);
    }else{
      eputf("no such VFS: \"%s\"\n", zVfs);
      exit(1);
    }
  }










  if( data.pAuxDb->zDbFilename==0 ){
#ifndef SQLITE_OMIT_MEMORYDB
    data.pAuxDb->zDbFilename = ":memory:";
    warnInmemoryDb = argc==1;
#else
    eputf("%s: Error: no database filename specified\n", Argv0);
    return 1;
#endif
  }
  data.out = stdout;
#ifndef SQLITE_SHELL_FIDDLE
  sqlite3_appendvfs_init(0,0,0);
#endif
28487
28488
28489
28490
28491
28492
28493
28494
28495
28496
28497
28498



28499
28500
28501
28502
28503


28504
28505
28506
28507
28508
28509
28510
      ** prior to sending the SQL into SQLite.  Useful for injecting
      ** crazy bytes in the middle of SQL statements for testing and debugging.
      */
      ShellSetFlag(&data, SHFLG_Backslash);
    }else if( cli_strcmp(z,"-bail")==0 ){
      /* No-op.  The bail_on_error flag should already be set. */
    }else if( cli_strcmp(z,"-version")==0 ){
      printf("%s %s (%d-bit)\n", sqlite3_libversion(), sqlite3_sourceid(),
             8*(int)sizeof(char*));
      return 0;
    }else if( cli_strcmp(z,"-interactive")==0 ){
      /* already handled */



    }else if( cli_strcmp(z,"-batch")==0 ){
      /* already handled */
    }else if( cli_strcmp(z,"-utf8")==0 ){
      /* already handled */
    }else if( cli_strcmp(z,"-no-utf8")==0 ){


      /* already handled */
    }else if( cli_strcmp(z,"-heap")==0 ){
      i++;
    }else if( cli_strcmp(z,"-pagecache")==0 ){
      i+=2;
    }else if( cli_strcmp(z,"-lookaside")==0 ){
      i+=2;







|
|


|
>
>
>





>
>







30595
30596
30597
30598
30599
30600
30601
30602
30603
30604
30605
30606
30607
30608
30609
30610
30611
30612
30613
30614
30615
30616
30617
30618
30619
30620
30621
30622
30623
      ** prior to sending the SQL into SQLite.  Useful for injecting
      ** crazy bytes in the middle of SQL statements for testing and debugging.
      */
      ShellSetFlag(&data, SHFLG_Backslash);
    }else if( cli_strcmp(z,"-bail")==0 ){
      /* No-op.  The bail_on_error flag should already be set. */
    }else if( cli_strcmp(z,"-version")==0 ){
      sputf(stdout, "%s %s (%d-bit)\n",
            sqlite3_libversion(), sqlite3_sourceid(), 8*(int)sizeof(char*));
      return 0;
    }else if( cli_strcmp(z,"-interactive")==0 ){
      /* Need to check for interactive override here to so that it can
      ** affect console setup (for Windows only) and testing thereof.
      */
      stdin_is_interactive = 1;
    }else if( cli_strcmp(z,"-batch")==0 ){
      /* already handled */
    }else if( cli_strcmp(z,"-utf8")==0 ){
      /* already handled */
    }else if( cli_strcmp(z,"-no-utf8")==0 ){
      /* already handled */
    }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
      /* already handled */
    }else if( cli_strcmp(z,"-heap")==0 ){
      i++;
    }else if( cli_strcmp(z,"-pagecache")==0 ){
      i+=2;
    }else if( cli_strcmp(z,"-lookaside")==0 ){
      i+=2;
28544
28545
28546
28547
28548
28549
28550
28551
28552
28553
28554
28555
28556
28557
28558
28559
28560
28561
28562
28563
28564
28565
28566
28567
28568
28569
28570
28571
28572
28573
28574
28575
28576
28577
28578
28579
28580
28581
28582
28583
28584
28585
28586
28587
28588
      if( z[0]=='.' ){
        rc = do_meta_command(z, &data);
        if( rc && bail_on_error ) return rc==2 ? 0 : rc;
      }else{
        open_db(&data, 0);
        rc = shell_exec(&data, z, &zErrMsg);
        if( zErrMsg!=0 ){
          utf8_printf(stderr,"Error: %s\n", zErrMsg);
          if( bail_on_error ) return rc!=0 ? rc : 1;
        }else if( rc!=0 ){
          utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
          if( bail_on_error ) return rc;
        }
      }
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
    }else if( cli_strncmp(z, "-A", 2)==0 ){
      if( nCmd>0 ){
        utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
                            " with \"%s\"\n", z);
        return 1;
      }
      open_db(&data, OPEN_DB_ZIPFILE);
      if( z[2] ){
        argv[i] = &z[2];
        arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
      }else{
        arDotCommand(&data, 1, argv+i, argc-i);
      }
      readStdin = 0;
      break;
#endif
    }else if( cli_strcmp(z,"-safe")==0 ){
      data.bSafeMode = data.bSafeModePersist = 1;
    }else if( cli_strcmp(z,"-unsafe-testing")==0 ){
      /* Acted upon in first pass. */
    }else{
      utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
      raw_printf(stderr,"Use -help for a list of options.\n");
      return 1;
    }
    data.cMode = data.mode;
  }

  if( !readStdin ){
    /* Run all arguments that do not begin with '-' as if they were separate







|


|






|
|

















|
|







30657
30658
30659
30660
30661
30662
30663
30664
30665
30666
30667
30668
30669
30670
30671
30672
30673
30674
30675
30676
30677
30678
30679
30680
30681
30682
30683
30684
30685
30686
30687
30688
30689
30690
30691
30692
30693
30694
30695
30696
30697
30698
30699
30700
30701
      if( z[0]=='.' ){
        rc = do_meta_command(z, &data);
        if( rc && bail_on_error ) return rc==2 ? 0 : rc;
      }else{
        open_db(&data, 0);
        rc = shell_exec(&data, z, &zErrMsg);
        if( zErrMsg!=0 ){
          eputf("Error: %s\n", zErrMsg);
          if( bail_on_error ) return rc!=0 ? rc : 1;
        }else if( rc!=0 ){
          eputf("Error: unable to process SQL \"%s\"\n", z);
          if( bail_on_error ) return rc;
        }
      }
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
    }else if( cli_strncmp(z, "-A", 2)==0 ){
      if( nCmd>0 ){
        eputf("Error: cannot mix regular SQL or dot-commands"
              " with \"%s\"\n", z);
        return 1;
      }
      open_db(&data, OPEN_DB_ZIPFILE);
      if( z[2] ){
        argv[i] = &z[2];
        arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
      }else{
        arDotCommand(&data, 1, argv+i, argc-i);
      }
      readStdin = 0;
      break;
#endif
    }else if( cli_strcmp(z,"-safe")==0 ){
      data.bSafeMode = data.bSafeModePersist = 1;
    }else if( cli_strcmp(z,"-unsafe-testing")==0 ){
      /* Acted upon in first pass. */
    }else{
      eputf("%s: Error: unknown option: %s\n", Argv0, z);
      eputz("Use -help for a list of options.\n");
      return 1;
    }
    data.cMode = data.mode;
  }

  if( !readStdin ){
    /* Run all arguments that do not begin with '-' as if they were separate
28598
28599
28600
28601
28602
28603
28604
28605
28606
28607
28608
28609
28610
28611
28612
28613
28614
28615
28616
28617
28618
28619
28620
28621
28622
28623
28624

28625
28626
28627
28628
28629
28630
28631
28632
28633
28634
28635
28636
28637
28638
28639
28640
28641
28642
28643
28644
28645
28646
28647
        }
      }else{
        open_db(&data, 0);
        echo_group_input(&data, azCmd[i]);
        rc = shell_exec(&data, azCmd[i], &zErrMsg);
        if( zErrMsg || rc ){
          if( zErrMsg!=0 ){
            utf8_printf(stderr,"Error: %s\n", zErrMsg);
          }else{
            utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
          }
          sqlite3_free(zErrMsg);
          free(azCmd);
          return rc!=0 ? rc : 1;
        }
      }
    }
  }else{
    /* Run commands received from standard input
    */
    if( stdin_is_interactive ){
      char *zHome;
      char *zHistory;
      const char *zCharset = "";
      int nHistory;
#if SHELL_WIN_UTF8_OPT
      switch( console_utf8_in+2*console_utf8_out ){

      default: case 0: break;
      case 1: zCharset = " (utf8 in)"; break;
      case 2: zCharset = " (utf8 out)"; break;
      case 3: zCharset = " (utf8 I/O)"; break;
      }
#endif
      printf(
        "SQLite version %s %.19s%s\n" /*extra-version-info*/
        "Enter \".help\" for usage hints.\n",
        sqlite3_libversion(), sqlite3_sourceid(), zCharset
      );
      if( warnInmemoryDb ){
        printf("Connected to a ");
        printBold("transient in-memory database");
        printf(".\nUse \".open FILENAME\" to reopen on a "
               "persistent database.\n");
      }
      zHistory = getenv("SQLITE_HISTORY");
      if( zHistory ){
        zHistory = strdup(zHistory);
      }else if( (zHome = find_home_dir(0))!=0 ){
        nHistory = strlen30(zHome) + 20;
        if( (zHistory = malloc(nHistory))!=0 ){







|

|













<

|
|
>
|
<
<
<
<

<
|
|
|
<

|

|
|







30711
30712
30713
30714
30715
30716
30717
30718
30719
30720
30721
30722
30723
30724
30725
30726
30727
30728
30729
30730
30731
30732
30733

30734
30735
30736
30737
30738




30739

30740
30741
30742

30743
30744
30745
30746
30747
30748
30749
30750
30751
30752
30753
30754
        }
      }else{
        open_db(&data, 0);
        echo_group_input(&data, azCmd[i]);
        rc = shell_exec(&data, azCmd[i], &zErrMsg);
        if( zErrMsg || rc ){
          if( zErrMsg!=0 ){
            eputf("Error: %s\n", zErrMsg);
          }else{
            eputf("Error: unable to process SQL: %s\n", azCmd[i]);
          }
          sqlite3_free(zErrMsg);
          free(azCmd);
          return rc!=0 ? rc : 1;
        }
      }
    }
  }else{
    /* Run commands received from standard input
    */
    if( stdin_is_interactive ){
      char *zHome;
      char *zHistory;

      int nHistory;
#if CIO_WIN_WC_XLATE
# define SHELL_CIO_CHAR_SET (stdout_is_console? " (UTF-16 console I/O)" : "")
#else
# define SHELL_CIO_CHAR_SET ""




#endif

      sputf(stdout, "SQLite version %s %.19s%s\n" /*extra-version-info*/
            "Enter \".help\" for usage hints.\n",
            sqlite3_libversion(), sqlite3_sourceid(), SHELL_CIO_CHAR_SET);

      if( warnInmemoryDb ){
        sputz(stdout, "Connected to a ");
        printBold("transient in-memory database");
        sputz(stdout, ".\nUse \".open FILENAME\" to reopen on a"
              " persistent database.\n");
      }
      zHistory = getenv("SQLITE_HISTORY");
      if( zHistory ){
        zHistory = strdup(zHistory);
      }else if( (zHome = find_home_dir(0))!=0 ){
        nHistory = strlen30(zHome) + 20;
        if( (zHistory = malloc(nHistory))!=0 ){
28665
28666
28667
28668
28669
28670
28671





28672
28673
28674
28675
28676
28677
28678
      data.in = stdin;
      rc = process_input(&data);
    }
  }
#ifndef SQLITE_SHELL_FIDDLE
  /* In WASM mode we have to leave the db state in place so that
  ** client code can "push" SQL into it after this call returns. */





  free(azCmd);
  set_table_name(&data, 0);
  if( data.db ){
    session_close_all(&data, -1);
    close_db(data.db);
  }
  for(i=0; i<ArraySize(data.aAuxDb); i++){







>
>
>
>
>







30772
30773
30774
30775
30776
30777
30778
30779
30780
30781
30782
30783
30784
30785
30786
30787
30788
30789
30790
      data.in = stdin;
      rc = process_input(&data);
    }
  }
#ifndef SQLITE_SHELL_FIDDLE
  /* In WASM mode we have to leave the db state in place so that
  ** client code can "push" SQL into it after this call returns. */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( data.expert.pExpert ){
    expertFinish(&data, 1, 0);
  }
#endif
  free(azCmd);
  set_table_name(&data, 0);
  if( data.db ){
    session_close_all(&data, -1);
    close_db(data.db);
  }
  for(i=0; i<ArraySize(data.aAuxDb); i++){
28693
28694
28695
28696
28697
28698
28699
28700
28701
28702
28703
28704
28705
28706
28707
28708
  free(data.colWidth);
  free(data.zNonce);
  /* Clear the global data structure so that valgrind will detect memory
  ** leaks */
  memset(&data, 0, sizeof(data));
#ifdef SQLITE_DEBUG
  if( sqlite3_memory_used()>mem_main_enter ){
    utf8_printf(stderr, "Memory leaked: %u bytes\n",
                (unsigned int)(sqlite3_memory_used()-mem_main_enter));
  }
#endif
#endif /* !SQLITE_SHELL_FIDDLE */
  return rc;
}









|
|







30805
30806
30807
30808
30809
30810
30811
30812
30813
30814
30815
30816
30817
30818
30819
30820
  free(data.colWidth);
  free(data.zNonce);
  /* Clear the global data structure so that valgrind will detect memory
  ** leaks */
  memset(&data, 0, sizeof(data));
#ifdef SQLITE_DEBUG
  if( sqlite3_memory_used()>mem_main_enter ){
    eputf("Memory leaked: %u bytes\n",
          (unsigned int)(sqlite3_memory_used()-mem_main_enter));
  }
#endif
#endif /* !SQLITE_SHELL_FIDDLE */
  return rc;
}


28731
28732
28733
28734
28735
28736
28737
28738
28739
28740
28741
28742
28743
28744
28745
                         SQLITE_FCNTL_VFS_POINTER, &pVfs);
  }
  return pVfs;
}

/* Only for emcc experimentation purposes. */
sqlite3 * fiddle_db_arg(sqlite3 *arg){
    printf("fiddle_db_arg(%p)\n", (const void*)arg);
    return arg;
}

/*
** Intended to be called via a SharedWorker() while a separate
** SharedWorker() (which manages the wasm module) is performing work
** which should be interrupted. Unfortunately, SharedWorker is not







|







30843
30844
30845
30846
30847
30848
30849
30850
30851
30852
30853
30854
30855
30856
30857
                         SQLITE_FCNTL_VFS_POINTER, &pVfs);
  }
  return pVfs;
}

/* Only for emcc experimentation purposes. */
sqlite3 * fiddle_db_arg(sqlite3 *arg){
    oputf("fiddle_db_arg(%p)\n", (const void*)arg);
    return arg;
}

/*
** Intended to be called via a SharedWorker() while a separate
** SharedWorker() (which manages the wasm module) is performing work
** which should be interrupted. Unfortunately, SharedWorker is not
28757
28758
28759
28760
28761
28762
28763
28764

28765
28766
28767









28768
28769
28770
28771
28772
28773
28774
28775
28776
    return globalDb
      ? sqlite3_db_filename(globalDb, zDbName ? zDbName : "main")
      : NULL;
}

/*
** Completely wipes out the contents of the currently-opened database
** but leaves its storage intact for reuse.

*/
void fiddle_reset_db(void){
  if( globalDb ){









    int rc = sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
    if( 0==rc ) rc = sqlite3_exec(globalDb, "VACUUM", 0, 0, 0);
    sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
  }
}

/*
** Uses the current database's VFS xRead to stream the db file's
** contents out to the given callback. The callback gets a single







|
>



>
>
>
>
>
>
>
>
>
|
|







30869
30870
30871
30872
30873
30874
30875
30876
30877
30878
30879
30880
30881
30882
30883
30884
30885
30886
30887
30888
30889
30890
30891
30892
30893
30894
30895
30896
30897
30898
    return globalDb
      ? sqlite3_db_filename(globalDb, zDbName ? zDbName : "main")
      : NULL;
}

/*
** Completely wipes out the contents of the currently-opened database
** but leaves its storage intact for reuse. If any transactions are
** active, they are forcibly rolled back.
*/
void fiddle_reset_db(void){
  if( globalDb ){
    int rc;
    while( sqlite3_txn_state(globalDb,0)>0 ){
      /*
      ** Resolve problem reported in
      ** https://sqlite.org/forum/forumpost/0b41a25d65
      */
      oputz("Rolling back in-progress transaction.\n");
      sqlite3_exec(globalDb,"ROLLBACK", 0, 0, 0);
    }
    rc = sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
    if( 0==rc ) sqlite3_exec(globalDb, "VACUUM", 0, 0, 0);
    sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
  }
}

/*
** Uses the current database's VFS xRead to stream the db file's
** contents out to the given callback. The callback gets a single

Changes to extsrc/sqlite3.c.

more than 10,000 changes

Changes to extsrc/sqlite3.h.

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
** been edited in any way since it was last checked in, then the last
** four hexadecimal digits of the hash may be modified.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.44.0"
#define SQLITE_VERSION_NUMBER 3044000
#define SQLITE_SOURCE_ID      "2023-11-01 11:23:50 17129ba1ff7f0daf37100ee82d507aef7827cf38de1866e2633096ae6ad81301"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros







|
|
|







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
** been edited in any way since it was last checked in, then the last
** four hexadecimal digits of the hash may be modified.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.46.0"
#define SQLITE_VERSION_NUMBER 3046000
#define SQLITE_SOURCE_ID      "2024-04-08 11:50:07 69ec714b2d698acf9e37635256c01b233ce32f22e8323e226441d5ddd948a940"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
416
417
418
419
420
421
422


423
424
425
426
427
428
429
** <ul>
** <li> The application must ensure that the 1st parameter to sqlite3_exec()
**      is a valid and open [database connection].
** <li> The application must not close the [database connection] specified by
**      the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not modify the SQL statement text passed into
**      the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.


** </ul>
*/
SQLITE_API int sqlite3_exec(
  sqlite3*,                                  /* An open database */
  const char *sql,                           /* SQL to be evaluated */
  int (*callback)(void*,int,char**,char**),  /* Callback function */
  void *,                                    /* 1st argument to callback */







>
>







416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
** <ul>
** <li> The application must ensure that the 1st parameter to sqlite3_exec()
**      is a valid and open [database connection].
** <li> The application must not close the [database connection] specified by
**      the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not modify the SQL statement text passed into
**      the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not dereference the arrays or string pointers
**       passed as the 3rd and 4th callback parameters after it returns.
** </ul>
*/
SQLITE_API int sqlite3_exec(
  sqlite3*,                                  /* An open database */
  const char *sql,                           /* SQL to be evaluated */
  int (*callback)(void*,int,char**,char**),  /* Callback function */
  void *,                                    /* 1st argument to callback */
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
** <li> [SQLITE_LOCK_SHARED],
** <li> [SQLITE_LOCK_RESERVED],
** <li> [SQLITE_LOCK_PENDING], or
** <li> [SQLITE_LOCK_EXCLUSIVE].
** </ul>
** xLock() upgrades the database file lock.  In other words, xLock() moves the
** database file lock in the direction NONE toward EXCLUSIVE. The argument to
** xLock() is always on of SHARED, RESERVED, PENDING, or EXCLUSIVE, never
** SQLITE_LOCK_NONE.  If the database file lock is already at or above the
** requested lock, then the call to xLock() is a no-op.
** xUnlock() downgrades the database file lock to either SHARED or NONE.
*  If the lock is already at or below the requested lock state, then the call
** to xUnlock() is a no-op.
** The xCheckReservedLock() method checks whether any database connection,
** either in this process or in some other process, is holding a RESERVED,
** PENDING, or EXCLUSIVE lock on the file.  It returns true
** if such a lock exists and false otherwise.
**
** The xFileControl() method is a generic interface that allows custom







|



|







760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
** <li> [SQLITE_LOCK_SHARED],
** <li> [SQLITE_LOCK_RESERVED],
** <li> [SQLITE_LOCK_PENDING], or
** <li> [SQLITE_LOCK_EXCLUSIVE].
** </ul>
** xLock() upgrades the database file lock.  In other words, xLock() moves the
** database file lock in the direction NONE toward EXCLUSIVE. The argument to
** xLock() is always one of SHARED, RESERVED, PENDING, or EXCLUSIVE, never
** SQLITE_LOCK_NONE.  If the database file lock is already at or above the
** requested lock, then the call to xLock() is a no-op.
** xUnlock() downgrades the database file lock to either SHARED or NONE.
** If the lock is already at or below the requested lock state, then the call
** to xUnlock() is a no-op.
** The xCheckReservedLock() method checks whether any database connection,
** either in this process or in some other process, is holding a RESERVED,
** PENDING, or EXCLUSIVE lock on the file.  It returns true
** if such a lock exists and false otherwise.
**
** The xFileControl() method is a generic interface that allows custom
2137
2138
2139
2140
2141
2142
2143
















2144
2145
2146
2147
2148
2149
2150
** [sqlite3_int64] parameter which is the default maximum size for an in-memory
** database created using [sqlite3_deserialize()].  This default maximum
** size can be adjusted up or down for individual databases using the
** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control].  If this
** configuration setting is never used, then the default maximum is determined
** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option.  If that
** compile-time option is not set, then the default maximum is 1073741824.
















** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD         1  /* nil */
#define SQLITE_CONFIG_MULTITHREAD          2  /* nil */
#define SQLITE_CONFIG_SERIALIZED           3  /* nil */
#define SQLITE_CONFIG_MALLOC               4  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_GETMALLOC            5  /* sqlite3_mem_methods* */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
** [sqlite3_int64] parameter which is the default maximum size for an in-memory
** database created using [sqlite3_deserialize()].  This default maximum
** size can be adjusted up or down for individual databases using the
** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control].  If this
** configuration setting is never used, then the default maximum is determined
** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option.  If that
** compile-time option is not set, then the default maximum is 1073741824.
**
** [[SQLITE_CONFIG_ROWID_IN_VIEW]]
** <dt>SQLITE_CONFIG_ROWID_IN_VIEW
** <dd>The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability
** for VIEWs to have a ROWID.  The capability can only be enabled if SQLite is
** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability
** defaults to on.  This configuration option queries the current setting or
** changes the setting to off or on.  The argument is a pointer to an integer.
** If that integer initially holds a value of 1, then the ability for VIEWs to
** have ROWIDs is activated.  If the integer initially holds zero, then the
** ability is deactivated.  Any other initial value for the integer leaves the
** setting unchanged.  After changes, if any, the integer is written with
** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off.  If SQLite
** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and
** recommended case) then the integer is always filled with zero, regardless
** if its initial value.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD         1  /* nil */
#define SQLITE_CONFIG_MULTITHREAD          2  /* nil */
#define SQLITE_CONFIG_SERIALIZED           3  /* nil */
#define SQLITE_CONFIG_MALLOC               4  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_GETMALLOC            5  /* sqlite3_mem_methods* */
2168
2169
2170
2171
2172
2173
2174

2175
2176
2177
2178
2179
2180
2181
#define SQLITE_CONFIG_WIN32_HEAPSIZE      23  /* int nByte */
#define SQLITE_CONFIG_PCACHE_HDRSZ        24  /* int *psz */
#define SQLITE_CONFIG_PMASZ               25  /* unsigned int szPma */
#define SQLITE_CONFIG_STMTJRNL_SPILL      26  /* int nByte */
#define SQLITE_CONFIG_SMALL_MALLOC        27  /* boolean */
#define SQLITE_CONFIG_SORTERREF_SIZE      28  /* int nByte */
#define SQLITE_CONFIG_MEMDB_MAXSIZE       29  /* sqlite3_int64 */


/*
** CAPI3REF: Database Connection Configuration Options
**
** These constants are the available integer configuration options that
** can be passed as the second argument to the [sqlite3_db_config()] interface.
**







>







2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
#define SQLITE_CONFIG_WIN32_HEAPSIZE      23  /* int nByte */
#define SQLITE_CONFIG_PCACHE_HDRSZ        24  /* int *psz */
#define SQLITE_CONFIG_PMASZ               25  /* unsigned int szPma */
#define SQLITE_CONFIG_STMTJRNL_SPILL      26  /* int nByte */
#define SQLITE_CONFIG_SMALL_MALLOC        27  /* boolean */
#define SQLITE_CONFIG_SORTERREF_SIZE      28  /* int nByte */
#define SQLITE_CONFIG_MEMDB_MAXSIZE       29  /* sqlite3_int64 */
#define SQLITE_CONFIG_ROWID_IN_VIEW       30  /* int* */

/*
** CAPI3REF: Database Connection Configuration Options
**
** These constants are the available integer configuration options that
** can be passed as the second argument to the [sqlite3_db_config()] interface.
**
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
#define SQLITE_DROP_VTABLE          30   /* Table Name      Module Name     */
#define SQLITE_FUNCTION             31   /* NULL            Function Name   */
#define SQLITE_SAVEPOINT            32   /* Operation       Savepoint Name  */
#define SQLITE_COPY                  0   /* No longer used */
#define SQLITE_RECURSIVE            33   /* NULL            NULL            */

/*
** CAPI3REF: Tracing And Profiling Functions
** METHOD: sqlite3
**
** These routines are deprecated. Use the [sqlite3_trace_v2()] interface
** instead of the routines described here.
**
** These routines register callback functions that can be used for
** tracing and profiling the execution of SQL statements.
**







|
|







3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
#define SQLITE_DROP_VTABLE          30   /* Table Name      Module Name     */
#define SQLITE_FUNCTION             31   /* NULL            Function Name   */
#define SQLITE_SAVEPOINT            32   /* Operation       Savepoint Name  */
#define SQLITE_COPY                  0   /* No longer used */
#define SQLITE_RECURSIVE            33   /* NULL            NULL            */

/*
** CAPI3REF: Deprecated Tracing And Profiling Functions
** DEPRECATED
**
** These routines are deprecated. Use the [sqlite3_trace_v2()] interface
** instead of the routines described here.
**
** These routines register callback functions that can be used for
** tracing and profiling the execution of SQL statements.
**
3950
3951
3952
3953
3954
3955
3956
3957

3958
3959
3960
3961
3962
3963
3964
3965

3966
3967
3968
3969
3970
3971
3972
** <li> sqlite3_extended_errcode()
** <li> sqlite3_errmsg()
** <li> sqlite3_errmsg16()
** <li> sqlite3_error_offset()
** </ul>
**
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
** text that describes the error, as either UTF-8 or UTF-16 respectively.

** (See how SQLite handles [invalid UTF] for exceptions to this rule.)
** ^(Memory to hold the error message string is managed internally.
** The application does not need to worry about freeing the result.
** However, the error string might be overwritten or deallocated by
** subsequent calls to other SQLite interface functions.)^
**
** ^The sqlite3_errstr() interface returns the English-language text
** that describes the [result code], as UTF-8.

** ^(Memory to hold the error message string is managed internally
** and must not be freed by the application)^.
**
** ^If the most recent error references a specific token in the input
** SQL, the sqlite3_error_offset() interface returns the byte offset
** of the start of that token.  ^The byte offset returned by
** sqlite3_error_offset() assumes that the input SQL is UTF8.







|
>






|
|
>







3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
** <li> sqlite3_extended_errcode()
** <li> sqlite3_errmsg()
** <li> sqlite3_errmsg16()
** <li> sqlite3_error_offset()
** </ul>
**
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
** text that describes the error, as either UTF-8 or UTF-16 respectively,
** or NULL if no error message is available.
** (See how SQLite handles [invalid UTF] for exceptions to this rule.)
** ^(Memory to hold the error message string is managed internally.
** The application does not need to worry about freeing the result.
** However, the error string might be overwritten or deallocated by
** subsequent calls to other SQLite interface functions.)^
**
** ^The sqlite3_errstr(E) interface returns the English-language text
** that describes the [result code] E, as UTF-8, or NULL if E is not an
** result code for which a text error message is available.
** ^(Memory to hold the error message string is managed internally
** and must not be freed by the application)^.
**
** ^If the most recent error references a specific token in the input
** SQL, the sqlite3_error_offset() interface returns the byte offset
** of the start of that token.  ^The byte offset returned by
** sqlite3_error_offset() assumes that the input SQL is UTF8.
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581

5582













5583
5584
5585
5586
5587
5588
5589

5590
5591
5592
5593
5594
5595
5596
** are innocuous.  Developers are advised to avoid using the
** SQLITE_INNOCUOUS flag for application-defined functions unless the
** function has been carefully audited and found to be free of potentially
** security-adverse side-effects and information-leaks.
** </dd>
**
** [[SQLITE_SUBTYPE]] <dt>SQLITE_SUBTYPE</dt><dd>
** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call
** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
** Specifying this flag makes no difference for scalar or aggregate user
** functions. However, if it is not specified for a user-defined window
** function, then any sub-types belonging to arguments passed to the window
** function may be discarded before the window function is called (i.e.

** sqlite3_value_subtype() will always return 0).













** </dd>
** </dl>
*/
#define SQLITE_DETERMINISTIC    0x000000800
#define SQLITE_DIRECTONLY       0x000080000
#define SQLITE_SUBTYPE          0x000100000
#define SQLITE_INNOCUOUS        0x000200000


/*
** CAPI3REF: Deprecated Functions
** DEPRECATED
**
** These functions are [deprecated].  In order to maintain
** backwards compatibility with older code, these functions continue







|

|
|
|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>







>







5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
** are innocuous.  Developers are advised to avoid using the
** SQLITE_INNOCUOUS flag for application-defined functions unless the
** function has been carefully audited and found to be free of potentially
** security-adverse side-effects and information-leaks.
** </dd>
**
** [[SQLITE_SUBTYPE]] <dt>SQLITE_SUBTYPE</dt><dd>
** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call
** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
** This flag instructs SQLite to omit some corner-case optimizations that
** might disrupt the operation of the [sqlite3_value_subtype()] function,
** causing it to return zero rather than the correct subtype().
** SQL functions that invokes [sqlite3_value_subtype()] should have this
** property.  If the SQLITE_SUBTYPE property is omitted, then the return
** value from [sqlite3_value_subtype()] might sometimes be zero even though
** a non-zero subtype was specified by the function argument expression.
**
** [[SQLITE_RESULT_SUBTYPE]] <dt>SQLITE_RESULT_SUBTYPE</dt><dd>
** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call
** [sqlite3_result_subtype()] to cause a sub-type to be associated with its
** result.
** Every function that invokes [sqlite3_result_subtype()] should have this
** property.  If it does not, then the call to [sqlite3_result_subtype()]
** might become a no-op if the function is used as term in an
** [expression index].  On the other hand, SQL functions that never invoke
** [sqlite3_result_subtype()] should avoid setting this property, as the
** purpose of this property is to disable certain optimizations that are
** incompatible with subtypes.
** </dd>
** </dl>
*/
#define SQLITE_DETERMINISTIC    0x000000800
#define SQLITE_DIRECTONLY       0x000080000
#define SQLITE_SUBTYPE          0x000100000
#define SQLITE_INNOCUOUS        0x000200000
#define SQLITE_RESULT_SUBTYPE   0x001000000

/*
** CAPI3REF: Deprecated Functions
** DEPRECATED
**
** These functions are [deprecated].  In order to maintain
** backwards compatibility with older code, these functions continue
5779
5780
5781
5782
5783
5784
5785






5786
5787
5788
5789
5790
5791
5792
** METHOD: sqlite3_value
**
** The sqlite3_value_subtype(V) function returns the subtype for
** an [application-defined SQL function] argument V.  The subtype
** information can be used to pass a limited amount of context from
** one SQL function to another.  Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.






*/
SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*);

/*
** CAPI3REF: Copy And Free SQL Values
** METHOD: sqlite3_value
**







>
>
>
>
>
>







5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
** METHOD: sqlite3_value
**
** The sqlite3_value_subtype(V) function returns the subtype for
** an [application-defined SQL function] argument V.  The subtype
** information can be used to pass a limited amount of context from
** one SQL function to another.  Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.
**
** Every [application-defined SQL function] that invoke this interface
** should include the [SQLITE_SUBTYPE] property in the text
** encoding argument when the function is [sqlite3_create_function|registered].
** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()
** might return zero instead of the upstream subtype in some corner cases.
*/
SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*);

/*
** CAPI3REF: Copy And Free SQL Values
** METHOD: sqlite3_value
**
5909
5910
5911
5912
5913
5914
5915
5916



5917
5918
5919
5920
5921
5922
5923





5924
5925
5926
5927
5928
5929
5930
** SQLite is free to discard the auxiliary data at any time, including: <ul>
** <li> ^(when the corresponding function parameter changes)^, or
** <li> ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
**      SQL statement)^, or
** <li> ^(when sqlite3_set_auxdata() is invoked again on the same
**       parameter)^, or
** <li> ^(during the original sqlite3_set_auxdata() call when a memory
**      allocation error occurs.)^ </ul>



**
** Note the last bullet in particular.  The destructor X in
** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
** sqlite3_set_auxdata() interface even returns.  Hence sqlite3_set_auxdata()
** should be called near the end of the function implementation and the
** function implementation should not make any use of P after
** sqlite3_set_auxdata() has been called.





**
** ^(In practice, auxiliary data is preserved between function calls for
** function parameters that are compile-time constants, including literal
** values and [parameters] and expressions composed from the same.)^
**
** The value of the N parameter to these interfaces should be non-negative.
** Future enhancements may make use of negative N values to define new







|
>
>
>

|




|
>
>
>
>
>







5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
** SQLite is free to discard the auxiliary data at any time, including: <ul>
** <li> ^(when the corresponding function parameter changes)^, or
** <li> ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
**      SQL statement)^, or
** <li> ^(when sqlite3_set_auxdata() is invoked again on the same
**       parameter)^, or
** <li> ^(during the original sqlite3_set_auxdata() call when a memory
**      allocation error occurs.)^
** <li> ^(during the original sqlite3_set_auxdata() call if the function
**      is evaluated during query planning instead of during query execution,
**      as sometimes happens with [SQLITE_ENABLE_STAT4].)^ </ul>
**
** Note the last two bullets in particular.  The destructor X in
** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
** sqlite3_set_auxdata() interface even returns.  Hence sqlite3_set_auxdata()
** should be called near the end of the function implementation and the
** function implementation should not make any use of P after
** sqlite3_set_auxdata() has been called.  Furthermore, a call to
** sqlite3_get_auxdata() that occurs immediately after a corresponding call
** to sqlite3_set_auxdata() might still return NULL if an out-of-memory
** condition occurred during the sqlite3_set_auxdata() call or if the
** function is being evaluated during query planning rather than during
** query execution.
**
** ^(In practice, auxiliary data is preserved between function calls for
** function parameters that are compile-time constants, including literal
** values and [parameters] and expressions composed from the same.)^
**
** The value of the N parameter to these interfaces should be non-negative.
** Future enhancements may make use of negative N values to define new
6190
6191
6192
6193
6194
6195
6196














6197
6198
6199
6200
6201
6202
6203
** The sqlite3_result_subtype(C,T) function causes the subtype of
** the result from the [application-defined SQL function] with
** [sqlite3_context] C to be the value T.  Only the lower 8 bits
** of the subtype T are preserved in current versions of SQLite;
** higher order bits are discarded.
** The number of subtype bytes preserved by SQLite might increase
** in future releases of SQLite.














*/
SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);

/*
** CAPI3REF: Define New Collating Sequences
** METHOD: sqlite3
**







>
>
>
>
>
>
>
>
>
>
>
>
>
>







6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
** The sqlite3_result_subtype(C,T) function causes the subtype of
** the result from the [application-defined SQL function] with
** [sqlite3_context] C to be the value T.  Only the lower 8 bits
** of the subtype T are preserved in current versions of SQLite;
** higher order bits are discarded.
** The number of subtype bytes preserved by SQLite might increase
** in future releases of SQLite.
**
** Every [application-defined SQL function] that invokes this interface
** should include the [SQLITE_RESULT_SUBTYPE] property in its
** text encoding argument when the SQL function is
** [sqlite3_create_function|registered].  If the [SQLITE_RESULT_SUBTYPE]
** property is omitted from the function that invokes sqlite3_result_subtype(),
** then in some cases the sqlite3_result_subtype() might fail to set
** the result subtype.
**
** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any
** SQL function that invokes the sqlite3_result_subtype() interface
** and that does not have the SQLITE_RESULT_SUBTYPE property will raise
** an error.  Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1
** by default.
*/
SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);

/*
** CAPI3REF: Define New Collating Sequences
** METHOD: sqlite3
**
6818
6819
6820
6821
6822
6823
6824






6825
6826
6827
6828
6829
6830
6831
**
** ^In the current implementation, the update hook
** is not invoked when conflicting rows are deleted because of an
** [ON CONFLICT | ON CONFLICT REPLACE] clause.  ^Nor is the update hook
** invoked when rows are deleted using the [truncate optimization].
** The exceptions defined in this paragraph might change in a future
** release of SQLite.






**
** The update hook implementation must not do anything that will modify
** the database connection that invoked the update hook.  Any actions
** to modify the database connection must be deferred until after the
** completion of the [sqlite3_step()] call that triggered the update hook.
** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
** database connections for the meaning of "modify" in this paragraph.







>
>
>
>
>
>







6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
**
** ^In the current implementation, the update hook
** is not invoked when conflicting rows are deleted because of an
** [ON CONFLICT | ON CONFLICT REPLACE] clause.  ^Nor is the update hook
** invoked when rows are deleted using the [truncate optimization].
** The exceptions defined in this paragraph might change in a future
** release of SQLite.
**
** Whether the update hook is invoked before or after the
** corresponding change is currently unspecified and may differ
** depending on the type of change. Do not rely on the order of the
** hook call with regards to the final result of the operation which
** triggers the hook.
**
** The update hook implementation must not do anything that will modify
** the database connection that invoked the update hook.  Any actions
** to modify the database connection must be deferred until after the
** completion of the [sqlite3_step()] call that triggered the update hook.
** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
** database connections for the meaning of "modify" in this paragraph.
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999


8000
8001
8002
8003
8004
8005
8006
** In such cases, the
** mutex must be exited an equal number of times before another thread
** can enter.)^  If the same thread tries to enter any mutex other
** than an SQLITE_MUTEX_RECURSIVE more than once, the behavior is undefined.
**
** ^(Some systems (for example, Windows 95) do not support the operation
** implemented by sqlite3_mutex_try().  On those systems, sqlite3_mutex_try()
** will always return SQLITE_BUSY. The SQLite core only ever uses
** sqlite3_mutex_try() as an optimization so this is acceptable
** behavior.)^


**
** ^The sqlite3_mutex_leave() routine exits a mutex that was
** previously entered by the same thread.   The behavior
** is undefined if the mutex is not currently entered by the
** calling thread or is not currently allocated.
**
** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(),







|
|
|
>
>







8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
** In such cases, the
** mutex must be exited an equal number of times before another thread
** can enter.)^  If the same thread tries to enter any mutex other
** than an SQLITE_MUTEX_RECURSIVE more than once, the behavior is undefined.
**
** ^(Some systems (for example, Windows 95) do not support the operation
** implemented by sqlite3_mutex_try().  On those systems, sqlite3_mutex_try()
** will always return SQLITE_BUSY. In most cases the SQLite core only uses
** sqlite3_mutex_try() as an optimization, so this is acceptable
** behavior. The exceptions are unix builds that set the
** SQLITE_ENABLE_SETLK_TIMEOUT build option. In that case a working
** sqlite3_mutex_try() is required.)^
**
** ^The sqlite3_mutex_leave() routine exits a mutex that was
** previously entered by the same thread.   The behavior
** is undefined if the mutex is not currently entered by the
** calling thread or is not currently allocated.
**
** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(),
8251
8252
8253
8254
8255
8256
8257

8258
8259
8260
8261
8262
8263
8264
#define SQLITE_TESTCTRL_BITVEC_TEST              8
#define SQLITE_TESTCTRL_FAULT_INSTALL            9
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS     10
#define SQLITE_TESTCTRL_PENDING_BYTE            11
#define SQLITE_TESTCTRL_ASSERT                  12
#define SQLITE_TESTCTRL_ALWAYS                  13
#define SQLITE_TESTCTRL_RESERVE                 14  /* NOT USED */

#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16  /* NOT USED */
#define SQLITE_TESTCTRL_SCRATCHMALLOC           17  /* NOT USED */
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS      17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
#define SQLITE_TESTCTRL_EXPLAIN_STMT            19  /* NOT USED */
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD    19







>







8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
#define SQLITE_TESTCTRL_BITVEC_TEST              8
#define SQLITE_TESTCTRL_FAULT_INSTALL            9
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS     10
#define SQLITE_TESTCTRL_PENDING_BYTE            11
#define SQLITE_TESTCTRL_ASSERT                  12
#define SQLITE_TESTCTRL_ALWAYS                  13
#define SQLITE_TESTCTRL_RESERVE                 14  /* NOT USED */
#define SQLITE_TESTCTRL_JSON_SELFCHECK          14
#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16  /* NOT USED */
#define SQLITE_TESTCTRL_SCRATCHMALLOC           17  /* NOT USED */
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS      17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
#define SQLITE_TESTCTRL_EXPLAIN_STMT            19  /* NOT USED */
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD    19
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
** recognized by SQLite.  Applications can uses these routines to determine
** whether or not a specific identifier needs to be escaped (for example,
** by enclosing in double-quotes) so as not to confuse the parser.
**
** The sqlite3_keyword_count() interface returns the number of distinct
** keywords understood by SQLite.
**
** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
** makes *Z point to that keyword expressed as UTF8 and writes the number
** of bytes in the keyword into *L.  The string that *Z points to is not
** zero-terminated.  The sqlite3_keyword_name(N,Z,L) routine returns
** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z
** or L are NULL or invalid pointers then calls to
** sqlite3_keyword_name(N,Z,L) result in undefined behavior.
**







|







8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
** recognized by SQLite.  Applications can uses these routines to determine
** whether or not a specific identifier needs to be escaped (for example,
** by enclosing in double-quotes) so as not to confuse the parser.
**
** The sqlite3_keyword_count() interface returns the number of distinct
** keywords understood by SQLite.
**
** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and
** makes *Z point to that keyword expressed as UTF8 and writes the number
** of bytes in the keyword into *L.  The string that *Z points to is not
** zero-terminated.  The sqlite3_keyword_name(N,Z,L) routine returns
** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z
** or L are NULL or invalid pointers then calls to
** sqlite3_keyword_name(N,Z,L) result in undefined behavior.
**
12731
12732
12733
12734
12735
12736
12737
12738
12739
12740
12741
12742
12743
12744
12745
12746
  const unsigned char *b;
};

/*
** EXTENSION API FUNCTIONS
**
** xUserData(pFts):
**   Return a copy of the context pointer the extension function was
**   registered with.
**
** xColumnTotalSize(pFts, iCol, pnToken):
**   If parameter iCol is less than zero, set output variable *pnToken
**   to the total number of tokens in the FTS5 table. Or, if iCol is
**   non-negative but less than the number of columns in the table, return
**   the total number of tokens in column iCol, considering all rows in
**   the FTS5 table.







|
|







12804
12805
12806
12807
12808
12809
12810
12811
12812
12813
12814
12815
12816
12817
12818
12819
  const unsigned char *b;
};

/*
** EXTENSION API FUNCTIONS
**
** xUserData(pFts):
**   Return a copy of the pUserData pointer passed to the xCreateFunction()
**   API when the extension function was registered.
**
** xColumnTotalSize(pFts, iCol, pnToken):
**   If parameter iCol is less than zero, set output variable *pnToken
**   to the total number of tokens in the FTS5 table. Or, if iCol is
**   non-negative but less than the number of columns in the table, return
**   the total number of tokens in column iCol, considering all rows in
**   the FTS5 table.
12764
12765
12766
12767
12768
12769
12770



12771
12772
12773
12774
12775
12776
12777
12778
12779
12780
12781


12782
12783
12784
12785
12786
12787
12788
12789
12790
12791
12792
12793
12794
12795
12796
12797
12798
12799

12800
12801
12802
12803
12804
12805
12806
12807
12808
12809
12810
12811
**   an OOM condition or IO error), an appropriate SQLite error code is
**   returned.
**
**   This function may be quite inefficient if used with an FTS5 table
**   created with the "columnsize=0" option.
**
** xColumnText:



**   This function attempts to retrieve the text of column iCol of the
**   current document. If successful, (*pz) is set to point to a buffer
**   containing the text in utf-8 encoding, (*pn) is set to the size in bytes
**   (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
**   if an error occurs, an SQLite error code is returned and the final values
**   of (*pz) and (*pn) are undefined.
**
** xPhraseCount:
**   Returns the number of phrases in the current query expression.
**
** xPhraseSize:


**   Returns the number of tokens in phrase iPhrase of the query. Phrases
**   are numbered starting from zero.
**
** xInstCount:
**   Set *pnInst to the total number of occurrences of all phrases within
**   the query within the current row. Return SQLITE_OK if successful, or
**   an error code (i.e. SQLITE_NOMEM) if an error occurs.
**
**   This API can be quite slow if used with an FTS5 table created with the
**   "detail=none" or "detail=column" option. If the FTS5 table is created
**   with either "detail=none" or "detail=column" and "content=" option
**   (i.e. if it is a contentless table), then this API always returns 0.
**
** xInst:
**   Query for the details of phrase match iIdx within the current row.
**   Phrase matches are numbered starting from zero, so the iIdx argument
**   should be greater than or equal to zero and smaller than the value
**   output by xInstCount().

**
**   Usually, output parameter *piPhrase is set to the phrase number, *piCol
**   to the column in which it occurs and *piOff the token offset of the
**   first token of the phrase. Returns SQLITE_OK if successful, or an error
**   code (i.e. SQLITE_NOMEM) if an error occurs.
**
**   This API can be quite slow if used with an FTS5 table created with the
**   "detail=none" or "detail=column" option.
**
** xRowid:
**   Returns the rowid of the current row.
**







>
>
>
|
|









>
>
|
|















|
>

|

|
|







12837
12838
12839
12840
12841
12842
12843
12844
12845
12846
12847
12848
12849
12850
12851
12852
12853
12854
12855
12856
12857
12858
12859
12860
12861
12862
12863
12864
12865
12866
12867
12868
12869
12870
12871
12872
12873
12874
12875
12876
12877
12878
12879
12880
12881
12882
12883
12884
12885
12886
12887
12888
12889
12890
**   an OOM condition or IO error), an appropriate SQLite error code is
**   returned.
**
**   This function may be quite inefficient if used with an FTS5 table
**   created with the "columnsize=0" option.
**
** xColumnText:
**   If parameter iCol is less than zero, or greater than or equal to the
**   number of columns in the table, SQLITE_RANGE is returned.
**
**   Otherwise, this function attempts to retrieve the text of column iCol of
**   the current document. If successful, (*pz) is set to point to a buffer
**   containing the text in utf-8 encoding, (*pn) is set to the size in bytes
**   (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
**   if an error occurs, an SQLite error code is returned and the final values
**   of (*pz) and (*pn) are undefined.
**
** xPhraseCount:
**   Returns the number of phrases in the current query expression.
**
** xPhraseSize:
**   If parameter iCol is less than zero, or greater than or equal to the
**   number of phrases in the current query, as returned by xPhraseCount,
**   0 is returned. Otherwise, this function returns the number of tokens in
**   phrase iPhrase of the query. Phrases are numbered starting from zero.
**
** xInstCount:
**   Set *pnInst to the total number of occurrences of all phrases within
**   the query within the current row. Return SQLITE_OK if successful, or
**   an error code (i.e. SQLITE_NOMEM) if an error occurs.
**
**   This API can be quite slow if used with an FTS5 table created with the
**   "detail=none" or "detail=column" option. If the FTS5 table is created
**   with either "detail=none" or "detail=column" and "content=" option
**   (i.e. if it is a contentless table), then this API always returns 0.
**
** xInst:
**   Query for the details of phrase match iIdx within the current row.
**   Phrase matches are numbered starting from zero, so the iIdx argument
**   should be greater than or equal to zero and smaller than the value
**   output by xInstCount(). If iIdx is less than zero or greater than
**   or equal to the value returned by xInstCount(), SQLITE_RANGE is returned.
**
**   Otherwise, output parameter *piPhrase is set to the phrase number, *piCol
**   to the column in which it occurs and *piOff the token offset of the
**   first token of the phrase. SQLITE_OK is returned if successful, or an
**   error code (i.e. SQLITE_NOMEM) if an error occurs.
**
**   This API can be quite slow if used with an FTS5 table created with the
**   "detail=none" or "detail=column" option.
**
** xRowid:
**   Returns the rowid of the current row.
**
12822
12823
12824
12825
12826
12827
12828




12829
12830
12831
12832
12833
12834
12835
**   current query is executed. Any column filter that applies to
**   phrase iPhrase of the current query is included in $p. For each
**   row visited, the callback function passed as the fourth argument
**   is invoked. The context and API objects passed to the callback
**   function may be used to access the properties of each matched row.
**   Invoking Api.xUserData() returns a copy of the pointer passed as
**   the third argument to pUserData.




**
**   If the callback function returns any value other than SQLITE_OK, the
**   query is abandoned and the xQueryPhrase function returns immediately.
**   If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.
**   Otherwise, the error code is propagated upwards.
**
**   If the query runs to completion without incident, SQLITE_OK is returned.







>
>
>
>







12901
12902
12903
12904
12905
12906
12907
12908
12909
12910
12911
12912
12913
12914
12915
12916
12917
12918
**   current query is executed. Any column filter that applies to
**   phrase iPhrase of the current query is included in $p. For each
**   row visited, the callback function passed as the fourth argument
**   is invoked. The context and API objects passed to the callback
**   function may be used to access the properties of each matched row.
**   Invoking Api.xUserData() returns a copy of the pointer passed as
**   the third argument to pUserData.
**
**   If parameter iPhrase is less than zero, or greater than or equal to
**   the number of phrases in the query, as returned by xPhraseCount(),
**   this function returns SQLITE_RANGE.
**
**   If the callback function returns any value other than SQLITE_OK, the
**   query is abandoned and the xQueryPhrase function returns immediately.
**   If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.
**   Otherwise, the error code is propagated upwards.
**
**   If the query runs to completion without incident, SQLITE_OK is returned.
12937
12938
12939
12940
12941
12942
12943

































12944
12945
12946
12947
12948
12949
12950
12951
12952
12953
**   xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
**   (or xInst/xInstCount). The chief advantage of this API is that it is
**   significantly more efficient than those alternatives when used with
**   "detail=column" tables.
**
** xPhraseNextColumn()
**   See xPhraseFirstColumn above.

































*/
struct Fts5ExtensionApi {
  int iVersion;                   /* Currently always set to 2 */

  void *(*xUserData)(Fts5Context*);

  int (*xColumnCount)(Fts5Context*);
  int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
  int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|







13020
13021
13022
13023
13024
13025
13026
13027
13028
13029
13030
13031
13032
13033
13034
13035
13036
13037
13038
13039
13040
13041
13042
13043
13044
13045
13046
13047
13048
13049
13050
13051
13052
13053
13054
13055
13056
13057
13058
13059
13060
13061
13062
13063
13064
13065
13066
13067
13068
13069
**   xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
**   (or xInst/xInstCount). The chief advantage of this API is that it is
**   significantly more efficient than those alternatives when used with
**   "detail=column" tables.
**
** xPhraseNextColumn()
**   See xPhraseFirstColumn above.
**
** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken)
**   This is used to access token iToken of phrase iPhrase of the current
**   query. Before returning, output parameter *ppToken is set to point
**   to a buffer containing the requested token, and *pnToken to the
**   size of this buffer in bytes.
**
**   If iPhrase or iToken are less than zero, or if iPhrase is greater than
**   or equal to the number of phrases in the query as reported by
**   xPhraseCount(), or if iToken is equal to or greater than the number of
**   tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken
     are both zeroed.
**
**   The output text is not a copy of the query text that specified the
**   token. It is the output of the tokenizer module. For tokendata=1
**   tables, this includes any embedded 0x00 and trailing data.
**
** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken)
**   This is used to access token iToken of phrase hit iIdx within the
**   current row. If iIdx is less than zero or greater than or equal to the
**   value returned by xInstCount(), SQLITE_RANGE is returned.  Otherwise,
**   output variable (*ppToken) is set to point to a buffer containing the
**   matching document token, and (*pnToken) to the size of that buffer in
**   bytes. This API is not available if the specified token matches a
**   prefix query term. In that case both output variables are always set
**   to 0.
**
**   The output text is not a copy of the document text that was tokenized.
**   It is the output of the tokenizer module. For tokendata=1 tables, this
**   includes any embedded 0x00 and trailing data.
**
**   This API can be quite slow if used with an FTS5 table created with the
**   "detail=none" or "detail=column" option.
*/
struct Fts5ExtensionApi {
  int iVersion;                   /* Currently always set to 3 */

  void *(*xUserData)(Fts5Context*);

  int (*xColumnCount)(Fts5Context*);
  int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
  int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);

12974
12975
12976
12977
12978
12979
12980







12981
12982
12983
12984
12985
12986
12987
  void *(*xGetAuxdata)(Fts5Context*, int bClear);

  int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
  void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);

  int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
  void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);







};

/*
** CUSTOM AUXILIARY FUNCTIONS
*************************************************************************/

/*************************************************************************







>
>
>
>
>
>
>







13090
13091
13092
13093
13094
13095
13096
13097
13098
13099
13100
13101
13102
13103
13104
13105
13106
13107
13108
13109
13110
  void *(*xGetAuxdata)(Fts5Context*, int bClear);

  int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
  void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);

  int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
  void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);

  /* Below this point are iVersion>=3 only */
  int (*xQueryToken)(Fts5Context*,
      int iPhrase, int iToken,
      const char **ppToken, int *pnToken
  );
  int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
};

/*
** CUSTOM AUXILIARY FUNCTIONS
*************************************************************************/

/*************************************************************************

Changes to skins/ardoise/css.txt.

614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
ol,
p,
pre,
table,
ul {
  margin-bottom: 1.5rem
}
.header {
  color: #888;
  font-weight: 400;
  padding-top: 10px;
  border-width: 0
}
.filetree li > ul:before,
.filetree li li:before {
  border-left: 2px solid #888;
  content: '';
  position: absolute
}
.filetree>ul,
.header .logo,
.header .logo h1 {
  display: inline-block
}
.header .login {
  padding-top: 2px;
  text-align: right
}
.header .login .button {
  margin: 0
}
.header h1 {
  margin: 0;
  color: #888;
  display: inline-block
}
.header .title h1 {
  padding-bottom: 10px
}
.header .login,
.header h1 small,
.header h2 small {
  color: #777
}
.middle {
  background-color: #1d2021;
  padding-bottom: 20px;
  max-width: 100%;
  box-sizing: border-box







|












|
|


|



|


|




|


|
|
|







614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
ol,
p,
pre,
table,
ul {
  margin-bottom: 1.5rem
}
header {
  color: #888;
  font-weight: 400;
  padding-top: 10px;
  border-width: 0
}
.filetree li > ul:before,
.filetree li li:before {
  border-left: 2px solid #888;
  content: '';
  position: absolute
}
.filetree>ul,
header .logo,
header .logo h1 {
  display: inline-block
}
header .login {
  padding-top: 2px;
  text-align: right
}
header .login .button {
  margin: 0
}
header h1 {
  margin: 0;
  color: #888;
  display: inline-block
}
header .title h1 {
  padding-bottom: 10px
}
header .login,
header h1 small,
header h2 small {
  color: #777
}
.middle {
  background-color: #1d2021;
  padding-bottom: 20px;
  max-width: 100%;
  box-sizing: border-box
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
}
.artifact_content blockquote:first-of-type {
  padding: 1px 20px;
  margin: 0 0 20px;
  background: #000;
  border-radius: 5px
}
.footer {
  padding: 10px 0 60px;
  border-top: 0;
  color: #888
}
.footer a {
  color: #527b8f;
  background-repeat: no-repeat;
  background-position: center top 10px
}
.footer a:hover {
  color: #eef8ff
}
.mainmenu {
  background-color: #161819;
  border-top-right-radius: 15px;
  border-top-left-radius: 15px;
  clear: both







|




|




|







682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
}
.artifact_content blockquote:first-of-type {
  padding: 1px 20px;
  margin: 0 0 20px;
  background: #000;
  border-radius: 5px
}
footer {
  padding: 10px 0 60px;
  border-top: 0;
  color: #888
}
footer a {
  color: #527b8f;
  background-repeat: no-repeat;
  background-position: center top 10px
}
footer a:hover {
  color: #eef8ff
}
.mainmenu {
  background-color: #161819;
  border-top-right-radius: 15px;
  border-top-left-radius: 15px;
  clear: both
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
.mainmenu li:hover {
  background-color: #ff8000;
  border-radius: 5px
}
.mainmenu li:hover a {
  color: #000
}
div#hbdrop {
  background-color: #161819;
  border-radius: 15px;
  display: none;
  width: 100%;
  position: absolute;
  z-index: 20;
}







|







731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
.mainmenu li:hover {
  background-color: #ff8000;
  border-radius: 5px
}
.mainmenu li:hover a {
  color: #000
}
nav#hbdrop {
  background-color: #161819;
  border-radius: 15px;
  display: none;
  width: 100%;
  position: absolute;
  z-index: 20;
}

Changes to skins/ardoise/footer.txt.