diff --git a/source/auto_vararg.h b/source/auto_vararg.h new file mode 100644 index 0000000..7829256 --- /dev/null +++ b/source/auto_vararg.h @@ -0,0 +1,44 @@ +#ifndef AUTO_VARARG +#define AUTO_VARARG + +/* The following horrid macros can be used + * to create vararg function which do not + * require the developer to pass in the + * argument count by hand. + */ + +// useless without it, so might as well include +#include <stdarg.h> + +#define PP_NARG(...) PP_NARG_(__VA_ARGS__, PP_RSEQ_N()) +#define PP_NARG_(...) PP_128TH_ARG(__VA_ARGS__) +#define PP_128TH_ARG( \ + _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ + _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ + _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ + _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ + _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ + _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ + _61,_62,_63,_64,_65,_66,_67,_68,_69,_70, \ + _71,_72,_73,_74,_75,_76,_77,_78,_79,_80, \ + _81,_82,_83,_84,_85,_86,_87,_88,_89,_90, \ + _91,_92,_93,_94,_95,_96,_97,_98,_99,_100, \ + _101,_102,_103,_104,_105,_106,_107,_108,_109,_110, \ + _111,_112,_113,_114,_115,_116,_117,_118,_119,_120, \ + _121,_122,_123,_124,_125,_126,_127,N,...) N +#define PP_RSEQ_N() \ + 127,126,125,124,123,122,121,120, \ + 119,118,117,116,115,114,113,112,111,110, \ + 109,108,107,106,105,104,103,102,101,100, \ + 99,98,97,96,95,94,93,92,91,90, \ + 89,88,87,86,85,84,83,82,81,80, \ + 79,78,77,76,75,74,73,72,71,70, \ + 69,68,67,66,65,64,63,62,61,60, \ + 59,58,57,56,55,54,53,52,51,50, \ + 49,48,47,46,45,44,43,42,41,40, \ + 39,38,37,36,35,34,33,32,31,30, \ + 29,28,27,26,25,24,23,22,21,20, \ + 19,18,17,16,15,14,13,12,11,10, \ + 9,8,7,6,5,4,3,2,1,0 + +#endif diff --git a/source/global.h b/source/global.h index 0c157a5..fca2925 100644 --- a/source/global.h +++ b/source/global.h @@ -229,7 +229,9 @@ char *pathcomponents(char *path, int components); char *read_block(void); char *scanpast(char c); -char **parse_options(int *argc, char **argv); +char **parse_options(int *argc, char **argv); +void readenv(void); + void error_usage(void); void longusage(void); void usage(void); diff --git a/source/library.h b/source/library.h index e3ff5c2..028465c 100644 --- a/source/library.h +++ b/source/library.h @@ -41,7 +41,6 @@ char *egrepinit(const char *egreppat); char *logdir(char *name); const char *basename(const char *path); FILE *myfopen(char *path, char *mode); -char *mygetenv(char *variable, char *deflt); int myopen(char *path, int flag, int mode); FILE *mypopen(char *cmd, char *mode); int mypclose(FILE *ptr); diff --git a/source/main.c b/source/main.c index ba59dde..fce98ae 100644 --- a/source/main.c +++ b/source/main.c @@ -50,13 +50,6 @@ #include <signal.h> #include <getopt.h> -/* defaults for unset environment variables */ -#define EDITOR "vi" -#define HOME "/" /* no $HOME --> use root directory */ -#define SHELL "sh" -#define LINEFLAG "+%s" /* default: used by vi and emacs */ -#define TMPDIR "/tmp" - /* note: these digraph character frequencies were calculated from possible printable digraphs in the cross-reference for the C compiler */ char dichar1[] = " teisaprnl(of)=c"; /* 16 most frequent first chars */ @@ -65,9 +58,6 @@ char dichar2[] = " tnerpla"; /* 8 most frequent second chars char dicode1[256]; /* digraph first character code */ char dicode2[256]; /* digraph second character code */ -char *editor, *shell, *lineflag; /* environment variables */ -char *home; /* Home directory */ -bool lineflagafterfile; char *argv0; /* command name */ bool compress = true; /* compress the characters in the crossref */ bool dbtruncated; /* database symbols are truncated to 8 chars */ @@ -94,14 +84,12 @@ long totalterms; /* total inverted index terms */ bool trun_syms; /* truncate symbols to 8 characters */ char tempstring[TEMPSTRING_LEN + 1]; /* use this as a buffer, instead of 'yytext', * which had better be left alone */ -char *tmpdir; /* temporary directory */ static char path[PATHLEN + 1]; /* file path */ /* Internal prototypes: */ static void skiplist(FILE *oldrefs); static void initcompress(void); -static inline void readenv(void); static inline void linemode_event_loop(void); static inline void screenmode_event_loop(void); @@ -207,17 +195,6 @@ void myexit(int sig) { exit(sig); } -static inline void readenv(void) { - editor = mygetenv("EDITOR", EDITOR); - editor = mygetenv("VIEWER", editor); /* use viewer if set */ - editor = mygetenv("CSCOPE_EDITOR", editor); /* has last word */ - home = mygetenv("HOME", HOME); - shell = mygetenv("SHELL", SHELL); - lineflag = mygetenv("CSCOPE_LINEFLAG", LINEFLAG); - lineflagafterfile = getenv("CSCOPE_LINEFLAG_AFTER_FILE") ? 1 : 0; - tmpdir = mygetenv("TMPDIR", TMPDIR); -} - static inline void linemode_event_loop(void) { int c; diff --git a/source/mygetenv.c b/source/mygetenv.c deleted file mode 100644 index 2f965c1..0000000 --- a/source/mygetenv.c +++ /dev/null @@ -1,45 +0,0 @@ -/*=========================================================================== - Copyright (c) 1998-2000, The Santa Cruz Operation - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - *Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - *Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - *Neither name of The Santa Cruz Operation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS - IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - DAMAGE. - =========================================================================*/ - -#include "library.h" - -#include <stdlib.h> - -/* return the non-null environment value or the default argument */ - -char *mygetenv(char *variable, char *deflt) { - char *value; - - value = getenv(variable); - if(value == NULL || *value == '\0') { return (deflt); } - return (value); -} diff --git a/source/opt.c b/source/opt.c index 9fd3d0c..ffe1b6a 100644 --- a/source/opt.c +++ b/source/opt.c @@ -3,14 +3,70 @@ #include "build.h" #include "vp.h" #include "version.inc" +#include "auto_vararg.h" #include <stdlib.h> /* atoi */ #include <getopt.h> +/* defaults for unset environment variables */ +#define DEFAULT_EDITOR "vi" +#define DEFAULT_HOME "/" /* no $HOME --> use root directory */ +#define DEFAULT_SHELL "sh" +#define DEFAULT_LINEFLAG "+%s" /* default: used by vi and emacs */ +#define DEFAULT_TMPDIR "/tmp" + +/* environment variable holders */ +char * editor; +char * home; +char * shell; +char * lineflag; +char * tmpdir; +bool lineflagafterfile; + bool remove_symfile_onexit = false; bool onesearch; /* one search only in line mode */ char *reflines; /* symbol reference lines file */ +/* From a list of envirnment variable names, + * return the first valid variable value + * or the user given default. + */ +#define coalesce_env(def, ...) _coalesce_env(def, PP_NARG(__VA_ARGS__), __VA_ARGS__) +static inline +char * _coalesce_env(char * mydefault, size_t argc, ...) { + char * r = mydefault; + va_list va; + va_start(va, argc); + + for (int i = 0; i < argc; i++) { + char * value = va_arg(va, char*); + value = getenv(value); + + if (value != NULL + && *value != '\0') { + r = value; + goto end; + } + } + + end: + va_end(va); + return r; +} + +/* XXX: Add CSOPE_* equivalents while preserving the originals. + * DO NOT do it without writting documentation + */ +void readenv(void) { + editor = coalesce_env(DEFAULT_EDITOR, "CSCOPE_EDITOR", "VIEWER", "EDITOR"); + home = coalesce_env(DEFAULT_HOME, "HOME"); + shell = coalesce_env(DEFAULT_SHELL, "SHELL"); + lineflag = coalesce_env(DEFAULT_LINEFLAG, "CSCOPE_LINEFLAG"); + tmpdir = coalesce_env(DEFAULT_TMPDIR, "TMPDIR"); + + lineflagafterfile = getenv("CSCOPE_LINEFLAG_AFTER_FILE") ? 1 : 0; +} + char **parse_options(int *argc, char **argv) { int opt; int longind;