texinfo-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[6138] parsetexi @value


From: Gavin D. Smith
Subject: [6138] parsetexi @value
Date: Sun, 22 Feb 2015 19:22:43 +0000

Revision: 6138
          http://svn.sv.gnu.org/viewvc/?view=rev&root=texinfo&revision=6138
Author:   gavin
Date:     2015-02-22 19:22:42 +0000 (Sun, 22 Feb 2015)
Log Message:
-----------
parsetexi @value

Modified Paths:
--------------
    trunk/parsetexi/ChangeLog
    trunk/parsetexi/end_line.c
    trunk/parsetexi/handle_commands.c
    trunk/parsetexi/input.c
    trunk/parsetexi/macro.c
    trunk/parsetexi/parser.c
    trunk/parsetexi/parser.h

Added Paths:
-----------
    trunk/parsetexi/test-files/macro.texi
    trunk/parsetexi/test-files/value.texi

Modified: trunk/parsetexi/ChangeLog
===================================================================
--- trunk/parsetexi/ChangeLog   2015-02-21 19:11:39 UTC (rev 6137)
+++ trunk/parsetexi/ChangeLog   2015-02-22 19:22:42 UTC (rev 6138)
@@ -1,3 +1,12 @@
+2015-02-22  Gavin Smith  <address@hidden>
+
+       * macro.c (store_value, fetch_value): New functions.
+       * end_line.c (parse_special_misc_command): First implementation.  
+       Handle @value.
+       * handle_commands.c (handle_misc_command) <MISC_special etc.>: 
+       More complete.
+       * parser.c (process_remaining_on_line): Handle @value.
+
 2015-02-18  Gavin Smith  <address@hidden>
 
        * api.c (build_index_data): New function.

Modified: trunk/parsetexi/end_line.c
===================================================================
--- trunk/parsetexi/end_line.c  2015-02-21 19:11:39 UTC (rev 6137)
+++ trunk/parsetexi/end_line.c  2015-02-22 19:22:42 UTC (rev 6138)
@@ -58,6 +58,87 @@
   return 1;
 }
 
+/* Process argument to special line command. */
+ELEMENT *
+parse_special_misc_command (char *line, enum command_id cmd
+                           /* , int *has_comment */)
+{
+#define ADD_ARG(string, len) do { \
+  ELEMENT *E = new_element (ET_NONE); \
+  text_append_n (&E->text, string, len); \
+  add_to_element_contents (args, E); \
+} while (0)
+
+  ELEMENT *args = new_element (ET_NONE);
+  char *p, *q;
+
+  switch (cmd)
+    {
+    case CM_set:
+      {
+        
+        /* Check if the line matches the Perl regular expression
+
+        /^\s+([\w\-][^\s{\\}~`\^+"<>|@]*)
+        (\@(c|comment)((\@|\s+).*)?|[^\S\f]+(.*?))?[^\S\f]*$/
+
+          */
+
+      p = line;
+      p += strspn (p, whitespace_chars);
+      if (!*p)
+        goto set_no_name;
+      if (!isalnum (*p) && *p != '-' && *p != '_')
+        goto set_invalid;
+      q = strpbrk (p,
+                   " \t\f\r\n"       /* whitespace */
+                   "{\\}~^+\"<>|@"); /* other bytes that aren't allowed */
+
+      ADD_ARG(p, q - p); /* name */
+
+      /* TODO: Skip optional comment. */
+      /* This is strange - how can you have a comment in the middle
+         of a line?  And what does "@comment@" mean? */
+
+      p = q + strspn (q, whitespace_chars);
+      /* Actually, whitespace characters except form feed. */
+
+      /* Find trailing whitespace on line. */
+      q = strchr (p, '\0');
+      while (strchr (whitespace_chars, *q))
+        q--;
+
+      if (q > p)
+        ADD_ARG(p, q - p + 1); /* value */
+      else
+        ADD_ARG("", 0);
+
+      store_value (args->contents.list[0]->text.text,
+                   args->contents.list[1]->text.text);
+      /* TODO - unless ignore_global_commands is on */
+
+      break;
+set_no_name:
+      line_error ("@set requires a name");
+      break;
+set_invalid:
+      line_error ("bad name for @set");
+      break;
+      }
+    case CM_clear:
+      break;
+    case CM_unmacro:
+      break;
+    case CM_clickstyle:
+      break;
+    default:
+      abort ();
+    }
+
+  return args;
+#undef ADD_ARG
+}
+
 /* Parse the arguments to a line command.  Return an element whose contents
    is an array of the arguments.  For some commands, there is further 
    processing of the arguments (for example, for an @alias, remember the

Modified: trunk/parsetexi/handle_commands.c
===================================================================
--- trunk/parsetexi/handle_commands.c   2015-02-21 19:11:39 UTC (rev 6137)
+++ trunk/parsetexi/handle_commands.c   2015-02-22 19:22:42 UTC (rev 6138)
@@ -1,3 +1,4 @@
+/* handle_commands.c -- what to do when a command name is first read */
 /* Copyright 2010, 2011, 2012, 2013, 2014, 2015
    Free Software Foundation, Inc.
 
@@ -19,6 +20,7 @@
 
 #include "parser.h"
 #include "input.h"
+#include "text.h"
 
 /* Return a containing @itemize or @enumerate if inside it. */
 // 1847
@@ -80,22 +82,71 @@
         current = begin_preformatted (current);
       */
     }
-  // all the cases using the raw line
+  /* All the cases using the raw line.
+     I don't understand what the difference is between these. */
   else if (arg_spec == MISC_skipline /* 4347 */
            || arg_spec == MISC_lineraw
            || arg_spec == MISC_special)
     {
+      ELEMENT *args = 0;
+      /* 4350 TODO: If the current input is the result of a macro expansion,
+         it may not be a complete line.  Check for this and acquire the rest
+         of the line if necessary. */
+
       misc = new_element (ET_NONE);
       misc->cmd = cmd_id;
 
-      /* If @set or @clear */
-      /* else */ /* 4402 */
+      if (arg_spec == MISC_skipline || arg_spec == MISC_lineraw)
         {
+          ELEMENT *arg;
+          args = new_element (ET_NONE);
+          arg = new_element (ET_NONE);
+          add_to_element_contents (args, arg);
+          text_append (&arg->text, line);
+        }
+      else /* arg_spec == MISC_special */
+        {
+          args = parse_special_misc_command (line, cmd_id); //4362
+          add_extra_string (misc, "arg_line", line);
+        }
+
+      if ((cmd_id == CM_set || cmd_id == CM_clear)
+          && 0 )
+        {
+          /* TODO: Handle @set txicodequoteundirected as an
+             obsolete alternative to @codequoteundirected. */
+        }
+      else // 4402
+        {
+          int i;
           add_to_element_contents (current, misc);
+
+          for (i = 0; i < args->contents.number; i++)
+            {
+              ELEMENT *misc_arg = new_element (ET_misc_arg);
+              text_append_n (&misc_arg->text, 
+                             args->contents.list[i]->text.text,
+                             args->contents.list[i]->text.end);
+              add_to_element_contents (misc, misc_arg);
+            }
+          /* TODO: Could we have just set misc->args directly as args? */
+
+          if (args->contents.number > 0 && arg_spec != MISC_skipline)
+            add_extra_key_misc_args (misc, "misc_args", args);
         }
-      current = end_line (current);
 
-      // 4429 @bye
+      /* if (!ignore_global_commands)
+        {
+        } */
+
+      // mark_and_warn_invalid ();
+      // register_global_command ();
+
+      if (arg_spec != MISC_special /* || !has_comment */ )
+        current = end_line (current);
+
+      // 4429 TODO @bye
+
       if (close_preformatted_command(cmd_id))
         current = begin_preformatted (current);
 

Modified: trunk/parsetexi/input.c
===================================================================
--- trunk/parsetexi/input.c     2015-02-21 19:11:39 UTC (rev 6137)
+++ trunk/parsetexi/input.c     2015-02-22 19:22:42 UTC (rev 6138)
@@ -28,13 +28,14 @@
 enum input_type { IN_file, IN_text };
 
 typedef struct {
-    enum input_type type;
+    enum input_type type; /* IN_file or IN_text */
 
     FILE *file;
     char *filename;
 
-    char *text;
-    char *ptext; /* How far we are through 'text'. */
+    char *text;  /* Input text to be parsed as Texinfo. */
+    char *ptext; /* How far we are through 'text'.  Used to split 'text'
+                    into lines. */
     int line_number;
 } INPUT;
 
@@ -45,13 +46,14 @@
 /* Current filename and line number. */
 LINE_NR line_nr;
 
-/* Collect text until a newline is found. */
-// I don't really understand the difference between this and next_text.
-// When would next_text not return a string ending in a newline?
-// Unlike new_text, new_line's return value doesn't end in '\n'.
-// Return value should not be freed by caller, and becomes invalid after
-// a subsequent call.
 // 1961
+/* Collect text from the input sources until a newline is found.  This is used 
+   instead of next_text when we need to be sure we get an entire line of 
+   Texinfo input (for example as a line argument to a command), which might 
not 
+   be the case if the input is the result of a macro expansion.
+
+   Return value should not be freed by caller, and becomes invalid after
+   a subsequent call. */
 char *
 new_line (void)
 {
@@ -107,7 +109,10 @@
             }
           p = strchrnul (i->ptext, '\n');
           new = strndup (i->ptext, p - i->ptext + 1);
-          i->ptext = p + 1;
+          if (*p)
+            i->ptext = p + 1;
+          else
+            i->ptext = p; /* The next time, we will pop the input source. */
           return new;
           // what if it doesn't end in a newline ?
 
@@ -171,6 +176,8 @@
     }
 }
 
+/* Store TEXT as a source for Texinfo content.  TEXT will be later free'd
+   and must be allocated on the heap. */
 void
 input_push_text (char *text)
 {

Modified: trunk/parsetexi/macro.c
===================================================================
--- trunk/parsetexi/macro.c     2015-02-21 19:11:39 UTC (rev 6137)
+++ trunk/parsetexi/macro.c     2015-02-22 19:22:42 UTC (rev 6138)
@@ -194,6 +194,8 @@
   size_t arg_number = 0;
   size_t arg_space = 0;
 
+  arg_list = malloc (sizeof (char *));
+
   text_init (&arg);
 
   while (braces_level > 0)
@@ -253,7 +255,8 @@
               if (arg_number == arg_space)
                 {
                   arg_list = realloc (arg_list,
-                                      (arg_space += 5) * sizeof (char *));
+                                      (1+(arg_space += 5)) * sizeof (char *));
+                  /* Include space for terminating null element. */
                   if (!arg_list)
                     abort ();
                 }
@@ -278,6 +281,7 @@
   line = pline;
 
   *line_inout = line;
+  arg_list[arg_number] = 0;
   return arg_list;
 }
 
@@ -304,11 +308,11 @@
 
       /* There should be at least a newline. */
       if (body[i]->text.end == 0)
-        abort ();
+        continue;
 
       ptext = body[i]->text.text;
       if (i == macro->contents.number - 1)
-        ; // strip newline
+        ; // TODO: strip newline
       
       while (1)
         {
@@ -406,12 +410,50 @@
     free (arguments);
   }
 
-
   // 3958 Pop macro stack
 
-  // 3961 Split expansion into lines.
+  // 3961
+  /* Put expansion in front of the current line. */
+  input_push_text (strdup (line));
+  line = strchr (line, '\0');
   input_push_text (expanded.text);
 
   *line_inout = line;
   return current;
 }
+
+
+/* @set and @value */
+
+typedef struct {
+    char *name;
+    char *value;
+} VALUE;
+
+static VALUE *value_list;
+static size_t value_number;
+static size_t value_space;
+
+void
+store_value (char *name, char *value)
+{
+  if (value_number == value_space)
+    {
+      value_list = realloc (value_list, (value_space += 5) * sizeof (VALUE));
+    }
+  value_list[value_number].name = name;
+  value_list[value_number++].value = value;
+}
+/* TODO: What if it is already defined? */
+
+char *
+fetch_value (char *name, int len)
+{
+  int i;
+  for (i = 0; i < value_number; i++)
+    {
+      if (!memcmp (value_list[i].name, name, len) && !value_list[i].name[len])
+        return value_list[i].value;
+    }
+  return 0;
+}

Modified: trunk/parsetexi/parser.c
===================================================================
--- trunk/parsetexi/parser.c    2015-02-21 19:11:39 UTC (rev 6137)
+++ trunk/parsetexi/parser.c    2015-02-22 19:22:42 UTC (rev 6138)
@@ -829,14 +829,60 @@
       line = line_after_command;
       debug ("COMMAND %s", command);
 
-#if 0
-      /* Check if this is an alias command */
+      /* TODO: Check if this is an alias command */
 
-      /* @value */
+      /* 4172 @value */
+      if (cmd_id == CM_value)
+        {
+          char *arg_start;
+          if (*line != '{')
+            goto value_invalid;
 
-      /* warn on deprecated command */
-#endif
+          line++;
+          if (!isalnum (*line) && *line != '-' && *line != '_')
+            goto value_invalid;
+          arg_start = line;
 
+          line++;
+          line = strpbrk (line,
+                   " \t\f\r\n"       /* whitespace */
+                   "{\\}~^+\"<>|@"); /* other bytes that aren't allowed */
+          if (*line != '}')
+            goto value_invalid;
+
+          if (1) /* @value syntax is valid */
+            {
+              char *value;
+value_valid:
+              value = fetch_value (arg_start, line - arg_start);
+              if (!value)
+                {
+                  line_errorf ("undefined flag: %.*s", line - arg_start, 
+                               arg_start);
+                }
+              else
+                {
+                  /* TODO: The Perl code has cases for the value being
+                     an array or hash - check when this can happen. */
+
+                  line++; /* past '}' */
+                  input_push_text (strdup (line));
+                  line = strchr (line, '\0');
+                  input_push_text (strdup (value));
+                  retval = 0;
+                  goto funexit;
+                  //return;
+                }
+            }
+          else
+            {
+value_invalid:
+              line_error ("bad syntax for @value");
+            }
+        }
+
+      /* TODO: warn on deprecated command */
+
       /* warn on not appearing at line beginning 4226 */
       if (!abort_empty_line (&current, NULL))
         //  && begin_line_commands (command))
@@ -889,7 +935,8 @@
         }
       /* line 4289 */
       /* the 'misc-commands' - no braces and not block commands (includes
-         @end) */
+         @end).  Mostly taking a line argument, except for a small number
+         of exceptions, like @tab. */
       else if (command_data(cmd_id).flags & CF_misc)
         {
           current = handle_misc_command (current, &line, cmd_id);

Modified: trunk/parsetexi/parser.h
===================================================================
--- trunk/parsetexi/parser.h    2015-02-21 19:11:39 UTC (rev 6137)
+++ trunk/parsetexi/parser.h    2015-02-22 19:22:42 UTC (rev 6138)
@@ -18,6 +18,7 @@
 /* In end_line.c */
 NODE_SPEC_EXTRA *parse_node_manual (ELEMENT *node);
 ELEMENT *end_line (ELEMENT *current);
+ELEMENT *parse_special_misc_command (char *line, enum command_id cmd);
 
 /* In debug.c */
 void debug (char *s, ...);
@@ -56,6 +57,8 @@
                                    ELEMENT *parent);
 ELEMENT *handle_macro (ELEMENT *current, char **line_inout,
                        enum command_id cmd_id);
+void store_value (char *name, char *value);
+char *fetch_value (char *name, int len);
 
 /* In multitable.c */
 ELEMENT *item_line_parent (ELEMENT *current);

Added: trunk/parsetexi/test-files/macro.texi
===================================================================
--- trunk/parsetexi/test-files/macro.texi                               (rev 0)
+++ trunk/parsetexi/test-files/macro.texi       2015-02-22 19:22:42 UTC (rev 
6138)
@@ -0,0 +1,17 @@
address@hidden Top
+
address@hidden foo {p, q}
+Together: \p\ & \q\.
address@hidden macro
address@hidden, b}
+
address@hidden, d}YYYYYYYYYYYYY
+
address@hidden bar
+Lah-di-dah.
+Dum-di-dum.
+
+
address@hidden macro
+
+flobble flible @bar{} worstst wortlsee

Added: trunk/parsetexi/test-files/value.texi
===================================================================
--- trunk/parsetexi/test-files/value.texi                               (rev 0)
+++ trunk/parsetexi/test-files/value.texi       2015-02-22 19:22:42 UTC (rev 
6138)
@@ -0,0 +1,5 @@
address@hidden foo This is a string.
+
+blah ger erg er rtggtrg @value{foo} ferfsergr @value{foo}
+
address@hidden




reply via email to

[Prev in Thread] Current Thread [Next in Thread]