Example #1
0
int usb_handle_packet(usb_t *self)
{
    uint32_t cmd;
    if (self->attached == 0)
    {
        /* only support metadata commands */
        metadata_hdr_t hdr;
        if (self->recv(&hdr, sizeof(hdr)) != sizeof(hdr))
            return 0;
        if (be16toh(hdr.version) != VERSION_CODE)
            return 0;
        const command_t *command = lookup_command((1<<31) | be16toh(hdr.command));
        if (command == NULL)
            return 0;
        return command->handler(self, &hdr);
    }
    else
    {
        /* only support data commands */
        data_hdr_t hdr;
        if (self->recv(&hdr, sizeof(hdr)) != sizeof(hdr))
            return 0;
        const command_t *command = lookup_command(be32toh(hdr.command));
        if (command == NULL)
            return 0;
        return command->handler(self, &hdr);
    }
}
Example #2
0
static redis_command *
get_redis_command (command_manager * mgr, ParseContext * ctx)
{
  char cmdbuf[REDIS_CMD_MAX_LEN + 1];
  sbuf_pos start_pos;
  ssize_t len;
  int ret;

  if (getArgumentCount (ctx) < 1)
    {
      return NULL;
    }

  ret = getArgumentPosition (ctx, 0, &start_pos, &len);
  assert (ret == OK);

  if (len > REDIS_CMD_MAX_LEN)
    {
      return NULL;
    }

  ret = sbuf_copy_buf (cmdbuf, start_pos, len);
  assert (ret == OK);
  cmdbuf[len] = '\0';

  return lookup_command (mgr->commands, cmdbuf);
}
Example #3
0
/* Check if line is "@end ..." for current command.  If so, advance LINE. */
int
is_end_current_command (ELEMENT *current, char **line,
                        enum command_id *end_cmd)
{
  char *linep;
  char *cmdname;

  linep = *line;

  linep += strspn (linep, whitespace_chars);
  if (!looking_at (linep, "@end"))
    return 0;

  linep += 4;
  if (!strchr (whitespace_chars, *linep))
    return 0;

  linep += strspn (linep, whitespace_chars);
  cmdname = read_command_name (&linep);
  *end_cmd = lookup_command (cmdname);
  free (cmdname);
  if (*end_cmd != current->cmd)
    return 0;

  *line = linep;
  return 1;
}
Example #4
0
File: psftp.c Project: rdebath/sgt
static int sftp_cmd_help(struct sftp_command *cmd)
{
    int i;
    if (cmd->nwords == 1) {
	/*
	 * Give short help on each command.
	 */
	int maxlen;
	maxlen = 0;
	for (i = 0; i < sizeof(sftp_lookup) / sizeof(*sftp_lookup); i++) {
	    int len;
	    if (!sftp_lookup[i].listed)
		continue;
	    len = strlen(sftp_lookup[i].name);
	    if (maxlen < len)
		maxlen = len;
	}
	for (i = 0; i < sizeof(sftp_lookup) / sizeof(*sftp_lookup); i++) {
	    const struct sftp_cmd_lookup *lookup;
	    if (!sftp_lookup[i].listed)
		continue;
	    lookup = &sftp_lookup[i];
	    printf("%-*s", maxlen+2, lookup->name);
	    if (lookup->longhelp == NULL)
		lookup = lookup_command(lookup->shorthelp);
	    printf("%s\n", lookup->shorthelp);
	}
    } else {
	/*
	 * Give long help on specific commands.
	 */
	for (i = 1; i < cmd->nwords; i++) {
	    const struct sftp_cmd_lookup *lookup;
	    lookup = lookup_command(cmd->words[i]);
	    if (!lookup) {
		printf("help: %s: command not found\n", cmd->words[i]);
	    } else {
		printf("%s", lookup->name);
		if (lookup->longhelp == NULL)
		    lookup = lookup_command(lookup->shorthelp);
		printf("%s", lookup->longhelp);
	    }
	}
    }
    return 1;
}
Example #5
0
gboolean
gb_vim_execute (GtkWidget      *active_widget,
                const gchar    *line,
                GError        **error)
{
  g_autofree gchar *name_slice = NULL;
  const GbVimCommand *command;
  const gchar *command_name = line;
  const gchar *options;
  g_autofree gchar *all_options = NULL;
  gboolean result;

  g_return_val_if_fail (GTK_IS_WIDGET (active_widget), FALSE);
  g_return_val_if_fail (line, FALSE);

  for (options = line; *options; options = g_utf8_next_char (options))
    {
      gunichar ch;

      ch = g_utf8_get_char (options);

      if (g_unichar_isspace (ch))
        break;
    }

  if (g_unichar_isspace (g_utf8_get_char (options)))
    {
      command_name = name_slice = g_strndup (line, options - line);
      options = g_utf8_next_char (options);
    }

  command = lookup_command (command_name);

  if (command == NULL)
    {
      if (looks_like_search_and_replace (line))
        return gb_vim_command_search (active_widget, line, "", error);

      g_set_error (error,
                   GB_VIM_ERROR,
                   GB_VIM_ERROR_NOT_FOUND,
                   _("Not a command: %s"),
                   command_name);

      return FALSE;
    }

  if (command->options_sup)
    all_options = g_strconcat (options, " ", command->options_sup, NULL);
  else
    all_options = g_strdup (options);

  result = command->func (active_widget, command_name, all_options, error);
  g_free (command->options_sup);

  return result;
}
Example #6
0
int 
Server_react(Server *server, void *socket, zmq_msg_t *msg)
{
	size_t cmdlen, msglen, datalen;
	char *eol, *message, *command;
	TCLIST *args;
	Command *cmd;
	void *data = NULL;
	
	message = zmq_msg_data(msg);
	msglen = zmq_msg_size(msg);
	zmq_msg_close(msg);
	
	eol = strchr(message, '\n');
	
	if (eol) {
		cmdlen = 1 + (eol - message);
		command = (char *)malloc((cmdlen + 1) * sizeof(char));
		memset(command, 0, cmdlen + 1);
		memcpy(command, message, cmdlen);
		args = tcstrsplit(tcstrsqzspc(command), " \t");
		cmd = lookup_command(tclistval2(args, 0));
		if (cmd == NULL) {
			ERROR("protocol error: %s", command);
			send(socket, "-INVALID_COMMAND");
			return 0;
		}
		if (msglen > cmdlen) {
			/* data size will always be last arg */
			datalen = tcatoi((char *)tclistval2(args, tclistnum(args) - 1));
			if ((datalen + cmdlen) != msglen) {
				ERROR("error receiving data or invalid data size");
				send(socket, "-INCORRECT_DATA_SIZE");
				return 0;
			}
			data = malloc(sizeof(char) * (datalen + 1));
			if (data == NULL) {
				ERROR("out of memory");
				send(socket, "-OUT_OF_MEMORY");
				return 0;
			}
			memset(data + datalen, 0, 1);
			memcpy(data, message + cmdlen, datalen);
			DEBUG("data received: %s", data);
		}
		cmd->fn(server, socket, args, data);
		return 1;
	}
	else {
		ERROR("request missing eol");
		send(socket, "-MISSING_EOL");
	}

	return 0;
}
Example #7
0
static EngineState
default_command(Command* cmd) {
    CmdData *cd = get_cmd_data(cmd);
    switch (lookup_command(cd->tag)) {
    case TRANSFORM_CMD:
        // for now let's assume we've been handed something
        // which should should be 'returned' from transform
        process_cmd(cd);
    }
    return Ok;
};
Example #8
0
File: psftp.c Project: rdebath/sgt
/* ----------------------------------------------------------------------
 * Command line reading and parsing.
 */
struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags)
{
    char *line;
    int linelen, linesize;
    struct sftp_command *cmd;
    char *p, *q, *r;
    int quoting;

    if ((mode == 0) || (modeflags & 1)) {
	printf("psftp> ");
    }
    fflush(stdout);

    cmd = smalloc(sizeof(struct sftp_command));
    cmd->words = NULL;
    cmd->nwords = 0;
    cmd->wordssize = 0;

    line = NULL;
    linesize = linelen = 0;
    while (1) {
	int len;
	char *ret;

	linesize += 512;
	line = srealloc(line, linesize);
	ret = fgets(line + linelen, linesize - linelen, fp);

	if (!ret || (linelen == 0 && line[0] == '\0')) {
	    cmd->obey = sftp_cmd_quit;
	    if ((mode == 0) || (modeflags & 1))
		printf("quit\n");
	    return cmd;		       /* eof */
	}
	len = linelen + strlen(line + linelen);
	linelen += len;
	if (line[linelen - 1] == '\n') {
	    linelen--;
	    line[linelen] = '\0';
	    break;
	}
    }
    if (modeflags & 1) {
	printf("%s\n", line);
    }

    p = line;
    while (*p && (*p == ' ' || *p == '\t'))
	p++;

    if (*p == '!') {
	/*
	 * Special case: the ! command. This is always parsed as
	 * exactly two words: one containing the !, and the second
	 * containing everything else on the line.
	 */
	cmd->nwords = cmd->wordssize = 2;
	cmd->words = srealloc(cmd->words, cmd->wordssize * sizeof(char *));
	cmd->words[0] = "!";
	cmd->words[1] = p+1;
    } else {

	/*
	 * Parse the command line into words. The syntax is:
	 *  - double quotes are removed, but cause spaces within to be
	 *    treated as non-separating.
	 *  - a double-doublequote pair is a literal double quote, inside
	 *    _or_ outside quotes. Like this:
	 *
	 *      firstword "second word" "this has ""quotes"" in" and""this""
	 *
	 * becomes
	 *
	 *      >firstword<
	 *      >second word<
	 *      >this has "quotes" in<
	 *      >and"this"<
	 */
	while (*p) {
	    /* skip whitespace */
	    while (*p && (*p == ' ' || *p == '\t'))
		p++;
	    /* mark start of word */
	    q = r = p;		       /* q sits at start, r writes word */
	    quoting = 0;
	    while (*p) {
		if (!quoting && (*p == ' ' || *p == '\t'))
		    break;		       /* reached end of word */
		else if (*p == '"' && p[1] == '"')
		    p += 2, *r++ = '"';    /* a literal quote */
		else if (*p == '"')
		    p++, quoting = !quoting;
		else
		    *r++ = *p++;
	    }
	    if (*p)
		p++;		       /* skip over the whitespace */
	    *r = '\0';
	    if (cmd->nwords >= cmd->wordssize) {
		cmd->wordssize = cmd->nwords + 16;
		cmd->words =
		    srealloc(cmd->words, cmd->wordssize * sizeof(char *));
	    }
	    cmd->words[cmd->nwords++] = q;
	}
    }

    /*
     * Now parse the first word and assign a function.
     */

    if (cmd->nwords == 0)
	cmd->obey = sftp_cmd_null;
    else {
	const struct sftp_cmd_lookup *lookup;
	lookup = lookup_command(cmd->words[0]);
	if (!lookup)
	    cmd->obey = sftp_cmd_unknown;
	else
	    cmd->obey = lookup->obey;
    }

    return cmd;
}
Example #9
0
gboolean
gb_vim_execute (GtkSourceView  *source_view,
                const gchar    *line,
                GError        **error)
{
  GtkTextBuffer *buffer;
  g_autofree gchar *name_slice = NULL;
  const GbVimCommand *command;
  const gchar *command_name = line;
  const gchar *options;
  g_autofree gchar *all_options = NULL;
  gboolean result;

  g_return_val_if_fail (GTK_SOURCE_IS_VIEW (source_view), FALSE);
  g_return_val_if_fail (line, FALSE);

  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view));

  if (!GTK_SOURCE_IS_BUFFER (buffer))
    {
      g_set_error (error,
                   GB_VIM_ERROR,
                   GB_VIM_ERROR_NOT_SOURCE_VIEW,
                   _("vim mode requires GtkSourceView"));
      return FALSE;
    }

  for (options = line; *options; options = g_utf8_next_char (options))
    {
      gunichar ch;

      ch = g_utf8_get_char (options);

      if (g_unichar_isspace (ch))
        break;
    }

  if (g_unichar_isspace (g_utf8_get_char (options)))
    {
      command_name = name_slice = g_strndup (line, options - line);
      options = g_utf8_next_char (options);
    }

  command = lookup_command (command_name);

  if (command == NULL)
    {
      if (looks_like_search_and_replace (line))
        return gb_vim_command_search (source_view, line, "", error);

      g_set_error (error,
                   GB_VIM_ERROR,
                   GB_VIM_ERROR_NOT_FOUND,
                   _("Not an editor command: %s"),
                   command_name);
      return FALSE;
    }

  if (command->options_sup)
    all_options = g_strconcat (options, " ", command->options_sup, NULL);
  else
    all_options = g_strdup (options);

  result = command->func (source_view, command_name, all_options, error);
  g_free (command->options_sup);

  return result;
}
Example #10
0
/* Parse input line and locate arguments (if any), keeping count of the number
 * of arguments and their locations.  Look up and call the corresponding cli
 * function if one is found and pass it the argv array.
 *
 * Returns: 0 on success: the input line contained at least a function name and
 *          that function exists and was called.
 *          1 on lookup failure: there is no corresponding function for the
 *          input line.
 *          2 on invalid syntax: the arguments list couldn't be parsed
 */
static int handle_input(char *inbuf)
{
	struct {
		unsigned inArg:1;
		unsigned inQuote:1;
		unsigned done:1;
	} stat;
	static char *argv[16];
	int argc = 0;
	int i = 0;
	const struct cli_command *command = NULL;
	const char *p;

	memset((void *)&argv, 0, sizeof(argv));
	memset(&stat, 0, sizeof(stat));

	do {
		switch (inbuf[i]) {
		case '\0':
			if (stat.inQuote)
				return 2;
			stat.done = 1;
			break;

		case '"':
			if (i > 0 && inbuf[i - 1] == '\\' && stat.inArg) {
				memcpy(&inbuf[i - 1], &inbuf[i],
				       strlen(&inbuf[i]) + 1);
				--i;
				break;
			}
			if (!stat.inQuote && stat.inArg)
				break;
			if (stat.inQuote && !stat.inArg)
				return 2;

			if (!stat.inQuote && !stat.inArg) {
				stat.inArg = 1;
				stat.inQuote = 1;
				argc++;
				argv[argc - 1] = &inbuf[i + 1];
			} else if (stat.inQuote && stat.inArg) {
				stat.inArg = 0;
				stat.inQuote = 0;
				inbuf[i] = '\0';
			}
			break;

		case ' ':
			if (i > 0 && inbuf[i - 1] == '\\' && stat.inArg) {
				memcpy(&inbuf[i - 1], &inbuf[i],
				       strlen(&inbuf[i]) + 1);
				--i;
				break;
			}
			if (!stat.inQuote && stat.inArg) {
				stat.inArg = 0;
				inbuf[i] = '\0';
			}
			break;

		default:
			if (!stat.inArg) {
				stat.inArg = 1;
				argc++;
				argv[argc - 1] = &inbuf[i];
			}
			break;
		}
	} while (!stat.done && ++i < INBUF_SIZE);

	if (stat.inQuote)
		return 2;

	if (argc < 1)
		return 0;

	wmprintf("\r\n");

	/*
	 * Some comamands can allow extensions like foo.a, foo.b and hence
	 * compare commands before first dot.
	 */
	i = ((p = strchr(argv[0], '.')) == NULL) ? 0 :
					(p - argv[0]);
	command = lookup_command(argv[0], i);
	if (command == NULL)
		return 1;

	command->function(argc, argv);

	return 0;
}
Example #11
0
/* Actions to be taken when a whole line of input has been processed */
ELEMENT *
end_line (ELEMENT *current)
{
  char *end_command = 0;
  enum command_id end_id;

  // 2621
  /* If empty line, start a new paragraph. */
  if (last_contents_child (current)
      && last_contents_child (current)->type == ET_empty_line)
    {
      debug ("END EMPTY LINE");
      if (current->type == ET_paragraph) /* 2625 */
        {
          ELEMENT *e;
          /* Remove empty_line element. */
          e = pop_element_from_contents (current);

          current = end_paragraph (current);

          /* Add empty_line to higher-level element. */
          add_to_element_contents (current, e);
        }
      //else if () // in menu_entry_description
      else if (!in_no_paragraph_contexts (current_context ()))
        {
          current = end_paragraph (current);
        }
    }

  // 2667
  /* The end of the line of a menu. */
  else if (current->type == ET_menu_entry_name
           || current->type == ET_menu_entry_node)
    {
      ELEMENT *end_comment;
      int empty_menu_entry_node = 0;

      if (current->type == ET_menu_entry_node)
        {
          ELEMENT *last = last_contents_child (current);

          if (current->contents.number > 0
              && (last->cmd == CM_c || last->cmd == CM_comment))
            {
              end_comment = pop_element_from_contents (current);
            }

          /* If contents empty or is all whitespace. */
          if (current->contents.number == 0
              || (current->contents.number == 1
                  && last->text.end > 0
                  && !last->text.text[strspn (last->text.text, 
                                              whitespace_chars)]))
            {
              empty_menu_entry_node = 1;
              if (end_comment)
                add_to_element_contents (current, end_comment);
            }
        }

      // 2689
      /* Abort the menu entry if there is no destination node given. */
      if (empty_menu_entry_node || current->type == ET_menu_entry_name)
        {
        }
      else // 2768
        {
          debug ("MENU ENTRY END LINE");
          current = current->parent;
          current = enter_menu_entry_node (current);
          if (end_comment)
            add_to_element_contents (current, end_comment);
        }
    }

  /* Is it a def line 2778 */
  else if (current->parent && current->parent->type == ET_def_line)
    {
      enum element_type def_command;

      if (pop_context () != ct_def)
        {
          abort ();
        }

#if 0
      /* current->parent is a ET_def_line, and current->parent->parent
         the def command. */
      def_command = current->parent->parent->cmd;
      // strip a trailing x
      parse_def (def_command, current->contents);
#endif

      current = current->parent->parent;
      current = begin_preformatted (current);

    }

  // 2872
  /* End of a line starting a block. */
  else if (current->type == ET_block_line_arg)
    {
      enum context c;
      // pop and check context_stack
      c = pop_context ();
      if (c != ct_line)
        {
          // bug
          abort ();
        }

      // 2881
      if (current->parent->cmd == CM_multitable)
        {
          /* Parse prototype row */
          // But not @columnfractions, I assume?
        }

      if (current->parent->cmd == CM_float) // 2943
        {
        }
      current = current->parent; //2965

      /* Don't consider empty argument of block @-command as argument,
         reparent them as contents. */
      if (current->args.list[0]->contents.number > 0
          && current->args.list[0]->contents.list[0]->type
             == ET_empty_line_after_command)
        {
          ELEMENT *e;
          e = current->args.list[0]->contents.list[0];
          insert_into_contents (current, e, 0);
          // TODO: Free lists?
          current->args.number = 0;
        }

      if (command_flags(current) & CF_blockitem) // 2981
        {
          if (current->cmd == CM_enumerate)
            {
            }
          else if (item_line_command (current->cmd)) // 3002
            {
              // check command_as_argument registered in 'extra', and
              // that it accepts arguments in braces
            }

          if (current->cmd == CM_itemize) // 3019
            {
              // check that command_as_argument is alone on the line
            }

          // check if command_as_argument isn't an accent command

          /* 3052 - if no command_as_argument given, default to @bullet for
             @itemize, and @asis for @table. */

          {
            ELEMENT *bi = new_element (ET_before_item);
            add_to_element_contents (current, bi);
            current = bi;
          }
        } /* CF_blockitem */

      // 3077
      if (command_flags(current) & CF_menu)
        {
          /* Start reading a menu.  Processing will continue in
             handle_menu in menus.c. */

          ELEMENT *menu_comment = new_element (ET_menu_comment);
          add_to_element_contents (current, menu_comment);
          current = menu_comment;
          debug ("MENU COMMENT OPEN");
          push_context (ct_preformatted);
        }
      current = begin_preformatted (current);
    }

  /* after an "@end verbatim" 3090 */
  else if (current->contents.number
           && last_contents_child(current)->type == ET_empty_line_after_command
    /* The Perl version gets the command with the 'command' key in 'extra'. */
           && contents_child_by_index(current, -2)
           && contents_child_by_index(current, -2)->cmd == CM_verbatim)
    {
      // I don't know what this means.  raw command is @html etc.?
      /*
     if we are after a @end verbatim, we must restart a preformatted if needed,
     since there is no @end command explicitly associated to raw commands
     it won't be done elsewhere.
      */

      current = begin_preformatted (current);
    }


  /* if it's a misc line arg 3100 */
  else if (current->type == ET_misc_line_arg)
    {
      int cmd_id, arg_type;
      enum context c;

      isolate_last_space (current, 0);

      current = current->parent;
      cmd_id = current->cmd;
      if (!cmd_id)
        abort ();

      arg_type = command_data(cmd_id).data;
       
      /* Check 'line' is top of the context stack */
      c = pop_context ();
      if (c != ct_line)
        {
          /* error */
          abort ();
        }

      // 3114
      debug ("MISC END %s", command_data(cmd_id).cmdname);

      if (arg_type > 0)
        {
          /* arg_type is number of args */
          // parse_line_command_args
          // save in 'misc_args' extra key
        }
      else if (arg_type == MISC_text) /* 3118 */
        {
          char *text;
         
          /* argument string has to be parsed as Texinfo. This calls convert in 
             Common/Text.pm on the first element of current->args. */
          /* however, this makes it impossible to decouple the parser and 
             output stages...  Any use of Texinfo::Convert is problematic. */

          if (current->args.number > 0)
            text = text_convert (current->args.list[0]);
          else
            text = "foo";

          if (!strcmp (text, ""))
            {
              /* 3123 warning - missing argument */
              abort ();
            }
          else
            {
              if (current->cmd == CM_end) /* 3128 */
                {
                  char *line = text;

                  /* Set end_command - used below. */
                  end_command = read_command_name (&line);

                  /* Check argument meets format of a Texinfo command
                     (alphanumberic character followed by alphanumeric 
                     characters or hyphens. */

                  /* Check if argument is a block Texinfo command. */
                  end_id = lookup_command (end_command);
                  if (end_id == -1 || !(command_data(end_id).flags & CF_block))
                    {
                      /* error - unknown @end */
                    }
                  else
                    {
                      debug ("END BLOCK %s", end_command);
                      /* 3140 Handle conditional block commands (e.g.  
                         @ifinfo) */

                      /* If we are in a non-ignored conditional, there is not
                         an element for the block in the tree; it is recorded 
                         in the conditional stack.  Pop it and check it is the 
                         same as the one given in the @end line. */

                      if (command_data(end_id).data == BLOCK_conditional)
                        {
                          if (conditional_number > 0)
                            {
                              enum command_id popped;
                              popped = pop_conditional_stack ();
                              if (popped != end_id)
                                abort ();
                            }
                        }
                    }
                }
              else if (current->cmd == CM_include) /* 3166 */
                {
                  debug ("Include %s", text);
                  input_push_file (text);
                }
              else if (current->cmd == CM_documentencoding)
                /* 3190 */
                {
                }
              else if (current->cmd == CM_documentlanguage)
                /* 3223 */
                {
                }
            }
        }
      else if (current->cmd == CM_node) /* 3235 */
        {
          int i;
          ELEMENT *arg;
          ELEMENT *first_arg;
          /* Construct 'nodes_manuals' array.  This would be an 'extra' 
             reference to an array that doesn't exist anywhere else. */

          /* This sets the 'node_content' and 'normalized' keys on each element 
             in 'nodes_manuals'. */
          //parse_node_manual ();
          
          /* In Perl a copy of the argument list is taken and the empty space 
             arguments are removed with trim_spaces_comment_from_content. */
          first_arg = current->args.list[0];
          arg = new_element (ET_NONE);
          arg->parent_type = route_not_in_tree;
          for (i = 0; i < first_arg->contents.number; i++)
            {
              if (first_arg->contents.list[i]->type
                    != ET_empty_spaces_after_command
                  && first_arg->contents.list[i]->type != ET_spaces_at_end)
                {
                  /* FIXME: Is this safe to serialize? */
                  /* For example, if there are extra keys in the elements under 
                     each argument?  They may not be set in a copy.
                     Hopefully there aren't many extra keys set on commands in 
                     node names. */
                  add_to_element_contents (arg, first_arg->contents.list[i]);
                }
            }
          add_extra_key_contents (current, "node_content", arg);

          /* Also set 'normalized' here.  The normalized labels are actually 
             the keys of "labels_information($parser)". */

          /*Check that the node name doesn't have a filename element for 
            referring to an external manual (_check_internal_node), and that it 
            is not empty (_check_empty_node).  */
          //check_node_label ();

          /* This sets 'node_content' and 'normalized' on the node, among
             other things (which were already set in parse_node_manual). */
          register_label (current, arg);

          current_node = current;
        }
      else if (current->cmd == CM_listoffloats) /* 3248 */
        {
        }
      else
        {
          /* All the other "line" commands" */
        }

      current = current->parent; /* 3285 */
      if (end_command) /* Set above */
        {
          /* more processing of @end */
          ELEMENT *end_elt;

          debug ("END COMMAND %s", end_command);

          /* Reparent the "@end" element to be a child of the block element. */
          end_elt = pop_element_from_contents (current);

          /* 3289 If not a conditional */
          if (command_data(end_id).data != BLOCK_conditional)
            {
              ELEMENT *closed_command;
              /* This closes tree elements (e.g. paragraphs) until we reach
                 end_command.  It can print an error if another block command
                 is found first. */
              current = close_commands (current, end_id,
                              &closed_command, 0); /* 3292 */
              if (!closed_command)
                abort (); // 3335

              close_command_cleanup (closed_command);
              // 3301 INLINE_INSERTCOPYING
              add_to_element_contents (closed_command, end_elt); // 3321
              // 3324 ET_menu_comment
              if (close_preformatted_command (end_id))
                current = begin_preformatted (current);
            }
        } /* 3340 */
      else
        {
          if (close_preformatted_command (cmd_id))
            current = begin_preformatted (current);
        }

      /* 3346 included file */

      /* 3350 */
      if (cmd_id == CM_setfilename && (current_node || current_section))
        {
          /* warning */
          abort ();
        }
      /* 3355 columnfractions */
      else if (cmd_id == CM_columnfractions)
        {
          ELEMENT *before_item;
          // check if in multitable

          // pop and check context stack

          current = current->parent;
          before_item = new_element (ET_before_item);
          add_to_element_contents (current, before_item);
          current = before_item;
        }
      else if (command_data(cmd_id).flags & CF_root) /* 3380 */
        {
          current = last_contents_child (current);
          
          /* 3383 Destroy all contents (why do we do this?) */
          while (last_contents_child (current))
            destroy_element (pop_element_from_contents (current));

          /* Set 'associated_section' extra key for a node. */
          if (cmd_id != CM_node && cmd_id != CM_part)
            {
              if (current_node)
                {
                  if (!lookup_extra_key (current_node, "associated_section"))
                    {
                      add_extra_key_element
                        (current_node, "associated_section", current);
                      add_extra_key_element
                        (current, "associated_node", current_node);
                    }
                }

              // "current parts" - 3394

              current_section = current;
            }
        } /* 3416 */
    }


  // something to do with an empty line /* 3419 */

  //if () /* 'line' or 'def' at top of "context stack" */
    {
      /* Recurse. */
    }
  return current;
} /* end_line 3487 */