[DRBD-cvs] svn commit by phil - r2052 - in trunk: . user - Rewrote
drbdadm's scanner/lexer and parser. The previou
drbd-cvs at lists.linbit.com
drbd-cvs at lists.linbit.com
Sun Jan 22 00:07:33 CET 2006
Author: phil
Date: 2006-01-22 00:07:32 +0100 (Sun, 22 Jan 2006)
New Revision: 2052
Added:
trunk/user/drbdadm_parser.c
trunk/user/drbdadm_parser.h
Removed:
trunk/user/drbdadm_parser.y
Modified:
trunk/ROADMAP
trunk/user/Makefile
trunk/user/drbdadm_scanner.fl
Log:
Rewrote drbdadm's scanner/lexer and parser. The previous scanner/lexer
was more a parser by itself, and the parser was in its own way obscure
as well.
The new scanner (flex based) only has a single context, the new parser is hand
written instead of bison based.
The old bindary was 966 960 Bytes, the new one is about 6% of this 59 728 .
The new scanner code is a lot easier to read, the new parser code is
less lines of C than it had lines of bison grammer, it is earsier to read
as well.
The new code executes about 10 times faster, than the old one.
The new code also has the extensive error reporting capability, that
drove the old implementation into its bloatness.
Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP 2006-01-19 17:39:52 UTC (rev 2051)
+++ trunk/ROADMAP 2006-01-21 23:07:32 UTC (rev 2052)
@@ -676,6 +676,8 @@
Use a _basic_ flex scanner, and a hand written parser for superb
errror reporting.
+ 99% DONE
+
31 Resizing several GB results in ko-count timeouts, maybe since the
secondary node does the enlargement of the bitmap in the receiver (?)
Modified: trunk/user/Makefile
===================================================================
--- trunk/user/Makefile 2006-01-19 17:39:52 UTC (rev 2051)
+++ trunk/user/Makefile 2006-01-21 23:07:32 UTC (rev 2052)
@@ -41,12 +41,6 @@
# for debug: flex -d -s -odrbdadm_scanner.c drbdadm_scanner.fl
-drbdadm_parser.h: drbdadm_parser.y
- bison -d -o drbdadm_parser.c drbdadm_parser.y
-
-drbdadm_parser.c: drbdadm_parser.y drbdadm.h drbd_limits.h drbdtool_common.h
- bison -d -o drbdadm_parser.c drbdadm_parser.y
-
drbdsetup: $(drbdsetup-obj)
$(CC) -o $@ $^
@@ -55,8 +49,6 @@
clean:
rm -f drbdadm_scanner.c
- rm -f drbdadm_parser.c
- rm -f drbdadm_parser.h
rm -f drbdsetup drbdadm drbdmeta *.o
rm -f *~
Added: trunk/user/drbdadm_parser.c
===================================================================
--- trunk/user/drbdadm_parser.c 2006-01-19 17:39:52 UTC (rev 2051)
+++ trunk/user/drbdadm_parser.c 2006-01-21 23:07:32 UTC (rev 2052)
@@ -0,0 +1,461 @@
+/*
+ drbdadm_parser.c a hand crafted parser
+
+ This file is part of drbd by Philipp Reisner.
+
+ Copyright (C) 2006, Philipp Reisner <philipp.reisner at linbit.com>.
+ Initial author.
+
+ drbd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ drbd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with drbd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ */
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "drbdadm.h"
+#include "drbd_limits.h"
+#include "drbdtool_common.h"
+#include "drbdadm_parser.h"
+
+YYSTYPE yylval;
+
+/////////////////////
+
+#define APPEND(LIST,ITEM) ({ \
+ typeof((LIST)) _l = (LIST); \
+ typeof((ITEM)) _i = (ITEM); \
+ typeof((ITEM)) _t; \
+ _i->next = NULL; \
+ if (_l == NULL) { _l = _i; } \
+ else { \
+ for (_t = _l; _t->next; _t = _t->next); \
+ _t->next = _i; \
+ }; \
+ _l; \
+})
+
+static int c_section_start;
+
+void
+m_strtoll_range(const char *s, char def_unit,
+ const char *name,
+ unsigned long long min, unsigned long long max)
+{
+ unsigned long long r = m_strtoll(s, def_unit);
+ char unit[] = { def_unit > '1' ? def_unit : 0, 0 };
+ if (min > r || r > max)
+ {
+ fprintf(stderr,
+ "%s:%d: %s %s => %llu%s out of range [%llu..%llu]%s.\n",
+ config_file, fline, name, s, r, unit, min, max, unit);
+ exit(E_config_invalid);
+ }
+ if (DEBUG_RANGE_CHECK)
+ {
+ fprintf(stderr,
+ "%s:%d: %s %s => %llu%s in range [%llu..%llu]%s.\n",
+ config_file, fline, name, s, r, unit, min, max, unit);
+ }
+}
+
+enum range_checks
+{
+ R_MINOR_COUNT,
+ R_DIALOG_REFRESH,
+ R_DISK_SIZE,
+ R_TIMEOUT,
+ R_CONNECT_INT,
+ R_PING_INT,
+ R_MAX_BUFFERS,
+ R_MAX_EPOCH_SIZE,
+ R_SNDBUF_SIZE,
+ R_KO_COUNT,
+ R_RATE,
+ R_GROUP,
+ R_AL_EXTENTS,
+ R_PORT,
+ R_META_IDX,
+ R_WFC_TIMEOUT,
+ R_DEGR_WFC_TIMEOUT,
+};
+
+void
+range_check(const enum range_checks what, const char *name, const char *value)
+{
+ switch (what)
+ {
+ default:
+ fprintf(stderr, "%s:%d: unknown range for %s => %s\n",
+ config_file, fline, name, value);
+ break;
+ case R_MINOR_COUNT:
+ m_strtoll_range(value, 1, name,
+ DRBD_MINOR_COUNT_MIN, DRBD_MINOR_COUNT_MAX);
+ break;
+ case R_DIALOG_REFRESH:
+ m_strtoll_range(value, 1, name,
+ DRBD_DIALOG_REFRESH_MIN, DRBD_DIALOG_REFRESH_MAX);
+ break;
+ case R_DISK_SIZE:
+ m_strtoll_range(value, 'K', name,
+ DRBD_DISK_SIZE_SECT_MIN >> 1,
+ DRBD_DISK_SIZE_SECT_MAX >> 1);
+ break;
+ case R_TIMEOUT:
+ m_strtoll_range(value, 1, name, DRBD_TIMEOUT_MIN, DRBD_TIMEOUT_MAX);
+ break;
+ case R_CONNECT_INT:
+ m_strtoll_range(value, 1, name, DRBD_CONNECT_INT_MIN,
+ DRBD_CONNECT_INT_MAX);
+ break;
+ case R_PING_INT:
+ m_strtoll_range(value, 1, name, DRBD_PING_INT_MIN, DRBD_PING_INT_MAX);
+ break;
+ case R_MAX_BUFFERS:
+ m_strtoll_range(value, 1, name, DRBD_MAX_BUFFERS_MIN,
+ DRBD_MAX_BUFFERS_MAX);
+ break;
+ case R_MAX_EPOCH_SIZE:
+ m_strtoll_range(value, 1, name, DRBD_MAX_EPOCH_SIZE_MIN,
+ DRBD_MAX_EPOCH_SIZE_MAX);
+ break;
+ case R_SNDBUF_SIZE:
+ m_strtoll_range(value, 1, name, DRBD_SNDBUF_SIZE_MIN,
+ DRBD_SNDBUF_SIZE_MAX);
+ break;
+ case R_KO_COUNT:
+ m_strtoll_range(value, 1, name, DRBD_KO_COUNT_MIN, DRBD_KO_COUNT_MAX);
+ break;
+ case R_RATE:
+ m_strtoll_range(value, 'K', name, DRBD_RATE_MIN, DRBD_RATE_MAX);
+ break;
+ case R_AL_EXTENTS:
+ m_strtoll_range(value, 1, name, DRBD_AL_EXTENTS_MIN,
+ DRBD_AL_EXTENTS_MAX);
+ break;
+ case R_PORT:
+ m_strtoll_range(value, 1, name, DRBD_PORT_MIN, DRBD_PORT_MAX);
+ break;
+ /* FIXME not yet implemented!
+ case R_META_IDX:
+ m_strtoll_range(value, 1, name, DRBD_META_IDX_MIN, DRBD_META_IDX_MAX);
+ break;
+ */
+ case R_WFC_TIMEOUT:
+ m_strtoll_range(value, 1, name, DRBD_WFC_TIMEOUT_MIN,
+ DRBD_WFC_TIMEOUT_MAX);
+ break;
+ case R_DEGR_WFC_TIMEOUT:
+ m_strtoll_range(value, 1, name, DRBD_DEGR_WFC_TIMEOUT_MIN,
+ DRBD_DEGR_WFC_TIMEOUT_MAX);
+ break;
+ }
+}
+
+static struct d_option* new_opt(char* name,char* value)
+{
+ struct d_option* cn = malloc(sizeof(struct d_option));
+
+ /* fprintf(stderr,"%s:%d: %s = %s\n",config_file,line,name,value); */
+ cn->name=name;
+ cn->value=value;
+ cn->mentioned=0;
+
+ return cn;
+}
+
+static void derror(struct d_host_info *host,
+ struct d_resource* res,
+ char* text)
+{
+ config_valid=0;
+ fprintf(stderr, "%s:%d: in resource %s, on %s { ... }:"
+ " '%s' keyword missing.\n",
+ config_file,c_section_start,res->name,host->name,text);
+}
+
+void check_meta_disk(struct d_host_info *host)
+{
+ if (strcmp(host->meta_disk, "internal") != 0) {
+ /* external */
+ if (host->meta_index == NULL) {
+ fprintf(stderr, "%s:%d: expected 'meta-disk = %s [index]'.\n",
+ config_file, fline, host->meta_disk);
+ }
+ /* index either some number, or "flexible" */
+ check_uniq("meta-disk", "%s:%s[%s]", host->name,
+ host->meta_disk, host->meta_index);
+ } else if (host->meta_index) {
+ /* internal */
+ if (strcmp(host->meta_index,"flexible") != 0) {
+ /* internal, not flexible, but index given: no sir! */
+ fprintf(stderr,
+ "%s:%d: no index allowed with 'meta-disk = internal'.\n",
+ config_file, fline);
+ } /* else internal, flexible: fine */
+ } else {
+ /* internal, not flexible */
+ host->meta_index = strdup("internal");
+ }
+}
+
+///////////////////////////
+
+
+#define EXP(TOKEN1) \
+({ \
+ int token; \
+ token = yylex(); \
+ if(token != TOKEN1) \
+ pe_expected_got( #TOKEN1, token ); \
+})
+
+#define EXP2(TOKEN1,TOKEN2) \
+({ \
+ int token; \
+ token = yylex(); \
+ if(token != TOKEN1 && token != TOKEN2) \
+ pe_expected_got( #TOKEN1 "|" # TOKEN2, token ); \
+})
+
+static void pe_expected(const char *exp)
+{
+ fprintf(stderr,"Parse error '%s' expected, at line %d\n",exp,line);
+ exit(10);
+}
+
+static void pe_expected_got(const char *exp, int got)
+{
+ fprintf(stderr,"Parse error '%s' expected but got %d, at line %d\n",
+ exp,got,line);
+ exit(10);
+}
+
+static void parse_global(void) {
+ EXP('{');
+ while(1) {
+ switch(yylex()) {
+ case TK_DISABLE_IP_VERIFICATION:
+ global_options.disable_ip_verification=1;
+ break;
+ case TK_MINOR_COUNT:
+ EXP(TK_INTEGER);
+ range_check(R_MINOR_COUNT,"minor-count",yylval.txt);
+ global_options.minor_count=atoi(yylval.txt);
+ break;
+ case TK_DIALOG_REFRESH:
+ EXP(TK_INTEGER);
+ range_check(R_DIALOG_REFRESH,"dialog-refresh",yylval.txt);
+ global_options.dialog_refresh=atoi(yylval.txt);
+ break;
+ case '}':
+ return;
+ default:
+ pe_expected("dialog-refresh | minor-count | "
+ "disable-ip-verification");
+ }
+ EXP(';');
+ }
+}
+
+static struct d_option* parse_options(int token_switch,int token_option)
+{
+ char *opt_name;
+ int token;
+
+ struct d_option* options = NULL;
+
+ EXP('{');
+ while(1) {
+ token = yylex();
+ if( token == token_switch) {
+ options = APPEND(options,new_opt(yylval.txt,NULL));
+ } else if ( token == token_option) {
+ opt_name=yylval.txt;
+ EXP2(TK_STRING,TK_INTEGER);
+ options = APPEND(options,new_opt(opt_name,yylval.txt));
+ } else if ( token == '}' ) {
+ return options;
+ } else {
+ pe_expected("An option keyword");
+ }
+ EXP(';');
+ }
+}
+
+static void parse_host_section(struct d_resource* res)
+{
+ struct d_host_info *host;
+
+ c_section_start = line;
+
+ host=calloc(1,sizeof(struct d_host_info));
+ EXP(TK_STRING);
+ host->name = yylval.txt;
+ if(strcmp(host->name, nodeinfo.nodename) == 0) {
+ res->me = host;
+ } else {
+ if (res->peer) {
+ config_valid = 0;
+ fprintf(stderr,
+ "%s:%d: in resource %s, on %s { ... } ... on %s { ... }:\n"
+ "\tThere are multiple host sections for the peer.\n"
+ "\tMaybe misspelled local host name '%s'?\n",
+ config_file, c_section_start, res->name,
+ res->peer->name, host->name, nodeinfo.nodename);
+ }
+ res->peer = host;
+ }
+
+ EXP('{');
+ while(1) {
+ switch(yylex()) {
+ case TK_DISK:
+ EXP(TK_STRING);
+ host->disk = yylval.txt;
+ check_uniq("disk", "%s:%s:%s","disk",
+ host->name,yylval.txt);
+ break;
+ case TK_DEVICE:
+ EXP(TK_STRING);
+ host->device = yylval.txt;
+ check_uniq("device", "%s:%s:%s","device",
+ host->name,yylval.txt);
+ break;
+ case TK_ADDRESS:
+ EXP(TK_IPADDR);
+ host->address = yylval.txt;
+ EXP(':');
+ EXP(TK_INTEGER);
+ host->port = yylval.txt;
+ range_check(R_PORT, "port", yylval.txt);
+ break;
+ case TK_META_DISK:
+ EXP(TK_STRING);
+ host->meta_disk = yylval.txt;
+ if(strcmp("internal",yylval.txt)) {
+ EXP('[');
+ EXP(TK_INTEGER);
+ host->meta_index = yylval.txt;
+ EXP(']');
+ }
+ check_meta_disk(host);
+ break;
+ case TK_FLEX_META_DISK:
+ EXP(TK_STRING);
+ host->meta_disk = yylval.txt;
+ host->meta_index = strdup("flexible");
+ check_meta_disk(host);
+ break;
+ case '}':
+ goto break_loop;
+ default:
+ pe_expected("disk | device | address | meta-disk "
+ "| flex-meta-disk");
+ }
+ EXP(';');
+ }
+ break_loop:
+ if (!host->device) derror(host,res,"device");
+ if (!host->disk) derror(host,res,"disk");
+ if (!host->address) derror(host,res,"address");
+ if (!host->meta_disk) derror(host,res,"meta-disk");
+}
+
+struct d_resource* parse_resource(char* res_name)
+{
+ struct d_resource* res;
+
+ res=calloc(1,sizeof(struct d_resource));
+ res->name = res_name;
+ res->next = NULL;
+
+ EXP('{');
+ while(1) {
+ switch(yylex()) {
+ case TK_PROTOCOL:
+ EXP(TK_STRING);
+ res->protocol=yylval.txt;
+ EXP(';');
+ break;
+ case TK_ON:
+ parse_host_section(res);
+ break;
+ case TK_DISK:
+ res->disk_options = parse_options(TK_DISK_SWITCH,
+ TK_DISK_OPTION);
+ break;
+ case TK_NET:
+ res->net_options = parse_options(TK_NET_SWITCH,
+ TK_NET_OPTION);
+ break;
+ case TK_SYNCER:
+ res->sync_options = parse_options(TK_SYNCER_SWITCH,
+ TK_SYNCER_OPTION);
+ break;
+ case TK_STARTUP:
+ res->startup_options=parse_options(TK_STARTUP_SWITCH,
+ TK_STARTUP_OPTION);
+ break;
+ case TK_HANDLER:
+ res->handlers = parse_options(0,
+ TK_HANDLER_OPTION);
+ break;
+ case '}': return res;
+ default:
+ pe_expected("protocol | on | disk | net | syncer |"
+ " startup | handler");
+ }
+ }
+}
+
+void parse_skip()
+{
+ int level=0;
+ do {
+ switch(yylex()) {
+ case '{':
+ level++;
+ break;
+ case '}':
+ level--;
+ break;
+ }
+ } while(level);
+}
+
+void yyparse(void)
+{
+ common = NULL;
+ config = NULL;
+
+ while(1) {
+ switch(yylex()) {
+ case TK_GLOBAL: parse_global(); break;
+ case TK_COMMON: common = parse_resource("common"); break;
+ case TK_RESOURCE:
+ EXP(TK_STRING);
+ config = APPEND( config , parse_resource(yylval.txt) );
+ break;
+ case TK_SKIP: parse_skip(); break;
+ case 0: return;
+ default:
+ pe_expected("global | common | resource | skip");
+ }
+ }
+}
Added: trunk/user/drbdadm_parser.h
===================================================================
--- trunk/user/drbdadm_parser.h 2006-01-19 17:39:52 UTC (rev 2051)
+++ trunk/user/drbdadm_parser.h 2006-01-21 23:07:32 UTC (rev 2052)
@@ -0,0 +1,76 @@
+/*
+ drbdadm_parser.h a hand crafted parser
+
+ This file is part of drbd by Philipp Reisner.
+
+ Copyright (C) 2006, Philipp Reisner <philipp.reisner at linbit.com>.
+ Initial author.
+
+ drbd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ drbd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with drbd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ */
+
+typedef union YYSTYPE {
+ char* txt;
+ struct d_option* d_option;
+ struct d_resource* d_resource;
+} YYSTYPE;
+
+#define yystype YYSTYPE /* obsolescent; will be withdrawn */
+#define YYSTYPE_IS_DECLARED 1
+#define YYSTYPE_IS_TRIVIAL 1
+
+extern YYSTYPE yylval;
+
+
+enum yytokentype {
+ TK_GLOBAL = 258,
+ TK_RESOURCE,
+ TK_ON,
+ TK_NET,
+ TK_DISK,
+ TK_SKIP,
+ TK_SYNCER,
+ TK_STARTUP,
+ TK_DISABLE_IO_HINTS,
+ TK_DISABLE_IP_VERIFICATION,
+ TK_DIALOG_REFRESH,
+ TK_PROTOCOL,
+ TK_HANDLER, // 270
+ TK_COMMON,
+ TK_ADDRESS,
+ TK_DEVICE,
+ TK_META_DISK,
+ TK_FLEX_META_DISK,
+ TK_MINOR_COUNT,
+
+ TK_IPADDR,
+ TK_INTEGER,
+ TK_STRING,
+ TK_ELSE, // 280
+
+ TK_DISK_SWITCH,
+ TK_DISK_OPTION,
+ TK_NET_SWITCH,
+ TK_NET_OPTION,
+ TK_SYNCER_SWITCH,
+ TK_SYNCER_OPTION,
+ TK_STARTUP_SWITCH,
+ TK_STARTUP_OPTION,
+ TK_HANDLER_OPTION
+};
+
+/* avoid compiler warnings about implicit declaration */
+int yylex(void);
Deleted: trunk/user/drbdadm_parser.y
===================================================================
--- trunk/user/drbdadm_parser.y 2006-01-19 17:39:52 UTC (rev 2051)
+++ trunk/user/drbdadm_parser.y 2006-01-21 23:07:32 UTC (rev 2052)
@@ -1,469 +0,0 @@
-%{
-
-#define _GNU_SOURCE
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "drbdadm.h"
-#include "drbd_limits.h"
-#include "drbdtool_common.h"
-
-extern void yyerror(char* text);
-extern int yylex(void);
-
-#define YYDEBUG 1
-
-#define APPEND(LIST,ITEM) ({ \
- typeof((LIST)) _l = (LIST); \
- typeof((ITEM)) _i = (ITEM); \
- typeof((ITEM)) _t; \
- _i->next = NULL; \
- if (_l == NULL) { _l = _i; } \
- else { \
- for (_t = _l; _t->next; _t = _t->next); \
- _t->next = _i; \
- }; \
- _l; \
-})
-
-static struct d_resource* c_res;
-static struct d_resource* c_config;
-static struct d_host_info* c_host;
-static char* c_hostname;
-static int c_section_start, n_hosts;
-
-void
-m_strtoll_range(const char *s, char def_unit,
- const char *name,
- unsigned long long min, unsigned long long max)
-{
- unsigned long long r = m_strtoll(s, def_unit);
- char unit[] = { def_unit > '1' ? def_unit : 0, 0 };
- if (min > r || r > max)
- {
- fprintf(stderr,
- "%s:%d: %s %s => %llu%s out of range [%llu..%llu]%s.\n",
- config_file, fline, name, s, r, unit, min, max, unit);
- exit(E_config_invalid);
- }
- if (DEBUG_RANGE_CHECK)
- {
- fprintf(stderr,
- "%s:%d: %s %s => %llu%s in range [%llu..%llu]%s.\n",
- config_file, fline, name, s, r, unit, min, max, unit);
- }
-}
-
-enum range_checks
-{
- R_MINOR_COUNT,
- R_DIALOG_REFRESH,
- R_DISK_SIZE,
- R_TIMEOUT,
- R_CONNECT_INT,
- R_PING_INT,
- R_MAX_BUFFERS,
- R_MAX_EPOCH_SIZE,
- R_SNDBUF_SIZE,
- R_KO_COUNT,
- R_RATE,
- R_GROUP,
- R_AL_EXTENTS,
- R_PORT,
- R_META_IDX,
- R_WFC_TIMEOUT,
- R_DEGR_WFC_TIMEOUT,
-};
-
-void
-range_check(const enum range_checks what, const char *name, const char *value)
-{
- switch (what)
- {
- default:
- fprintf(stderr, "%s:%d: unknown range for %s => %s\n",
- config_file, fline, name, value);
- break;
- case R_MINOR_COUNT:
- m_strtoll_range(value, 1, name,
- DRBD_MINOR_COUNT_MIN, DRBD_MINOR_COUNT_MAX);
- break;
- case R_DIALOG_REFRESH:
- m_strtoll_range(value, 1, name,
- DRBD_DIALOG_REFRESH_MIN, DRBD_DIALOG_REFRESH_MAX);
- break;
- case R_DISK_SIZE:
- m_strtoll_range(value, 'K', name,
- DRBD_DISK_SIZE_SECT_MIN >> 1,
- DRBD_DISK_SIZE_SECT_MAX >> 1);
- break;
- case R_TIMEOUT:
- m_strtoll_range(value, 1, name, DRBD_TIMEOUT_MIN, DRBD_TIMEOUT_MAX);
- break;
- case R_CONNECT_INT:
- m_strtoll_range(value, 1, name, DRBD_CONNECT_INT_MIN,
- DRBD_CONNECT_INT_MAX);
- break;
- case R_PING_INT:
- m_strtoll_range(value, 1, name, DRBD_PING_INT_MIN, DRBD_PING_INT_MAX);
- break;
- case R_MAX_BUFFERS:
- m_strtoll_range(value, 1, name, DRBD_MAX_BUFFERS_MIN,
- DRBD_MAX_BUFFERS_MAX);
- break;
- case R_MAX_EPOCH_SIZE:
- m_strtoll_range(value, 1, name, DRBD_MAX_EPOCH_SIZE_MIN,
- DRBD_MAX_EPOCH_SIZE_MAX);
- break;
- case R_SNDBUF_SIZE:
- m_strtoll_range(value, 1, name, DRBD_SNDBUF_SIZE_MIN,
- DRBD_SNDBUF_SIZE_MAX);
- break;
- case R_KO_COUNT:
- m_strtoll_range(value, 1, name, DRBD_KO_COUNT_MIN, DRBD_KO_COUNT_MAX);
- break;
- case R_RATE:
- m_strtoll_range(value, 'K', name, DRBD_RATE_MIN, DRBD_RATE_MAX);
- break;
- case R_AL_EXTENTS:
- m_strtoll_range(value, 1, name, DRBD_AL_EXTENTS_MIN,
- DRBD_AL_EXTENTS_MAX);
- break;
- case R_PORT:
- m_strtoll_range(value, 1, name, DRBD_PORT_MIN, DRBD_PORT_MAX);
- break;
- /* FIXME not yet implemented!
- case R_META_IDX:
- m_strtoll_range(value, 1, name, DRBD_META_IDX_MIN, DRBD_META_IDX_MAX);
- break;
- */
- case R_WFC_TIMEOUT:
- m_strtoll_range(value, 1, name, DRBD_WFC_TIMEOUT_MIN,
- DRBD_WFC_TIMEOUT_MAX);
- break;
- case R_DEGR_WFC_TIMEOUT:
- m_strtoll_range(value, 1, name, DRBD_DEGR_WFC_TIMEOUT_MIN,
- DRBD_DEGR_WFC_TIMEOUT_MAX);
- break;
- }
-}
-
-static struct d_option* new_opt(char* name,char* value)
-{
- struct d_option* cn = malloc(sizeof(struct d_option));
-
- /* fprintf(stderr,"%s:%d: %s = %s\n",config_file,line,name,value); */
- cn->name=name;
- cn->value=value;
- cn->mentioned=0;
-
- return cn;
-}
-
-static void derror(char* text)
-{
- config_valid=0;
- fprintf(stderr, "%s:%d: in resource %s, on %s { ... }:"
- " '%s' keyword missing.\n",
- config_file,c_section_start,c_res->name,c_hostname,text);
-}
-
-static void host_sec(char *name)
-{
- c_host->name = name;
- if (!c_host->device) derror("device");
- if (!c_host->disk) derror("disk");
- if (!c_host->address) derror("address");
- if (!c_host->meta_disk) derror("meta-disk");
-
- if (strcmp(name, nodeinfo.nodename) == 0) {
- // if (c_res->me) error(...); -- already done by check_uniq in the rules.
- c_res->me = c_host;
- } else {
- if (c_res->peer) {
- config_valid = 0;
- fprintf(stderr,
- "%s:%d: in resource %s, on %s { ... } ... on %s { ... }:\n"
- "\tThere are multiple host sections for the peer.\n"
- "\tMaybe misspelled local host name '%s'?\n",
- config_file, c_section_start, c_res->name,
- c_res->peer->name, c_hostname, nodeinfo.nodename);
- }
- c_res->peer = c_host;
- }
-}
-
-static struct d_resource* new_resource(char* name)
-{
- struct d_resource* res;
- res=calloc(1,sizeof(struct d_resource));
- res->name=name;
- res->next = NULL;
-
- return res;
-}
-
-void check_meta_disk()
-{
- if (strcmp(c_host->meta_disk, "internal") != 0) {
- /* external */
- if (c_host->meta_index == NULL) {
- fprintf(stderr, "%s:%d: expected 'meta-disk = %s [index]'.\n",
- config_file, fline, c_host->meta_disk);
- }
- /* index either some number, or "flexible" */
- check_uniq("meta-disk", "%s:%s[%s]", c_hostname,
- c_host->meta_disk, c_host->meta_index);
- } else if (c_host->meta_index) {
- /* internal */
- if (strcmp(c_host->meta_index,"flexible") != 0) {
- /* internal, not flexible, but index given: no sir! */
- fprintf(stderr,
- "%s:%d: no index allowed with 'meta-disk = internal'.\n",
- config_file, fline);
- } /* else internal, flexible: fine */
- } else {
- /* internal, not flexible */
- c_host->meta_index = strdup("internal");
- }
-}
-
-#define CHKU(what,val) \
- c_host->what = val; \
- check_uniq( #what, "%s:%s:%s", #what, c_hostname,val)
-
-#define CHKS(sname) \
- check_uniq(sname " section","%s:" sname, c_res->name)
-%}
-
-%union {
- char* txt;
- struct d_option* d_option;
- struct d_resource* d_resource;
-}
-
-%token TK_GLOBAL TK_RESOURCE
-%token TK_ON TK_NET TK_DISK_S TK_SYNCER TK_STARTUP
-%token TK_DISABLE_IO_HINTS
-%token TK_DISABLE_IP_VERIFICATION
-%token TK_PROTOCOL TK_HANDLERS TK_COMMON
-%token TK_ADDRESS TK_DISK TK_DEVICE TK_META_DISK TK_FLEX_META_DISK
-%token <txt> TK_MINOR_COUNT TK_INTEGER TK_STRING
-%token <txt> TK_ON_IO_ERROR TK_SIZE TK_SPLIT_BRAIN_FIX
-%token <txt> TK_TIMEOUT TK_CONNECT_INT TK_PING_INT TK_MAX_BUFFERS TK_IPADDR
-%token <txt> TK_MAX_EPOCH_SIZE TK_SNDBUF_SIZE
-%token <txt> TK_SKIP_SYNC TK_USE_CSUMS TK_RATE TK_SYNC_AFTER TK_AL_EXTENTS
-%token <txt> TK_WFC_TIMEOUT TK_DEGR_WFC_TIMEOUT
-%token <txt> TK_KO_COUNT TK_ON_DISCONNECT TK_DIALOG_REFRESH
-%token <txt> TK_ALLOW_TWO_PRIMARIES
-%token <txt> TK_PRI_ON_INCON_DEGR TK_PRI_LOST_AFTER_SB
-%token <txt> TK_OUTDATE_PEER TK_CRAM_HMAC_ALG TK_SHARED_SECRET
-%token <txt> TK_AFTER_SB_PRI
-
-%type <txt> hostname resource_name
-%type <d_option> disk_stmts disk_stmt
-%type <d_option> net_stmts net_stmt
-%type <d_option> sync_stmts sync_stmt
-%type <d_option> startup_stmts startup_stmt
-%type <d_option> handler_stmts handler_stmt
-%type <d_resource> resources resource
-
-%%
-config: global_sec common resources { config=$3; }
- ;
-
-global_sec: /* empty */
- | TK_GLOBAL glob_stmts
- ;
-
-glob_stmts: /* empty */
- | glob_stmts glob_stmt
- ;
-
-glob_stmt: TK_DISABLE_IO_HINTS
- {
- fprintf(stderr,
- "%s:%d: in global section, "
- "useless use of no longer available option \"disable_io_hints\".\n",
- config_file, line);
- }
- | TK_DISABLE_IP_VERIFICATION
- { global_options.disable_ip_verification=1; }
- | TK_MINOR_COUNT TK_INTEGER
- {
- range_check(R_MINOR_COUNT,$1,$2);
- global_options.minor_count=atoi($2);
- }
- | TK_DIALOG_REFRESH TK_INTEGER
- {
- range_check(R_DIALOG_REFRESH,$1,$2);
- global_options.dialog_refresh=atoi($2);
- }
- ;
-
-common: /* empty */ { common = NULL; }
- | TK_COMMON { c_res = new_resource("common"); }
- res_stmts { common = c_res; }
- ;
-
-resources: /* empty */ { $$ = 0; c_config = 0; }
- | resources resource { $$=APPEND($1,$2); c_config=$$; }
- ;
-
-resource: TK_RESOURCE { n_hosts = 0; } resource_name res_stmts
- { $$ = c_res; validate_resource(c_res); }
- ;
-
-resource_name: TK_STRING
- {
- int uniq;
- c_resource_start = line;
- c_res = new_resource($1);
- uniq = check_uniq("resource","%s",$1);
- if (!uniq) exit(E_config_invalid);
- }
- ;
-
-res_stmts: /* empty */
- | res_stmts res_stmt
- | res_stmts section
- ;
-
-res_stmt: TK_PROTOCOL TK_STRING { c_res->protocol=$2; }
- ;
-
-section: TK_DISK_S disk_stmts
- { CHKS("disk"); c_res->disk_options=$2; }
- | TK_NET net_stmts
- { CHKS("net"); c_res->net_options=$2; }
- | TK_SYNCER sync_stmts
- { CHKS("syncer"); c_res->sync_options=$2; }
- | TK_STARTUP startup_stmts
- { CHKS("startup"); c_res->startup_options=$2; }
- | TK_ON hostname host_stmts { host_sec($2); }
- | TK_HANDLERS handler_stmts
- { CHKS("handlers"); c_res->handlers=$2; }
- ;
-
-hostname: TK_STRING
- {
- int uniq;
- c_section_start = line;
- c_hostname = $1;
- uniq = check_uniq("host section", "%s: on %s",
- c_res->name, c_hostname);
- if (!uniq)
- exit(E_config_invalid);
- if (++n_hosts > 2) {
- fprintf(stderr,
- "%s:%d: in resource %s, "
- "unsupported third host section on %s { ... }.\n",
- config_file, c_section_start, c_res->name,
- c_hostname);
- exit(E_config_invalid);
- }
- }
- ;
-
-disk_stmts: /* empty */ { $$ = NULL; }
- | disk_stmts disk_stmt { $$=APPEND($1,$2); }
- ;
-
-disk_stmt: TK_ON_IO_ERROR TK_STRING { $$=new_opt($1,$2); }
- | TK_SIZE TK_INTEGER
- { $$=new_opt($1,$2); range_check(R_DISK_SIZE,$1,$2); }
- | TK_SPLIT_BRAIN_FIX { $$=new_opt($1,NULL); }
- ;
-
-net_stmts: /* empty */ { $$ = NULL; }
- | net_stmts net_stmt { $$=APPEND($1,$2); }
- ;
-
-net_stmt: TK_TIMEOUT TK_INTEGER
- { range_check(R_TIMEOUT,$1,$2); $$=new_opt($1,$2); }
- | TK_CONNECT_INT TK_INTEGER
- { range_check(R_CONNECT_INT,$1,$2); $$=new_opt($1,$2); }
- | TK_PING_INT TK_INTEGER
- { range_check(R_PING_INT,$1,$2); $$=new_opt($1,$2); }
- | TK_MAX_BUFFERS TK_INTEGER
- { range_check(R_MAX_BUFFERS,$1,$2); $$=new_opt($1,$2); }
- | TK_MAX_EPOCH_SIZE TK_INTEGER
- { range_check(R_MAX_EPOCH_SIZE,$1,$2); $$=new_opt($1,$2); }
- | TK_SNDBUF_SIZE TK_INTEGER
- { range_check(R_SNDBUF_SIZE,$1,$2); $$=new_opt($1,$2); }
- | TK_KO_COUNT TK_INTEGER
- { range_check(R_KO_COUNT,$1,$2); $$=new_opt($1,$2); }
- | TK_ON_DISCONNECT TK_STRING { $$=new_opt($1,$2); }
- | TK_ALLOW_TWO_PRIMARIES { $$=new_opt($1,NULL); }
- | TK_CRAM_HMAC_ALG TK_STRING { $$=new_opt($1,$2); }
- | TK_SHARED_SECRET TK_STRING { $$=new_opt($1,$2); }
- | TK_AFTER_SB_PRI TK_STRING { $$=new_opt($1,$2); }
- ;
-
-sync_stmts: /* empty */ { $$ = NULL; }
- | sync_stmts sync_stmt { $$=APPEND($1,$2); }
- ;
-
-sync_stmt: TK_SKIP_SYNC { $$=new_opt($1,NULL); }
- | TK_USE_CSUMS { $$=new_opt($1,NULL); }
- | TK_RATE TK_INTEGER
- { range_check(R_RATE,$1,$2); $$=new_opt($1,$2); }
- | TK_SYNC_AFTER TK_STRING { $$=new_opt($1,$2); }
- | TK_AL_EXTENTS TK_INTEGER { $$=new_opt($1,$2); }
- { range_check(R_AL_EXTENTS,$1,$2); $$=new_opt($1,$2); }
- ;
-
-host_stmts: /* empty */ { c_host=calloc(1,sizeof(struct d_host_info)); }
- | host_stmts host_stmt
- ;
-
-host_stmt: TK_DISK TK_STRING { CHKU(disk,$2); }
- | TK_DEVICE TK_STRING { CHKU(device,$2); }
- | TK_ADDRESS ip_and_port
- { check_uniq("IP","%s:%s", c_host->address,c_host->port); }
- | TK_META_DISK meta_disk_and_index { check_meta_disk(); }
- | TK_FLEX_META_DISK flex_meta_disk { check_meta_disk(); }
- ;
-
-
-ip_and_port: TK_IPADDR TK_INTEGER
- {
- range_check(R_PORT, "port", $2);
- c_host->address=$1; c_host->port = $2;
- }
- ;
-
-flex_meta_disk:
- TK_STRING
- {
- c_host->meta_disk = $1;
- /* overload index once more */
- c_host->meta_index = strdup("flexible");
- }
- ;
-meta_disk_and_index:
- TK_STRING TK_INTEGER
- { c_host->meta_disk = $1; c_host->meta_index = $2; }
- | TK_STRING { c_host->meta_disk = $1; }
- ;
-
-startup_stmts: /* empty */ { $$ = NULL; }
- | startup_stmts startup_stmt { $$=APPEND($1,$2); }
- ;
-
-startup_stmt: TK_WFC_TIMEOUT TK_INTEGER
- { range_check(R_WFC_TIMEOUT,$1,$2); $$=new_opt($1,$2); }
- | TK_DEGR_WFC_TIMEOUT TK_INTEGER
- { range_check(R_DEGR_WFC_TIMEOUT,$1,$2);$$=new_opt($1,$2); }
- ;
-
-handler_stmts: /* empty */ { $$ = NULL; }
- | handler_stmts handler_stmt { $$=APPEND($1,$2); }
- ;
-
-handler_stmt: TK_PRI_ON_INCON_DEGR TK_STRING { $$=new_opt($1,$2); }
- | TK_PRI_LOST_AFTER_SB TK_STRING { $$=new_opt($1,$2); }
- | TK_OUTDATE_PEER TK_STRING { $$=new_opt($1,$2); }
- ;
Modified: trunk/user/drbdadm_scanner.fl
===================================================================
--- trunk/user/drbdadm_scanner.fl 2006-01-19 17:39:52 UTC (rev 2051)
+++ trunk/user/drbdadm_scanner.fl 2006-01-21 23:07:32 UTC (rev 2052)
@@ -1,427 +1,104 @@
%{
-/*
-*/
-
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
-#include "drbdadm.h"
#include "drbdadm_parser.h"
+#include "drbdadm.h"
-static void update_lcnt(void);
-static void section(int);
-static void named_section(int);
-static void do_assign(int);
+void long_string(char* text);
static void unescape(void);
-static void unescape_midx(void);
-/* static char* const escape(char* const str); */
-static void syntax_error(char*);
-static void expect_error(char*);
-#define CP yylval.txt = strdup(yytext);
+#if 0
+#define DP printf("'%s' ",yytext)
+#else
+#define DP
+#endif
+#define CP yylval.txt = strdup(yytext)
+
#define YY_NO_UNPUT 1
-static int yy_top_state(void) __attribute((unused)); /* no unused warning */
static void yyunput (int c, register char * yy_bp ) __attribute((unused));
-#define PRINTF(fmt, args...) \
- fprintf(stderr, "%s:%d: " fmt, config_file, line , ## args )
+int skip_level=0;
-/* This is an "unusual" scanner. If someone tells me how to do this in
- * the parser instead, tell me. I just was not able to make the error
- * handling of yacc do what I want.
- * -- lge
- */
-
%}
%option noyywrap
-%option stack
-%x RESOURCE GLOBAL
-%x STARTUP DISK NET SYNCER HOST HANDLERS COMMON
-%x SEMICOLON ASSIGN NUM NUM_U NAME STRING PROTO IO_ERROR ON_DISCONNECT
-%x IP_AND_PORT PORT FLEX_META_DISK META_DISK META_IDX
-%x LS LBRACE IGNORE_SECTION
+NUM [0-9]{1,8}[MKG]?
+SNUMB [0-9]{1,3}
+IPV4ADDR ({SNUMB}"."){3}{SNUMB}
+WS [ \t]
+OPCHAR [{};\[\]:]
+DQSTRING \"[^\"\\\n]{1,255}\"
+STRING [a-zA-Z0-9/._-]{1,80}
+LONG_STRING [a-zA-Z0-9/._-]{81}
-LS [ \t]{1,80}
-WS ({LS}|\n)
-COMMENT_START \#
-ASSIGN {LS}
-OUT_OF_RANGE_NUM [0-9]{10,}[kmgKMG]?
-NUM [0-9]{1,9}
-NUM_U [0-9]{1,9}[kmgKMG]?
-NAME [/_.A-Za-z0-9-]{1,80}
-ENAME [/_.A-Za-z0-9-]{81}
-L_NO_DQUOTES [^\"\\\n]
-STRING ({NAME}|\"{L_NO_DQUOTES}{1,220}\")
-ESTRING (\"{L_NO_DQUOTES}{221}|\"\")
-DISK disk
-INTERN internal|\"internal\"
-META_IDX {LS}?\[{LS}?{NUM}{LS}?\]
-O_IDX {WS}meta-index{ASSIGN}
-IGNORE {WS}
-SKIP skip({LS}[^{\n]{0,80})?
-NDELIM [^ \t\n#;{}]{1,50}
-_1_254 [1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4]
-_0_255 0|[1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]
-IPV4ADDR {_1_254}\.{_0_255}\.{_0_255}\.{_1_254}
-PORT {WS}port{ASSIGN}{NUM}
-COMMON common
-AFTER_SB_PRI after-sb-[012]pri
+%x in_string id skip
%%
-<INITIAL,RESOURCE>{
- {SKIP} section(IGNORE_SECTION);
-}
+\n { line++; }
+#[^\n]* /* ignore comments */
+{WS} /* ignore whitespaces */
+{OPCHAR} { DP; return yytext[0]; }
+on { DP; return TK_ON; }
+net { DP; return TK_NET; }
+skip { DP; return TK_SKIP; }
+disk { DP; return TK_DISK; }
+syncer { DP; return TK_SYNCER; }
+device { DP; return TK_DEVICE; }
+global { DP; return TK_GLOBAL; }
+common { DP; return TK_COMMON; }
+address { DP; return TK_ADDRESS; }
+startup { DP; return TK_STARTUP; }
+handlers { DP; return TK_HANDLER; }
+protocol { DP; return TK_PROTOCOL; }
+minor-count { DP; return TK_MINOR_COUNT; }
+disable-io-hints { DP; return TK_DISABLE_IO_HINTS; }
+disable-ip-verfification {DP; return TK_DISABLE_IP_VERIFICATION;}
+dialog-refresh { DP; return TK_DIALOG_REFRESH; }
+resource { DP; return TK_RESOURCE; }
+meta-disk { DP; return TK_META_DISK; }
+flexible-meta-disk { DP; return TK_FLEX_META_DISK; }
+size { DP; CP; return TK_DISK_OPTION; }
+on-io-error { DP; CP; return TK_DISK_OPTION; }
+split-brain-fix { DP; CP; return TK_DISK_SWITCH; }
+timeout { DP; CP; return TK_NET_OPTION; }
+ping-int { DP; CP; return TK_NET_OPTION; }
+max-buffers { DP; CP; return TK_NET_OPTION; }
+sndbuf-size { DP; CP; return TK_NET_OPTION; }
+connect-int { DP; CP; return TK_NET_OPTION; }
+max-epoch-size { DP; CP; return TK_NET_OPTION; }
+after-sb-[012]pri { DP; CP; return TK_NET_OPTION; }
+allow-two-primaries { DP; CP; return TK_NET_SWITCH; }
+rate { DP; CP; return TK_SYNCER_OPTION; }
+after { DP; CP; return TK_SYNCER_OPTION; }
+use-csums { DP; CP; return TK_SYNCER_SWITCH; }
+skip-sync { DP; CP; return TK_SYNCER_SWITCH; }
+al-extents { DP; CP; return TK_SYNCER_OPTION; }
+wfc-timeout { DP; CP; return TK_STARTUP_OPTION; }
+degr-wfc-timeout { DP; CP; return TK_STARTUP_OPTION; }
+pri-on-incon-degr { DP; CP; return TK_HANDLER_OPTION; }
+pri-lost-after-sb { DP; CP; return TK_HANDLER_OPTION; }
+outdate-peer { DP; CP; return TK_HANDLER_OPTION; }
+{IPV4ADDR} { DP; CP; return TK_IPADDR; }
+{NUM} { DP; CP; return TK_INTEGER; }
+{DQSTRING} { unescape(); DP; CP; return TK_STRING; }
+{STRING} { DP; CP; return TK_STRING; }
+{LONG_STRING} { long_string( yylval.txt ); }
+[^\n] { DP; return TK_ELSE; }
-<INITIAL,ASSIGN,LBRACE,META_IDX,RESOURCE,GLOBAL,STARTUP,DISK,NET,SYNCER,HOST,HANDLERS,PORT>{
- {COMMENT_START} {
- char c;
- while ((c = input()) != '\n' && c != EOF);
- if (c == '\n') ++line;
- }
-}
-
-<INITIAL>{
- {WS} update_lcnt();
- global section(GLOBAL); return TK_GLOBAL;
- resource named_section(RESOURCE); return TK_RESOURCE;
- \} syntax_error("unmached closing brace.");
- common section(COMMON); return TK_COMMON;
- {NDELIM} expect_error("one of 'global|resource'");
-}
-
-<RESOURCE,GLOBAL,IGNORE_SECTION,STARTUP,DISK,NET,SYNCER,HOST,HANDLERS,COMMON>{
- {IGNORE} update_lcnt();
- \} yy_pop_state();
-}
-
-<NAME>{
- {ENAME} syntax_error("name too long.\n");
- {NAME} yy_pop_state(); CP; return TK_STRING;
- [^ \t\n#]{1,80} expect_error("name"); /* not referenced currently */
-}
-
-<SEMICOLON>{
- {LS} /* ignore */
- ; yy_pop_state();
- \n yy_pop_state(); PRINTF("missing ';'\n"); line++;
- {NDELIM} expect_error("';'");
-}
-
-<ASSIGN>{
- {ASSIGN} yy_pop_state(); fline = line;
- = syntax_error("don't use '=' signs anymore!");
- {WS} syntax_error("linebreak between option and value not allowed.\n");
- {NDELIM} expect_error("whitespace");
-}
-
-<NUM,NUM_U>{
- {OUT_OF_RANGE_NUM} {
- PRINTF("%s: number exeeds limit of 9 digits\n", yytext);
- exit(E_syntax);
- }
-}
-
-<NUM>{
- {NUM} yy_pop_state(); CP; return TK_INTEGER;
- {NDELIM} expect_error("integer"); yy_pop_state();
-}
-
-<NUM_U>{
- {NUM_U} yy_pop_state(); CP; return TK_INTEGER;
- {NDELIM} expect_error("[0-9]+[KMG]?"); yy_pop_state();
-}
-
-<STRING>{
- {ENAME} syntax_error("name too long.\n");
- {ESTRING} syntax_error("string terminator missing or string too long.\n");
- {STRING} yy_pop_state(); unescape(); CP; return TK_STRING;
- {NDELIM} expect_error("string"); yy_pop_state();
-}
-
-<PROTO>{
- \"[abcABC]\" yy_pop_state(); unescape(); CP; return TK_STRING;
- [abcABC] yy_pop_state(); CP; return TK_STRING;
- {NDELIM} expect_error("one of 'A|B|C'"); yy_pop_state();
-}
-
-<PORT>{
- : BEGIN(NUM); /* this is only reached when I have a colon */
- {WS} update_lcnt();
- port{ASSIGN} {
- /* or a 'port = ' following the 'address = ' */
- update_lcnt(); BEGIN(NUM);
- PRINTF("'port=<port>' deprecated, "
- "please use 'IP:port' instead.\n");
- }
-}
-
-<IP_AND_PORT>{
- {LS} /* ignore */
- \" syntax_error("please do not quote IP:PORT.\n");
- {IPV4ADDR}/:{NUM} BEGIN(PORT); CP; return TK_IPADDR;
- {IPV4ADDR}/{PORT} BEGIN(PORT); CP; return TK_IPADDR;
- {IPV4ADDR} syntax_error("':PORT' missing from IP:PORT.\n");
- {NDELIM} expect_error("IP and port 'XXX.XXX.XXX.XXX:PORT'");
-}
-
-<META_IDX>{
- {META_IDX} unescape_midx(); yy_pop_state(); CP; return TK_INTEGER;
- {WS} update_lcnt();
- {O_IDX} {
- update_lcnt(); BEGIN(NUM);
- PRINTF("'meta-index=<idx>' deprecated, "
- "please use 'meta-disk /di/sk [idx]' instead.\n");
- }
-}
-
-<FLEX_META_DISK>{
- {INTERN} unescape(); yy_pop_state(); CP; return TK_STRING;
- {INTERN}{META_IDX} |
- {INTERN}{O_IDX} syntax_error("don't give an index for flexible meta-data.");
- {ESTRING} syntax_error("string terminator missing or string too long.\n");
- {STRING} unescape(); yy_pop_state(); CP; return TK_STRING;
- {STRING}{META_IDX} |
- {STRING}{O_IDX}{NUM} syntax_error("don't give an index for flexible meta-data.");
- {STRING}{LS}?{NDELIM} |
- {NDELIM} expect_error("either 'internal' or '/dev/ice/name [index]'");
-}
-
-<META_DISK>{
- {INTERN} unescape(); yy_pop_state(); CP; return TK_STRING;
- {INTERN}{META_IDX} |
- {INTERN}{O_IDX} syntax_error("don't give an index for internal meta-data.");
- {ESTRING} syntax_error("string terminator missing or string too long.\n");
- {STRING}/{META_IDX} |
- {STRING}/{O_IDX}{NUM} unescape(); BEGIN(META_IDX); CP; return TK_STRING;
- {STRING}{LS}?{NDELIM} expect_error("meta-disk: index missing; either 'internal' or '/dev/ice/name [index]'");
- {NDELIM} expect_error("either 'internal' or '/dev/ice/name [index]'");
-}
-
-<LS>{
- {LS} update_lcnt(); yy_pop_state();
- {NDELIM} expect_error("whitespace"); yy_pop_state();
-}
-
-<LBRACE>{
- {WS} update_lcnt();
- \{ update_lcnt(); yy_pop_state();
- [^{ \t\n]{1,40} expect_error("'{'");
-}
-
-<IGNORE_SECTION>{
- [^{}\n]{1,80} /* no ECHO */
- {WS} update_lcnt(); /* no ECHO */
- \{ yy_push_state(IGNORE_SECTION);
-}
-
-<GLOBAL>{
- minor-count do_assign(NUM); CP; return TK_MINOR_COUNT;
- disable-io-hints yy_push_state(SEMICOLON); return TK_DISABLE_IO_HINTS;
- dialog-refresh do_assign(NUM); CP; return TK_DIALOG_REFRESH;
- disable-ip-verification yy_push_state(SEMICOLON); return TK_DISABLE_IP_VERIFICATION;
- {NDELIM} expect_error("'minor-count|disable-io-hints|dialog-refresh'");
-}
-
-<RESOURCE>{
- on named_section(HOST); return TK_ON;
- startup section(STARTUP); return TK_STARTUP;
- syncer section(SYNCER); return TK_SYNCER;
- disk section(DISK); return TK_DISK_S;
- net section(NET); return TK_NET;
- handlers section(HANDLERS); return TK_HANDLERS;
-
- protocol do_assign(PROTO); CP; return TK_PROTOCOL;
- {NDELIM} {
- expect_error(
- "one of 'protocol"
- "startup|disk|net|syncer|on <HOSTNAME>'|"
- "handlers");
- }
-}
-
-<STARTUP>{
- wfc-timeout do_assign(NUM); CP; return TK_WFC_TIMEOUT;
- degr-wfc-timeout do_assign(NUM); CP; return TK_DEGR_WFC_TIMEOUT;
- {NDELIM} expect_error("one of 'wfc-timeout|degr-wfc-timeout'");
-}
-
-<DISK>{
- on-io-error do_assign(IO_ERROR); CP; return TK_ON_IO_ERROR;
- split-brain-fix yy_push_state(SEMICOLON); CP; return TK_SPLIT_BRAIN_FIX;
- size do_assign(NUM_U); CP; return TK_SIZE;
- {NDELIM} expect_error("'on-io-error|split-brain-fix|size'");
-}
-
-<IO_ERROR>{
- pass_on |
- panic |
- detach yy_pop_state(); CP; return TK_STRING;
- {NDELIM} expect_error("one of 'pass_on|panic|detach'");
-}
-
-<ON_DISCONNECT>{
- reconnect |
- stand_alone |
- freeze_io yy_pop_state(); CP; return TK_STRING;
- {NDELIM} expect_error("one of 'reconnect|stand_alone|freeze_io'");
-}
-
-<NET>{
- sndbuf-size do_assign(NUM_U); CP; return TK_SNDBUF_SIZE;
- timeout do_assign(NUM); CP; return TK_TIMEOUT;
- ping-int do_assign(NUM); CP; return TK_PING_INT;
- connect-int do_assign(NUM); CP; return TK_CONNECT_INT;
- max-buffers do_assign(NUM); CP; return TK_MAX_BUFFERS;
- max-epoch-size do_assign(NUM); CP; return TK_MAX_EPOCH_SIZE;
- ko-count do_assign(NUM); CP; return TK_KO_COUNT;
- on-disconnect do_assign(ON_DISCONNECT); CP; return TK_ON_DISCONNECT;
- allow-two-primaries yy_push_state(SEMICOLON); CP; return TK_ALLOW_TWO_PRIMARIES;
- cram-hmac-alg do_assign(STRING); CP; return TK_CRAM_HMAC_ALG;
- shared-secret do_assign(STRING); CP; return TK_SHARED_SECRET;
- {AFTER_SB_PRI} do_assign(STRING); CP; return TK_AFTER_SB_PRI;
-
- {NDELIM} expect_error("one of 'sndbuf-size|timeout|ping-int|connect-int|max-buffers|max-epoch-size|ko-count|on-disconnect|cram-hmac-alg|shared-secret|after-sb-[012]pri'");
-}
-
-<SYNCER>{
- rate do_assign(NUM_U); CP; return TK_RATE;
- after do_assign(STRING);CP; return TK_SYNC_AFTER;
- al-extents do_assign(NUM); CP; return TK_AL_EXTENTS;
- {NDELIM} expect_error("one of 'rate|after|al-extents'");
-}
-
-<HOST>{
- address do_assign(IP_AND_PORT); CP; return TK_ADDRESS;
- device do_assign(STRING); CP; return TK_DEVICE;
- {DISK} do_assign(STRING); CP; return TK_DISK;
- flex-meta-disk |
- flexible-meta-disk do_assign(FLEX_META_DISK);CP; return TK_FLEX_META_DISK;
- meta-disk do_assign(META_DISK); CP; return TK_META_DISK;
- {NDELIM} expect_error("one of 'address|device|disk|meta-disk'");
-}
-
-<HANDLERS>{
- pri-on-incon-degr do_assign(STRING); CP; return TK_PRI_ON_INCON_DEGR;
- pri-lost-after-sb do_assign(STRING); CP; return TK_PRI_LOST_AFTER_SB;
- outdate-peer do_assign(STRING); CP; return TK_OUTDATE_PEER;
- {NDELIM} {
- expect_error(
- "one of 'pri-on-incon-degr|"
- "pri-lost-after-sb|"
- "outdate-peer");
- }
-}
-
-<COMMON>{
- startup section(STARTUP); return TK_STARTUP;
- syncer section(SYNCER); return TK_SYNCER;
- disk section(DISK); return TK_DISK_S;
- net section(NET); return TK_NET;
- handlers section(HANDLERS); return TK_HANDLERS;
-
- {NDELIM} {
- expect_error(
- "one of 'startup|disk|net|syncer|handlers");
- }
-}
-
-<*>{
- \{ syntax_error("unexpected opening brace.");
- \n syntax_error("unexpected end of line, maybe missing ';' ? ");
- . expect_error("something else");
- <<EOF>> {
- if (YY_START != INITIAL)
- syntax_error("unexpected end of file. Maybe missing closing brace?.");
- /* else
- fprintf(stderr,"\n--- End of File. OK\n");
- */
- yyterminate();
- }
-}
-
%%
-static void syntax_error(char *err)
-{
- PRINTF("%s\n", err);
- exit(E_syntax);
-}
-static void expect_error(char *err)
-{
- PRINTF("%s expected, not '%s'.\n", err, yytext);
- exit(E_syntax);
-}
-static void update_lcnt(void)
+void long_string(char* text)
{
- char *p = yytext;
- while (*p) {
- if (*p++ == '\n')
- ++line;
- }
+ fprintf(stderr,"Too long token '%s' in line %d.\n",text,line);
+ exit(2);
}
-static void section(int sect)
-{
- static int s = 0;
- static int g = 0;
- if (sect != IGNORE_SECTION) {
- ++s;
- if (sect == GLOBAL) {
- if (s != 1) {
- if (g)
- syntax_error("only one global { ... } section allowed.\n");
- syntax_error("global { ... } section must be first.\n");
- }
- ++g;
- }
- }
- yy_push_state(sect);
- yy_push_state(LBRACE);
- fline = line;
-}
-
-static void named_section(int sect)
-{
- section(sect);
- yy_push_state(STRING);
- yy_push_state(LS);
-}
-
-static void do_assign(int what)
-{
- yy_push_state(SEMICOLON);
- yy_push_state(what);
- yy_push_state(ASSIGN);
-}
-
-/*
-static char* const escape(char* const str)
-{
- static char buffer[1024];
- char *ue = str, *e = buffer;
-
- if (!str || !str[0]) {
- return "\"\"";
- }
- *e++ = '"';
- while(*ue) {
- if (*ue == '"' || *ue == '\\') {
- *e++ = '\\';
- }
- if (e-buffer >= 1021) { PRINTF("string too long.\n"); exit(E_syntax); }
- *e++ = *ue++;
- }
- *e++ = '"';
- *e++ = '\0';
- return buffer;
-}
-*/
-
static void unescape(void)
{
/* backslash escapes from string */
@@ -438,19 +115,3 @@
}
*e = '\0';
}
-
-static void unescape_midx(void)
-{
- char *b;
- int n;
-
- b = strrchr(yytext, '[');
- if (b) {
- n = atoi(b + 1);
- n = snprintf(yytext, yyleng, "%d", n);
- if (0 < n && n < yyleng)
- return; /* ok */
- }
- fprintf(stderr, "Oops, thinko in %s:%d.\n", __FILE__, __LINE__);
- exit(E_thinko);
-}
More information about the drbd-cvs
mailing list