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