/ Check-in [1f0197d5]
Login

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

Overview
Comment:Bug fixes from Oleg Oleinick (CVS 195)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:1f0197d504fa2bde15b287ac6c0102cacdb1e482
User & Date: drh 2001-04-03 16:53:22
Context
2001-04-04
11:48
Added transaction support (CVS 196) check-in: 35a8feed user: drh tags: trunk
2001-04-03
16:53
Bug fixes from Oleg Oleinick (CVS 195) check-in: 1f0197d5 user: drh tags: trunk
2001-03-20
22:15
Version 1.0.27 (CVS 476) check-in: 833291c2 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Makefile.in.

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
         update.o util.o vdbe.o where.o tclsqlite.o

# All of the source code files.
#
SRC = \
  $(TOP)/src/build.c \
  $(TOP)/src/dbbe.c \
  $(TOP)/src/dbbegdbm.c \
  $(TOP)/src/dbbemem.c \
  $(TOP)/src/dbbe.h \
  $(TOP)/src/dbbemem.c \
  $(TOP)/src/delete.c \
  $(TOP)/src/expr.c \
  $(TOP)/src/insert.c \
  $(TOP)/src/main.c \
  $(TOP)/src/parse.y \
  $(TOP)/src/printf.c \







<
|
|







52
53
54
55
56
57
58

59
60
61
62
63
64
65
66
67
         update.o util.o vdbe.o where.o tclsqlite.o

# All of the source code files.
#
SRC = \
  $(TOP)/src/build.c \
  $(TOP)/src/dbbe.c \

  $(TOP)/src/dbbe.h \
  $(TOP)/src/dbbegdbm.c \
  $(TOP)/src/dbbemem.c \
  $(TOP)/src/delete.c \
  $(TOP)/src/expr.c \
  $(TOP)/src/insert.c \
  $(TOP)/src/main.c \
  $(TOP)/src/parse.y \
  $(TOP)/src/printf.c \

Changes to VERSION.

1
1.0.27
|
1
1.0.28

Changes to src/dbbe.h.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
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
...
161
162
163
164
165
166
167
168

169
170
171
** This file defines the interface to the database backend (Dbbe).
**
** The database backend is designed to be as general as possible
** so that it can easily be replaced by a different backend.
** This library was originally designed to support the following
** backends: GDBM, NDBM, SDBM, Berkeley DB.
**
** $Id: dbbe.h,v 1.11 2001/03/20 22:05:00 drh Exp $
*/
#ifndef _SQLITE_DBBE_H_
#define _SQLITE_DBBE_H_
#include <stdio.h>

/*
** The database backend supports two opaque structures.  A Dbbe is
................................................................................
** of this structure is assigned to the Dbbe structure that sqlileDbbeOpen
** returns.
*/
struct DbbeMethods {
  /* Close the whole database. */
  void (*Close)(Dbbe*);

  /* Open a cursor into particular file of a previously opened database.
  ** Create the file if it doesn't already exist and writeable!=0.  zName
  ** is the base name of the file to be opened.  This routine will add

  ** an appropriate path and extension to the filename to locate the 
  ** actual file.
  **
  ** The keyType parameter is TRUE if this table will only be accessed
  ** using integer keys.  This parameter allows the database backend to
  ** use a faster algorithm for the special case of integer keys, if it
  ** wants to.
  **
  ** If zName is 0 or "", then a temporary file is created that
  ** will be deleted when closed.
  */
  int (*OpenCursor)(Dbbe*, const char *zName, int writeable, 
                    int intKeyOnly, DbbeCursor**);

  /* Delete a table from the database */
  void (*DropTable)(Dbbe*, const char *zTableName);
................................................................................
** the backend drivers only.  Users should not access or modify
** this structure in any way other than the read the method pointers
** in Dbbe.x.
*/
struct Dbbe {
  struct DbbeMethods *x; /* Backend-specific methods for database access */
  /* There used to be other information here, but it has since
  ** been removed.  */

};

#endif /* defined(_SQLITE_DBBE_H_) */







|







 







|
|
|
>
|


|




|







 







|
>



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
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
...
162
163
164
165
166
167
168
169
170
171
172
173
** This file defines the interface to the database backend (Dbbe).
**
** The database backend is designed to be as general as possible
** so that it can easily be replaced by a different backend.
** This library was originally designed to support the following
** backends: GDBM, NDBM, SDBM, Berkeley DB.
**
** $Id: dbbe.h,v 1.12 2001/04/03 16:53:22 drh Exp $
*/
#ifndef _SQLITE_DBBE_H_
#define _SQLITE_DBBE_H_
#include <stdio.h>

/*
** The database backend supports two opaque structures.  A Dbbe is
................................................................................
** of this structure is assigned to the Dbbe structure that sqlileDbbeOpen
** returns.
*/
struct DbbeMethods {
  /* Close the whole database. */
  void (*Close)(Dbbe*);

  /* Open a cursor into a particular table of a previously opened database.
  ** Create the table if it doesn't already exist and writeable!=0.  zName
  ** is the base name of the table to be opened.  If the database is 
  ** implement as one file per table, then this routine will add an
  ** appropriate path and extension to the table name to locate the 
  ** actual file.
  **
  ** The intKeyOnly parameter is TRUE if this table will only be accessed
  ** using integer keys.  This parameter allows the database backend to
  ** use a faster algorithm for the special case of integer keys, if it
  ** wants to.
  **
  ** If zName is 0 or "", then a temporary table is created that
  ** will be deleted when closed.
  */
  int (*OpenCursor)(Dbbe*, const char *zName, int writeable, 
                    int intKeyOnly, DbbeCursor**);

  /* Delete a table from the database */
  void (*DropTable)(Dbbe*, const char *zTableName);
................................................................................
** the backend drivers only.  Users should not access or modify
** this structure in any way other than the read the method pointers
** in Dbbe.x.
*/
struct Dbbe {
  struct DbbeMethods *x; /* Backend-specific methods for database access */
  /* There used to be other information here, but it has since
  ** been removed.  We'll keep the same design, though, in case we
  ** ever want to add some new fields in the future. */
};

#endif /* defined(_SQLITE_DBBE_H_) */

Changes to src/dbbegdbm.c.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
42
43
44
45
46
47
48



49
50
51
52
53
54
55
...
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
** sqlite and the code that does the actually reading and writing
** of information to the disk.
**
** This file uses GDBM as the database backend.  It should be
** relatively simple to convert to a different database such
** as NDBM, SDBM, or BerkeleyDB.
**
** $Id: dbbegdbm.c,v 1.4 2001/03/20 22:05:00 drh Exp $
*/
#include "sqliteInt.h"
#include <gdbm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>
................................................................................
/*
** Information about each open disk file is an instance of this 
** structure.  There will only be one such structure for each
** disk file.  If the VDBE opens the same file twice (as will happen
** for a self-join, for example) then two DbbeCursor structures are
** created but there is only a single BeFile structure with an
** nRef of 2.



*/
typedef struct BeFile BeFile;
struct BeFile {
  char *zName;            /* Name of the file */
  GDBM_FILE dbf;          /* The file itself */
  int nRef;               /* Number of references */
  int delOnClose;         /* Delete when closing */
................................................................................
}

/*
** This variable contains pointers to all of the access methods
** used to implement the GDBM backend.
*/
static struct DbbeMethods gdbmMethods = {
  /* n         Close */   sqliteGdbmClose,
  /*      OpenCursor */   sqliteGdbmOpenCursor,
  /*       DropTable */   sqliteGdbmDropTable,
  /* ReorganizeTable */   sqliteGdbmReorganizeTable,
  /*     CloseCursor */   sqliteGdbmCloseCursor,
  /*           Fetch */   sqliteGdbmFetch,
  /*            Test */   sqliteGdbmTest,
  /*         CopyKey */   sqliteGdbmCopyKey,







|







 







>
>
>







 







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
...
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
** sqlite and the code that does the actually reading and writing
** of information to the disk.
**
** This file uses GDBM as the database backend.  It should be
** relatively simple to convert to a different database such
** as NDBM, SDBM, or BerkeleyDB.
**
** $Id: dbbegdbm.c,v 1.5 2001/04/03 16:53:22 drh Exp $
*/
#include "sqliteInt.h"
#include <gdbm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>
................................................................................
/*
** Information about each open disk file is an instance of this 
** structure.  There will only be one such structure for each
** disk file.  If the VDBE opens the same file twice (as will happen
** for a self-join, for example) then two DbbeCursor structures are
** created but there is only a single BeFile structure with an
** nRef of 2.
**
** This backend uses a separate disk file for each database table
** and index.
*/
typedef struct BeFile BeFile;
struct BeFile {
  char *zName;            /* Name of the file */
  GDBM_FILE dbf;          /* The file itself */
  int nRef;               /* Number of references */
  int delOnClose;         /* Delete when closing */
................................................................................
}

/*
** This variable contains pointers to all of the access methods
** used to implement the GDBM backend.
*/
static struct DbbeMethods gdbmMethods = {
  /*           Close */   sqliteGdbmClose,
  /*      OpenCursor */   sqliteGdbmOpenCursor,
  /*       DropTable */   sqliteGdbmDropTable,
  /* ReorganizeTable */   sqliteGdbmReorganizeTable,
  /*     CloseCursor */   sqliteGdbmCloseCursor,
  /*           Fetch */   sqliteGdbmFetch,
  /*            Test */   sqliteGdbmTest,
  /*         CopyKey */   sqliteGdbmCopyKey,

Changes to src/dbbemem.c.

23
24
25
26
27
28
29


30
31
32
33
34
35
36
37
38
...
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
*************************************************************************
** This file contains code to implement the database backend (DBBE)
** for sqlite.  The database backend is the interface between
** sqlite and the code that does the actually reading and writing
** of information to the disk.
**
** This file uses an in-memory hash table as the database backend. 


**
** $Id: dbbemem.c,v 1.11 2001/03/20 22:05:00 drh Exp $
*/
#include "sqliteInt.h"
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>

................................................................................
}

/*
** This variable contains pointers to all of the access methods
** used to implement the MEMORY backend.
*/
static struct DbbeMethods memoryMethods = {
  /* n         Close */   sqliteMemClose,
  /*      OpenCursor */   sqliteMemOpenCursor,
  /*       DropTable */   sqliteMemDropTable,
  /* ReorganizeTable */   sqliteMemReorganizeTable,
  /*     CloseCursor */   sqliteMemCloseCursor,
  /*           Fetch */   sqliteMemFetch,
  /*            Test */   sqliteMemTest,
  /*         CopyKey */   sqliteMemCopyKey,







>
>

|







 







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
*************************************************************************
** This file contains code to implement the database backend (DBBE)
** for sqlite.  The database backend is the interface between
** sqlite and the code that does the actually reading and writing
** of information to the disk.
**
** This file uses an in-memory hash table as the database backend. 
** Nothing is ever written to disk using this backend.  All information
** is forgotten when the program exits.
**
** $Id: dbbemem.c,v 1.12 2001/04/03 16:53:22 drh Exp $
*/
#include "sqliteInt.h"
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>

................................................................................
}

/*
** This variable contains pointers to all of the access methods
** used to implement the MEMORY backend.
*/
static struct DbbeMethods memoryMethods = {
  /*           Close */   sqliteMemClose,
  /*      OpenCursor */   sqliteMemOpenCursor,
  /*       DropTable */   sqliteMemDropTable,
  /* ReorganizeTable */   sqliteMemReorganizeTable,
  /*     CloseCursor */   sqliteMemCloseCursor,
  /*           Fetch */   sqliteMemFetch,
  /*            Test */   sqliteMemTest,
  /*         CopyKey */   sqliteMemCopyKey,

Added src/pager.h.

















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
** Copyright (c) 2001 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License as published by the Free Software Foundation; either
** version 2 of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** General Public License for more details.
** 
** You should have received a copy of the GNU General Public
** License along with this library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA  02111-1307, USA.
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This header file defines the interface that the sqlite page cache
** subsystem.  The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
** @(#) $Id: pager.h,v 1.1 2001/04/03 16:53:22 drh Exp $
*/
#include "sqliteInt.h"

/*
** The size of one page
*/
#define SQLITE_PAGE_SIZE 1024

/*
** The type used to represent a page number.  The first page in a file
** is called page 1.  0 is used to represent "not a page".
*/
typedef unsigned int Pgno;

/*
** Each open file is managed by a separate instance of the "Pager" structure.
*/
typedef struct Pager Pager;

int sqlite_pager_open(Pager **ppPager, const char *zFilename);
int sqlite_pager_close(Pager *pPager);
int sqlite_pager_get(Pager *pPager, Pgno pgno, void **ppPage);
int sqlite_pager_unref(void*);
Pgno sqlite_pager_pagenumber(void*);
int sqlite_pager_write(void*);
int sqlite_pager_pagecount(Pager*);
int sqlite_pager_commit(Pager*);
int sqlite_pager_rollback(Pager*);

Changes to src/sqlite.h.in.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
138
139
140
141
142
143
144


145
146
147
148
149
150
151
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This header file defines the interface that the sqlite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.9 2001/01/20 19:52:49 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** The version of the SQLite library.
................................................................................
#define SQLITE_NOMEM     6    /* A malloc() failed */
#define SQLITE_READONLY  7    /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT 8    /* Operation terminated by sqlite_interrupt() */
#define SQLITE_IOERR     9    /* Disk full or other I/O error */
#define SQLITE_CORRUPT   10   /* The database disk image is malformed */
#define SQLITE_NOTFOUND  11   /* Table or record not found */
#define SQLITE_FULL      12   /* Insertion failed because database is full */



/* This function causes any pending database operation to abort and
** return at its earliest opportunity.  This routine is typically
** called in response to a user action such as pressing "Cancel"
** or Ctrl-C where the user wants a long query operation to halt
** immediately.
*/







|







 







>
>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This header file defines the interface that the sqlite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.10 2001/04/03 16:53:22 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** The version of the SQLite library.
................................................................................
#define SQLITE_NOMEM     6    /* A malloc() failed */
#define SQLITE_READONLY  7    /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT 8    /* Operation terminated by sqlite_interrupt() */
#define SQLITE_IOERR     9    /* Disk full or other I/O error */
#define SQLITE_CORRUPT   10   /* The database disk image is malformed */
#define SQLITE_NOTFOUND  11   /* Table or record not found */
#define SQLITE_FULL      12   /* Insertion failed because database is full */
#define SQLITE_CANTOPEN  13   /* Unable to open the database file */
#define SQLITE_PROTOCOL  14   /* Database lock protocol error */

/* This function causes any pending database operation to abort and
** return at its earliest opportunity.  This routine is typically
** called in response to a user action such as pressing "Cancel"
** or Ctrl-C where the user wants a long query operation to halt
** immediately.
*/

Changes to src/tclsqlite.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
49
50
51
52
53
54
55

56
57
58
59
60
61
62
..
84
85
86
87
88
89
90


91
92
93
94
95
96
97
98
...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
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
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.13 2001/01/31 13:28:09 drh Exp $
*/
#ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */

#include "sqlite.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
................................................................................
*/
typedef struct CallbackData CallbackData;
struct CallbackData {
  Tcl_Interp *interp;       /* The TCL interpreter */
  char *zArray;             /* The array into which data is written */
  Tcl_Obj *pCode;           /* The code to execute for each row */
  int once;                 /* Set only for the first invocation of callback */

};

/*
** Called for each row of the result.
*/
static int DbEvalCallback(
  void *clientData,      /* An instance of CallbackData */
................................................................................
      char *z = azCol[i];
      if( z==0 ) z = "";
      Tcl_SetVar(cbData->interp, azN[i], z, 0);
    }
  }
  cbData->once = 0;
  rc = Tcl_EvalObj(cbData->interp, cbData->pCode);


  return rc!=TCL_OK && rc!=TCL_CONTINUE;
}

/*
** This is an alternative callback for database queries.  Instead
** of invoking a TCL script to handle the result, this callback just
** appends each column of the result to a list.  After the query
** is complete, the list is returned.
................................................................................
** and calls that connection "db1".  The second command causes this
** subroutine to be invoked.
*/
static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
  SqliteDb *pDb = (SqliteDb*)cd;
  int choice;
  static char *DB_optStrs[] = {
     "busy",   "close",  "complete",  "eval",  "timeout"
  };
  enum DB_opts {
     DB_BUSY,  DB_CLOSE, DB_COMPLETE, DB_EVAL, DB_TIMEOUT
  };

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
................................................................................
    zSql = Tcl_GetStringFromObj(objv[2], 0);
    Tcl_IncrRefCount(objv[2]);
    if( objc==5 ){
      cbData.interp = interp;
      cbData.once = 1;
      cbData.zArray = Tcl_GetStringFromObj(objv[3], 0);
      cbData.pCode = objv[4];

      zErrMsg = 0;
      Tcl_IncrRefCount(objv[3]);
      Tcl_IncrRefCount(objv[4]);
      rc = sqlite_exec(pDb->db, zSql, DbEvalCallback, &cbData, &zErrMsg);
      Tcl_DecrRefCount(objv[4]);
      Tcl_DecrRefCount(objv[3]);

    }else{
      Tcl_Obj *pList = Tcl_NewObj();

      rc = sqlite_exec(pDb->db, zSql, DbEvalCallback2, pList, &zErrMsg);
      Tcl_SetObjResult(interp, pList);
    }
    if( zErrMsg ){
      Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
      free(zErrMsg);



    }
    Tcl_DecrRefCount(objv[2]);
    return rc;
  }

  /*
  **     $db timeout MILLESECONDS







|







 







>







 







>
>
|







 







|







 







>






>


>






>
>
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
...
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
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.14 2001/04/03 16:53:22 drh Exp $
*/
#ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */

#include "sqlite.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
................................................................................
*/
typedef struct CallbackData CallbackData;
struct CallbackData {
  Tcl_Interp *interp;       /* The TCL interpreter */
  char *zArray;             /* The array into which data is written */
  Tcl_Obj *pCode;           /* The code to execute for each row */
  int once;                 /* Set only for the first invocation of callback */
  int tcl_rc;               /* Return code from TCL script */
};

/*
** Called for each row of the result.
*/
static int DbEvalCallback(
  void *clientData,      /* An instance of CallbackData */
................................................................................
      char *z = azCol[i];
      if( z==0 ) z = "";
      Tcl_SetVar(cbData->interp, azN[i], z, 0);
    }
  }
  cbData->once = 0;
  rc = Tcl_EvalObj(cbData->interp, cbData->pCode);
  if( rc==TCL_CONTINUE ) rc = TCL_OK;
  cbData->tcl_rc = rc;
  return rc!=TCL_OK;
}

/*
** This is an alternative callback for database queries.  Instead
** of invoking a TCL script to handle the result, this callback just
** appends each column of the result to a list.  After the query
** is complete, the list is returned.
................................................................................
** and calls that connection "db1".  The second command causes this
** subroutine to be invoked.
*/
static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
  SqliteDb *pDb = (SqliteDb*)cd;
  int choice;
  static char *DB_optStrs[] = {
     "busy",   "close",  "complete",  "eval",  "timeout", 0
  };
  enum DB_opts {
     DB_BUSY,  DB_CLOSE, DB_COMPLETE, DB_EVAL, DB_TIMEOUT
  };

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
................................................................................
    zSql = Tcl_GetStringFromObj(objv[2], 0);
    Tcl_IncrRefCount(objv[2]);
    if( objc==5 ){
      cbData.interp = interp;
      cbData.once = 1;
      cbData.zArray = Tcl_GetStringFromObj(objv[3], 0);
      cbData.pCode = objv[4];
      cbData.tcl_rc = TCL_OK;
      zErrMsg = 0;
      Tcl_IncrRefCount(objv[3]);
      Tcl_IncrRefCount(objv[4]);
      rc = sqlite_exec(pDb->db, zSql, DbEvalCallback, &cbData, &zErrMsg);
      Tcl_DecrRefCount(objv[4]);
      Tcl_DecrRefCount(objv[3]);
      if( cbData.tcl_rc==TCL_BREAK ){ cbData.tcl_rc = TCL_OK; }
    }else{
      Tcl_Obj *pList = Tcl_NewObj();
      cbData.tcl_rc = TCL_OK;
      rc = sqlite_exec(pDb->db, zSql, DbEvalCallback2, pList, &zErrMsg);
      Tcl_SetObjResult(interp, pList);
    }
    if( zErrMsg ){
      Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
      free(zErrMsg);
      rc = TCL_ERROR;
    }else{
      rc = cbData.tcl_rc;
    }
    Tcl_DecrRefCount(objv[2]);
    return rc;
  }

  /*
  **     $db timeout MILLESECONDS

Deleted src/test.file.

1
hi
<


Changes to test/dbbe.test.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
130
131
132
133
134
135
136
137
138
139
140
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is exercising the code in dbbe.c.
#
# $Id: dbbe.test,v 1.6 2001/03/20 12:55:14 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to open a database that does not exist.
#
do_test dbbe-1.1 {
................................................................................
  forcedelete testdb
  sqlite db testdb 0666
  execsql {CREATE TABLE t1(x int)}
  db close
  sqlite db testdb 0444
  set v [catch {execsql {INSERT INTO t1 VALUES(1)}} msg]
  lappend v $msg
} {7 {table t1 is readonly}}


finish_test







|







 







|



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
130
131
132
133
134
135
136
137
138
139
140
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is exercising the code in dbbe.c.
#
# $Id: dbbe.test,v 1.7 2001/04/03 16:53:22 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to open a database that does not exist.
#
do_test dbbe-1.1 {
................................................................................
  forcedelete testdb
  sqlite db testdb 0666
  execsql {CREATE TABLE t1(x int)}
  db close
  sqlite db testdb 0444
  set v [catch {execsql {INSERT INTO t1 VALUES(1)}} msg]
  lappend v $msg
} {1 {table t1 is readonly}}


finish_test

Changes to test/lock.test.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is database locks.
#
# $Id: lock.test,v 1.7 2001/03/20 12:55:14 drh Exp $

if {$dbprefix=="gdbm:" && $::tcl_platform(platform)!="windows"} {

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a largish table
................................................................................
} {}

do_probtest lock-1.2 {
  # Now try to update the database
  #
  set v [catch {execsql {UPDATE big SET f2='xyz' WHERE f1=11}} msg]
  lappend v $msg
} {5 {table big is locked}}

do_probtest lock-1.3 {
  # Try to update the database in a separate process
  #
  set f [open update.sql w]
  puts $f ".timeout 0"
  puts $f "UPDATE big SET f2='xyz' WHERE f1=11;"







|







 







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is database locks.
#
# $Id: lock.test,v 1.8 2001/04/03 16:53:22 drh Exp $

if {$dbprefix=="gdbm:" && $::tcl_platform(platform)!="windows"} {

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a largish table
................................................................................
} {}

do_probtest lock-1.2 {
  # Now try to update the database
  #
  set v [catch {execsql {UPDATE big SET f2='xyz' WHERE f1=11}} msg]
  lappend v $msg
} {1 {table big is locked}}

do_probtest lock-1.3 {
  # Try to update the database in a separate process
  #
  set f [open update.sql w]
  puts $f ".timeout 0"
  puts $f "UPDATE big SET f2='xyz' WHERE f1=11;"

Added test/tclsqlite.test.

































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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
# Copyright (c) 1999, 2000 D. Richard Hipp
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
# 
# You should have received a copy of the GNU General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA  02111-1307, USA.
#
# Author contact information:
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for TCL interface to the
# SQLite library. 
#
# Actually, all tests are based on the TCL interface, so the main
# interface is pretty well tested.  This file contains some addition
# tests for fringe issues that the main test suite does not cover.
#
# $Id: tclsqlite.test,v 1.1 2001/04/03 16:53:22 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Check the error messages generated by tclsqlite
#
do_test tcl-1.1 {
  set v [catch {sqlite bogus} msg]
  lappend v $msg
} {1 {wrong # args: should be "sqlite HANDLE FILENAME ?MODE?"}}
do_test tcl-1.2 {
  set v [catch {db bogus} msg]
  lappend v $msg
} {1 {bad option "bogus": must be busy, close, complete, eval, or timeout}}
do_test tcl-1.3 {
  execsql {CREATE TABLE t1(a int, b int)}
  execsql {INSERT INTO t1 VALUES(10,20)}
  set v [catch {
    db eval {SELECT * FROM t1} data {
      error "The error message"
    }
  } msg]
  lappend v $msg
} {1 {The error message}}
do_test tcl-1.4 {
  set v [catch {
    db eval {SELECT * FROM t2} data {
      error "The error message"
    }
  } msg]
  lappend v $msg
} {1 {no such table: t2}}
do_test tcl-1.5 {
  set v [catch {
    db eval {SELECT * FROM t1} data {
      break
    }
  } msg]
  lappend v $msg
} {0 {}}
do_test tcl-1.6 {
  set v [catch {
    db eval {SELECT * FROM t1} data {
      expr x*
    }
  } msg]
  lappend v $msg
} {1 {syntax error in expression "x*"}}

finish_test

Changes to tool/lemon.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
259
260
261
262
263
264
265

266
267
268
269
270
271
272
...
275
276
277
278
279
280
281


282
283
284
285
286
287
288
....
1212
1213
1214
1215
1216
1217
1218

1219
1220
1221

1222
1223
1224
1225
1226
1227
1228
....
1963
1964
1965
1966
1967
1968
1969



1970
1971
1972
1973
1974
1975
1976
....
1981
1982
1983
1984
1985
1986
1987


1988
1989
1990
1991
1992
1993
1994
....
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
....
2639
2640
2641
2642
2643
2644
2645


2646
2647
2648
2649
2650
2651
2652
....
2693
2694
2695
2696
2697
2698
2699
2700
2701



2702
2703
2704
2705
2706
2707
2708
2709
2710
....
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
....
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
....
2836
2837
2838
2839
2840
2841
2842



2843
2844
2845
2846
2847
2848
2849
....
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
....
3154
3155
3156
3157
3158
3159
3160














3161
3162
3163
3164
3165
3166
3167
/*
** Copyright (c) 1991, 1994, 1997, 1998 D. Richard Hipp
**
** This file contains all sources (including headers) to the LEMON
** LALR(1) parser generator.  The sources have been combined into a
** single file to make it easy to include LEMON as part of another
** program.
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License as published by the Free Software Foundation; either
** version 2 of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
................................................................................
  int nterminal;           /* Number of terminal symbols */
  struct symbol **symbols; /* Sorted array of pointers to symbols */
  int errorcnt;            /* Number of errors */
  struct symbol *errsym;   /* The error symbol */
  char *name;              /* Name of the generated parser */
  char *arg;               /* Declaration of the 3th argument to parser */
  char *tokentype;         /* Type of terminal symbols in the parser stack */

  char *start;             /* Name of the start symbol for the grammar */
  char *stacksize;         /* Size of the parser stack */
  char *include;           /* Code to put at the start of the C file */
  int  includeln;          /* Line number for start of include code */
  char *error;             /* Code to execute when an error is seen */
  int  errorln;            /* Line number for start of error code */
  char *overflow;          /* Code to execute on a stack overflow */
................................................................................
  int  failureln;          /* Line number for start of failure code */
  char *accept;            /* Code to execute when the parser excepts */
  int  acceptln;           /* Line number for the start of accept code */
  char *extracode;         /* Code appended to the generated file */
  int  extracodeln;        /* Line number for the start of the extra code */
  char *tokendest;         /* Code to execute to destroy token data */
  int  tokendestln;        /* Line number for token destroyer code */


  char *filename;          /* Name of the input file */
  char *outname;           /* Name of the current output file */
  char *tokenprefix;       /* A prefix added to token names in the .h file */
  int nconflict;           /* Number of parsing conflicts */
  int tablesize;           /* Size of the parse tables */
  int basisflag;           /* Print only basis configurations */
  char *argv0;             /* Name of the program */
................................................................................
  Symbol_init();
  State_init();
  lem.argv0 = argv[0];
  lem.filename = OptArg(0);
  lem.basisflag = basisflag;
  lem.nconflict = 0;
  lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0;

  lem.stacksize = 0;
  lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest =
     lem.tokenprefix = lem.outname = lem.extracode = 0;

  lem.tablesize = 0;
  Symbol_new("$");
  lem.errsym = Symbol_new("error");

  /* Parse the input file */
  Parse(&lem);
  if( lem.errorcnt ) exit(lem.errorcnt);
................................................................................
          psp->decllnslot = &psp->gp->includeln;
	}else if( strcmp(x,"code")==0 ){
          psp->declargslot = &(psp->gp->extracode);
          psp->decllnslot = &psp->gp->extracodeln;
	}else if( strcmp(x,"token_destructor")==0 ){
          psp->declargslot = &psp->gp->tokendest;
          psp->decllnslot = &psp->gp->tokendestln;



	}else if( strcmp(x,"token_prefix")==0 ){
          psp->declargslot = &psp->gp->tokenprefix;
	}else if( strcmp(x,"syntax_error")==0 ){
          psp->declargslot = &(psp->gp->error);
          psp->decllnslot = &psp->gp->errorln;
	}else if( strcmp(x,"parse_accept")==0 ){
          psp->declargslot = &(psp->gp->accept);
................................................................................
	}else if( strcmp(x,"stack_overflow")==0 ){
          psp->declargslot = &(psp->gp->overflow);
          psp->decllnslot = &psp->gp->overflowln;
        }else if( strcmp(x,"extra_argument")==0 ){
          psp->declargslot = &(psp->gp->arg);
        }else if( strcmp(x,"token_type")==0 ){
          psp->declargslot = &(psp->gp->tokentype);


        }else if( strcmp(x,"stack_size")==0 ){
          psp->declargslot = &(psp->gp->stacksize);
        }else if( strcmp(x,"start_symbol")==0 ){
          psp->declargslot = &(psp->gp->start);
        }else if( strcmp(x,"left")==0 ){
          psp->preccounter++;
          psp->declassoc = LEFT;
................................................................................
            if( c=='\n' ) lineno++;
            if( prevc=='\\' ) prevc = 0;
            else              prevc = c;
	  }
	}
      }
      if( c==0 ){
        ErrorMsg(ps.filename,startline,
"C code starting on this line is not terminated before the end of the file.");
        ps.errorcnt++;
        nextcp = cp;
      }else{
        nextcp = cp+1;
      }
    }else if( isalnum(c) ){          /* Identifiers */
................................................................................
  if( cp ){
    sprintf(buf,"%.*s.lt",(int)cp-(int)lemp->filename,lemp->filename);
  }else{
    sprintf(buf,"%s.lt",lemp->filename);
  }
  if( access(buf,004)==0 ){
    tpltname = buf;


  }else{
    tpltname = pathsearch(lemp->argv0,templatename,0);
  }
  if( tpltname==0 ){
    fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
    templatename);
    lemp->errorcnt++;
................................................................................
 char *cp;

 int linecnt = 0;
 if( sp->type==TERMINAL ){
   cp = lemp->tokendest;
   if( cp==0 ) return;
   fprintf(out,"#line %d \"%s\"\n{",lemp->tokendestln,lemp->filename);
 }else{
   cp = sp->destructor;



   if( cp==0 ) return;
   fprintf(out,"#line %d \"%s\"\n{",sp->destructorln,lemp->filename);
 }
 for(; *cp; cp++){
   if( *cp=='$' && cp[1]=='$' ){
     fprintf(out,"(yypminor->yy%d)",sp->dtnum);
     cp++;
     continue;
   }
................................................................................
 }
 (*lineno) += 3 + linecnt;
 fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname);
 return;
}

/*
** Return TRUE (non-zero) if the given symbol has a distructor.
*/
int has_destructor(sp, lemp)
struct symbol *sp;
struct lemon *lemp;
{
  int ret;
  if( sp->type==TERMINAL ){
    ret = lemp->tokendest!=0;
  }else{
    ret = sp->destructor!=0;
  }
  return ret;
}

/* 
** Generate code which executes when the rule "rp" is reduced.  Write
** the code to "out".  Make sure lineno stays up-to-date.
................................................................................
 }

 /* Generate destructor code for RHS symbols which are not used in the
 ** reduce code */
 for(i=0; i<rp->nrhs; i++){
   if( rp->rhsalias[i] && !used[i] ){
     ErrorMsg(lemp->filename,rp->ruleline,
       "Label $%s$ for \"%s(%s)\" is never used.",
       rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
     lemp->errorcnt++;
   }else if( rp->rhsalias[i]==0 ){
     if( has_destructor(rp->rhs[i],lemp) ){
       fprintf(out,"  yy_destructor(%d,&yymsp[%d].minor);\n",
          rp->rhs[i]->index,i-rp->nrhs+1); (*lineno)++;
     }else{
................................................................................
  char *name;               /* Name of the parser */

  /* Allocate and initialize types[] and allocate stddt[] */
  arraysize = lemp->nsymbol * 2;
  types = (char**)malloc( arraysize * sizeof(char*) );
  for(i=0; i<arraysize; i++) types[i] = 0;
  maxdtlength = 0;



  for(i=0; i<lemp->nsymbol; i++){
    int len;
    struct symbol *sp = lemp->symbols[i];
    if( sp->datatype==0 ) continue;
    len = strlen(sp->datatype);
    if( len>maxdtlength ) maxdtlength = len;
  }
................................................................................
  if( types==0 || stddt==0 ){
    fprintf(stderr,"Out of memory.\n");
    exit(1);
  }

  /* Build a hash table of datatypes. The ".dtnum" field of each symbol
  ** is filled in with the hash index plus 1.  A ".dtnum" value of 0 is
  ** used for terminal symbols and for nonterminals which don't specify

  ** a datatype using the %type directive. */

  for(i=0; i<lemp->nsymbol; i++){
    struct symbol *sp = lemp->symbols[i];
    char *cp;
    if( sp==lemp->errsym ){
      sp->dtnum = arraysize+1;
      continue;
    }
    if( sp->type!=NONTERMINAL || sp->datatype==0 ){
      sp->dtnum = 0;
      continue;
    }
    cp = sp->datatype;

    j = 0;
    while( isspace(*cp) ) cp++;
    while( *cp ) stddt[j++] = *cp++;
    while( j>0 && isspace(stddt[j-1]) ) j--;
    stddt[j] = 0;
    hash = 0;
    for(j=0; stddt[j]; j++){
................................................................................
  }
  for(i=0; i<lemp->nsymbol; i++){
    struct symbol *sp = lemp->symbols[i];
    if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
    fprintf(out,"    case %d:\n",sp->index); lineno++;
    emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
    fprintf(out,"      break;\n"); lineno++;














  }
  tplt_xfer(lemp->name,in,out,&lineno);

  /* Generate code which executes whenever the parser stack overflows */
  tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
  tplt_xfer(lemp->name,in,out,&lineno);






|
|







 







>







 







>
>







 







>



>







 







>
>
>







 







>
>







 







|







 







>
>







 







|

>
>
>

|







 







|









|







 







|







 







>
>
>







 







|
>
|
>







|




>







 







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







1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
....
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
....
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
....
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
....
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
....
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
....
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
....
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
....
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
....
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
....
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
....
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
/*
** Copyright (c) 1991, 1994, 1997, 1998 D. Richard Hipp
**
** This file contains all sources (including headers) to the LEMON
** LALR(1) parser generator.  The sources have been combined into a
** single file to make it easy to include LEMON in the source tree
** and Makefile of another program.
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License as published by the Free Software Foundation; either
** version 2 of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
................................................................................
  int nterminal;           /* Number of terminal symbols */
  struct symbol **symbols; /* Sorted array of pointers to symbols */
  int errorcnt;            /* Number of errors */
  struct symbol *errsym;   /* The error symbol */
  char *name;              /* Name of the generated parser */
  char *arg;               /* Declaration of the 3th argument to parser */
  char *tokentype;         /* Type of terminal symbols in the parser stack */
  char *vartype;           /* The default type of non-terminal symbols */
  char *start;             /* Name of the start symbol for the grammar */
  char *stacksize;         /* Size of the parser stack */
  char *include;           /* Code to put at the start of the C file */
  int  includeln;          /* Line number for start of include code */
  char *error;             /* Code to execute when an error is seen */
  int  errorln;            /* Line number for start of error code */
  char *overflow;          /* Code to execute on a stack overflow */
................................................................................
  int  failureln;          /* Line number for start of failure code */
  char *accept;            /* Code to execute when the parser excepts */
  int  acceptln;           /* Line number for the start of accept code */
  char *extracode;         /* Code appended to the generated file */
  int  extracodeln;        /* Line number for the start of the extra code */
  char *tokendest;         /* Code to execute to destroy token data */
  int  tokendestln;        /* Line number for token destroyer code */
  char *vardest;           /* Code for the default non-terminal destructor */
  int  vardestln;          /* Line number for default non-term destructor code*/
  char *filename;          /* Name of the input file */
  char *outname;           /* Name of the current output file */
  char *tokenprefix;       /* A prefix added to token names in the .h file */
  int nconflict;           /* Number of parsing conflicts */
  int tablesize;           /* Size of the parse tables */
  int basisflag;           /* Print only basis configurations */
  char *argv0;             /* Name of the program */
................................................................................
  Symbol_init();
  State_init();
  lem.argv0 = argv[0];
  lem.filename = OptArg(0);
  lem.basisflag = basisflag;
  lem.nconflict = 0;
  lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0;
  lem.vartype = 0;
  lem.stacksize = 0;
  lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest =
     lem.tokenprefix = lem.outname = lem.extracode = 0;
  lem.vardest = 0;
  lem.tablesize = 0;
  Symbol_new("$");
  lem.errsym = Symbol_new("error");

  /* Parse the input file */
  Parse(&lem);
  if( lem.errorcnt ) exit(lem.errorcnt);
................................................................................
          psp->decllnslot = &psp->gp->includeln;
	}else if( strcmp(x,"code")==0 ){
          psp->declargslot = &(psp->gp->extracode);
          psp->decllnslot = &psp->gp->extracodeln;
	}else if( strcmp(x,"token_destructor")==0 ){
          psp->declargslot = &psp->gp->tokendest;
          psp->decllnslot = &psp->gp->tokendestln;
	}else if( strcmp(x,"default_destructor")==0 ){
          psp->declargslot = &psp->gp->vardest;
          psp->decllnslot = &psp->gp->vardestln;
	}else if( strcmp(x,"token_prefix")==0 ){
          psp->declargslot = &psp->gp->tokenprefix;
	}else if( strcmp(x,"syntax_error")==0 ){
          psp->declargslot = &(psp->gp->error);
          psp->decllnslot = &psp->gp->errorln;
	}else if( strcmp(x,"parse_accept")==0 ){
          psp->declargslot = &(psp->gp->accept);
................................................................................
	}else if( strcmp(x,"stack_overflow")==0 ){
          psp->declargslot = &(psp->gp->overflow);
          psp->decllnslot = &psp->gp->overflowln;
        }else if( strcmp(x,"extra_argument")==0 ){
          psp->declargslot = &(psp->gp->arg);
        }else if( strcmp(x,"token_type")==0 ){
          psp->declargslot = &(psp->gp->tokentype);
        }else if( strcmp(x,"default_type")==0 ){
          psp->declargslot = &(psp->gp->vartype);
        }else if( strcmp(x,"stack_size")==0 ){
          psp->declargslot = &(psp->gp->stacksize);
        }else if( strcmp(x,"start_symbol")==0 ){
          psp->declargslot = &(psp->gp->start);
        }else if( strcmp(x,"left")==0 ){
          psp->preccounter++;
          psp->declassoc = LEFT;
................................................................................
            if( c=='\n' ) lineno++;
            if( prevc=='\\' ) prevc = 0;
            else              prevc = c;
	  }
	}
      }
      if( c==0 ){
        ErrorMsg(ps.filename,ps.tokenlineno,
"C code starting on this line is not terminated before the end of the file.");
        ps.errorcnt++;
        nextcp = cp;
      }else{
        nextcp = cp+1;
      }
    }else if( isalnum(c) ){          /* Identifiers */
................................................................................
  if( cp ){
    sprintf(buf,"%.*s.lt",(int)cp-(int)lemp->filename,lemp->filename);
  }else{
    sprintf(buf,"%s.lt",lemp->filename);
  }
  if( access(buf,004)==0 ){
    tpltname = buf;
  }else if( access(templatename,004)==0 ){
    tpltname = templatename;
  }else{
    tpltname = pathsearch(lemp->argv0,templatename,0);
  }
  if( tpltname==0 ){
    fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
    templatename);
    lemp->errorcnt++;
................................................................................
 char *cp;

 int linecnt = 0;
 if( sp->type==TERMINAL ){
   cp = lemp->tokendest;
   if( cp==0 ) return;
   fprintf(out,"#line %d \"%s\"\n{",lemp->tokendestln,lemp->filename);
 }else if( sp->destructor ){
   cp = sp->destructor;
   fprintf(out,"#line %d \"%s\"\n{",sp->destructorln,lemp->filename);
 }else if( lemp->vardest ){
   cp = lemp->vardest;
   if( cp==0 ) return;
   fprintf(out,"#line %d \"%s\"\n{",lemp->vardestln,lemp->filename);
 }
 for(; *cp; cp++){
   if( *cp=='$' && cp[1]=='$' ){
     fprintf(out,"(yypminor->yy%d)",sp->dtnum);
     cp++;
     continue;
   }
................................................................................
 }
 (*lineno) += 3 + linecnt;
 fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname);
 return;
}

/*
** Return TRUE (non-zero) if the given symbol has a destructor.
*/
int has_destructor(sp, lemp)
struct symbol *sp;
struct lemon *lemp;
{
  int ret;
  if( sp->type==TERMINAL ){
    ret = lemp->tokendest!=0;
  }else{
    ret = lemp->vardest!=0 || sp->destructor!=0;
  }
  return ret;
}

/* 
** Generate code which executes when the rule "rp" is reduced.  Write
** the code to "out".  Make sure lineno stays up-to-date.
................................................................................
 }

 /* Generate destructor code for RHS symbols which are not used in the
 ** reduce code */
 for(i=0; i<rp->nrhs; i++){
   if( rp->rhsalias[i] && !used[i] ){
     ErrorMsg(lemp->filename,rp->ruleline,
       "Label %s for \"%s(%s)\" is never used.",
       rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
     lemp->errorcnt++;
   }else if( rp->rhsalias[i]==0 ){
     if( has_destructor(rp->rhs[i],lemp) ){
       fprintf(out,"  yy_destructor(%d,&yymsp[%d].minor);\n",
          rp->rhs[i]->index,i-rp->nrhs+1); (*lineno)++;
     }else{
................................................................................
  char *name;               /* Name of the parser */

  /* Allocate and initialize types[] and allocate stddt[] */
  arraysize = lemp->nsymbol * 2;
  types = (char**)malloc( arraysize * sizeof(char*) );
  for(i=0; i<arraysize; i++) types[i] = 0;
  maxdtlength = 0;
  if( lemp->vartype ){
    maxdtlength = strlen(lemp->vartype);
  }
  for(i=0; i<lemp->nsymbol; i++){
    int len;
    struct symbol *sp = lemp->symbols[i];
    if( sp->datatype==0 ) continue;
    len = strlen(sp->datatype);
    if( len>maxdtlength ) maxdtlength = len;
  }
................................................................................
  if( types==0 || stddt==0 ){
    fprintf(stderr,"Out of memory.\n");
    exit(1);
  }

  /* Build a hash table of datatypes. The ".dtnum" field of each symbol
  ** is filled in with the hash index plus 1.  A ".dtnum" value of 0 is
  ** used for terminal symbols.  If there is no %default_type defined then
  ** 0 is also used as the .dtnum value for nonterminals which do not specify
  ** a datatype using the %type directive.
  */
  for(i=0; i<lemp->nsymbol; i++){
    struct symbol *sp = lemp->symbols[i];
    char *cp;
    if( sp==lemp->errsym ){
      sp->dtnum = arraysize+1;
      continue;
    }
    if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
      sp->dtnum = 0;
      continue;
    }
    cp = sp->datatype;
    if( cp==0 ) cp = lemp->vartype;
    j = 0;
    while( isspace(*cp) ) cp++;
    while( *cp ) stddt[j++] = *cp++;
    while( j>0 && isspace(stddt[j-1]) ) j--;
    stddt[j] = 0;
    hash = 0;
    for(j=0; stddt[j]; j++){
................................................................................
  }
  for(i=0; i<lemp->nsymbol; i++){
    struct symbol *sp = lemp->symbols[i];
    if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
    fprintf(out,"    case %d:\n",sp->index); lineno++;
    emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
    fprintf(out,"      break;\n"); lineno++;
  }
  if( lemp->vardest ){
    struct symbol *dflt_sp = 0;
    for(i=0; i<lemp->nsymbol; i++){
      struct symbol *sp = lemp->symbols[i];
      if( sp==0 || sp->type==TERMINAL ||
          sp->index<=0 || sp->destructor!=0 ) continue;
      fprintf(out,"    case %d:\n",sp->index); lineno++;
      dflt_sp = sp;
    }
    if( dflt_sp!=0 ){
      emit_destructor_code(out,dflt_sp,lemp,&lineno);
      fprintf(out,"      break;\n"); lineno++;
    }
  }
  tplt_xfer(lemp->name,in,out,&lineno);

  /* Generate code which executes whenever the parser stack overflows */
  tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
  tplt_xfer(lemp->name,in,out,&lineno);

Changes to tool/lempar.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
...
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
...
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
...
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
...
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
/* Driver template for the LEMON parser generator.
** Copyright 1991-1995 by D. Richard Hipp.
*
* This version is specially modified for use with sqlite.
* @(#) $Id: lempar.c,v 1.1 2000/05/29 14:26:02 drh Exp $
*
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Library General Public
** License as published by the Free Software Foundation; either
** version 2 of the License, or (at your option) any later version.
** 
** This library is distributed in the hope that it will be useful,
................................................................................
**      line of trace output.  If NULL, then tracing is
**      turned off.
** </ul>
**
** Outputs:
** None.
*/
/* SQLITE MODIFICATION: Give the function file scope */
void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
  yyTraceFILE = TraceFILE;
  yyTracePrompt = zTracePrompt;
  if( yyTraceFILE==0 ) yyTracePrompt = 0;
  else if( yyTracePrompt==0 ) yyTraceFILE = 0;
}

................................................................................
static char *yyTokenName[] = { 
%%
};
#define YYTRACE(X) if( yyTraceFILE ) fprintf(yyTraceFILE,"%sReduce [%s].\n",yyTracePrompt,X);
#else
#define YYTRACE(X)
#endif













/* 
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
** malloc.
**
** Inputs:
** A pointer to the function used to allocate memory.
**
** Outputs:
** A pointer to a parser.  This pointer is used in subsequent calls
** to Parse and ParseFree.
*/
/* SQLITE MODIFICATION: Give the function file scope */
void *ParseAlloc(void *(*mallocProc)()){
  yyParser *pParser;
  pParser = (yyParser*)(*mallocProc)( sizeof(yyParser), __FILE__, __LINE__ );
  if( pParser ){
    pParser->idx = -1;
  }
  return pParser;
}

/* The following function deletes the value associated with a
................................................................................
** <ul>
** <li>  A pointer to the parser.  This should be a pointer
**       obtained from ParseAlloc.
** <li>  A pointer to a function used to reclaim memory obtained
**       from malloc.
** </ul>
*/
/* SQLITE MODIFICATION: Give the function file scope */
void ParseFree(
  void *p,               /* The parser to be deleted */
  void (*freeProc)()     /* Function used to reclaim memory */
){
  yyParser *pParser = (yyParser*)p;
  if( pParser==0 ) return;
  while( pParser->idx>=0 ) yy_pop_parser_stack(pParser);
  (*freeProc)(pParser, __FILE__, __LINE__);
}

/*
** Find the appropriate action for a parser given the look-ahead token.
**
** If the look-ahead token is YYNOCODE, then check to see if the action is
** independent of the look-ahead.  If it is, return the action, otherwise
................................................................................
static struct {
  YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */
  unsigned char nrhs;     /* Number of right-hand side symbols in the rule */
} yyRuleInfo[] = {
%%
};

static void yy_accept();  /* Forward declaration */

/*
** Perform a reduce action and the shift that must immediately
** follow the reduce.
*/
static void yy_reduce(
  yyParser *yypParser,         /* The parser */
................................................................................
** <li> The minor token number.
** <li> An option argument of a grammar-specified type.
** </ul>
**
** Outputs:
** None.
*/
/* SQLITE MODIFICATION: Give the function file scope */
void Parse(
  void *yyp,                   /* The parser */
  int yymajor,                 /* The major token code number */
  ParseTOKENTYPE yyminor       /* The value for the token */
  ParseANSIARGDECL
){
  YYMINORTYPE yyminorunion;


<
<
<
<







 







<







 







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













<
|

|







 







<

|
|




|







 







|







 







<







1
2




3
4
5
6
7
8
9
...
169
170
171
172
173
174
175

176
177
178
179
180
181
182
...
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
...
279
280
281
282
283
284
285

286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
...
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
...
476
477
478
479
480
481
482

483
484
485
486
487
488
489
/* Driver template for the LEMON parser generator.
** Copyright 1991-1995 by D. Richard Hipp.




**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Library General Public
** License as published by the Free Software Foundation; either
** version 2 of the License, or (at your option) any later version.
** 
** This library is distributed in the hope that it will be useful,
................................................................................
**      line of trace output.  If NULL, then tracing is
**      turned off.
** </ul>
**
** Outputs:
** None.
*/

void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
  yyTraceFILE = TraceFILE;
  yyTracePrompt = zTracePrompt;
  if( yyTraceFILE==0 ) yyTracePrompt = 0;
  else if( yyTracePrompt==0 ) yyTraceFILE = 0;
}

................................................................................
static char *yyTokenName[] = { 
%%
};
#define YYTRACE(X) if( yyTraceFILE ) fprintf(yyTraceFILE,"%sReduce [%s].\n",yyTracePrompt,X);
#else
#define YYTRACE(X)
#endif

/*
** This function returns the symbolic name associated with a token
** value.
*/
const char *ParseTokenName(int tokenType){
  if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
    return yyTokenName[tokenType];
  }else{
    return "Unknown";
  }
}

/* 
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
** malloc.
**
** Inputs:
** A pointer to the function used to allocate memory.
**
** Outputs:
** A pointer to a parser.  This pointer is used in subsequent calls
** to Parse and ParseFree.
*/

void *ParseAlloc(void *(*mallocProc)(int)){
  yyParser *pParser;
  pParser = (yyParser*)(*mallocProc)( (int)sizeof(yyParser) );
  if( pParser ){
    pParser->idx = -1;
  }
  return pParser;
}

/* The following function deletes the value associated with a
................................................................................
** <ul>
** <li>  A pointer to the parser.  This should be a pointer
**       obtained from ParseAlloc.
** <li>  A pointer to a function used to reclaim memory obtained
**       from malloc.
** </ul>
*/

void ParseFree(
  void *p,                    /* The parser to be deleted */
  void (*freeProc)(void*)     /* Function used to reclaim memory */
){
  yyParser *pParser = (yyParser*)p;
  if( pParser==0 ) return;
  while( pParser->idx>=0 ) yy_pop_parser_stack(pParser);
  (*freeProc)((void*)pParser);
}

/*
** Find the appropriate action for a parser given the look-ahead token.
**
** If the look-ahead token is YYNOCODE, then check to see if the action is
** independent of the look-ahead.  If it is, return the action, otherwise
................................................................................
static struct {
  YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */
  unsigned char nrhs;     /* Number of right-hand side symbols in the rule */
} yyRuleInfo[] = {
%%
};

static void yy_accept(yyParser *  ParseANSIARGDECL);  /* Forward Declaration */

/*
** Perform a reduce action and the shift that must immediately
** follow the reduce.
*/
static void yy_reduce(
  yyParser *yypParser,         /* The parser */
................................................................................
** <li> The minor token number.
** <li> An option argument of a grammar-specified type.
** </ul>
**
** Outputs:
** None.
*/

void Parse(
  void *yyp,                   /* The parser */
  int yymajor,                 /* The major token code number */
  ParseTOKENTYPE yyminor       /* The value for the token */
  ParseANSIARGDECL
){
  YYMINORTYPE yyminorunion;

Changes to www/changes.tcl.

12
13
14
15
16
17
18






19
20
21
22
23
24
25
}


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}







chng {2001 Mar 20 (1.0.27)} {
<li>When doing DELETE and UPDATE, the library used to write the record
    numbers of records to be deleted or updated into a temporary file.
    This is changed so that the record numbers are held in memory.</li>
<li>The DELETE command without a WHILE clause just removes the database
    files from the disk, rather than going through and deleting record







>
>
>
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
}


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}

chng {2001 Apr 3 (1.0.28)} {
<li>Changes to the "lemon" parser generator to help it work better when
    compiled using MSVC.</li>
<li>Bug fixes in the TCL interface identified by Oleg Oleinick.</li>
}

chng {2001 Mar 20 (1.0.27)} {
<li>When doing DELETE and UPDATE, the library used to write the record
    numbers of records to be deleted or updated into a temporary file.
    This is changed so that the record numbers are held in memory.</li>
<li>The DELETE command without a WHILE clause just removes the database
    files from the disk, rather than going through and deleting record