aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxl/libxlu_disk_l.l
diff options
context:
space:
mode:
authorIan Jackson <ian.jackson@eu.citrix.com>2011-06-28 12:19:11 +0100
committerIan Jackson <ian.jackson@eu.citrix.com>2011-06-28 12:19:11 +0100
commit5c206536adf068f418d19195841ee18eb4537b6e (patch)
tree4c36fe860600999e481333826196143cd9e0cdd8 /tools/libxl/libxlu_disk_l.l
parenteaed6ac8500f4a501ed02cebb4f99b3c8cf94adb (diff)
downloadxen-5c206536adf068f418d19195841ee18eb4537b6e.tar.gz
xen-5c206536adf068f418d19195841ee18eb4537b6e.tar.bz2
xen-5c206536adf068f418d19195841ee18eb4537b6e.zip
libxl: disks: new xlu_disk_parse function
Introduce new flex/regexp-based parser for disk configuration strings. Callers will be updated in following patches. The existing xm command line syntax for block-attach expects multiple arguments containing different parameters for different parts of the disk specification, so we supply a parser function which can take multiple strings and scan them in sequence. Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com> Committed-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Diffstat (limited to 'tools/libxl/libxlu_disk_l.l')
-rw-r--r--tools/libxl/libxlu_disk_l.l217
1 files changed, 217 insertions, 0 deletions
diff --git a/tools/libxl/libxlu_disk_l.l b/tools/libxl/libxlu_disk_l.l
new file mode 100644
index 0000000000..48a1314e0f
--- /dev/null
+++ b/tools/libxl/libxlu_disk_l.l
@@ -0,0 +1,217 @@
+/* -*- fundamental -*- */
+/*
+ * libxlu_disk_l.l - parser for disk specification strings
+ *
+ * Copyright (C) 2011 Citrix Ltd.
+ * Author Ian Jackson <ian.jackson@eu.citrix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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 Lesser General Public License for more details.
+ */
+
+/*
+ * Parsing the old xm/xend/xl-4.1 disk specs is a tricky problem,
+ * because the target string might in theory contain "," which is the
+ * delimiter we use for stripping off things on the RHS, and ":",
+ * which is the delimiter we use for stripping off things on the LHS.
+ *
+ * In this parser we do not support such target strings in the old
+ * syntax; if the target string has to contain "," or ":" the new
+ * syntax's "target=" should be used.
+ */
+
+%{
+#include "libxlu_disk_i.h"
+
+#define YY_NO_INPUT
+
+/* Some versions of flex have a bug (Fedora bugzilla 612465) which causes
+ * it to fail to declare these functions, which it defines. So declare
+ * them ourselves. Hopefully we won't have to simultaneously support
+ * a flex version which declares these differently somehow. */
+int xlu__disk_yyget_column(yyscan_t yyscanner);
+void xlu__disk_yyset_column(int column_no, yyscan_t yyscanner);
+
+
+/*----- useful macros and functions used in actions -----
+ * we use macros in the actual rules to keep the actions short
+ * and particularly to avoid repeating boilerplate values such as
+ * DPC->disk, yytext, etc. */
+
+#define DPC ((DiskParseContext*)yyextra)
+
+/* Sets an enum, checking it hasn't already been set to a different value */
+#define DSET(dpc,member,enumname,str,valname) do{ \
+ if (dpc->disk->member != LIBXL_DISK_##enumname##_UNKNOWN && \
+ dpc->disk->member != LIBXL_DISK_##enumname##_##valname) { \
+ xlu__disk_err(dpc, str, TOSTRING(member) " respecified"); \
+ } else { \
+ dpc->disk->member = LIBXL_DISK_##enumname##_##valname; \
+ } \
+ }while(0)
+
+/* For actions whose patterns contain '=', finds the start of the value */
+#define FROMEQUALS (strchr(yytext,'=')+1)
+
+/* Chops the delimiter off, modifying yytext and yyleng. */
+#define STRIP(delim) do{ \
+ if (yyleng>0 && yytext[yyleng-1]==(delim)) \
+ yytext[--yyleng] = 0; \
+ }while(0)
+
+/* Sets a string value, checking it hasn't been set already. */
+#define SAVESTRING(what,loc,val) do{ \
+ savestring(DPC, what " respecified", &DPC->disk->loc, (val)); \
+ }while(0)
+static void savestring(DiskParseContext *dpc, const char *what_respecified,
+ char **update, const char *value) {
+ if (*update) {
+ if (**update) { xlu__disk_err(dpc,value,what_respecified); return; }
+ free(*update); /* do not complain about overwriting empty strings */
+ }
+ *update = strdup(value);
+}
+
+/* Sets ->readwrite from the string. This ought to be an enum, perhaps. */
+static void setaccess(DiskParseContext *dpc, const char *str) {
+ if (!strcmp(str, "r") || !strcmp(str, "ro")) {
+ dpc->disk->readwrite = 0;
+ } else if (!strcmp(str, "rw") || !strcmp(str, "w") || !strcmp(str,"")) {
+ dpc->disk->readwrite = 1;
+ } else {
+ xlu__disk_err(dpc,str,"unknown value for access");
+ }
+}
+
+/* Sets ->format from the string. IDL should provide something for this. */
+static void setformat(DiskParseContext *dpc, const char *str) {
+ if (!strcmp(str,"") ||
+ !strcmp(str,"raw")) DSET(dpc,format,FORMAT,str,RAW);
+ else if (!strcmp(str,"qcow")) DSET(dpc,format,FORMAT,str,QCOW);
+ else if (!strcmp(str,"qcow2")) DSET(dpc,format,FORMAT,str,QCOW2);
+ else if (!strcmp(str,"vhd")) DSET(dpc,format,FORMAT,str,VHD);
+ else xlu__disk_err(dpc,str,"unknown value for format");
+}
+
+#define DEPRECATE(usewhatinstead) /* not currently reported */
+
+%}
+
+%option warn
+%option nodefault
+%option batch
+%option 8bit
+%option noyywrap
+%option reentrant
+%option prefix="xlu__disk_yy"
+%option nounput
+
+%x LEXERR
+
+%%
+
+ /*----- the scanner rules which do the parsing -----*/
+
+[ \t\n]+/([^ \t\n].*)? { /* ignore whitespace before parameters */ }
+
+ /* ordinary parameters setting enums or strings */
+
+format=[^,]*,? { STRIP(','); setformat(DPC, FROMEQUALS); }
+
+cdrom,? { DPC->disk->is_cdrom = 1; }
+devtype=cdrom,? { DPC->disk->is_cdrom = 1; }
+devtype=disk,? { DPC->disk->is_cdrom = 0; }
+devtype=[^,]*,? { xlu__disk_err(DPC,yytext,"unknown value for type"); }
+
+access=[^,]*,? { STRIP(','); setaccess(DPC, FROMEQUALS); }
+
+vdev=[^,]*,? { STRIP(','); SAVESTRING("vdev", vdev, FROMEQUALS); }
+script=[^,]*,? { STRIP(','); SAVESTRING("script", script, FROMEQUALS); }
+
+ /* the target magic parameter, eats the rest of the string */
+
+target=.* { STRIP(','); SAVESTRING("target", pdev_path, FROMEQUALS); }
+
+ /* unknown parameters */
+
+[a-z][-a-z0-9]*=[^,],? { xlu__disk_err(DPC,yytext,"unknown parameter"); }
+
+ /* deprecated prefixes */
+
+ /* the "/.*" in these patterns ensures that they count as if they
+ * matched the whole string, so these patterns take precedence */
+
+(raw|qcow2?|vhd):/.* {
+ STRIP(':');
+ DPC->had_depr_prefix=1; DEPRECATE("use `[format=]...,'");
+ setformat(DPC, yytext);
+ }
+
+iscsi:|e?nbd:drbd:/.* {
+ STRIP(':');
+ DPC->had_depr_prefix=1; DEPRECATE("use `script=...'");
+ SAVESTRING("script", script, yytext);
+ }
+
+tapdisk:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); }
+tap2?:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); }
+aio:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); }
+ioemu:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); }
+file:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); }
+phy:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); }
+
+[a-z][a-z0-9]*:/([^a-z0-9].*)? {
+ xlu__disk_err(DPC,yytext,"unknown deprecated disk prefix");
+ return 0;
+ }
+
+ /* positional parameters */
+
+[^=,]*,|[^=,]+,? {
+ char *colon;
+ STRIP(',');
+
+ if (DPC->err) {
+ /* previous errors may just lead to subsequent ones */
+ } else if (!DPC->disk->pdev_path) {
+ SAVESTRING("target", pdev_path, yytext);
+ } else if (!DPC->had_depr_prefix &&
+ DPC->disk->format == LIBXL_DISK_FORMAT_UNKNOWN) {
+ setformat(DPC,yytext);
+ } else if (!DPC->disk->vdev) {
+ colon = strrchr(yytext, ':');
+ if (colon) {
+ DEPRECATE("use `devtype=...'");
+ *colon++ = 0;
+ if (!strcmp(colon,"cdrom")) {
+ DPC->disk->is_cdrom = 1;
+ } else if (!strcmp(colon,"disk")) {
+ DPC->disk->is_cdrom = 0;
+ } else {
+ xlu__disk_err(DPC,colon,"unknown deprecated type");
+ }
+ }
+ SAVESTRING("vdev", vdev, yytext);
+ } else if (!DPC->access_set) {
+ DPC->access_set = 1;
+ setaccess(DPC,yytext);
+ } else {
+ xlu__disk_err(DPC,yytext,"too many positional parameters");
+ return 0; /* don't print any more errors */
+ }
+}
+
+. {
+ BEGIN(LEXERR);
+ yymore();
+}
+<LEXERR>.* {
+ xlu__disk_err(DPC,yytext,"bad disk syntax"); return 0;
+}