diff --git a/README.md b/README.md index 0bac36c..2ff0849 100644 --- a/README.md +++ b/README.md @@ -204,6 +204,7 @@ When contributing to this library, it is therefore important to ensure that all We are currently on major release v4. Breaking changes should be marked with the [deprecated](https://www.doxygen.nl/manual/commands.html#cmddeprecated) doxygen tag. The following changes are planned when the next major/breaking release (v5) becomes necessary: +* mf_getuniquelibref.sas to have the deprecated maxtried parameter removed (no longer needed) * mp_testservice.sas to be renamed as mp_execute.sas (as it doesn't actually test anything) * `insert_cmplib` option of mcf_xxx macros will be deprecated (the option is now checked automatically with value inserted only if needed) * mcf_xxx macros to have `wrap=` option defaulted to YES for convenience. Set this option explicitly to avoid issues. diff --git a/all.sas b/all.sas index f0f0b21..6f17814 100644 --- a/all.sas +++ b/all.sas @@ -970,29 +970,46 @@ or %index(&pgm,/tests/testteardown) > mclib3 - @param prefix= first part of libref. Remember that librefs can only be 8 characters, - so a 7 letter prefix would mean that maxtries should be 10. - @param maxtries= the last part of the libref. Provide an integer value. + A blank value is returned if no usable libname is determined. + + @param [in] prefix= (mclib) first part of the returned libref. As librefs can + be as long as 8 characters, a maximum length of 7 characters is premitted + for this prefix. + @param [in] maxtries= Deprecated parameter. Remains here to ensure a + non-breaking change. Will be removed in v5. @version 9.2 @author Allan Bowe **/ - %macro mf_getuniquelibref(prefix=mclib,maxtries=1000); - %local x libref; - %let x=0; - %do x=0 %to &maxtries; - %if %sysfunc(libref(&prefix&x)) ne 0 %then %do; - %let libref=&prefix&x; - %let rc=%sysfunc(libname(&libref,%sysfunc(pathname(work)))); - %if &rc %then %put %sysfunc(sysmsg()); - &prefix&x - %*put &sysmacroname: Libref &libref assigned as WORK and returned; + %local x; + + %if ( %length(&prefix) gt 7 ) %then %do; + %put %str(ERR)OR: The prefix parameter cannot exceed 7 characters.; + 0 %return; %end; + %else %if (%sysfunc(NVALID(&prefix,v7))=0) %then %do; + %put %str(ERR)OR: Invalid prefix (&prefix); + 0 + %return; %end; - %put unable to find available libref in range &prefix.0-&maxtries; + + /* Set maxtries equal to '10 to the power of [# unused characters] - 1' */ + %let maxtries=%eval(10**(8-%length(&prefix))-1); + + %do x = 0 %to &maxtries; + %if %sysfunc(libref(&prefix&x)) ne 0 %then %do; + &prefix&x + %return; + %end; + %let x = %eval(&x + 1); + %end; + + %put %str(ERR)OR: No usable libref in range &prefix.0-&maxtries; + %put %str(ERR)OR- Try reducing the prefix or deleting some libraries!; + 0 %mend mf_getuniquelibref;/** @file mf_getuniquename.sas @brief Returns a shortened (32 char) GUID as a valid SAS name @@ -3146,7 +3163,9 @@ run; %let ds=&syslast; - proc compare base=&scopeds compare=&ds; + proc compare + base=&scopeds(where=(upcase(name) not in (%mf_getquotedstr(&ilist)))) + compare=&ds; run; %if &sysinfo=0 %then %do; diff --git a/base/mf_getuniquelibref.sas b/base/mf_getuniquelibref.sas index 8fe1ef9..c5eb387 100644 --- a/base/mf_getuniquelibref.sas +++ b/base/mf_getuniquelibref.sas @@ -14,27 +14,44 @@ > mclib3 - @param prefix= first part of libref. Remember that librefs can only be 8 characters, - so a 7 letter prefix would mean that maxtries should be 10. - @param maxtries= the last part of the libref. Provide an integer value. + A blank value is returned if no usable libname is determined. + + @param [in] prefix= (mclib) first part of the returned libref. As librefs can + be as long as 8 characters, a maximum length of 7 characters is premitted + for this prefix. + @param [in] maxtries= Deprecated parameter. Remains here to ensure a + non-breaking change. Will be removed in v5. @version 9.2 @author Allan Bowe **/ - %macro mf_getuniquelibref(prefix=mclib,maxtries=1000); - %local x libref; - %let x=0; - %do x=0 %to &maxtries; - %if %sysfunc(libref(&prefix&x)) ne 0 %then %do; - %let libref=&prefix&x; - %let rc=%sysfunc(libname(&libref,%sysfunc(pathname(work)))); - %if &rc %then %put %sysfunc(sysmsg()); - &prefix&x - %*put &sysmacroname: Libref &libref assigned as WORK and returned; + %local x; + + %if ( %length(&prefix) gt 7 ) %then %do; + %put %str(ERR)OR: The prefix parameter cannot exceed 7 characters.; + 0 %return; %end; + %else %if (%sysfunc(NVALID(&prefix,v7))=0) %then %do; + %put %str(ERR)OR: Invalid prefix (&prefix); + 0 + %return; %end; - %put unable to find available libref in range &prefix.0-&maxtries; + + /* Set maxtries equal to '10 to the power of [# unused characters] - 1' */ + %let maxtries=%eval(10**(8-%length(&prefix))-1); + + %do x = 0 %to &maxtries; + %if %sysfunc(libref(&prefix&x)) ne 0 %then %do; + &prefix&x + %return; + %end; + %let x = %eval(&x + 1); + %end; + + %put %str(ERR)OR: No usable libref in range &prefix.0-&maxtries; + %put %str(ERR)OR- Try reducing the prefix or deleting some libraries!; + 0 %mend mf_getuniquelibref; \ No newline at end of file diff --git a/base/mp_assertscope.sas b/base/mp_assertscope.sas index 786361c..5421371 100644 --- a/base/mp_assertscope.sas +++ b/base/mp_assertscope.sas @@ -104,7 +104,9 @@ %let ds=&syslast; - proc compare base=&scopeds compare=&ds; + proc compare + base=&scopeds(where=(upcase(name) not in (%mf_getquotedstr(&ilist)))) + compare=&ds; run; %if &sysinfo=0 %then %do; diff --git a/tests/crossplatform/mf_getuniquelibref.test.sas b/tests/crossplatform/mf_getuniquelibref.test.sas new file mode 100644 index 0000000..16ecc4b --- /dev/null +++ b/tests/crossplatform/mf_getuniquelibref.test.sas @@ -0,0 +1,54 @@ +/** + @file + @brief Testing mf_getuniquelibref macro + @details To test performance you can also use the following macro: + +