# HG changeset patch # User Paul Boddie # Date 1572381859 -3600 # Node ID e7b8a728fd7f058575353bfb40b0fde675598527 # Parent 802db78b7bfa5bd183d883c96c0a74a3321492d5 Added an output directory option; added handling of file opening errors. diff -r 802db78b7bfa -r e7b8a728fd7f client.c --- a/client.c Tue Oct 29 20:49:42 2019 +0100 +++ b/client.c Tue Oct 29 21:44:19 2019 +0100 @@ -28,28 +28,59 @@ /* Program state set in the main program. */ -extern char *output_basename; +extern char *output_prefix, *output_dir; extern int output_client, output_headers, output_verbose; +/* Generate an error message for file opening failure. */ + +static void open_error(const char *dir, const char *name) +{ + fprintf(stderr, "Could not open source file for writing: %s/%s\n", dir, name); +} + +/* Obtain a new basename string. */ + +static char *make_basename(const char *path) +{ + char s[strlen(path) + 1]; + + strcpy(s, path); + return strdup(basename(s)); +} + +/* Obtain a new directory name string. */ + +static char *make_dirname(const char *path) +{ + char s[strlen(path) + 1]; + + strcpy(s, path); + return strdup(dirname(s)); +} + /* Obtain a file pointer using a parameterised filename. */ -static FILE *get_output_file(const char *filename_template, const char *identifier) +static FILE *get_output_file(const char *filename_template, const char *dir, const char *name) { FILE *fp; char *filename; - /* NOTE: Return errors! */ - - if (asprintf(&filename, filename_template, identifier) == -1) - return NULL; + if (asprintf(&filename, filename_template, dir, name) == -1) + fp = NULL; else { fp = fopen(filename, "w"); free(filename); - return fp; } + + /* Write an error message upon failure. */ + + if (fp == NULL) + open_error(dir, name); + + return fp; } /* Find an attribute value. */ @@ -152,9 +183,9 @@ /* Filename definitions. */ -static char source_filename[] = "%s_client.c"; -static char header_filename[] = "%s_client.h"; -static char common_filename[] = "%s_common.h"; +static char source_filename[] = "%s/%s_client.c"; +static char header_filename[] = "%s/%s_client.h"; +static char common_filename[] = "%s/%s_common.h"; /* Prologue definitions and other templates. */ @@ -188,36 +219,65 @@ void write_files(struct interface *iface) { FILE *source_fp = NULL, *header_fp = NULL, *common_fp = NULL; + char *output_basename, *output_dirname; struct interface *i; - char *basename_header; + + /* Obtain a prefix for the output files. */ - /* Obtain a basename for the output files. */ + if (output_prefix == NULL) + { + for (i = iface; i->tail != NULL; i = i->tail); + output_prefix = i->name; + } + + /* Obtain the basename of the output prefix. */ + + output_basename = make_basename(output_prefix); + + /* NOTE: Should exit with an error. */ if (output_basename == NULL) + return; + + /* Obtain the directory name from the output prefix. */ + + if (output_dir == NULL) + output_dirname = make_dirname(output_prefix); + else + output_dirname = output_dir; + + /* NOTE: Should exit with an error. */ + + if (output_dirname == NULL) { - for (i = iface; i->tail != NULL; i = i->tail); - output_basename = i->name; + free(output_basename); + return; } - /* Obtain the basename for use in includes. */ - - basename_header = basename(output_basename); - /* Open the separate files and write the details of each interface. */ if (output_client) - source_fp = get_output_file(source_filename, output_basename); + { + source_fp = get_output_file(source_filename, output_dirname, output_basename); + if (source_fp == NULL) + return; + } if (output_headers) { - header_fp = get_output_file(header_filename, output_basename); - common_fp = get_output_file(common_filename, output_basename); + header_fp = get_output_file(header_filename, output_dirname, output_basename); + if (header_fp == NULL) + return; + + common_fp = get_output_file(common_filename, output_dirname, output_basename); + if (common_fp == NULL) + return; } /* Emit prologues. */ if (source_fp != NULL) - fprintf(source_fp, source_prologue, basename_header, basename_header); + fprintf(source_fp, source_prologue, output_basename, output_basename); if (header_fp != NULL) fputs(header_prologue, header_fp); @@ -239,6 +299,13 @@ if (common_fp != NULL) fclose(common_fp); + + /* Free the names. */ + + if (output_dir == NULL) + free(output_dirname); + + free(output_basename); } /* Generate the source file corresponding to the interface. */ diff -r 802db78b7bfa -r e7b8a728fd7f main.c --- a/main.c Tue Oct 29 20:49:42 2019 +0100 +++ b/main.c Tue Oct 29 21:44:19 2019 +0100 @@ -36,7 +36,8 @@ /* Current filename and output options. */ -char *output_basename = NULL; +char *output_prefix = NULL; +char *output_dir = NULL; int output_client = 0; int output_headers = 0; int output_verbose = 0; @@ -66,12 +67,13 @@ /* Option definitions. */ static struct option long_options[] = { -/* long opt following var pointer short opt */ - {"all", no_argument, NULL, 'a' }, - {"client", no_argument, NULL, 'c' }, - {"headers", no_argument, NULL, 'h' }, - {"verbose", no_argument, NULL, 'v' }, - {0, 0, 0, 0 }, +/* long opt following var pointer short opt */ + {"all", no_argument, NULL, 'a' }, + {"client", no_argument, NULL, 'c' }, + {"dir", required_argument, NULL, 'd' }, + {"headers", no_argument, NULL, 'h' }, + {"verbose", no_argument, NULL, 'v' }, + {0, 0, 0, 0 }, }; @@ -92,7 +94,7 @@ while (1) { - option = getopt_long(argc, argv, "achv", long_options, NULL); + option = getopt_long(argc, argv, "acd:hv", long_options, NULL); if (option == -1) break; @@ -100,6 +102,7 @@ { case 'a': output_client = 1; output_headers = 1; break; case 'c': output_client = 1; break; + case 'd': output_dir = optarg; break; case 'h': output_headers = 1; break; case 'v': output_verbose = 1; break; default: return 1; @@ -114,9 +117,9 @@ /* Handle actual files. */ - output_basename = make_basename(arg); + output_prefix = make_basename(arg); - if (output_basename != NULL) + if (output_prefix != NULL) { fp = fopen(arg, "r"); @@ -131,7 +134,7 @@ reset(); } - free(output_basename); + free(output_prefix); } }