/* * io.c - implementation of stream I/O for D compiler * CSE 413 au07 */ #include #include #include #include "io.h" /*----- local constants and variables -----*/ /* longest possible prefix string (including '\0') */ #define MAX_PREFIX_LENGTH 21 /* prefix string to prepend to input lines echoed to standard output */ static char prefix[MAX_PREFIX_LENGTH] = "# "; /* true if echoing input lines to output, false otherwise */ static int echoing = 1; /* maximum length of constructed output file name */ #define MAX_OUTPUT_FILENAME_LENGTH 1024 /* default extension for output file name */ #define DEFAULT_OUTFILE_EXTENSION ".s" /*-----local function declarations-----*/ static void make_outfile_name(char* outfile_name, char* infile_name); /* * Initialize I/O routines. Parameters argc and argv should be those passed * to method main. * If there are no parameters, input is read from stdin and output written * to stdout. * If there is one parameter, it is taken as the name of the input file, and * stdin is redirected to that file. In this case, stdout is redirected to * a new file whose name is the input file name without it's final extension * (following a trailing "."), and with the extension ".s". * If there are two parameters, they are taken as the name of the input and * output files respectively, and stdin and stdout are redirected accordingly. * If either the input or output file cannot be opened, execution of the * program is terminated with a call to exit(). */ void io_init(int argc, char* argv[]) { FILE* open_result; char* output_file_name; char outfile_name[MAX_OUTPUT_FILENAME_LENGTH]; if (argc < 2) { return; } /* At least one file argument. Attempt to redirect stdin. */ open_result = freopen(argv[1], "r", stdin); if (open_result == NULL) { fprintf(stderr, "attempt to open input file >%s< failed\n", argv[1]); exit(EXIT_FAILURE); } /* output file name is 2nd file argument if given, otherwise result * of massaging input file name */ if (argc < 3) { make_outfile_name(outfile_name, argv[1]); output_file_name = outfile_name; } else { output_file_name = argv[2]; } open_result = freopen(output_file_name, "w", stdout); if (open_result == NULL) { fprintf(stderr, "attempt to open output file>%s< failed\n", output_file_name); exit(EXIT_FAILURE); } /* success */ return; } /* * Construct output file name from input file name by stripping final * extension and adding default output extension. * pre: infile_name is the input file name, not null or something else */ static void make_outfile_name(char* outfile_name, char* infile_name) { char* last_dot_loc; int pos; last_dot_loc = strrchr(infile_name, '.'); if (last_dot_loc == NULL) { /* no extension: output file = input file + default extension */ strcpy(outfile_name, infile_name); } else { /* copy input file name without final extension */ pos = last_dot_loc - infile_name; strncpy(outfile_name, infile_name, pos); outfile_name[pos] = '\0'; } /* append extension */ strcat(outfile_name, DEFAULT_OUTFILE_EXTENSION); } /* * Read the next line of input into s. Return a pointer to s if the read * succeeds, or NULL if there is no more input. (e.g., same as gets). * Copy the input line to output if a line is read and echoing is enabled. * pre: s has enough space for the entire next line. */ char* getline(char* s) { char* result; result = gets(s); if (result != NULL && echoing) { printf("%s%s\n", prefix, s); } return result; } /* * Write s to output and advance to the next line. */ void putline(char* s) { printf("%s\n", s); } /* * Write s to output without advancing to a new line. */ void putstr(char* s) { printf("%s", s); } /* * Turn echoing of input on or off as specified (default is on). * Return the previous echo setting. */ int set_echo(int on_off) { int old_echo; old_echo = echoing; echoing = on_off; return old_echo; } /* * Set the echo prefix to the given string. Default is "# ". * pre: prefix is not too long (see constant in io.c) */ void set_echo_prefix(char* new_prefix) { strcpy(prefix, new_prefix); }