OSDN Git Service

Rewrite nodeRead() in a less obfuscated fashion, per discussion with
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 6 May 2004 14:01:33 +0000 (14:01 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 6 May 2004 14:01:33 +0000 (14:01 +0000)
Neil Conway.

src/backend/nodes/outfuncs.c
src/backend/nodes/read.c
src/backend/nodes/readfuncs.c
src/include/nodes/readfuncs.h

index 4db6517..788e7dc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.233 2004/03/17 20:48:42 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.234 2004/05/06 14:01:33 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -130,7 +130,6 @@ _outToken(StringInfo str, char *s)
        /* These characters only need to be quoted at the start of the string */
        if (*s == '<' ||
                *s == '\"' ||
-               *s == '@' ||
                isdigit((unsigned char) *s) ||
                ((*s == '+' || *s == '-') &&
                 (isdigit((unsigned char) s[1]) || s[1] == '.')))
index 55368a0..402c999 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/read.c,v 1.39 2004/01/09 03:07:32 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/read.c,v 1.40 2004/05/06 14:01:33 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -20,7 +20,6 @@
 #include "postgres.h"
 
 #include <ctype.h>
-#include <errno.h>
 
 #include "nodes/pg_list.h"
 #include "nodes/readfuncs.h"
@@ -51,7 +50,7 @@ stringToNode(char *str)
 
        pg_strtok_ptr = str;            /* point pg_strtok at the string to read */
 
-       retval = nodeRead(true);        /* do the reading */
+       retval = nodeRead(NULL, 0);     /* do the reading */
 
        pg_strtok_ptr = save_strtok;
 
@@ -184,9 +183,8 @@ debackslash(char *token, int length)
 
 #define RIGHT_PAREN (1000000 + 1)
 #define LEFT_PAREN     (1000000 + 2)
-#define NODE_SYM       (1000000 + 3)
-#define AT_SYMBOL      (1000000 + 4)
-#define ATOM_TOKEN     (1000000 + 5)
+#define LEFT_BRACE     (1000000 + 3)
+#define OTHER_TOKEN    (1000000 + 4)
 
 /*
  * nodeTokenType -
@@ -194,7 +192,7 @@ debackslash(char *token, int length)
  *       It returns one of the following valid NodeTags:
  *             T_Integer, T_Float, T_String, T_BitString
  *       and some of its own:
- *             RIGHT_PAREN, LEFT_PAREN, NODE_SYM, AT_SYMBOL, ATOM_TOKEN
+ *             RIGHT_PAREN, LEFT_PAREN, LEFT_BRACE, OTHER_TOKEN
  *
  *       Assumption: the ascii representation is legal
  */
@@ -245,15 +243,13 @@ nodeTokenType(char *token, int length)
        else if (*token == ')')
                retval = RIGHT_PAREN;
        else if (*token == '{')
-               retval = NODE_SYM;
-       else if (*token == '@' && length == 1)
-               retval = AT_SYMBOL;
+               retval = LEFT_BRACE;
        else if (*token == '\"' && length > 1 && token[length - 1] == '\"')
                retval = T_String;
        else if (*token == 'b')
                retval = T_BitString;
        else
-               retval = ATOM_TOKEN;
+               retval = OTHER_TOKEN;
        return retval;
 }
 
@@ -266,77 +262,70 @@ nodeTokenType(char *token, int length)
  *     * Value token nodes (integers, floats, or strings);
  *     * General nodes (via parseNodeString() from readfuncs.c);
  *     * Lists of the above.
+ * The return value is declared void *, not Node *, to avoid having to
+ * cast it explicitly in callers that assign to fields of different types.
+ *
+ * External callers should always pass NULL/0 for the arguments.  Internally
+ * a non-NULL token may be passed when the upper recursion level has already
+ * scanned the first token of a node's representation.
  *
  * We assume pg_strtok is already initialized with a string to read (hence
  * this should only be invoked from within a stringToNode operation).
- * Any callers should set read_car_only to true.
  */
 void *
-nodeRead(bool read_car_only)
+nodeRead(char *token, int tok_len)
 {
-       char       *token;
-       int                     tok_len;
+       Node       *result;
        NodeTag         type;
-       Node       *this_value,
-                          *return_value;
-       bool            make_dotted_pair_cell = false;
 
-       token = pg_strtok(&tok_len);
+       if (token == NULL)                      /* need to read a token? */
+       {
+               token = pg_strtok(&tok_len);
 
-       if (token == NULL)
-               return NULL;
+               if (token == NULL)              /* end of input */
+                       return NULL;
+       }
 
        type = nodeTokenType(token, tok_len);
 
        switch (type)
        {
-               case NODE_SYM:
-                       this_value = parseNodeString();
+               case LEFT_BRACE:
+                       result = parseNodeString();
                        token = pg_strtok(&tok_len);
                        if (token == NULL || token[0] != '}')
                                elog(ERROR, "did not find '}' at end of input node");
-                       if (!read_car_only)
-                               make_dotted_pair_cell = true;
-                       else
-                               make_dotted_pair_cell = false;
                        break;
                case LEFT_PAREN:
-                       if (!read_car_only)
                        {
-                               List       *l = makeNode(List);
-
-                               lfirst(l) = nodeRead(false);
-                               lnext(l) = nodeRead(false);
-                               this_value = (Node *) l;
+                               List       *l = NIL;
+
+                               for (;;)
+                               {
+                                       token = pg_strtok(&tok_len);
+                                       if (token == NULL)
+                                               elog(ERROR, "unterminated List structure");
+                                       if (token[0] == ')')
+                                               break;
+                                       l = lappend(l, nodeRead(token, tok_len));
+                               }
+                               result = (Node *) l;
+                               break;
                        }
-                       else
-                               this_value = nodeRead(false);
-                       break;
                case RIGHT_PAREN:
-                       this_value = NULL;
-                       break;
-               case AT_SYMBOL:
-                       this_value = NULL;
+                       elog(ERROR, "unexpected right parenthesis");
+                       result = NULL;  /* keep compiler happy */
                        break;
-               case ATOM_TOKEN:
+               case OTHER_TOKEN:
                        if (tok_len == 0)
                        {
-                               /* must be "<>" */
-                               this_value = NULL;
-
-                               /*
-                                * It might be NULL but it is an atom!
-                                */
-                               if (read_car_only)
-                                       make_dotted_pair_cell = false;
-                               else
-                                       make_dotted_pair_cell = true;
+                               /* must be "<>" --- represents a null pointer */
+                               result = NULL;
                        }
                        else
                        {
-                               /* !attention! result is not a Node.  Use with caution. */
-                               this_value = (Node *) debackslash(token, tok_len);
-                               make_dotted_pair_cell = true;
+                               elog(ERROR, "unrecognized token: \"%.*s\"", tok_len, token);
+                               result = NULL;  /* keep compiler happy */
                        }
                        break;
                case T_Integer:
@@ -345,8 +334,7 @@ nodeRead(bool read_car_only)
                         * we know that the token terminates on a char atol will stop
                         * at
                         */
-                       this_value = (Node *) makeInteger(atol(token));
-                       make_dotted_pair_cell = true;
+                       result = (Node *) makeInteger(atol(token));
                        break;
                case T_Float:
                        {
@@ -354,14 +342,12 @@ nodeRead(bool read_car_only)
 
                                memcpy(fval, token, tok_len);
                                fval[tok_len] = '\0';
-                               this_value = (Node *) makeFloat(fval);
-                               make_dotted_pair_cell = true;
+                               result = (Node *) makeFloat(fval);
                        }
                        break;
                case T_String:
                        /* need to remove leading and trailing quotes, and backslashes */
-                       this_value = (Node *) makeString(debackslash(token + 1, tok_len - 2));
-                       make_dotted_pair_cell = true;
+                       result = (Node *) makeString(debackslash(token + 1, tok_len - 2));
                        break;
                case T_BitString:
                        {
@@ -370,27 +356,14 @@ nodeRead(bool read_car_only)
                                /* skip leading 'b' */
                                strncpy(val, token + 1, tok_len - 1);
                                val[tok_len - 1] = '\0';
-                               this_value = (Node *) makeBitString(val);
+                               result = (Node *) makeBitString(val);
                                break;
                        }
                default:
                        elog(ERROR, "unrecognized node type: %d", (int) type);
-                       this_value = NULL;      /* keep compiler happy */
+                       result = NULL;  /* keep compiler happy */
                        break;
        }
-       if (make_dotted_pair_cell)
-       {
-               List       *l = makeNode(List);
 
-               lfirst(l) = this_value;
-
-               if (!read_car_only)
-                       lnext(l) = nodeRead(false);
-               else
-                       lnext(l) = NULL;
-               return_value = (Node *) l;
-       }
-       else
-               return_value = this_value;
-       return return_value;
+       return (void *) result;
 }
index 1163456..0e37459 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.166 2004/03/17 20:48:42 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.167 2004/05/06 14:01:33 tgl Exp $
  *
  * NOTES
  *       Path and Plan nodes do not have any readfuncs support, because we
 /* Read a Node field */
 #define READ_NODE_FIELD(fldname) \
        token = pg_strtok(&length);             /* skip :fldname */ \
-       local_node->fldname = nodeRead(true)
+       local_node->fldname = nodeRead(NULL, 0)
 
 /* Read an integer-list field */
 #define READ_INTLIST_FIELD(fldname) \
        token = pg_strtok(&length);             /* skip :fldname */ \
-       local_node->fldname = toIntList(nodeRead(true))
+       local_node->fldname = toIntList(nodeRead(NULL, 0))
 
 /* Read an OID-list field */
 #define READ_OIDLIST_FIELD(fldname) \
        token = pg_strtok(&length);             /* skip :fldname */ \
-       local_node->fldname = toOidList(nodeRead(true))
+       local_node->fldname = toOidList(nodeRead(NULL, 0))
 
 /* Routine exit */
 #define READ_DONE() \
index 0c67f3e..c3cfd9e 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/readfuncs.h,v 1.18 2003/11/29 22:41:06 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/readfuncs.h,v 1.19 2004/05/06 14:01:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,7 +21,7 @@
  */
 extern char *pg_strtok(int *length);
 extern char *debackslash(char *token, int length);
-extern void *nodeRead(bool read_car_only);
+extern void *nodeRead(char *token, int tok_len);
 
 /*
  * prototypes for functions in readfuncs.c