Code

liboconfig/scanner.l: Added support for wrapping lines.
authorSebastian Harl <sh@tokkee.org>
Sat, 12 Jul 2008 09:33:27 +0000 (11:33 +0200)
committerFlorian Forster <octo@huhu.verplant.org>
Tue, 15 Jul 2008 06:48:58 +0000 (08:48 +0200)
Lines may now be wrapped by using "\" as the last character before the
newline. This allows long lines to be split into multiple lines. This also
applies to quoted strings, which are, however, treated special in that
whitespace at the beginning of the following lines will be ignored. This
allows for nicely indenting the wrapped lines.

The following example:

  Foo a very very very long list of options \
      that does not fit on one line
  Bar "a very very very long string \
      which does not fit on one line"

... is equivalent to:

  Foo a very very very long list of options that does not fit on one line
  Bar "a very very very long string which does not fit on one line"

Signed-off-by: Sebastian Harl <sh@tokkee.org>
Signed-off-by: Florian Forster <octo@huhu.verplant.org>
src/liboconfig/scanner.l

index 4d9fc3de811bce2f7b79da20b566e65171d9baa0..0f146ca488dd23faece3cf7968e4a7ba5bca8a61 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * oconfig - src/scanner.l
  * Copyright (C) 2007  Florian octo Forster <octo at verplant.org>
+ * Copyright (C) 2008  Sebastian tokkee Harl <sh at tokkee.org>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
 #include "oconfig.h"
 #include "aux_types.h"
 #include "parser.h"
+
+/* multiline string buffer */
+static char *ml_buffer = NULL;
+static int   ml_pos    = 0;
+static int   ml_len    = 0;
+
+#define ml_free (ml_len - ml_pos)
+
+static void ml_append (char *);
+
+#ifdef yyterminate
+# undef yyterminate
+#endif
+#define yyterminate() \
+       do { free (ml_buffer); ml_buffer = NULL; ml_pos = 0; ml_len = 0; \
+               return YY_NULL; } while (0)
 %}
 %option yylineno
 %option noyywrap
+%x ML
 WHITE_SPACE [\ \t\b]
-QUOTED_STRING \"([^\\"]+|\\.)*\"
+NON_WHITE_SPACE [^\ \t\b]
+QUOTED_STRING ([^\\"]+|\\.)*
 UNQUOTED_STRING [0-9A-Za-z_]+
 HEX_NUMBER 0[xX][0-9a-fA-F]+
 OCT_NUMBER 0[0-7]+
@@ -43,6 +62,8 @@ IPV4_ADDR {IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}(:{PORT})?
 {WHITE_SPACE}          |
 {COMMENT}              {/* ignore */}
 
+\\\n                   {/* continue line */}
+
 \n                     {return (EOL);}
 "/"                    {return (SLASH);}
 "<"                    {return (OPENBRAC);}
@@ -54,6 +75,50 @@ IPV4_ADDR {IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}(:{PORT})?
 
 {NUMBER}               {yylval.number = strtod (yytext, NULL); return (NUMBER);}
 
-{QUOTED_STRING}                {yylval.string = yytext; return (QUOTED_STRING);}
+\"{QUOTED_STRING}\"    {yylval.string = yytext; return (QUOTED_STRING);}
 {UNQUOTED_STRING}      {yylval.string = yytext; return (UNQUOTED_STRING);}
+
+\"{QUOTED_STRING}\\\n {
+       ml_pos = 0;
+
+       /* remove "\\\n" */
+       yytext[strlen (yytext) - 2] = '\0';
+
+       ml_append (yytext);
+       BEGIN (ML);
+}
+<ML>^{WHITE_SPACE}+ {/* remove leading white-space */}
+<ML>{NON_WHITE_SPACE}{QUOTED_STRING}\\\n {
+       /* remove "\\\n" */
+       yytext[strlen (yytext) - 2] = '\0';
+
+       ml_append(yytext);
+}
+<ML>{NON_WHITE_SPACE}{QUOTED_STRING}\" {
+       ml_append(yytext);
+       yylval.string = ml_buffer;
+
+       BEGIN (INITIAL);
+       return (QUOTED_STRING);
+}
 %%
+static void ml_append (char *string)
+{
+       int len = strlen (string);
+       int s;
+
+       if (ml_free <= len) {
+               ml_len += len - ml_free + 1;
+               ml_buffer = (char *)realloc (ml_buffer, ml_len);
+               if (NULL == ml_buffer)
+                       YY_FATAL_ERROR ("out of dynamic memory in ml_append");
+       }
+
+       s = snprintf (ml_buffer + ml_pos, ml_free, "%s", string);
+       if ((0 > s) || (ml_free <= s))
+               YY_FATAL_ERROR ("failed to write to multiline buffer");
+
+       ml_pos += s;
+       return;
+} /* ml_append */
+