summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2004-05-06 14:01:33 +0000
committerTom Lane2004-05-06 14:01:33 +0000
commit2595212bc38b3aa3ff50341324fd61083a0b5f64 (patch)
tree17f53256ed18b4b9612784f01f56f9db2ec910c9
parentf020d6eed9d29e8a02354a58e5ece4491d4cad42 (diff)
Rewrite nodeRead() in a less obfuscated fashion, per discussion with
Neil Conway.
-rw-r--r--src/backend/nodes/outfuncs.c1
-rw-r--r--src/backend/nodes/read.c123
-rw-r--r--src/backend/nodes/readfuncs.c6
-rw-r--r--src/include/nodes/readfuncs.h2
4 files changed, 52 insertions, 80 deletions
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 2f82d85f55..0b5eae89f4 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -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] == '.')))
diff --git a/src/backend/nodes/read.c b/src/backend/nodes/read.c
index 619977ec6b..64dc3b8c75 100644
--- a/src/backend/nodes/read.c
+++ b/src/backend/nodes/read.c
@@ -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;
}
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index c3de6f542c..8e08c4cd52 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -99,17 +99,17 @@
/* 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() \
diff --git a/src/include/nodes/readfuncs.h b/src/include/nodes/readfuncs.h
index 8416f87396..929270124e 100644
--- a/src/include/nodes/readfuncs.h
+++ b/src/include/nodes/readfuncs.h
@@ -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