F diff --git a/system_part.c b/system_part.c --- a/system_part.c +++ b/system_part.c#define VOLGIT_SYSTEM_PART_C VOLGIT_SYSTEM_PART_C#include <system_part.h>- const char *default_header="<!DOCTYPE html><html><head><title>GIT</title></head><body>";- const char *default_footer="</body></html>";+ const char *const default_header="<!DOCTYPE html><html><head><title>GIT</title></head><body>";+ const char *const default_footer="</body></html>";- struct Volgit_Options options;+ struct Volgit_Options options+ =+ {+ .input_path=NULL,+ .output_path=NULL,+ .header=default_header,+ .footer=default_footer,+ .output_dir_fd=-1,+ .tree_cutoff=NO_TREE_CUTOFF,+ .output_is_tree_like=0,+ };++ const char *usage=+ "Options: \n"+ " --input <repository path>\n"+ " --output <name of directory where output is going to be stored>\n"+ " --header <file containing content which is prepended to all generated files>\n"+ " --footer <file containing content which is appended to all generated files>\n"+ " --tree \n"+ " Use 'tree' like output for directory index\n"+ " --tree-cutoff <number>\n"+ " The tree output can get too bulky\n"+ " so you can set a depth at which the output\n"+ " is seperated into a different file\n"+ " -h --help\n"+ " Print this message\n";++ static inline int get_next_option_or_die(int i,int argc,const char *error_message)+ {+ if(i+1>=argc)+ die(error_message);+ return i+1;+ }void parse_options(int argc,char **argv){+ #define if_option(option) if(!strncmp(argv[i],option,sizeof(option)))+ int i;+ if(argc==1)+ die(usage);- options.header=default_header;- options.footer=default_footer;- switch(argc)+ for(i=1;i<argc;++i){- case 5:- options.header=read_file(argv[3]);- options.footer=read_file(argv[4]);- /*falltrough*/- case 3:- options.input_path=argv[1];- options.output_path=argv[2];- break;- default:- die("Usage: volgit source destination [ file-containint-header file-containing-footer ]\n");- }+ if_option("--output")+ {+ i=get_next_option_or_die(i,argc,"expected a file name after --output flag\n");++ options.output_path=argv[i];+ options.output_dir_fd=open(options.output_path,O_RDONLY|O_DIRECTORY);++ if(options.output_dir_fd==-1)+ {+ mkdir(options.output_path,0775);+ options.output_dir_fd=open(options.output_path,O_RDONLY|O_DIRECTORY);+ if(options.output_dir_fd==-1)+ die("Could not open output dir\n");+ }+ }else if_option("--input")+ {+ i=get_next_option_or_die(i,argc,"expected a file name after --input flag\n");+ options.input_path=argv[i];+ }else if_option("--header")+ {+ i=get_next_option_or_die(i,argc,"expected an argument after --header flag\n");+ options.header=read_file(argv[i]);+ }else if_option("--footer")+ {+ i=get_next_option_or_die(i,argc,"expected an argument after --footer flag\n");+ options.footer=read_file(argv[i]);+ }else if_option("--tree")+ {+ options.output_is_tree_like=1;+ }else if_option("--tree-cutoff")+ {+ i=get_next_option_or_die(i,argc,"expected an argument after --tree-cutoff flag\n");+ if(sscanf(argv[i],"%d",&options.tree_cutoff))+ die("expected a number after the --tree-cutoff flag\n");+ }else if_option("-h")+ {+ die(usage);+ }else if_option("--help")+ {+ die(usage);+ }else+ {+ die("Invalid command argument '%s'. Try using -h\n",argv[i]);+ }- options.output_dir_fd=open(options.output_path,O_RDONLY|O_DIRECTORY);- if(options.output_dir_fd==-1)- {- mkdir(options.output_path,0775);- options.output_dir_fd=open(options.output_path,O_RDONLY|O_DIRECTORY);- if(options.output_dir_fd==-1)- die("Could not open output dir\n");}++ if(options.input_path==NULL)+ die("You need to specify an input path\n");+ if(options.output_path==NULL)+ die("You need to specify an output path\n");++ #undef if_option}char* read_file(const char *filename){die("Ran out of memory!\n");read(file,ret,file_stats.st_size);+ ret[file_stats.st_size]='\0';close(file);++return ret;}F diff --git a/system_part.h b/system_part.h --- a/system_part.h +++ b/system_part.h#include <stdarg.h>#include <string.h>- extern const char *default_header;- extern const char *default_footer;++ #define NO_TREE_CUTOFF -1++ extern const char *const default_header;+ extern const char *const default_footer;extern struct Volgit_Options{const char *input_path;const char *output_path;++ /*pointers to the actual text from the header and footer files*/const char *header;const char *footer;+int output_dir_fd;+ int tree_cutoff; /*-1 means no cutoff*/+ _Bool output_is_tree_like;}options;void die(const char *format, ...);