1 %{
2 /*-------------------------------------------------------------------------
3  *
4  * syncrep_gram.y				- Parser for synchronous_standby_names
5  *
6  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *	  src/backend/replication/syncrep_gram.y
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "replication/syncrep.h"
18 
19 /* Result of parsing is returned in one of these two variables */
20 SyncRepConfigData *syncrep_parse_result;
21 char	   *syncrep_parse_error_msg;
22 
23 static SyncRepConfigData *create_syncrep_config(const char *num_sync,
24 					  List *members);
25 
26 /*
27  * Bison doesn't allocate anything that needs to live across parser calls,
28  * so we can easily have it use palloc instead of malloc.  This prevents
29  * memory leaks if we error out during parsing.  Note this only works with
30  * bison >= 2.0.  However, in bison 1.875 the default is to use alloca()
31  * if possible, so there's not really much problem anyhow, at least if
32  * you're building with gcc.
33  */
34 #define YYMALLOC palloc
35 #define YYFREE   pfree
36 
37 %}
38 
39 %expect 0
40 %name-prefix="syncrep_yy"
41 
42 %union
43 {
44 	char	   *str;
45 	List	   *list;
46 	SyncRepConfigData *config;
47 }
48 
49 %token <str> NAME NUM JUNK
50 
51 %type <config> result standby_config
52 %type <list> standby_list
53 %type <str> standby_name
54 
55 %start result
56 
57 %%
58 result:
59 		standby_config				{ syncrep_parse_result = $1; }
60 	;
61 
62 standby_config:
63 		standby_list				{ $$ = create_syncrep_config("1", $1); }
64 		| NUM '(' standby_list ')'	{ $$ = create_syncrep_config($1, $3); }
65 	;
66 
67 standby_list:
68 		standby_name						{ $$ = list_make1($1); }
69 		| standby_list ',' standby_name		{ $$ = lappend($1, $3); }
70 	;
71 
72 standby_name:
73 		NAME						{ $$ = $1; }
74 		| NUM						{ $$ = $1; }
75 	;
76 %%
77 
78 
79 static SyncRepConfigData *
80 create_syncrep_config(const char *num_sync, List *members)
81 {
82 	SyncRepConfigData *config;
83 	int			size;
84 	ListCell   *lc;
85 	char	   *ptr;
86 
87 	/* Compute space needed for flat representation */
88 	size = offsetof(SyncRepConfigData, member_names);
foreach(lc,members)89 	foreach(lc, members)
90 	{
91 		char	   *standby_name = (char *) lfirst(lc);
92 
93 		size += strlen(standby_name) + 1;
94 	}
95 
96 	/* And transform the data into flat representation */
97 	config = (SyncRepConfigData *) palloc(size);
98 
99 	config->config_size = size;
100 	config->num_sync = atoi(num_sync);
101 	config->nmembers = list_length(members);
102 	ptr = config->member_names;
foreach(lc,members)103 	foreach(lc, members)
104 	{
105 		char	   *standby_name = (char *) lfirst(lc);
106 
107 		strcpy(ptr, standby_name);
108 		ptr += strlen(standby_name) + 1;
109 	}
110 
111 	return config;
112 }
113 
114 #include "syncrep_scanner.c"
115