]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Update Lemon so that it accepts filename arguments to directives like
authordrh <>
Wed, 5 Mar 2025 13:39:33 +0000 (13:39 +0000)
committerdrh <>
Wed, 5 Mar 2025 13:39:33 +0000 (13:39 +0000)
"%include".  Ex:  "<tt>%include &lt;./subdir/file-to-include.txt&gt;</tt>".
This was capability needed by pikchr and backported here for safe keeping.
SQLite does not need this capability, though it doesn't hurt to have it in tree.

FossilOrigin-Name: 52b97a7ad5d944e44240f624b30a76398d10ef945d8edc4b7d7b36ed2e515327

doc/lemon.html
manifest
manifest.uuid
tool/lemon.c

index 24bccce082c9c81fdd5d8383d56c14d241759ffb..ad1d3c19902610171f565c52c9dbd8b52675eaea 100644 (file)
@@ -725,6 +725,10 @@ as part of the output file.</p>
 <p>There can be multiple <tt>%code</tt> directives.  The arguments of
 all <tt>%code</tt> directives are concatenated.</p>
 
+<p>If the argument to <tt>%code</tt> is a filename within <tt>&lt;...&gt;</tt>
+then the content of the named file is inserted instead of the text of the
+argument itself.
+
 <a id='default_destructor'></a>
 <h4>4.4.2 The <tt>%default_destructor</tt> directive</h4>
 
@@ -920,6 +924,11 @@ For example:</p>
 <p>This might be needed, for example, if some of the C actions in the
 grammar call functions that are prototyped in unistd.h.</p>
 
+<p>If the argument to <tt>%include</tt> is a filename within
+<tt>&lt;...&gt;</tt> then the content of that file is inserted instead
+of the text of the argument itself.
+
+
 <p>Use the <tt><a href="#pcode">%code</a></tt> directive to add code to
 the end of the generated parser.</p>
 
index 4111a6e2e78f30fa2c47a582b22a25777aae9db6..dd9082c0d72ad7b2b2f89fc0ceccf9143f964802 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\spointless\scomparison\sof\san\sunsigned\sinteger\sto\sless\sthan\szero\sin\sLemon.
-D 2025-03-04T17:06:38.231
+C Update\sLemon\sso\sthat\sit\saccepts\sfilename\sarguments\sto\sdirectives\slike\n"%include".\s\sEx:\s\s"<tt>%include\s&lt;./subdir/file-to-include.txt&gt;</tt>".\nThis\swas\scapability\sneeded\sby\spikchr\sand\sbackported\shere\sfor\ssafe\skeeping.\nSQLite\sdoes\snot\sneed\sthis\scapability,\sthough\sit\sdoesn't\shurt\sto\shave\sit\sin\stree.
+D 2025-03-05T13:39:33.597
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
@@ -59,7 +59,7 @@ F doc/compile-for-unix.md c9dce1ddd4bf0d25efccc5c63eb047e78c01ce06a6ff29c73e0a8a
 F doc/compile-for-windows.md 5141661e783c9ca9e3fd30e813345898712f5c311d71316f183db87038fa28a6
 F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
 F doc/jsonb.md ede3238186e3a90bb79d20b2a6a06d0f9429a38e069e9da0efbad0f2ed48b924
-F doc/lemon.html 7504a6dc9b56dd376a046833ea9cc8b08def93f19bfad6eab9f1a365a4b5f49a
+F doc/lemon.html 6aa6b6a75890bc71a6ad2b94e0723c273818b8b5e43b591eb483a6db0838441f
 F doc/pager-invariants.txt 83aa3a4724b2d7970cc3f3461f0295c46d4fc19a835a5781cbb35cb52feb0577
 F doc/shared_schema.md 759fc374709fccf4e5d2d0cbd05f8fedd38fb022bdd8a6c5b5f492684c7023b9
 F doc/tcl-extension-testing.md 864875c3b672db79e7d42348dd726f9a4fbd852b1d8e5efcf09fe3d1ff6bf2a2
@@ -2152,7 +2152,7 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
 F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
 F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
-F tool/lemon.c 7bcb2260da613323718746469e314025b46f33ccb8c6753dbc39eb76bed756c8
+F tool/lemon.c 5f999ac3801e8b585149a5fd5c7c2bbdde3baca98985ebe68e1a41b8e19d19a4
 F tool/lempar.c bdffd3b233a4e4e78056c9c01fadd2bb3fe902435abde3bce3d769fdf0d5cca2
 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
@@ -2225,8 +2225,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P b51690e180cfb6034c772899f068453da8484a830283f7c152cfb6fa4330c31e
-R 3a658530666f2614542125c8c0123731
+P 559560da45d0e22ccc6f47dd9eb5ba16851ea444da7e4e951f07b8aa6f6b3753
+R 07ddd929d7c988ac87c481e6c4cfbbbc
 U drh
-Z a3c8a6bfe570a8e9f50de3de3edd3fe5
+Z c7f5ed8a6a37ec5d454f01999c7e18cd
 # Remove this line to create a well-formed Fossil manifest.
index 6d0ac883f0eab7d4da698778cfa72b34ac9e8a37..eadf04136e249bbd39244befe7dde99e684ab722 100644 (file)
@@ -1 +1 @@
-559560da45d0e22ccc6f47dd9eb5ba16851ea444da7e4e951f07b8aa6f6b3753
+52b97a7ad5d944e44240f624b30a76398d10ef945d8edc4b7d7b36ed2e515327
index 6d18e6ddb704afb11a8032c082830d1be6e53e7d..3ce574482d0a691f88c5bd20d2a5f7b7f6732405 100644 (file)
@@ -2314,6 +2314,8 @@ void OptPrint(void){
   }
 }
 /*********************** From the file "parse.c" ****************************/
+
+
 /*
 ** Input file parser for the LEMON parser generator.
 */
@@ -2369,6 +2371,60 @@ struct pstate {
   struct rule *lastrule;     /* Pointer to the most recently parsed rule */
 };
 
+/*
+** input x[] is a filename enclosed in <...>.  This routine strives
+** to load the complete text of the named file into memory obtained
+** from lemon_malloc() and return that text.  The complete filename
+** (without the enclosing <...>) is also written into memory obtained
+** from lemon_malloc() and written back into *pzFN.
+**
+** Except, if any error occurs, the error message is set on psp and
+** no memory is allocated and a NULL is returned.
+*/
+static char *load_file_content(
+  struct pstate *psp,   /* Parsing context */
+  const char *x,        /* Filename enclosed in <....> */
+  char **pzFN           /* Write true filename here */
+){
+  char *zContent;
+  char *zFN;
+  int nFN;
+  FILE *in;
+  int nAlloc;
+  int nContent;
+  
+  *pzFN = 0;
+  nFN = lemonStrlen(x);
+  zFN = lemon_malloc( nFN );
+  memcpy(zFN, x+1, nFN-1);
+  zFN[nFN-1] = 0;
+  in = fopen(zFN, "rb");
+  if( in==0 ){
+    ErrorMsg(psp->filename,psp->tokenlineno,
+       "Cannot read file \"%s\"", zFN);
+    psp->errorcnt++;
+    lemon_free(zFN);
+    return 0;
+  }
+  *pzFN = zFN;
+  nAlloc = 2000;
+  zContent = lemon_malloc( nAlloc );
+  nContent = 0;
+  while( nContent<nAlloc-1 ){
+    long got = fread(&zContent[nContent], 1, nAlloc-nContent-1, in);
+    if( got<=0 ) break;
+    nContent += got;
+    if( nContent>=nAlloc-1 ){
+      nAlloc *= 2;
+      zContent = lemon_realloc(zContent, nAlloc);
+    }
+  }
+  zContent[nContent] = 0;
+  fclose(in);
+  return zContent;
+}
+
+
 /* Parse a single token */
 static void parseonetoken(struct pstate *psp)
 {
@@ -2746,14 +2802,30 @@ static void parseonetoken(struct pstate *psp)
       }
       break;
     case WAITING_FOR_DECL_ARG:
-      if( x[0]=='{' || x[0]=='\"' || ISALNUM(x[0]) ){
+      if( x[0]=='{' || x[0]=='\"' || ISALNUM(x[0]) 
+       || (x[0]=='<' && psp->insertLineMacro)
+      ){
         const char *zOld, *zNew;
-        char *zBuf, *z;
+        char *zBuf;
+        const char *z;
         int nOld, n, nLine = 0, nNew, nBack;
         int addLineMacro;
         char zLine[50];
-        zNew = x;
-        if( zNew[0]=='"' || zNew[0]=='{' ) zNew++;
+        char *zToFreeTxt = 0;
+        char *zToFreeFN = 0;
+        const char *zFN = psp->filename;
+        int ln = psp->tokenlineno;
+
+        if( x[0]=='<' ){
+          zToFreeTxt = load_file_content(psp,x,&zToFreeFN);
+          if( psp->errorcnt ) break;
+          zNew = zToFreeTxt;
+          zFN = zToFreeFN;
+          ln = 1;
+        }else{
+          zNew = x;
+          if( zNew[0]=='"' || zNew[0]=='{' ) zNew++;
+        }
         nNew = lemonStrlen(zNew);
         if( *psp->declargslot ){
           zOld = *psp->declargslot;
@@ -2766,13 +2838,14 @@ static void parseonetoken(struct pstate *psp)
                        && psp->insertLineMacro
                        && psp->tokenlineno>1
                        && (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0);
-        if( addLineMacro ){
-          for(z=psp->filename, nBack=0; *z; z++){
+        if( addLineMacro || x[0]=='<' ){
+          addLineMacro = 1;
+          for(z=zFN, nBack=0; *z; z++){
             if( *z=='\\' ) nBack++;
           }
-          lemon_sprintf(zLine, "#line %d ", psp->tokenlineno);
+          lemon_sprintf(zLine, "#line %d ", ln);
           nLine = lemonStrlen(zLine);
-          n += nLine + lemonStrlen(psp->filename) + nBack;
+          n += nLine + lemonStrlen(zFN) + nBack;
         }
         *psp->declargslot = (char *) lemon_realloc(*psp->declargslot, n);
         zBuf = *psp->declargslot + nOld;
@@ -2783,7 +2856,7 @@ static void parseonetoken(struct pstate *psp)
           memcpy(zBuf, zLine, nLine);
           zBuf += nLine;
           *(zBuf++) = '"';
-          for(z=psp->filename; *z; z++){
+          for(z=zFN; *z; z++){
             if( *z=='\\' ){
               *(zBuf++) = '\\';
             }
@@ -2799,6 +2872,8 @@ static void parseonetoken(struct pstate *psp)
         zBuf += nNew;
         *zBuf = 0;
         psp->state = WAITING_FOR_DECL_OR_RULE;
+        lemon_free(zToFreeTxt);
+        lemon_free(zToFreeFN);
       }else{
         ErrorMsg(psp->filename,psp->tokenlineno,
           "Illegal argument to %%%s: %s",psp->declkeyword,x);
@@ -3166,6 +3241,18 @@ void Parse(struct lemon *gp)
       }else{
         nextcp = cp+1;
       }
+    }else if( c=='<' ){                /* Pathname in <...> */
+      cp++;
+      while( (c= *cp)!=0 && c!='>' && (c&0xfc)!=0 ){ cp++; }
+      if( (c&0xfc)==0 ){
+        ErrorMsg(ps.filename,startline,
+            c==0 ? "Unterminated filename"
+                 : "Control-character in filename");
+        ps.errorcnt++;
+        nextcp = cp;
+      }else{
+        nextcp = cp+1;
+      }
     }else if( c=='{' ){               /* A block of C code */
       int level;
       cp++;