99 *
1010 *
1111 * IDENTIFICATION
12- * $PostgreSQL: pgsql/src/backend/nodes/read.c,v 1.39 2004/01/09 03:07:32 momjian Exp $
12+ * $PostgreSQL: pgsql/src/backend/nodes/read.c,v 1.40 2004/05/06 14:01:33 tgl Exp $
1313 *
1414 * HISTORY
1515 * AUTHORDATEMAJOR EVENT
2020#include "postgres.h"
2121
2222#include <ctype.h>
23- #include <errno.h>
2423
2524#include "nodes/pg_list.h"
2625#include "nodes/readfuncs.h"
@@ -51,7 +50,7 @@ stringToNode(char *str)
5150
5251pg_strtok_ptr = str ;/* point pg_strtok at the string to read */
5352
54- retval = nodeRead (true );/* do the reading */
53+ retval = nodeRead (NULL , 0 );/* do the reading */
5554
5655pg_strtok_ptr = save_strtok ;
5756
@@ -184,17 +183,16 @@ debackslash(char *token, int length)
184183
185184#define RIGHT_PAREN (1000000 + 1)
186185#define LEFT_PAREN (1000000 + 2)
187- #define NODE_SYM (1000000 + 3)
188- #define AT_SYMBOL (1000000 + 4)
189- #define ATOM_TOKEN (1000000 + 5)
186+ #define LEFT_BRACE (1000000 + 3)
187+ #define OTHER_TOKEN (1000000 + 4)
190188
191189/*
192190 * nodeTokenType -
193191 * returns the type of the node token contained in token.
194192 * It returns one of the following valid NodeTags:
195193 *T_Integer, T_Float, T_String, T_BitString
196194 * and some of its own:
197- *RIGHT_PAREN, LEFT_PAREN,NODE_SYM, AT_SYMBOL, ATOM_TOKEN
195+ *RIGHT_PAREN, LEFT_PAREN,LEFT_BRACE, OTHER_TOKEN
198196 *
199197 * Assumption: the ascii representation is legal
200198 */
@@ -245,15 +243,13 @@ nodeTokenType(char *token, int length)
245243else if (* token == ')' )
246244retval = RIGHT_PAREN ;
247245else if (* token == '{' )
248- retval = NODE_SYM ;
249- else if (* token == '@' && length == 1 )
250- retval = AT_SYMBOL ;
246+ retval = LEFT_BRACE ;
251247else if (* token == '\"' && length > 1 && token [length - 1 ]== '\"' )
252248retval = T_String ;
253249else if (* token == 'b' )
254250retval = T_BitString ;
255251else
256- retval = ATOM_TOKEN ;
252+ retval = OTHER_TOKEN ;
257253return retval ;
258254}
259255
@@ -266,77 +262,70 @@ nodeTokenType(char *token, int length)
266262 ** Value token nodes (integers, floats, or strings);
267263 ** General nodes (via parseNodeString() from readfuncs.c);
268264 ** Lists of the above.
265+ * The return value is declared void *, not Node *, to avoid having to
266+ * cast it explicitly in callers that assign to fields of different types.
267+ *
268+ * External callers should always pass NULL/0 for the arguments. Internally
269+ * a non-NULL token may be passed when the upper recursion level has already
270+ * scanned the first token of a node's representation.
269271 *
270272 * We assume pg_strtok is already initialized with a string to read (hence
271273 * this should only be invoked from within a stringToNode operation).
272- * Any callers should set read_car_only to true.
273274 */
274275void *
275- nodeRead (bool read_car_only )
276+ nodeRead (char * token , int tok_len )
276277{
277- char * token ;
278- int tok_len ;
278+ Node * result ;
279279NodeTag type ;
280- Node * this_value ,
281- * return_value ;
282- bool make_dotted_pair_cell = false;
283280
284- token = pg_strtok (& tok_len );
281+ if (token == NULL )/* need to read a token? */
282+ {
283+ token = pg_strtok (& tok_len );
285284
286- if (token == NULL )
287- return NULL ;
285+ if (token == NULL )/* end of input */
286+ return NULL ;
287+ }
288288
289289type = nodeTokenType (token ,tok_len );
290290
291291switch (type )
292292{
293- case NODE_SYM :
294- this_value = parseNodeString ();
293+ case LEFT_BRACE :
294+ result = parseNodeString ();
295295token = pg_strtok (& tok_len );
296296if (token == NULL || token [0 ]!= '}' )
297297elog (ERROR ,"did not find '}' at end of input node" );
298- if (!read_car_only )
299- make_dotted_pair_cell = true;
300- else
301- make_dotted_pair_cell = false;
302298break ;
303299case LEFT_PAREN :
304- if (!read_car_only )
305300{
306- List * l = makeNode (List );
307-
308- lfirst (l )= nodeRead (false);
309- lnext (l )= nodeRead (false);
310- this_value = (Node * )l ;
301+ List * l = NIL ;
302+
303+ for (;;)
304+ {
305+ token = pg_strtok (& tok_len );
306+ if (token == NULL )
307+ elog (ERROR ,"unterminated List structure" );
308+ if (token [0 ]== ')' )
309+ break ;
310+ l = lappend (l ,nodeRead (token ,tok_len ));
311+ }
312+ result = (Node * )l ;
313+ break ;
311314}
312- else
313- this_value = nodeRead (false);
314- break ;
315315case RIGHT_PAREN :
316- this_value = NULL ;
317- break ;
318- case AT_SYMBOL :
319- this_value = NULL ;
316+ elog (ERROR ,"unexpected right parenthesis" );
317+ result = NULL ;/* keep compiler happy */
320318break ;
321- case ATOM_TOKEN :
319+ case OTHER_TOKEN :
322320if (tok_len == 0 )
323321{
324- /* must be "<>" */
325- this_value = NULL ;
326-
327- /*
328- * It might be NULL but it is an atom!
329- */
330- if (read_car_only )
331- make_dotted_pair_cell = false;
332- else
333- make_dotted_pair_cell = true;
322+ /* must be "<>" --- represents a null pointer */
323+ result = NULL ;
334324}
335325else
336326{
337- /* !attention! result is not a Node. Use with caution. */
338- this_value = (Node * )debackslash (token ,tok_len );
339- make_dotted_pair_cell = true;
327+ elog (ERROR ,"unrecognized token: \"%.*s\"" ,tok_len ,token );
328+ result = NULL ;/* keep compiler happy */
340329}
341330break ;
342331case T_Integer :
@@ -345,23 +334,20 @@ nodeRead(bool read_car_only)
345334 * we know that the token terminates on a char atol will stop
346335 * at
347336 */
348- this_value = (Node * )makeInteger (atol (token ));
349- make_dotted_pair_cell = true;
337+ result = (Node * )makeInteger (atol (token ));
350338break ;
351339case T_Float :
352340{
353341char * fval = (char * )palloc (tok_len + 1 );
354342
355343memcpy (fval ,token ,tok_len );
356344fval [tok_len ]= '\0' ;
357- this_value = (Node * )makeFloat (fval );
358- make_dotted_pair_cell = true;
345+ result = (Node * )makeFloat (fval );
359346}
360347break ;
361348case T_String :
362349/* need to remove leading and trailing quotes, and backslashes */
363- this_value = (Node * )makeString (debackslash (token + 1 ,tok_len - 2 ));
364- make_dotted_pair_cell = true;
350+ result = (Node * )makeString (debackslash (token + 1 ,tok_len - 2 ));
365351break ;
366352case T_BitString :
367353{
@@ -370,27 +356,14 @@ nodeRead(bool read_car_only)
370356/* skip leading 'b' */
371357strncpy (val ,token + 1 ,tok_len - 1 );
372358val [tok_len - 1 ]= '\0' ;
373- this_value = (Node * )makeBitString (val );
359+ result = (Node * )makeBitString (val );
374360break ;
375361}
376362default :
377363elog (ERROR ,"unrecognized node type: %d" , (int )type );
378- this_value = NULL ;/* keep compiler happy */
364+ result = NULL ;/* keep compiler happy */
379365break ;
380366}
381- if (make_dotted_pair_cell )
382- {
383- List * l = makeNode (List );
384367
385- lfirst (l )= this_value ;
386-
387- if (!read_car_only )
388- lnext (l )= nodeRead (false);
389- else
390- lnext (l )= NULL ;
391- return_value = (Node * )l ;
392- }
393- else
394- return_value = this_value ;
395- return return_value ;
368+ return (void * )result ;
396369}