#include "print_cmd.h"
#include "command.h"
#include "safe_malloc.h"
#include <string.h>
#include <stdio.h>
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;
}
}
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;
}
}
}
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);
}