#ifndef __NLL_COMMAND_H_INCLUDED__
#define __NLL_COMMAND_H_INCLUDED__

typedef enum {
  COMMAND_UNKNOWN = 0,
  COMMAND_NONE,

  COMMAND_COMMENT,
  COMMAND_END,
  COMMAND_EXIT,
  COMMAND_ARGS,
  COMMAND_LET,
  COMMAND_PRINT,
  COMMAND_GOTO,
  COMMAND_GONEXT,
  COMMAND_GOSUB,
  COMMAND_RETURN,
  COMMAND_IF,
  COMMAND_ELSE,
  COMMAND_ENDIF,
  COMMAND_LOOP,
  COMMAND_LOOPEND,
  COMMAND_FOR,
  COMMAND_NEXT,
  COMMAND_DISCARD,
  COMMAND_DIM,
  COMMAND_MEMORY,
  COMMAND_PUSH,
  COMMAND_POP,
  COMMAND_DFROM,
  COMMAND_DREAD,
  COMMAND_DATA,
  COMMAND_RUN,
  COMMAND_STOP,
  COMMAND_SKIP,
  COMMAND_BREAK,
  COMMAND_STEP,
  COMMAND_CONTINUE,
  COMMAND_NEW,
  COMMAND_LIST,
  COMMAND_SAVE,
  COMMAND_LOAD,
  COMMAND_STDIN,
  COMMAND_STDOUT,
  COMMAND_EVAL,
  COMMAND_EVALF,
  COMMAND_EDIT,
  COMMAND_WAIT,
  COMMAND_DUMP,

  COMMAND_LAST
} command_type_t;

typedef enum {
  COMMAND_ARG_UNKNOWN = 0,
  COMMAND_ARG_LABEL,
  COMMAND_ARG_VARIABLE,
  COMMAND_ARG_FORMULA,
  COMMAND_ARG_WORD,
} command_arg_type_t;

typedef const struct command_ope {
  const char *name;
  const char *other_name;
  command_type_t type;
} *command_ope_t;

typedef struct command_arg {
  command_arg_type_t type;
  union {
    struct {
      label_t label;
    } label;
    struct {
      variable_t variable;
    } variable;
    struct {
      element_t element;
    } formula;
    struct {
      char word[COMMAND_ARG_WORD_MAXLEN + 1];
    } word;
  } arg;
} *command_arg_t;

struct command {
  struct command *next;
  command_ope_t ope;
  char *line;
  int errcode;
  struct {
    label_t label;
    variable_t variable;
    element_t args;
  } label;
  element_t prefix;
  struct command_arg args[COMMAND_ARG_MAXNUM];
};

int command_alloc_num(void);
int command_pool_num(void);
int command_check(void);
int command_search(char *p, char **endp, command_ope_t *opep);
int command_list(FILE *fp);
int command_get(command_type_t type, command_ope_t *opep);
int command_alloc(command_t *commandp);
int command_free(command_t command);
int command_set_label(command_t command, const char *name, spot_t spot);
int command_clear_label(command_t command);
int command_clear(command_t command);
int command_clean(command_t command);
int command_init(void);
int command_done(void);
int command_dump(FILE *fp, command_t command);

#endif
