Gregory (Grisha) Trubetskoy wrote:

On Wed, 9 Nov 2005, Jim Gallacher wrote:

This just get's stranger and stranger. Regenerating psp_parser.c from the current psp_parser.l has caused my psp pages to go completely pair-shaped. Things that rendered correctly before now puke up hairballs.

For example the psp code (where my_link = 'some_url'):
   <a href="<%= my_link %>">My Link</a>
used to render as:
   <a href="some_url">My Link</a>
but now renders as:
   <a href=,0); req.write(str( my_link ),0); req.write(r>My Link</a>


You may find it useful to use the _psp module from the command line, since what you really want to see is not what it renders as, but the Python code it generates:

from mod_python import _psp
s = _psp.parse("/path/to/your/file")
print s

See below for test results.


Changing the double quote to a single quote fixes the problem.
   <a href='<%= my_link %>'>My Link</a>


This doesn't make a lot of sense, because PSP does not concern itself with quotes - it scans for the "<%=" and once it has seen one then "%>", the quotes would remain untouched, so the problem is elsewhere.

I don't want to refactor *all* of my psp pages, so I guess we'll need to fix psp_parser. ;)


Just be careful, you may be trying to fix what is not broken in the first place. I use the 3.1.4 PSP very heavily and there is not a single glitch with it that I know of, and I can certainly use any kind of quote I want.

And this was my experience as well up to and including 3.2.4b, until I deleted psp_parser.c and regenerated it. Then everything went wrong with the site the I'm developing. I've been testing all the betas against this code since I figured I'd be more likely to spot strange problems. I did. :(

I'd start out with confirming your theory that psp_parser.c is stale somehow - that should be pretty easy - just generate a new one and diff it with what's in SVN.

$ svn co $MP_TRUNK /tmp/mod_python
$ cd /tmp/mod_python
$ ./configure
$ make
$ make install
$ echo "run parser test from command line"
$ mv src/psp_parser.c psp_parser.c.orig
$ make clean
$ make
$ make install
$ diff -u src psp_parser.c.orig psp_parser.c > psp_parser.diff
$ echo "re-run parser test from command line"

See attached diff. The 2 files are not the same.

Test results using mod_python._psp.parse('test.psp') from the command line interpreter:

test.psp
--------
<%
x = 'XXXX'
%>
test '<%= x %>'
test "<%= x %>"


Code generated from current psp_parser.c
----------------------------------------
req.write("""""",0);
x = 'XXXX'
req.write("""
test '""",0); req.write(str( x ),0); req.write("""'
test \"""",0); req.write(str( x ),0); req.write("""\"
""",0)

Output from generated code (GOOD!)
----------------------------------

test '
XXXX
'
test "
XXXX
"

Code generated with recreated psp_parser.c
------------------------------------------

req.write(r"""""",0);
x = 'XXXX'
req.write(r"""
test '""",0); req.write(str( x ),0); req.write(r"""'
test """",0); req.write(str( x ),0); req.write(r""""
""",0)

Output from generated code (BAD!)
---------------------------------

test '
XXXX
'
test ,0); req.write(str( x ),0); req.write(r


So it's not my imagination. :)

I'll dig through the svn logs and check the history of psp_parser.l and psp_parser.c. Maybe there will be some clues in there. Won't get to it until Sunday though.

The most recent change in SVN seems to have been adding an 'r' before the triple quote for the <TEXT> portion (r""" instead of just """), which should have solved some backslash problems.

Again, I haven't tested anything, but looking at the code, it seems to me that indeed there should be a problem exactly as Anton reported it and that my fix would be necessary, _and_ it may also apply to other special sequences such as tab \t. I may be missing something, but I just wnated to warn you that you may be missing something :-)

I'm pretty sure I'm missing something! :)

Jim
--- src/psp_parser.c.orig       2005-11-10 10:36:29.000000000 -0500
+++ src/psp_parser.c    2005-11-10 10:38:21.000000000 -0500
@@ -343,8 +343,8 @@
        *yy_cp = '\0'; \
        yyg->yy_c_buf_p = yy_cp;
 
-#define YY_NUM_RULES 20
-#define YY_END_OF_BUFFER 21
+#define YY_NUM_RULES 21
+#define YY_END_OF_BUFFER 22
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -352,15 +352,16 @@
        flex_int32_t yy_verify;
        flex_int32_t yy_nxt;
        };
-static yyconst flex_int16_t yy_accept[69] =
+static yyconst flex_int16_t yy_accept[72] =
     {   0,
-        0,    0,    0,    0,    0,    0,    0,   13,    0,    0,
-        0,    0,   21,    2,    1,    2,    8,    7,    8,    8,
-       12,    9,   12,   12,   11,   16,   15,   16,   16,   13,
-       20,   20,   20,   20,    1,    7,    4,    9,   10,   15,
-       14,   13,   18,    0,    0,    0,    3,    5,    0,    0,
-        6,    0,   19,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,   17,    0
+        0,    0,    0,    0,    0,    0,    0,   14,    0,    0,
+        0,    0,   22,    2,    1,    2,    8,    7,    8,    8,
+        8,   13,   10,   13,   13,   12,   17,   16,   17,   17,
+       14,   21,   21,   21,   21,    1,    7,    0,    4,   10,
+       11,   16,   15,   14,   19,    0,    0,    9,    0,    3,
+        5,    0,    0,    6,    0,   20,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,   18,
+        0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -402,60 +403,60 @@
         1
     } ;
 
-static yyconst flex_int16_t yy_base[75] =
+static yyconst flex_int16_t yy_base[78] =
     {   0,
-        0,    2,    4,    6,   14,   21,    8,   29,   19,   20,
-       76,   75,   82,   85,   85,   78,   85,   85,   77,   72,
-       85,   85,   75,   65,   85,   85,   85,   73,   63,   17,
-       85,   62,   53,   64,   85,   85,   31,   85,   85,   85,
-       85,   38,   85,   57,   63,   61,   85,   85,   49,   55,
-       85,   45,   85,   50,   48,   58,   24,   44,   31,   33,
-       40,   37,   41,   29,    0,   14,    7,   85,   51,   53,
-       55,   57,   59,    0
+        0,    2,    4,   12,   20,   27,   34,   40,    2,   10,
+       80,   79,   86,   89,   89,   82,   89,   89,   81,   77,
+       75,   89,   89,   78,   68,   89,   89,   89,   76,   66,
+       30,   89,   65,   56,   67,   89,   89,   68,   38,   89,
+       89,   89,   89,   48,   89,   59,   65,   89,   63,   89,
+       89,   51,   57,   89,   47,   89,   52,   50,   60,    8,
+       46,   33,   32,   28,   29,    6,   20,    0,   15,   13,
+       89,   53,   55,   57,   59,   61,    0
     } ;
 
-static yyconst flex_int16_t yy_def[75] =
+static yyconst flex_int16_t yy_def[78] =
     {   0,
-       69,   69,   70,   70,   71,   71,   72,   72,   73,   73,
-       73,   73,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   74,   74,   74,    0,   68,   68,
-       68,   68,   68,   68
+       72,   72,   73,   73,   74,   74,   75,   75,   76,   76,
+       76,   76,   71,   71,   71,   71,   71,   71,   71,   71,
+       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
+       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
+       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
+       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
+       71,   71,   71,   71,   71,   71,   71,   77,   77,   77,
+        0,   71,   71,   71,   71,   71,   71
     } ;
 
-static yyconst flex_int16_t yy_nxt[107] =
+static yyconst flex_int16_t yy_nxt[111] =
     {   0,
-       66,   68,   15,   16,   15,   16,   18,   19,   18,   19,
-       27,   28,   67,   20,   29,   20,   22,   23,   42,   67,
-       24,   42,   25,   22,   23,   32,   32,   24,   57,   25,
-       30,   27,   28,   30,   65,   29,   33,   33,   46,   42,
-       58,   47,   42,   48,   62,   64,   65,   63,   61,   60,
-       63,   14,   14,   17,   17,   21,   21,   26,   26,   31,
-       31,   59,   57,   56,   55,   54,   53,   52,   51,   50,
-       49,   45,   44,   43,   41,   40,   39,   38,   37,   36,
-       35,   68,   34,   34,   13,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       69,   71,   15,   16,   15,   16,   18,   19,   33,   20,
+       67,   68,   60,   21,   18,   19,   33,   20,   70,   34,
+       70,   21,   23,   24,   61,   68,   25,   34,   26,   23,
+       24,   44,   65,   25,   44,   26,   28,   29,   66,   66,
+       30,   31,   28,   29,   31,   49,   30,   64,   50,   44,
+       51,   63,   44,   14,   14,   17,   17,   22,   22,   27,
+       27,   32,   32,   62,   60,   59,   58,   57,   56,   55,
+       54,   53,   52,   48,   47,   46,   45,   43,   42,   41,
+       40,   39,   38,   37,   36,   71,   35,   35,   13,   71,
+       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
 
-       68,   68,   68,   68,   68,   68
+       71,   71,   71,   71,   71,   71,   71,   71,   71,   71
     } ;
 
-static yyconst flex_int16_t yy_chk[107] =
+static yyconst flex_int16_t yy_chk[111] =
     {   0,
-       74,    0,    1,    1,    2,    2,    3,    3,    4,    4,
-        7,    7,   67,    3,    7,    4,    5,    5,   30,   66,
-        5,   30,    5,    6,    6,    9,   10,    6,   57,    6,
-        8,    8,    8,    8,   64,    8,    9,   10,   37,   42,
-       57,   37,   42,   37,   61,   63,   63,   62,   60,   59,
-       61,   69,   69,   70,   70,   71,   71,   72,   72,   73,
-       73,   58,   56,   55,   54,   52,   50,   49,   46,   45,
-       44,   34,   33,   32,   29,   28,   24,   23,   20,   19,
-       16,   13,   12,   11,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       77,    0,    1,    1,    2,    2,    3,    3,    9,    3,
+       66,   66,   60,    3,    4,    4,   10,    4,   70,    9,
+       69,    4,    5,    5,   60,   67,    5,   10,    5,    6,
+        6,   31,   64,    6,   31,    6,    7,    7,   64,   65,
+        7,    8,    8,    8,    8,   39,    8,   63,   39,   44,
+       39,   62,   44,   72,   72,   73,   73,   74,   74,   75,
+       75,   76,   76,   61,   59,   58,   57,   55,   53,   52,
+       49,   47,   46,   38,   35,   34,   33,   30,   29,   25,
+       24,   21,   20,   19,   16,   13,   12,   11,   71,   71,
+       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
 
-       68,   68,   68,   68,   68,   68
+       71,   71,   71,   71,   71,   71,   71,   71,   71,   71
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -482,7 +483,7 @@
  * implied.  See the License for the specific language governing
  * permissions and limitations under the License.
  *
- * $Id: psp_parser.c 126440 2005-01-25 22:53:06Z nlehuen $
+ * $Id: psp_parser.l 106619 2004-11-25 22:10:52Z nd $
  *
  * This file originally written by Sterling Hughes.
  * 
@@ -508,7 +509,7 @@
 
 
 
-#line 512 "psp_parser.c"
+#line 513 "psp_parser.c"
 
 #define INITIAL 0
 #define TEXT 1
@@ -517,11 +518,11 @@
 #define DIR 4
 #define COMMENT 5
 
+#ifndef YY_NO_UNISTD_H
 /* Special case for "unistd.h", since it is non-ANSI. We include it way
  * down here because we want the user's section 1 to have been scanned first.
  * The user has a chance to override it with an option.
  */
-#ifndef WIN32
 #include <unistd.h>
 #endif
 
@@ -734,7 +735,7 @@
 #line 47 "psp_parser.l"
 
 
-#line 736 "psp_parser.c"
+#line 739 "psp_parser.c"
 
        if ( yyg->yy_init )
                {
@@ -788,13 +789,13 @@
                        while ( yy_chk[yy_base[yy_current_state] + yy_c] != 
yy_current_state )
                                {
                                yy_current_state = (int) 
yy_def[yy_current_state];
-                               if ( yy_current_state >= 69 )
+                               if ( yy_current_state >= 72 )
                                        yy_c = yy_meta[(unsigned int) yy_c];
                                }
                        yy_current_state = yy_nxt[yy_base[yy_current_state] + 
(unsigned int) yy_c];
                        ++yy_cp;
                        }
-               while ( yy_base[yy_current_state] != 85 );
+               while ( yy_base[yy_current_state] != 89 );
 
 yy_find_action:
                yy_act = yy_accept[yy_current_state];
@@ -823,7 +824,7 @@
 YY_RULE_SETUP
 #line 49 "psp_parser.l"
 {
-    psp_string_appendl(&PSP_PG(pycode), STATIC_STR("req.write(\"\"\"")); 
+    psp_string_appendl(&PSP_PG(pycode), STATIC_STR("req.write(r\"\"\"")); 
 
     yyless(0);
     BEGIN TEXT;
@@ -833,7 +834,7 @@
 YY_RULE_SETUP
 #line 56 "psp_parser.l"
 {
-    psp_string_appendl(&PSP_PG(pycode), STATIC_STR("req.write(\"\"\"")); 
+    psp_string_appendl(&PSP_PG(pycode), STATIC_STR("req.write(r\"\"\"")); 
 
     yyless(0);
     BEGIN TEXT;
@@ -885,15 +886,23 @@
 YY_RULE_SETUP
 #line 89 "psp_parser.l"
 {
-    if (yytext[0] == '"') {
-        psp_string_appendl(&PSP_PG(pycode), STATIC_STR("\\\""));
-    } else {
-        psp_string_appendc(&PSP_PG(pycode), yytext[0]);
-    }
+    /*   " no longer needs to be escaped */
+    psp_string_appendc(&PSP_PG(pycode), yytext[0]);
+}
+       YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 94 "psp_parser.l"
+{
+    /* close python triplequoted string, put in a triple quote enclosed
+     * itself by single quotes, then restart the python triplequoted
+     * string. */
+    psp_string_appendl(&PSP_PG(pycode), STATIC_STR("\"\"\" +'\"\"\"'+ 
r\"\"\""));
+
 }
        YY_BREAK
 case YY_STATE_EOF(TEXT):
-#line 97 "psp_parser.l"
+#line 102 "psp_parser.l"
 {
     yypop_buffer_state(yyscanner);
     if (!YY_CURRENT_BUFFER) {
@@ -907,10 +916,10 @@
     }
 }
        YY_BREAK
-case 9:
-/* rule 9 can match eol */
+case 10:
+/* rule 10 can match eol */
 YY_RULE_SETUP
-#line 110 "psp_parser.l"
+#line 115 "psp_parser.l"
 {
     psp_string_appendc(&PSP_PG(pycode), '\n');
         
@@ -918,13 +927,13 @@
     BEGIN INDENT;
 }
        YY_BREAK
-case 10:
+case 11:
 YY_RULE_SETUP
-#line 117 "psp_parser.l"
+#line 122 "psp_parser.l"
 {
 
     if (PSP_PG(is_psp_echo)) {
-        psp_string_appendl(&PSP_PG(pycode), STATIC_STR("),0); 
req.write(\"\"\""));
+        psp_string_appendl(&PSP_PG(pycode), STATIC_STR("),0); 
req.write(r\"\"\""));
         PSP_PG(is_psp_echo) = 0;
     } 
     else {
@@ -940,31 +949,31 @@
             PSP_PG(after_colon) = 0;
         }
         OUTPUT_WHITESPACE(&PSP_PG(whitespace));
-        psp_string_appendl(&PSP_PG(pycode), STATIC_STR("req.write(\"\"\""));
+        psp_string_appendl(&PSP_PG(pycode), STATIC_STR("req.write(r\"\"\""));
     }
     
     BEGIN TEXT;
 }
        YY_BREAK
-case 11:
+case 12:
 YY_RULE_SETUP
-#line 142 "psp_parser.l"
+#line 147 "psp_parser.l"
 {
     psp_string_appendc(&PSP_PG(pycode), yytext[0]);
     PSP_PG(after_colon) = 1;
 }
        YY_BREAK
-case 12:
+case 13:
 YY_RULE_SETUP
-#line 147 "psp_parser.l"
+#line 152 "psp_parser.l"
 {
     psp_string_appendc(&PSP_PG(pycode), yytext[0]);
     PSP_PG(after_colon) = 0;
 }
        YY_BREAK
-case 13:
+case 14:
 YY_RULE_SETUP
-#line 152 "psp_parser.l"
+#line 157 "psp_parser.l"
 {
 
     CLEAR_WHITESPACE(&PSP_PG(whitespace)); 
@@ -974,37 +983,37 @@
     BEGIN PYCODE;
 }
        YY_BREAK
-case 14:
+case 15:
 YY_RULE_SETUP
-#line 161 "psp_parser.l"
+#line 166 "psp_parser.l"
 {
     yyless(0);
     BEGIN PYCODE;
 }
        YY_BREAK
-case 15:
-/* rule 15 can match eol */
+case 16:
+/* rule 16 can match eol */
 YY_RULE_SETUP
-#line 166 "psp_parser.l"
+#line 171 "psp_parser.l"
 {
     CLEAR_WHITESPACE(&PSP_PG(whitespace)); 
     yyless(0);
     BEGIN PYCODE;
 }
        YY_BREAK
-case 16:
+case 17:
 YY_RULE_SETUP
-#line 172 "psp_parser.l"
+#line 177 "psp_parser.l"
 {
     CLEAR_WHITESPACE(&PSP_PG(whitespace)); 
     yyless(0);
     BEGIN PYCODE;
 }
        YY_BREAK
-case 17:
-/* rule 17 can match eol */
+case 18:
+/* rule 18 can match eol */
 YY_RULE_SETUP
-#line 178 "psp_parser.l"
+#line 183 "psp_parser.l"
 {
 
     char *filename;
@@ -1046,26 +1055,26 @@
     if (PSP_PG(dir)) free(path);
 }
        YY_BREAK
-case 18:
+case 19:
 YY_RULE_SETUP
-#line 220 "psp_parser.l"
+#line 225 "psp_parser.l"
 {
     BEGIN TEXT;
 }
        YY_BREAK
-case 19:
+case 20:
 YY_RULE_SETUP
-#line 224 "psp_parser.l"
+#line 229 "psp_parser.l"
 {
     BEGIN TEXT;
 }
        YY_BREAK
-case 20:
+case 21:
 YY_RULE_SETUP
-#line 228 "psp_parser.l"
+#line 233 "psp_parser.l"
 ECHO;
        YY_BREAK
-#line 1067 "psp_parser.c"
+#line 1078 "psp_parser.c"
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(PYCODE):
 case YY_STATE_EOF(INDENT):
@@ -1356,7 +1365,7 @@
                while ( yy_chk[yy_base[yy_current_state] + yy_c] != 
yy_current_state )
                        {
                        yy_current_state = (int) yy_def[yy_current_state];
-                       if ( yy_current_state >= 69 )
+                       if ( yy_current_state >= 72 )
                                yy_c = yy_meta[(unsigned int) yy_c];
                        }
                yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned 
int) yy_c];
@@ -1385,11 +1394,11 @@
        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                {
                yy_current_state = (int) yy_def[yy_current_state];
-               if ( yy_current_state >= 69 )
+               if ( yy_current_state >= 72 )
                        yy_c = yy_meta[(unsigned int) yy_c];
                }
        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) 
yy_c];
-       yy_is_jam = (yy_current_state == 68);
+       yy_is_jam = (yy_current_state == 71);
 
        return yy_is_jam ? 0 : yy_current_state;
 }
@@ -1819,15 +1828,16 @@
 /** Setup the input buffer state to scan a string. The next call to yylex() 
will
  * scan from a @e copy of @a str.
  * @param str a NUL-terminated string to scan
+ * @param yy_str a NUL-terminated string to scan
  * @param yyscanner The scanner object.
  * @return the newly allocated buffer state object.
  * @note If you want to scan bytes that may contain NUL values, then use
  *       yy_scan_bytes() instead.
  */
-YY_BUFFER_STATE yy_scan_string (yyconst char * str , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_string (yyconst char * yy_str , yyscan_t yyscanner)
 {
     
-       return yy_scan_bytes(str,strlen(str) ,yyscanner);
+       return yy_scan_bytes(yy_str,strlen(yy_str) ,yyscanner);
 }
 
 /** Setup the input buffer state to scan the given bytes. The next call to 
yylex() will
@@ -2185,7 +2195,7 @@
 #undef YY_DECL_IS_OURS
 #undef YY_DECL
 #endif
-#line 228 "psp_parser.l"
+#line 233 "psp_parser.l"
 
 
 

Reply via email to