Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Limit the total data in a single row to 2^16-1 bytes. (CVS 248) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
8fdec4d8b6043471f21235bc8918c9a8 |
User & Date: | drh 2001-09-15 13:15:13.000 |
Context
2001-09-15
| ||
14:43 | Separate columns in keys using nulls instead of tabs. (CVS 249) (check-in: 8e2f3f751e user: drh tags: trunk) | |
13:15 | Limit the total data in a single row to 2^16-1 bytes. (CVS 248) (check-in: 8fdec4d8b6 user: drh tags: trunk) | |
00:59 | Removing some surplus files. (CVS 1723) (check-in: 8ad996fdac user: drh tags: trunk) | |
Changes
Changes to src/btree.c.
︙ | ︙ | |||
17 18 19 20 21 22 23 | ** Boston, MA 02111-1307, USA. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* | | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | ** Boston, MA 02111-1307, USA. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** $Id: btree.c,v 1.28 2001/09/15 13:15:13 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. |
︙ | ︙ | |||
69 70 71 72 73 74 75 | /* ** Primitive data types. u32 must be 4 bytes and u16 must be 2 bytes. ** The uptr type must be big enough to hold a pointer. ** Change these typedefs when porting to new architectures. */ typedef unsigned int uptr; | > > | | | > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | /* ** Primitive data types. u32 must be 4 bytes and u16 must be 2 bytes. ** The uptr type must be big enough to hold a pointer. ** Change these typedefs when porting to new architectures. */ typedef unsigned int uptr; /* There are already definedin sqliteInt.h... ** typedef unsigned int u32; ** typedef unsigned short int u16; ** typedef unsigned char u8; */ /* ** This macro casts a pointer to an integer. Useful for doing ** pointer arithmetic. */ #define Addr(X) ((uptr)X) |
︙ | ︙ |
Changes to src/pager.h.
︙ | ︙ | |||
21 22 23 24 25 26 27 | ** 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. ** | | > > > > > > | 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 | ** 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.10 2001/09/15 13:15:13 drh Exp $ */ /* ** The size of one page */ #define SQLITE_PAGE_SIZE 1024 /* ** Maximum number of pages in one database. (This is a limitation of ** imposed by 4GB files size limits.) */ #define SQLITE_MAX_PAGE 1073741823 /* ** 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; /* |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
20 21 22 23 24 25 26 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** This header file defines the interface that the sqlite library ** presents to client programs. ** | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | ** 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.16 2001/09/15 13:15:13 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ #include <stdarg.h> /* Needed for the definition of va_list */ /* ** The version of the SQLite library. |
︙ | ︙ | |||
157 158 159 160 161 162 163 164 165 166 167 168 169 170 | #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 */ #define SQLITE_EMPTY 15 /* Database table is empty */ #define SQLITE_SCHEMA 16 /* The database schema changed */ /* 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. */ | > | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | #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 */ #define SQLITE_EMPTY 15 /* Database table is empty */ #define SQLITE_SCHEMA 16 /* The database schema changed */ #define SQLITE_TOOBIG 17 /* Too much data for one row of a table */ /* 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/sqliteInt.h.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | > | > > | 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 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.49 2001/09/15 13:15:13 drh Exp $ */ #include "sqlite.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> /* ** The maximum number of in-memory pages to use for the main database ** table and for temporary tables. */ #define MAX_PAGES 100 #define TEMP_PAGES 25 /* ** Integers of known sizes. These typedefs much change for architectures ** where the sizes very. */ typedef unsigned int u32; /* 4-byte unsigned integer */ typedef unsigned short int u16; /* 2-byte unsigned integer */ typedef unsigned char u8; /* 1-byte unsigned integer */ /* ** If memory allocation problems are found, recompile with ** ** -DMEMORY_DEBUG=1 ** ** to enable some sanity checking on malloc() and free(). To |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
22 23 24 25 26 27 28 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.24 2001/09/15 13:15:13 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* ** If malloc() ever fails, this global variable gets set to 1. |
︙ | ︙ | |||
993 994 995 996 997 998 999 1000 1001 1002 1003 | case SQLITE_CORRUPT: z = "database disk image is malformed"; break; case SQLITE_NOTFOUND: z = "table or record not found"; break; case SQLITE_FULL: z = "database is full"; break; case SQLITE_CANTOPEN: z = "unable to open database file"; break; case SQLITE_PROTOCOL: z = "database locking protocol failure"; break; case SQLITE_EMPTY: z = "table contains no data"; break; case SQLITE_SCHEMA: z = "database schema has changed"; break; default: z = "unknown error"; break; } return z; } | > | 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 | case SQLITE_CORRUPT: z = "database disk image is malformed"; break; case SQLITE_NOTFOUND: z = "table or record not found"; break; case SQLITE_FULL: z = "database is full"; break; case SQLITE_CANTOPEN: z = "unable to open database file"; break; case SQLITE_PROTOCOL: z = "database locking protocol failure"; break; case SQLITE_EMPTY: z = "table contains no data"; break; case SQLITE_SCHEMA: z = "database schema has changed"; break; case SQLITE_TOOBIG: z = "too much data for one table row"; break; default: z = "unknown error"; break; } return z; } |
Changes to src/vdbe.c.
︙ | ︙ | |||
37 38 39 40 41 42 43 | ** inplicit conversion from one type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | ** inplicit conversion from one type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.68 2001/09/15 13:15:13 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include <unistd.h> /* ** SQL is translated into a sequence of instructions to be |
︙ | ︙ | |||
452 453 454 455 456 457 458 | ** Hence, a negative P2 value is a label that has yet to be resolved. */ int sqliteVdbeMakeLabel(Vdbe *p){ int i; i = p->nLabel++; if( i>=p->nLabelAlloc ){ p->nLabelAlloc = p->nLabelAlloc*2 + 10; | | | 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 | ** Hence, a negative P2 value is a label that has yet to be resolved. */ int sqliteVdbeMakeLabel(Vdbe *p){ int i; i = p->nLabel++; if( i>=p->nLabelAlloc ){ p->nLabelAlloc = p->nLabelAlloc*2 + 10; p->aLabel = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0])); } if( p->aLabel==0 ){ p->nLabel = 0; p->nLabelAlloc = 0; return 0; } p->aLabel[i] = -1; |
︙ | ︙ | |||
1770 1771 1772 1773 1774 1775 1776 | } /* Opcode: MakeRecord P1 * * ** ** Convert the top P1 entries of the stack into a single entry ** suitable for use as a data record in a database table. To do this ** all entries (except NULLs) are converted to strings and | | > | | | < > > | | | > > > > | | | | 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 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 1822 1823 | } /* Opcode: MakeRecord P1 * * ** ** Convert the top P1 entries of the stack into a single entry ** suitable for use as a data record in a database table. To do this ** all entries (except NULLs) are converted to strings and ** concatenated. The null-terminators are included on all string ** except for NULL columns which are represented by zero bytes. ** The lowest entry ** on the stack is the first in the concatenation and the top of ** the stack is the last. After all columns are concatenated, an ** index header is added. The index header consists of P1 16-bit integers ** which hold the offset of the beginning of each column data from the ** beginning of the completed record including the header. ** ** The OP_Column opcode is used to unpack a record manufactured with ** the opcode. */ case OP_MakeRecord: { char *zNewRecord; int nByte; int nField; int i, j; u16 addr; nField = pOp->p1; VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) nByte = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ if( Stringify(p, i) ) goto no_mem; nByte += aStack[i].n; } } nByte += sizeof(addr)*nField; if( nByte>65535 ){ rc = SQLITE_TOOBIG; goto abort_due_to_error; } zNewRecord = sqliteMalloc( nByte ); if( zNewRecord==0 ) goto no_mem; j = 0; addr = sizeof(addr)*nField; for(i=p->tos-nField+1; i<=p->tos; i++){ memcpy(&zNewRecord[j], (char*)&addr, sizeof(addr)); j += sizeof(addr); if( (aStack[i].flags & STK_Null)==0 ){ addr += aStack[i].n; } } for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ memcpy(&zNewRecord[j], zStack[i], aStack[i].n); |
︙ | ︙ | |||
1902 1903 1904 1905 1906 1907 1908 | char *zNewKey; int nByte; int nField; int i, j; nField = pOp->p1; VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) | | | | 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 | char *zNewKey; int nByte; int nField; int i, j; nField = pOp->p1; VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) nByte = sizeof(u32); for(i=p->tos-nField+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ nByte++; }else{ if( Stringify(p, i) ) goto no_mem; nByte += aStack[i].n; } } zNewKey = sqliteMalloc( nByte ); if( zNewKey==0 ) goto no_mem; j = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ memcpy(&zNewKey[j], zStack[i], aStack[i].n-1); j += aStack[i].n-1; } if( i<p->tos ) zNewKey[j++] = '\t'; } zNewKey[j++] = 0; Integerify(p, p->tos-nField); memcpy(&zNewKey[j], &aStack[p->tos-nField].i, sizeof(u32)); PopStack(p, nField+1); VERIFY( NeedStack(p, p->tos+1); ) p->tos++; aStack[p->tos].n = nByte; aStack[p->tos].flags = STK_Str|STK_Dyn; zStack[p->tos] = zNewKey; break; |
︙ | ︙ | |||
2365 2366 2367 2368 2369 2370 2371 | p->aCsr[i].keyAsData = pOp->p2; } break; } /* Opcode: Column P1 P2 * ** | | | > > | < | < < < < | | 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 | p->aCsr[i].keyAsData = pOp->p2; } break; } /* Opcode: Column P1 P2 * ** ** Interpret the data that cursor P1 points to as ** a structure built using the MakeRecord instruction. ** (See the MakeRecord opcode for additional information about ** the format of the data.) ** Push onto the stack the value of the P2-th column contained ** in the data. ** ** If the KeyAsData opcode has previously executed on this cursor, ** then the field might be extracted from the key rather than the ** data. */ case OP_Column: { int amt, offset, nCol, payloadSize; u16 aHdr[10]; static const int mxHdr = sizeof(aHdr)/sizeof(aHdr[0]); int i = pOp->p1; int p2 = pOp->p2; int tos = p->tos+1; BtCursor *pCrsr; char *z; |
︙ | ︙ | |||
2413 2414 2415 2416 2417 2418 2419 | ** The code is complicated by efforts to minimize the number ** of invocations of xRead() since that call can be expensive. ** For the common case where P2 is small, xRead() is invoked ** twice. For larger values of P2, it has to be called ** three times. */ (*xSize)(pCrsr, &payloadSize); | | | | | | > | > > > > | 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 | ** The code is complicated by efforts to minimize the number ** of invocations of xRead() since that call can be expensive. ** For the common case where P2 is small, xRead() is invoked ** twice. For larger values of P2, it has to be called ** three times. */ (*xSize)(pCrsr, &payloadSize); if( payloadSize < sizeof(aHdr[0])*(p2+1) ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } if( p2+1<mxHdr ){ (*xRead)(pCrsr, 0, sizeof(aHdr[0])*(p2+2), (char*)aHdr); nCol = aHdr[0]; nCol /= sizeof(aHdr[0]); offset = aHdr[p2]; if( p2 == nCol-1 ){ amt = payloadSize - offset; }else{ amt = aHdr[p2+1] - offset; } }else{ sqliteBtreeData(pCrsr, 0, sizeof(aHdr[0]), (char*)aHdr); nCol = aHdr[0]/sizeof(aHdr[0]); if( p2 == nCol-1 ){ (*xRead)(pCrsr, sizeof(aHdr[0])*p2, sizeof(aHdr[0]), (char*)aHdr); offset = aHdr[0]; amt = payloadSize - offset; }else{ (*xRead)(pCrsr, sizeof(aHdr[0])*p2, sizeof(aHdr[0])*2, (char*)aHdr); offset = aHdr[0]; amt = aHdr[1] - offset; } } if( payloadSize < nCol || amt<0 || offset<0 ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } /* amt and offset now hold the offset to the start of data and the ** amount of data. Go get the data and put it on the stack. */ if( amt==0 ){ aStack[tos].flags = STK_Null; }else{ z = sqliteMalloc( amt ); if( z==0 ) goto no_mem; (*xRead)(pCrsr, offset, amt, z); aStack[tos].flags = STK_Str | STK_Dyn; |
︙ | ︙ | |||
2476 2477 2478 2479 2480 2481 2482 | VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int v; if( p->aCsr[i].recnoIsValid ){ v = p->aCsr[i].lastRecno; }else{ | | | 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 | VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int v; if( p->aCsr[i].recnoIsValid ){ v = p->aCsr[i].lastRecno; }else{ sqliteBtreeKey(pCrsr, 0, sizeof(u32), (char*)&v); } aStack[tos].i = v; aStack[tos].flags = STK_Int; } break; } |
︙ | ︙ | |||
2622 2623 2624 2625 2626 2627 2628 | pCrsr->atFirst = 0; res = 0; }else{ rx = sqliteBtreeNext(pCur, &res); if( rx!=SQLITE_OK ) goto abort_due_to_error; } sqliteBtreeKeySize(pCur, &size); | | | | 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 | pCrsr->atFirst = 0; res = 0; }else{ rx = sqliteBtreeNext(pCur, &res); if( rx!=SQLITE_OK ) goto abort_due_to_error; } sqliteBtreeKeySize(pCur, &size); if( res>0 || size!=pCrsr->nKey+sizeof(u32) || sqliteBtreeKey(pCur, 0, pCrsr->nKey, pCrsr->zBuf)!=pCrsr->nKey || strncmp(pCrsr->zKey, pCrsr->zBuf, pCrsr->nKey)!=0 ){ pc = pOp->p2 - 1; POPSTACK; }else{ int recno; sqliteBtreeKey(pCur, pCrsr->nKey, sizeof(u32), (char*)&recno); p->aCsr[i].lastRecno = aStack[tos].i = recno; p->aCsr[i].recnoIsValid = 1; aStack[tos].flags = STK_Int; } } break; } |
︙ | ︙ | |||
2808 2809 2810 2811 2812 2813 2814 | case OP_ListWrite: { int i = pOp->p1; Keylist *pKeylist; VERIFY( if( i<0 || i>=p->nList ) goto bad_instruction; ) VERIFY( if( p->tos<0 ) goto not_enough_stack; ) pKeylist = p->apList[i]; if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){ | | | 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 | case OP_ListWrite: { int i = pOp->p1; Keylist *pKeylist; VERIFY( if( i<0 || i>=p->nList ) goto bad_instruction; ) VERIFY( if( p->tos<0 ) goto not_enough_stack; ) pKeylist = p->apList[i]; if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){ pKeylist = sqliteMalloc( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) ); if( pKeylist==0 ) goto no_mem; pKeylist->nKey = 1000; pKeylist->nRead = 0; pKeylist->nUsed = 0; pKeylist->pNext = p->apList[i]; p->apList[i] = pKeylist; } |
︙ | ︙ | |||
3770 3771 3772 3773 3774 3775 3776 | if( aStack[i].flags & STK_Null ){ fprintf(p->trace, " NULL"); }else if( aStack[i].flags & STK_Int ){ fprintf(p->trace, " i:%d", aStack[i].i); }else if( aStack[i].flags & STK_Real ){ fprintf(p->trace, " r:%g", aStack[i].r); }else if( aStack[i].flags & STK_Str ){ | > > > | > > > | > > > | < > | > > > | 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 | if( aStack[i].flags & STK_Null ){ fprintf(p->trace, " NULL"); }else if( aStack[i].flags & STK_Int ){ fprintf(p->trace, " i:%d", aStack[i].i); }else if( aStack[i].flags & STK_Real ){ fprintf(p->trace, " r:%g", aStack[i].r); }else if( aStack[i].flags & STK_Str ){ int j, k; char zBuf[100]; zBuf[0] = ' '; zBuf[1] = (aStack[i].flags & STK_Dyn)!=0 ? 'z' : 's'; zBuf[2] = ':'; k = 3; for(j=0; j<15 && j<aStack[i].n; j++){ int c = zStack[i][j]; if( c==0 && j==aStack[i].n-1 ) break; if( isprint(c) && !isspace(c) ){ zBuf[k++] = c; }else{ zBuf[k++] = '.'; } } zBuf[k++] = 0; fprintf(p->trace, "%s", zBuf); }else{ fprintf(p->trace, " ???"); } } fprintf(p->trace,"\n"); } #endif |
︙ | ︙ |