[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 (¤t, 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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [6138] parsetexi @value,
Gavin D. Smith <=