From: Tom Lane Date: Thu, 6 May 2004 14:01:33 +0000 (+0000) Subject: Rewrite nodeRead() in a less obfuscated fashion, per discussion with X-Git-Tag: REL9_0_0~12874 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=eee6f9d5c2689660fe3e4586e4b144ea06f04202;p=pg-rex%2Fsyncrep.git Rewrite nodeRead() in a less obfuscated fashion, per discussion with Neil Conway. --- diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 4db6517cd7..788e7dc5af 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -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] == '.'))) diff --git a/src/backend/nodes/read.c b/src/backend/nodes/read.c index 55368a0b23..402c999113 100644 --- a/src/backend/nodes/read.c +++ b/src/backend/nodes/read.c @@ -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 -#include #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 116345686b..0e37459970 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -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 @@ -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 0c67f3e3a3..c3cfd9e3d5 100644 --- a/src/include/nodes/readfuncs.h +++ b/src/include/nodes/readfuncs.h @@ -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