diff --git a/README.md b/README.md
index 59357b9..48a9756 100644
--- a/README.md
+++ b/README.md
@@ -93,7 +93,7 @@ This is a list of locations where the SAS Packages Framework is used:
If you want to share that you are using the SPF let me know and I'll update the list.
-If you find the SPF usefull **share info** about it or **give it a [star](https://github.com/yabwon/SAS_PACKAGES/stargazers)** so more people will know.
+If you find the SPF useful **share info** about it or **give it a [star](https://github.com/yabwon/SAS_PACKAGES/stargazers)** so more people will know.
---
@@ -146,7 +146,7 @@ SHA256 digest for macroArray: DF63B0E027827A82038F1C8422787A0BC569BA93104BA1778D
[Documentation for macroArray](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/macroarray.md "Documentation for macroArray")
-- **BasePlus**\[1.14\] adds a bunch of functionalities I am missing in BASE SAS, such as:
+- **BasePlus**\[1.15\] adds a bunch of functionalities I am missing in BASE SAS, such as:
```sas
call arrMissToRight(myArray);
call arrFillMiss(17, myArray);
@@ -164,7 +164,7 @@ format x bool.;
%zipLibrary(sashelp,libOut=work)
```
-SHA256 digest for BasePlus: 12A9A2155D9C6F969DF0A66E3A18D0938B8194FA3AA9D70EDDE1CB71DEF9691E
+SHA256 digest for BasePlus: 0331C673052D5221DA98C5CC93295634D8A0BC62C7D2FEF9D0D85B0B2DEDE4E9
[Documentation for BasePlus](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md "Documentation for BasePlus")
diff --git a/packages/README.md b/packages/README.md
index f66ea8e..ffd560f 100644
--- a/packages/README.md
+++ b/packages/README.md
@@ -90,7 +90,7 @@ SHA256 digest for macroArray: DF63B0E027827A82038F1C8422787A0BC569BA93104BA1778D
---
-- **BasePlus**\[1.14\] adds a bunch of functionalities I am missing in BASE SAS, such as:
+- **BasePlus**\[1.15\] adds a bunch of functionalities I am missing in BASE SAS, such as:
```sas
call arrMissToRight(myArray);
call arrFillMiss(17, myArray);
@@ -108,7 +108,7 @@ format x bool.;
%zipLibrary(sashelp,libOut=work)
```
-SHA256 digest for BasePlus: 12A9A2155D9C6F969DF0A66E3A18D0938B8194FA3AA9D70EDDE1CB71DEF9691E
+SHA256 digest for BasePlus: 0331C673052D5221DA98C5CC93295634D8A0BC62C7D2FEF9D0D85B0B2DEDE4E9
[Documentation for BasePlus](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md "Documentation for BasePlus")
diff --git a/packages/SHA256_for_packages.txt b/packages/SHA256_for_packages.txt
index ad126d9..3e6c78f 100644
--- a/packages/SHA256_for_packages.txt
+++ b/packages/SHA256_for_packages.txt
@@ -1,3 +1,6 @@
+/* 20220508 */
+BasePlus: 0331C673052D5221DA98C5CC93295634D8A0BC62C7D2FEF9D0D85B0B2DEDE4E9
+
/* 20220420 */
BasePlus: 12A9A2155D9C6F969DF0A66E3A18D0938B8194FA3AA9D70EDDE1CB71DEF9691E
DFA: 6B3FB0B06B47A7EF1BB004B483B0F39B8F553F7F16D02A7E24CDE388BBA704EA
diff --git a/packages/baseplus.md b/packages/baseplus.md
index 6095908..3c24ca3 100644
--- a/packages/baseplus.md
+++ b/packages/baseplus.md
@@ -45,12 +45,17 @@
* [`%RainCloudPlot()` macro](#raincloudplot-macro)
* [`%zipLibrary()` macro](#ziplibrary-macro)
* [`%unzipLibrary()` macro](#unziplibrary-macro)
+ * [`%LDSN()` macro](#ldsn-macro)
+ * [`%LVarNm()` macro](#lvarnm-macro)
+ * [`%LVarNmLab()` macro](#lvarnmlab-macro)
+
+
* [License](#license)
---
-# The BasePlus package [ver. 1.14] ###############################################
+# The BasePlus package [ver. 1.15] ###############################################
The **BasePlus** package implements useful
functions and functionalities I miss in the BASE SAS.
@@ -67,7 +72,9 @@ Kudos to all who inspired me to generate this package:
*Richard DeVenezia*,
*Christian Graffeuille*,
*Allan Bowe*,
-*Anamaria Calai*.
+*Anamaria Calai*,
+*Michal Ludwicki*,
+*Quentin McMullen*.
---
@@ -187,7 +194,6 @@ Kudos to all who inspired me to generate this package:
%rainCloudPlot(sashelp.cars,DriveTrain,Invoice)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
**Example 10**: Zip SAS library.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
@@ -196,64 +202,77 @@ Kudos to all who inspired me to generate this package:
%unzipLibrary(%sysfunc(pathname(work)), zip=sashelp, mode=S, clean=1)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**Example 11**: Long dataset names.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
+data %LDSN( work. peanut butter & jelly time with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s (drop = sex rename=(name=first_name) where = (age in (12,13,14))) );
+ set sashelp.class;
+run;
+proc print data = %LDSN( work. peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s );
+run;
+data MyNextDataset;
+ set %LDSN( work. peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s );
+ where age > 12;
+run;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---
Package contains:
-1. macro deduplistc
-2. macro deduplistp
-3. macro deduplists
-4. macro deduplistx
-5. macro functionexists
-6. macro getvars
-7. macro qdeduplistx
-8. macro qgetvars
-9. macro qzipevalf
-10. macro raincloudplot
-11. macro symdelglobal
-12. macro unziplibrary
-13. macro zipevalf
-14. macro ziplibrary
-15. format bool
-16. format boolz
-17. format ceil
-18. format floor
-19. format int
-20. function arrfill
-21. function arrfillc
-22. function arrmissfill
-23. function arrmissfillc
-24. function arrmisstoleft
-25. function arrmisstoleftc
-26. function arrmisstoright
-27. function arrmisstorightc
-28. function bracketsc
-29. function bracketsn
-30. function catxfc
-31. function catxfi
-32. function catxfj
-33. function catxfn
-34. function deldataset
-35. function semicolonc
-36. function semicolonn
-37. format brackets
-38. format semicolon
-39. proto qsortincbyprocproto
-40. function frommissingtonumberbs
-41. function fromnumbertomissing
-42. function quicksort4notmiss
-43. function quicksorthash
-44. function quicksorthashsddv
-45. function quicksortlight
-
-
+1. macro deduplistc
+2. macro deduplistp
+3. macro deduplists
+4. macro deduplistx
+5. macro functionexists
+6. macro getvars
+7. macro ldsn
+8. macro lvarnm
+9. macro lvarnmlab
+10. macro qdeduplistx
+11. macro qgetvars
+12. macro qzipevalf
+13. macro raincloudplot
+14. macro symdelglobal
+15. macro unziplibrary
+16. macro zipevalf
+17. macro ziplibrary
+18. format bool
+19. format boolz
+20. format ceil
+21. format floor
+22. format int
+23. functions arrfill
+24. functions arrfillc
+25. functions arrmissfill
+26. functions arrmissfillc
+27. functions arrmisstoleft
+28. functions arrmisstoleftc
+29. functions arrmisstoright
+30. functions arrmisstorightc
+31. functions bracketsc
+32. functions bracketsn
+33. functions catxfc
+34. functions catxfi
+35. functions catxfj
+36. functions catxfn
+37. functions deldataset
+38. functions semicolonc
+39. functions semicolonn
+40. format brackets
+41. format semicolon
+42. proto qsortincbyprocproto
+43. functions frommissingtonumberbs
+44. functions fromnumbertomissing
+45. functions quicksort4notmiss
+46. functions quicksorthash
+47. functions quicksorthashsddv
+48. functions quicksortlight
*SAS package generated by generatePackage, version 20220420*
The SHA256 hash digest for package BasePlus:
-`12A9A2155D9C6F969DF0A66E3A18D0938B8194FA3AA9D70EDDE1CB71DEF9691E`
+`0331C673052D5221DA98C5CC93295634D8A0BC62C7D2FEF9D0D85B0B2DEDE4E9`
---
# Content description ############################################################################################
@@ -3497,6 +3516,286 @@ run;
---
+## >>> `%LDSN()` macro: <<< #######################
+
+The LDSN (Long DataSet Names) macro function
+allows to use an "arbitrary" text string to name a dataset.
+
+---
+
+The idea for the macro came from the following story:
+
+Good friend of mine, who didn't use SAS for quite some time,
+told me that he lost a few hours for debugging because
+he forgot that the SAS dataset name limitation is 32 bytes.
+
+I replied that it shouldn't be a problem to do a workaround
+for this inconvenience with a macro and the `MD5()` hashing function.
+
+I said: *The macro should take an "arbitrary string" for a dataset
+name, convert it, with help of `MD5()`, to a hash digest, and
+create a dataset with an "artificial" `hex16.` formated name.*
+
+Starting with something like this:
+
+~~~~~~~~~~~~~~~~~~~~~~~sas
+data %LDSN(work. peanut butter & jelly with a hot-dog in [a box] and s*t*a*r*s (drop = sex rename=(name=first_name) where = (age in (12,13,14))) );
+ set sashelp.class;
+run;
+~~~~~~~~~~~~~~~~~~~~~~~
+
+the macro would do:
+
+~~~~~~~~~~~~~~~~~~~~~~~sas
+%sysfunc(MD5(peanut butter & jelly with a hot-dog in [a box] and s*t*a*r*s), hex16.)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+and (under the hood) return and execute the following code:
+
+~~~~~~~~~~~~~~~~~~~~~~~sas
+data work.DSN_41D599EF51FBA58_(drop = sex rename=(name=first_name) where = (age in (12,13,14))) ;
+ set sashelp.class;
+run;
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Also in the next data step user should be able to do:
+
+~~~~~~~~~~~~~~~~~~~~~~~sas
+data my_next_data_step;
+ set %DSN(work. peanut butter & jelly with a hot-dog in [a box] and s*t*a*r*s);
+run;
+~~~~~~~~~~~~~~~~~~~~~~~
+
+and work without the "dataset-name-length-limitation" issue.
+
+---
+
+See examples below for the details.
+
+The `%LDSN()` macro executes like a pure macro code.
+
+**Known "Limitations":**
+
+- dataset name _cannot_ contain dots (`.`) since they are used as separators!
+
+- dataset name _cannot_ contain round brackets(`(` and `)`) since they are used as separators
+ (but `[]` and `{}` are allowed)!
+
+- dataset name _cannot_ contain unpaired quotes (`'` and `"`),
+ text: `a "hot-dog"` is ok, but `John's dog` is not!
+
+**Behaviour:**
+
+- dataset name text is *converted to upcase*
+
+- dataset name text *leading and trailing spaces are ignored*,
+ e.g. the following will give the same hash digest:
+ `%ldsn(work.test)`, `%ldsn( work.test)`, `%ldsn(work.test )`,
+ `%ldsn(work .test)`, `%ldsn(work. test)`, `%ldsn(work . test)`.
+
+- if the user want to add an extra suffix to the dataset the `%ldsn()` macro
+ **has** to be wrapped inside the `%unquote()` macro function.
+~~~~~~~~~~~~~~~~~~~~~~~sas
+data
+ %unquote(%LDSN(WORK.some strange! DS name))_1
+ %unquote(%LDSN(WORK.some strange! DS name))_2
+;
+ set sashelp.class;
+
+ if SEX="M" then output %unquote(%LDSN(WORK.some strange! DS name))_1;
+ else output %unquote(%LDSN(WORK.some strange! DS name))_2;
+run;
+~~~~~~~~~~~~~~~~~~~~~~~
+ The reason for this is a "bug" like behaviour of SAS tokenizer/macroprocesor.
+ See the following SAS-L discussion thread:
+ `https://listserv.uga.edu/scripts/wa-UGA.exe?A2=SAS-L;4b2bcf80.2205A&S=`
+
+- macro calls of the form:
+ `data %LDSN(); run;`, `data %LDSN( ); run;`, `data %LDSN( . ); run;` or even
+ `data %LDSN( . (keep=x)); run;` are resolved to empty string, so the result is
+ equivalent to `data; run;`
+
+### SYNTAX: ###################################################################
+
+The basic syntax is the following, the `<...>` means optional parameters:
+~~~~~~~~~~~~~~~~~~~~~~~sas
+%LDSN(
+ arbitrary text string (in line with limitations)
+)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+### EXAMPLES AND USECASES: ####################################################
+
+**EXAMPLE 1.**
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
+options nomprint source nomlogic nosymbolgen ls = max ps = max;
+
+data %LDSN( work. peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s (drop = sex rename=(name=first_name) where = (age in (12,13,14))) );
+ set sashelp.class;
+run;
+
+proc print data = %LDSN( work. peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s );
+run;
+
+data MyNextDataset;
+ set %LDSN( work. peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s );
+ where age > 12;
+run;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+---
+
+## >>> `%LVarNm()` macro: <<< #######################
+
+The LVarNm() macro function works like the LDSN() macro function, but for variables.
+Supported by LVarNmLab() macro function which allows to remember "user names" in labels.
+
+The motivation for the macro was similar one as for the LDSN() macro.
+
+---
+
+See examples below for the details.
+
+The `%LVarNm()` macro executes like a pure macro code.
+
+**Known "Limitations":**
+
+- variable name _cannot_ contain unpaired quotes (`'` and `"`),
+ text: `a "hot-dog"` is ok, but `John's dog` is not!
+
+**Behaviour:**
+
+- variable name text is *converted to upcase*
+
+- variable name text *leading and trailing spaces are ignored*,
+ e.g. the following will give the same hash digest:
+ `%LVarNm(test)`, `%LVarNm( test)`, `%LVarNm(test )`.
+
+- if the user want to add an extra suffix to the variable,
+ e.g. to get a numerical suffix, the `%LVarNm()` macro
+ **has** to be wrapped inside the `%unquote()` macro function.
+~~~~~~~~~~~~~~~~~~~~~~~sas
+data test4;
+ array X[*] %unquote(%LVarNm(some strange! name))_0 - %unquote(%LVarNm(some strange! name))_10;
+
+ do i = lbound(X) to hbound(X);
+ X[i] = 2**(i-1);
+ put X[i]=;
+ end;
+run;
+~~~~~~~~~~~~~~~~~~~~~~~
+ The reason for this is a "bug" like behaviour of SAS tokenizer/macroprocesor.
+ See the following SAS-L discussion thread:
+ `https://listserv.uga.edu/scripts/wa-UGA.exe?A2=SAS-L;4b2bcf80.2205A&S=`
+
+### SYNTAX: ###################################################################
+
+The basic syntax is the following, the `<...>` means optional parameters:
+~~~~~~~~~~~~~~~~~~~~~~~sas
+%LVarNm(
+ arbitrary text string (in line with limitations)
+)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+---
+
+
+### EXAMPLES AND USECASES: ####################################################
+
+**EXAMPLE 1.**
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
+options ls=max;
+data test;
+ %LVarNmLab( peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s )
+
+ do %LVarNm( peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s ) = 1 to 10;
+
+ y = 5 + %LVarNm( peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s ) * 17;
+ output;
+ end;
+run;
+
+data test2;
+ set test;
+ where %LVarNm( peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s ) < 5;
+run;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+**EXAMPLE 2.**
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
+data test3;
+ %LVarNmLab() = 17;
+
+ %LVarNm() = 17;
+
+ %LVarNm( ) = 42;
+
+ %LVarNm( ) = 303;
+run;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+**EXAMPLE 3.**
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
+data test3;
+ %LVarNm(test) = 1;
+
+ %LVarNm( test) = 2;
+
+ %LVarNm(test ) = 3;
+run;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+**EXAMPLE 4.**
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
+data test4;
+ array X[*] %unquote(%LVarNm(some strange! name))_0 - %unquote(%LVarNm(some strange! name))_10;
+
+ do i = lbound(X) to hbound(X);
+ X[i] = 2**(i-1);
+ put X[i]=;
+ end;
+run;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+## >>> `%LVarNmLab()` macro: <<< #######################
+
+The LVarNmLab() macro function supports LVarNm() and allows to remember "user names" in labels.
+
+The motivation for the macro was similar one as for the LDSN() macro.
+
+---
+
+See examples in LVarNm() documentation for the details.
+
+The `%LVarNmLab()` macro executes like a pure macro code.
+
+**Known "Limitations":**
+
+- variable name _cannot_ contain unpaired quotes (`'` and `"`),
+ text: `a "hot-dog"` is ok, but `John's dog` is not!
+
+**Behaviour:**
+
+- variable name text is *converted to upcase*
+
+- variable name text *leading and trailing spaces are ignored*,
+ e.g. the following will give the same hash digest:
+ `%LVarNmLab(test)`, `%LVarNmLab( test)`, `%LVarNmLab(test )`.
+
+### SYNTAX: ###################################################################
+
+The basic syntax is the following, the `<...>` means optional parameters:
+~~~~~~~~~~~~~~~~~~~~~~~sas
+%LVarNmLab(
+ arbitrary text string (in line with limitations)
+)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+---
+
## License ####################################################################
Copyright (c) 2020 Bartosz Jablonski
diff --git a/packages/baseplus.zip b/packages/baseplus.zip
index f8b7385..311f4f8 100644
Binary files a/packages/baseplus.zip and b/packages/baseplus.zip differ