View of xos/usr/xsh/print_cmd.c


XOS | Parent Directory | View | Download

/* Copyright (C) 2008  Emmanuel Varoquaux
 
   This file is part of XOS.
 
   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 Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
#include "print_cmd.h"
 
#include "command.h"
#include "safe_malloc.h"
 
#include <string.h>
#include <stdio.h>
 
/* string_buffer */
 
void string_buffer_init(struct string_buffer_struct *string_buffer)
{
  string_buffer->buf = NULL;
  string_buffer->size = 0;
}
 
char *string_buffer_release(struct string_buffer_struct *string_buffer)
{
  char *string;
 
  string = string_buffer->buf;
  string_buffer->buf = NULL;
  string_buffer->size = 0;
  return string;
}
 
static void string_buffer_append(struct string_buffer_struct *string_buffer, const char *str)
{
  size_t str_len;
  size_t size;
 
  str_len = strlen(str);
  if (!string_buffer->buf) {
    size = 1;
    while (size <= str_len)
      size *= 2;
    string_buffer->buf = safe_malloc(size);
    string_buffer->size = size;
    strcpy(string_buffer->buf, str);
    string_buffer->pos = str_len;
  }
  else {
    if (string_buffer->pos + str_len >= string_buffer->size) {
      size = string_buffer->size;
      while (size <= string_buffer->pos + str_len)
        size *= 2;
      string_buffer->buf = safe_realloc(string_buffer->buf, size);
      string_buffer->size = size;
    }
    strcpy(string_buffer->buf + string_buffer->pos, str);
    string_buffer->pos += str_len;
  }
}
 
/* print_cmd */
 
static void do_print_command(const struct command_struct *command, struct string_buffer_struct *string_buffer);
static void do_print_pipeline(const struct pipeline_struct *pipeline, struct string_buffer_struct *string_buffer);
static void do_print_and_or_list(const struct and_or_list_struct *and_or_list, struct string_buffer_struct *string_buffer);
static void do_print_list(const struct list_struct *list, struct string_buffer_struct *string_buffer);
 
static void print_argument(const struct argument_struct *argument, struct string_buffer_struct *string_buffer)
{
  string_buffer_append(string_buffer, argument->word);
}
 
static void append_number(int num, struct string_buffer_struct *string_buffer)
{
  char buf[sizeof (int) * 8 + 1];
 
  sprintf(buf, "%d", num);
  string_buffer_append(string_buffer, buf);
}
 
static void print_redirect(const struct redirect_struct *redirect, struct string_buffer_struct *string_buffer)
{
  switch (redirect->type) {
  case RT_REDIRECT_INPUT:
  case RT_DUPLICATE_INPUT:
  case RT_READ_WRITE:
    if (redirect->fd != 0)
      append_number(redirect->fd, string_buffer);
    break;
  case RT_REDIRECT_OUTPUT:
  case RT_REDIRECT_OUTPUT_FORCE:
  case RT_REDIRECT_OUTPUT_APPEND:
  case RT_DUPLICATE_OUTPUT:
    if (redirect->fd != 1)
      append_number(redirect->fd, string_buffer);
    break;
  }
  switch (redirect->type) {
  case RT_REDIRECT_INPUT:
    string_buffer_append(string_buffer, "< ");
    break;
  case RT_REDIRECT_OUTPUT:
    string_buffer_append(string_buffer, "> ");
    break;
  case RT_REDIRECT_OUTPUT_FORCE:
    string_buffer_append(string_buffer, ">| ");
    break;
  case RT_REDIRECT_OUTPUT_APPEND:
    string_buffer_append(string_buffer, ">> ");
    break;
  case RT_DUPLICATE_INPUT:
    string_buffer_append(string_buffer, "<&");
    break;
  case RT_DUPLICATE_OUTPUT:
    string_buffer_append(string_buffer, ">&");
    break;
  case RT_READ_WRITE:
    string_buffer_append(string_buffer, "<> ");
    break;
  }
  string_buffer_append(string_buffer, redirect->filename);
}
 
static void print_simple_command(const struct simple_command_struct *simple_command, struct string_buffer_struct *string_buffer)
{
  const struct argument_struct *argument;
  const struct redirect_struct *redirect;
 
  if (simple_command->command_name) {
    string_buffer_append(string_buffer, simple_command->command_name);
    for (argument = simple_command->first_argument; argument; argument = argument->next) {
      string_buffer_append(string_buffer, " ");
      print_argument(argument, string_buffer);
    }
    if (simple_command->first_redirect)
      string_buffer_append(string_buffer, " ");
  }
  for (redirect = simple_command->first_redirect; redirect; redirect = redirect->next) {
    print_redirect(redirect, string_buffer);
    if (redirect->next)
      string_buffer_append(string_buffer, " ");
  }
}
 
static void print_compound_command(const struct compound_command_struct *compound_command, struct string_buffer_struct *string_buffer)
{
  const struct redirect_struct *redirect;
 
  switch (compound_command->type) {
  case CC_SUBSHELL:
    string_buffer_append(string_buffer, "( ");
    do_print_list(compound_command->list, string_buffer);
    string_buffer_append(string_buffer, " )");
    if (compound_command->first_redirect)
      string_buffer_append(string_buffer, " ");
    break;
  }
  for (redirect = compound_command->first_redirect; redirect; redirect = redirect->next) {
    print_redirect(redirect, string_buffer);
    if (redirect->next)
      string_buffer_append(string_buffer, " ");
  }
}
 
static void do_print_command(const struct command_struct *command, struct string_buffer_struct *string_buffer)
{
  switch (command->type) {
  case CT_SIMPLE:
    return print_simple_command(&command->simple_command, string_buffer);
  case CT_COMPOUND:
    return print_compound_command(&command->compound_command, string_buffer);
  }
}
 
void print_command(const struct command_struct *command, int *line_number, struct string_buffer_struct *string_buffer)
{
  *line_number = command->line_number;
  do_print_command(command, string_buffer);
}
 
static void do_print_pipeline(const struct pipeline_struct *pipeline, struct string_buffer_struct *string_buffer)
{
  const struct command_struct *command;
 
  for (command = pipeline->first_command; command; command = command->next) {
    do_print_command(command, string_buffer);
    if (command->next)
      string_buffer_append(string_buffer, " | ");
  }
}
 
void print_pipeline(const struct pipeline_struct *pipeline, int *line_number, struct string_buffer_struct *string_buffer)
{
  *line_number = pipeline->line_number;
  do_print_pipeline(pipeline, string_buffer);
}
 
static void do_print_and_or_list(const struct and_or_list_struct *and_or_list, struct string_buffer_struct *string_buffer)
{
  const struct pipeline_struct *pipeline;
 
  for (pipeline = and_or_list->first_pipeline; pipeline; pipeline = pipeline->next) {
    do_print_pipeline(pipeline, string_buffer);
    if (pipeline->next)
      switch (pipeline->operator) {
      case AO_AND:
        string_buffer_append(string_buffer, " && ");
        break;
      case AO_OR:
        string_buffer_append(string_buffer, " || ");
        break;
      }
  }
}
 
/* Attention, n'imprime pas le " &" pour les listes asynchrones. */
void print_and_or_list(const struct and_or_list_struct *and_or_list, int *line_number, struct string_buffer_struct *string_buffer)
{
  *line_number = and_or_list->line_number;
  do_print_and_or_list(and_or_list, string_buffer);
}
 
static void do_print_list(const struct list_struct *list, struct string_buffer_struct *string_buffer)
{
  const struct and_or_list_struct *and_or_list;
 
  for (and_or_list = list->first_and_or_list; and_or_list; and_or_list = and_or_list->next) {
    do_print_and_or_list(and_or_list, string_buffer);
    if (and_or_list->asynchronous) {
      string_buffer_append(string_buffer, " &");
      if (and_or_list->next)
        string_buffer_append(string_buffer, " ");
    }
    else
      if (and_or_list->next)
        string_buffer_append(string_buffer, "; ");
  }
}
 
void print_list(const struct list_struct *list, int *line_number, struct string_buffer_struct *string_buffer)
{
  *line_number = list->line_number;
  do_print_list(list, string_buffer);
}