commit e6f06d7b716746456e9692aa356a1d725c72ec71 Author: yabwon Date: Sun Oct 13 10:50:44 2019 +0200 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f4ba4a0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 yabwon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d40a56e --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# SAS_PACKAGES + SAS Packages Repository diff --git a/desktop.ini b/desktop.ini new file mode 100644 index 0000000..c144943 --- /dev/null +++ b/desktop.ini @@ -0,0 +1,6 @@ +[.ShellClassInfo] +IconResource=D:\Instalki\Ikony\SAS.ico,0 +[ViewState] +Mode= +Vid= +FolderType=Generic diff --git a/dfa.zip b/dfa.zip new file mode 100644 index 0000000..77d9889 Binary files /dev/null and b/dfa.zip differ diff --git a/dynmacroarray.zip b/dynmacroarray.zip new file mode 100644 index 0000000..5b1aaa0 Binary files /dev/null and b/dynmacroarray.zip differ diff --git a/generatePackage.sas b/generatePackage.sas new file mode 100644 index 0000000..6bbc002 --- /dev/null +++ b/generatePackage.sas @@ -0,0 +1,944 @@ +/*** HELP START ***/ + +/**############################################################################**/ +/* */ +/* Copyright Bartosz Jablonski, September 2019. */ +/* */ +/* Code is free and open source. If you want - you can use it. */ +/* I tested it the best I could */ +/* but it comes with absolutely no warranty whatsoever. */ +/* If you cause any damage or something - it will be your own fault. */ +/* You've been warned! You are using it on your own risk. */ +/* However, if you decide to use it don't forget to mention author: */ +/* Bartosz Jablonski (yabwon@gmail.com) */ +/* */ +/* Here is the official version: */ +/* + Copyright (c) 2019 Bartosz Jablonski (yabwon@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ +/**#############################################################################**/ + +/* Macros to generte SAS packages */ +/* A SAS package is a zip file containing a group + of SAS codes (macros, functions, datasteps generating + data, etc.) wrapped up together and %INCLUDEed by + a single load.sas file (also embeaded inside the zip). +*/ + +/*** HELP END ***/ + + +/*** HELP START ***/ +%macro GeneratePackge( + filesLocation=%sysfunc(pathname(work))/%lowcase(&packageName.) /* place for packages' files */ +)/secure; +/*** HELP END ***/ +%local zipReferrence filesWithCodes _DESCR_ _LIC_ _RC_; +%let zipReferrence = _%sysfunc(datetime(), hex6.)_; +%let filesWithCodes = WORK._%sysfunc(datetime(), hex16.)_; +%let _DESCR_ = _%sysfunc(datetime(), hex6.)d; +%let _LIC_ = _%sysfunc(datetime(), hex6.)l; + +/* collect package metadata from the description.sas file */ +filename &_DESCR_. "&filesLocation./description.sas" lrecl = 256; +/* file contains licence */ +filename &_LIC_. "&filesLocation./license.sas" lrecl = 256; + +%if %sysfunc(fexist(&_DESCR_.)) %then + %do; + %put NOTE: Creating package%str(%')s metadata; + + %local packageName /* name of the package, required */ + packageVersion /* version of the package, required */ + packageTitle /* title of the package, required*/ + packageAuthor /* required */ + packageMaintainer /* required */ + packageEncoding /* required */ + packageLicense /* required */ + packageRequired /* optional */ + ; + data _null_; + infile &_DESCR_.; + input; + + select; + when(upcase(scan(_INFILE_, 1, ":")) = "PACKAGE") call symputX("packageName", scan(_INFILE_, 2, ":"),"L"); + when(upcase(scan(_INFILE_, 1, ":")) = "VERSION") call symputX("packageVersion", scan(_INFILE_, 2, ":"),"L"); + when(upcase(scan(_INFILE_, 1, ":")) = "AUTHOR") call symputX("packageAuthor", scan(_INFILE_, 2, ":"),"L"); + when(upcase(scan(_INFILE_, 1, ":")) = "MAINTAINER") call symputX("packageMaintainer", scan(_INFILE_, 2, ":"),"L"); + when(upcase(scan(_INFILE_, 1, ":")) = "TITLE") call symputX("packageTitle", scan(_INFILE_, 2, ":"),"L"); + when(upcase(scan(_INFILE_, 1, ":")) = "ENCODING") call symputX("packageEncoding", scan(_INFILE_, 2, ":"),"L"); + when(upcase(scan(_INFILE_, 1, ":")) = "LICENSE") call symputX("packageLicense", scan(_INFILE_, 2, ":"),"L"); + when(upcase(scan(_INFILE_, 1, ":")) = "REQUIRED") call symputX("packageRequired", scan(_INFILE_, 2, ":"),"L"); + + /* stop at the begining of description */ + when(upcase(scan(_INFILE_, 1, ":")) = "DESCRIPTION START") stop; + otherwise; + end; + run; + + /* test for required descriptors */ + %if (%nrbquote(&packageName.) = ) + or (%nrbquote(&packageVersion.) = ) + or (%nrbquote(&packageAuthor.) = ) + or (%nrbquote(&packageMaintainer.) = ) + or (%nrbquote(&packageTitle.) = ) + or (%nrbquote(&packageEncoding.) = ) + or (%nrbquote(&packageLicense.) = ) + %then + %do; + %put ERROR: At least one of descriptors is missing!; + %put ERROR- They are required to create package.; + %put ERROR- &=packageName.; + %put ERROR- &=packageTitle.; + %put ERROR- &=packageVersion.; + %put ERROR- &=packageAuthor.; + %put ERROR- &=packageMaintainer.; + %put ERROR- &=packageEncoding.; + %put ERROR- &=packageLicense.; + %put ERROR- ; + %abort; + %end; + /* test for package name */ + %if %sysfunc(lengthn(&packageName.)) > 24 %then + %do; + %put ERROR: Package name is more than 24 characters long.; + %put ERROR- The name is used for functions%str(%') dataset name; + %put ERROR- and for formats%str(%') catalog name (with sufix).; + %put ERROR- The length is %sysfunc(lengthn(&packageName.)). Try something shorter.; + %abort; + %end; + %else %if %sysfunc(lengthn(&packageName.)) < 3 %then + %do; + %put WARNING: Package name is less than 3 characters.; + %put WARNING- Maybe consider some _meaningful_ name?; + %end; + /* test characters in package name */ + %if %qsysfunc(lengthn(%qsysfunc(compress(&packageName.,,KDF)))) NE %qsysfunc(lengthn(&packageName.)) %then + %do; + %put ERROR: Package name contains illegal symbols.; + %put ERROR- The name is used for functions%str(%') dataset name; + %put ERROR- and for formats%str(%') catalog name.; + %put ERROR- Only English letters, underscore(_), and digits are allowed.; + %put ERROR- Try something else. Maybe: %qsysfunc(compress(&packageName.,,KDF)) will do?; + %abort; + %end; + + %end; +%else + %do; + %put ERROR: The description.sas file is missing!; + %put ERROR- The file is required to create package%str(%')s metadata; + %abort; + %end; + +/* create or replace the ZIP file for package */ +filename &zipReferrence. ZIP "&filesLocation./%lowcase(&packageName.).zip"; + +%if %sysfunc(fexist(&zipReferrence.)) %then + %do; + %put NOTE: Deleting file "&filesLocation./%lowcase(&packageName.).zip"; + %let _RC_ = %sysfunc(fdelete(&zipReferrence.)); + %end; + +/*** HELP START ***/ +/* + Locate all files with code in base folder (i.e. at filesLocation directory) +*/ +/* + Remember to prepare the description.sas file for you package. + The collon (:) is a field separator and is restricted + in lines of the header part. + The file should contain the following obligatory information: +-------------------------------------------------------------------------------------------- +>> **HEADER** << +Type: Package +Package: ShortPackageName +Title: A title/brief info for log note about your packages +Version: X.Y +Author: Firstname1 Lastname1 (xxxxxx1@yyyyy.com), Firstname2 Lastname2 (xxxxxx2@yyyyy.com) +Maintainer: Firstname Lastname (xxxxxx@yyyyy.com) +License: MIT +Encoding: UTF8 + +>> **DESCRIPTION** << +>> All the text below will be used in help << +DESCRIPTION START: + Xxxxxxxxxxx xxxxxxx xxxxxx xxxxxxxx xxxxxxxx. Xxxxxxx + xxxx xxxxxxxxxxxx xx xxxxxxxxxxx xxxxxx. Xxxxxxx xxx + xxxx xxxxxx. Xxxxxxxxxxxxx xxxxxxxxxx xxxxxxx. +DESCRIPTION END: +-------------------------------------------------------------------------------------------- + + Name of the 'type' of folder and files.sas inside must be in _low_ case letters. + + If order of loading is important, the 'sequential number' + can be used to order multiple types in the wey you wish. + + The "tree structure" of the folder could be for example as follows: + +-------------------------------------------------------------------------------------------- + + .. + | + +-000_libname [one file one libname] + | | + | +-abc.sas [a file with a code creating libname ABC] + | + +-001_macro [one file one macro] + | | + | +-hij.sas [a file with a code creating macro HIJ] + | | + | +-klm.sas [a file with a code creating macro KLM] + | + +-002_function [one file one function, + | | option OUTLIB= should be: work.&packageName.fcmp.package + | | option INLIB= should be: work.&packageName.fcmp + | | (both literally with macrovariable name and "fcmp" sufix)] + | | + | +-efg.sas [a file with a code creating function EFG] + | + +-003_format [one file one format, + | | option LIB= should be: work.&packageName.format + | | (literally with macrovariable name and "format" sufix)] + | | + | +-efg.sas [a file with a code creating format EFG and informat EFG] + | + +-004_data [one file one dataset] + | | + | +-abc.efg.sas [a file with a code creating dataset EFG in library ABC] + | + +-005_exec [so called "free code", content of the files will be printed + | | to the log before execution] + | | + | +- + | + +-006_format [if your codes depend eachother you can order them in folders, + | | e.g. code from 003_... will be executed before 006_...] + | | + | +-abc.sas [a file with a code creating format ABC, + | used in the definition of the format EFG] + +-007_function + | | + | +- + | + +-_ + | + +-... + | + +-00n_clean [if you need to clean something up after exec file execution, + | | content of the files will be printed to the log before execution] + | | + | +- + +-... + ... +-------------------------------------------------------------------------------------------- + +*/ +/*** HELP END ***/ + +/* collect the data */ +data &filesWithCodes.; + base = "&filesLocation."; + length folder file lowcase_name $ 256 folderRef fileRef $ 8; + drop lowcase_name; + + folderRef = "_%sysfunc(datetime(), hex6.)0"; + + rc=filename(folderRef, base); + folderid=dopen(folderRef); + + do i=1 to dnum(folderId); drop i; + folder = dread(folderId, i); + if folder NE lowcase(folder) then + do; + put 'ERROR: Folder should be named ONLY with low case letters.'; + put 'ERROR- Current value is: ' folder; + lowcase_name = lowcase(folder); + put 'ERROR- Try: ' lowcase_name; + put; + abort; + end; + order = scan(folder, 1, "_"); + type = scan(folder,-1, "_"); + + fileRef = "_%sysfunc(datetime(), hex6.)1"; + rc = filename(fileRef, catx("/", base, folder)); + fileId = dopen(fileRef); + + file = ' '; + if fileId then + do j = 1 to dnum(fileId); drop j; + file = dread(fileId, j); + if file NE lowcase(file) then + do; + put 'ERROR: File with code should be named ONLY with low case letters.'; + put 'ERROR- Current value is: ' file; + lowcase_name = lowcase(file); + put 'ERROR- Try: ' lowcase_name; + put; + abort; + end; + fileshort = substr(file, 1, length(file) - 4); /* filename.sas -> filename */ + output; + end; + rc = dclose(fileId); + rc = filename(fileRef); + end; + + rc = dclose(folderid); + rc = filename(folderRef); + stop; +run; +proc sort data = &filesWithCodes.; + by order type file; +run; +/* +proc contents data = &filesWithCodes.; +run; +*/ +title1 "Package's location is: &filesLocation."; +title2 "User: &SYSUSERID., datetime: %qsysfunc(datetime(), datetime21.), SAS version: &SYSVLONG4."; +title3 "Package's encoding: '&packageEncoding.', session's encoding: '&SYSENCODING.'."; +title4 " ______________________________ "; +title5 "List of files for package: &packageName. (version &packageVersion.), license: &packageLicense."; +proc print data = &filesWithCodes.(drop=base); +run; +title; + +/* packages's description */ +data _null_; + infile &_DESCR_.; + file &zipReferrence.(description.sas); + input; + put _INFILE_; +run; + +/* package's license */ +%if %sysfunc(fexist(&_LIC_.)) %then + %do; + data _null_; + infile &_LIC_.; + file &zipReferrence.(license.sas); + input; + put _INFILE_; + run; + %end; +%else + %do; + %put WARNING:[License] No license.sas file provided, default (MIT) licence file will be generated.; + %let packageLicense = MIT; + data _null_; + file &zipReferrence.(license.sas); + put " "; + put " Copyright (c) %sysfunc(today(),year4.) &packageAuthor. "; + put " "; + put " Permission is hereby granted, free of charge, to any person obtaining a copy "; + put ' of this software and associated documentation files (the "Software"), to deal '; + put " in the Software without restriction, including without limitation the rights "; + put " to use, copy, modify, merge, publish, distribute, sublicense, and/or sell "; + put " copies of the Software, and to permit persons to whom the Software is "; + put " furnished to do so, subject to the following conditions: "; + put " "; + put " The above copyright notice and this permission notice shall be included "; + put " in all copies or substantial portions of the Software. "; + put " "; + put ' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR '; + put " IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, "; + put " FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE "; + put " AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER "; + put " LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, "; + put " OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE "; + put " SOFTWARE. "; + put " "; + run; + %end; + +/* package's metadata */ +data _null_; + if 0 then set &filesWithCodes. nobs=NOBS; + if NOBS = 0 then + do; + putlog "WARNING:[&sysmacroname.] No files to create package."; + stop; + end; + file &zipReferrence.(packagemetadata.sas); + + put ' data _null_; '; /* simple "%local" returns error while loading package */ + put ' call symputX("packageName", " ", "L");'; + put ' call symputX("packageVersion", " ", "L");'; + put ' call symputX("packageTitle", " ", "L");'; + put ' call symputX("packageAuthor", " ", "L");'; + put ' call symputX("packageMaintainer", " ", "L");'; + put ' call symputX("packageEncoding", " ", "L");'; + put ' call symputX("packageLicense", " ", "L");'; + put ' run; '; + + put ' %let packageName =' "&packageName.;"; + put ' %let packageVersion =' "&packageVersion.;"; + put ' %let packageTitle =' "&packageTitle.;"; + put ' %let packageAuthor =' "&packageAuthor.;"; + put ' %let packageMaintainer =' "&packageMaintainer.;"; + put ' %let packageEncoding =' "&packageEncoding.;"; + put ' %let packageLicense =' "&packageLicense.;"; + put ' ; '; + + stop; +run; + +/* loading package's files */ +data _null_; + if NOBS = 0 then stop; + + file &zipReferrence.(load.sas) lrecl=32767; + + put 'filename package list;' /; + put ' %put NOTE- ;'; + put ' %put NOTE: ' @; put "Loading package &packageName., version &packageVersion., license &packageLicense.; "; + put ' %put NOTE: ' @; put "*** &packageTitle. ***; "; + put ' %put NOTE- ' @; put "Generated: %sysfunc(datetime(), datetime21.); "; + put ' %put NOTE- ' @; put "Author(s): &packageAuthor.; "; + put ' %put NOTE- ' @; put "Maintainer(s): &packageMaintainer.; "; + put ' %put NOTE- ;'; + put ' %put NOTE- Write %nrstr(%%)helpPackage(' "&packageName." ') for the description;'; + put ' %put NOTE- ;'; + put ' %put NOTE- *** START ***; ' /; + + put '%include package(packagemetadata.sas) / nosource2;' /; /* <- copied also to loadPackage macro */ + isFunction = 0; + isFormat = 0; + + %if %bquote(&packageRequired.) ne %then + %do; + put ' data _null_; '; + put ' call symputX("packageRequiredErrors", 0, "L"); '; + put ' run; '; + put ' %put NOTE- *Testing required SAS components*%sysfunc(dosubl( '; + put ' options nonotes nosource %str(;) '; + put ' options ls=max ps=max %str(;) '; + put ' /* temporary redirect log */ '; + put ' filename _stinit_ TEMP %str(;) '; + put ' proc printto log = _stinit_ %str(;) run %str(;) '; + put ' /* print out setinit */ '; + put ' proc setinit %str(;) run %str(;) '; + put ' proc printto %str(;) run %str(;) '; + + put ' data _null_ %str(;) '; + put ' /* loadup checklist of required SAS components */ '; + put ' if _n_ = 1 then '; + put ' do %str(;) '; + put ' length req $ 256 %str(;) '; + put ' declare hash R() %str(;) '; + put ' _N_ = R.defineKey("req") %str(;) '; + put ' _N_ = R.defineDone() %str(;) '; + put ' declare hiter iR("R") %str(;) '; + length packageRequired $ 32767; + packageRequired = upcase(symget('packageRequired')); + put ' do req = %bquote(' / packageRequired / ') %str(;) '; + put ' _N_ = R.add(key:req,data:req) %str(;) '; + put ' end %str(;) '; + put ' end %str(;) '; + put ' '; + put ' /* read in output from proc setinit */ '; + put ' infile _stinit_ end=eof %str(;) '; + put ' input %str(;) '; + /*put ' put "*> " _infile_ %str(;)';*/ /* for testing */ + put ' '; + put ' /* if component is in setinit remove it from checklist */ '; + put ' if _infile_ =: "---" then '; + put ' do %str(;) '; + put ' req = upcase(substr(_infile_, 4, 64)) %str(;) '; + put ' if R.find(key:req) = 0 then '; + put ' do %str(;) '; + put ' _N_ = R.remove() %str(;) '; + put ' end %str(;) '; + put ' end %str(;) '; + put ' '; + put ' /* if checklist is not null rise error */ '; + put ' if eof and R.num_items > 0 then '; + put ' do %str(;) '; + put ' put "ERROR- ###########################################" %str(;) '; + put ' put "ERROR- The following SAS components are missing! " %str(;) '; + put ' call symputX("packageRequiredErrors", 1, "L") %str(;) '; + put ' do while(iR.next() = 0) %str(;) '; + put ' put "ERROR- " req %str(;) '; + put ' end %str(;) '; + put ' put "ERROR- ###########################################" %str(;) '; + put ' put %str(;) '; + put ' end %str(;) '; + put ' run %str(;) '; + put ' filename _stinit_ clear %str(;) '; + put ' options notes source %str(;) '; + put ' ))*; '; + put ' data _null_; '; + put ' if symget("packageRequiredErrors") = "1" then '; + put ' do; '; + put ' put "ERROR: Loading package &packageName. will be aborted!";'; + put ' put "ERROR- Required SAS components are missing."; '; + put ' ABORT; '; + put ' end; '; + put ' run; '; + %end; + + do until(eof); + set &filesWithCodes. end = EOF nobs=NOBS; + if (upcase(type)=:'CLEAN') then continue; /* cleaning files are only included in unload.sas */ + put '%put NOTE- ;'; + put '%put NOTE- Element of type ' type 'from the file "' file +(-1) '" will be included;' /; + + if upcase(type)=:'EXEC' then + do; + put '%put NOTE- ;'; + put '%put NOTE- Executing the following code: ;'; + put '%put NOTE- *****************************;'; + put 'data _null_;'; + put ' infile package(_' folder +(-1) "." file +(-1) ') lrecl=32767;'; + put ' input;'; + put ' putlog "*> " _infile_;'; + put 'run;' /; + put '%put NOTE- *****************************;'; + put '%put NOTE- ;'; + end; + + put '%include package(_' folder +(-1) "." file +(-1) ') / nosource2;' /; + + isFunction + (upcase(type)=:'FUNCTION'); + isFormat + (upcase(type)=:'FORMAT'); + + /* add the link to the functions' dataset, only for the first occurence */ + if 1 = isFunction and (upcase(type)=:'FUNCTION') then + do; + put "options APPEND=(cmplib = work.%lowcase(&packageName.fcmp));"; + put '%put NOTE- ;'; + put '%put NOTE:[CMPLIB] %sysfunc(getoption(cmplib));' /; + end; + + /* add the link to the formats' catalog, only for the first occurence */ + if 1 = isFormat and (upcase(type)=:'FORMAT') then + do; + put "options INSERT=( fmtsearch = work.%lowcase(&packageName.format) );"; + put '%put NOTE- ;'; + put '%put NOTE:[FMTSEARCH] %sysfunc(getoption(fmtsearch));'/; + end; + end; + + put '%put NOTE- ;'; + put '%put NOTE: '"Loading package &packageName., version &packageVersion., license &packageLicense.;"; + put '%put NOTE- *** END ***;' /; + put "/* load.sas end */" /; + stop; +run; + +/* unloading package's objects */ +data _null_; + /* break if no data */ + if NOBS = 0 then stop; + + file &zipReferrence.(unload.sas); + + put 'filename package list;' /; + put '%put NOTE: '"Unloading package &packageName., version &packageVersion., license &packageLicense.;"; + put '%put NOTE- *** START ***;' /; + + /* include "cleaning" files */ + EOF = 0; + do until(EOF); + set &filesWithCodes. end = EOF nobs = NOBS; + if not (upcase(type)=:'CLEAN') then continue; + put '%put NOTE- Code of type ' type 'generated from the file "' file +(-1) '" will be executed;'; + put '%put NOTE- ;' /; + put '%put NOTE- Executing the following code: ;'; + put '%put NOTE- *****************************;'; + put 'data _null_;'; + put ' infile package(_' folder +(-1) "." file +(-1) ') lrecl=32767;'; + put ' input;'; + put ' putlog "*> " _infile_;'; + put 'run;' /; + put '%put NOTE- *****************************;'; + put '%put NOTE- ;' /; + + put '%include package(_' folder +(-1) "." file +(-1) ') / nosource2;' /; + end; + + /* delete macros and formats */ + put 'proc sql;'; + put ' create table _%sysfunc(datetime(), hex16.)_ as'; + put ' select memname, objname, objtype'; + put ' from dictionary.catalogs'; + put ' where '; + put ' ('; + put ' objname in ("*"' /; + /* list of macros */ + EOF = 0; + do until(EOF); + set &filesWithCodes. end = EOF nobs = NOBS; + if not (upcase(type)=:'MACRO') then continue; + put '%put NOTE- Element of type ' type 'generated from the file "' file +(-1) '" will be deleted;'; + put '%put NOTE- ;' /; + put ',"' fileshort upcase32. '"'; + end; + /**/ + put ' )'; + put ' and objtype = "MACRO"'; + put ' and libname = "WORK"'; + put ' )'; + put ' or'; + put ' ('; + put ' objname in ("*"' /; + /* list of formats */ + isFormat = 0; + EOF = 0; + do until(EOF); + set &filesWithCodes. end = EOF; + if not (upcase(type)=:'FORMAT') then continue; + put '%put NOTE- Element of type ' type 'generated from the file "' file +(-1) '" will be deleted;'; + put '%put NOTE- ;' /; + put ',"' fileshort upcase32. '"'; + isFormat + 1; + end; + put ' )'; + put ' and objtype in ("FORMAT" "FORMATC" "INFMT" "INFMTC")'; + put ' and libname = "WORK"'; + put " and memname = '%upcase(&packageName.format)'"; + put ' )'; + + put ' order by objtype, memname, objname'; + put ' ;'; + put 'quit;'; + + put 'data _null_;'; + put ' do until(last.memname);'; + put ' set _last_;'; + put ' by objtype memname;'; + put ' if first.memname then call execute("proc catalog cat = work." !! strip(memname) !! " force;");'; + put ' call execute("delete " !! strip(objname) !! " / et =" !! objtype !! "; run;");'; + put ' end;'; + put ' call execute("quit;");'; + put 'run;'; + put 'proc delete data = _last_;'; + put 'run;'; + + /* delete the link to the formats catalog */ + if isFormat then + do; + put "proc delete data = work.%lowcase(&packageName.format)(mtype = catalog);"; + put 'run;'; + put 'options fmtsearch = (%unquote(%sysfunc(tranwrd(' / + '%lowcase(%sysfunc(getoption(fmtsearch)))' / + ',%str(' "work.%lowcase(&packageName.)format" '), %str() ))));'; + put 'options fmtsearch = (%unquote(%sysfunc(compress(' / + '%sysfunc(getoption(fmtsearch))' / + ', %str(()) ))));'; + put '%put NOTE:[FMTSEARCH] %sysfunc(getoption(fmtsearch));' /; + end; + + /* delete functions */ + put "proc fcmp outlib = work.%lowcase(&packageName.fcmp).package;"; + isFunction = 0; + EOF = 0; + do until(EOF); + set &filesWithCodes. end = EOF; + if not (upcase(type)=:'FUNCTION') then continue; + put '%put NOTE- Element of type ' type 'generated from the file "' file +(-1) '" will be deleted;'; + put '%put NOTE- ;' /; + put 'deletefunc ' fileshort ';'; + isFunction + 1; + end; + put "run;" /; + + /* delete the link to the functions dataset */ + if isFunction then + do; + put 'options cmplib = (%unquote(%sysfunc(tranwrd(' / + '%lowcase(%sysfunc(getoption(cmplib)))' / + ',%str(' "work.%lowcase(&packageName.fcmp)" '), %str() ))));'; + put 'options cmplib = (%unquote(%sysfunc(compress(' / + '%sysfunc(getoption(cmplib))' / + ',%str(()) ))));'; + put '%put; %put NOTE:[CMPLIB] %sysfunc(getoption(cmplib));' /; + end; + + /* delete datasets */ + put "proc sql noprint;"; + EOF = 0; + do until(EOF); + set &filesWithCodes. end = EOF; + if not (upcase(type)=:'DATA') then continue; + put '%put NOTE- Element of type ' type 'generated from the file "' file +(-1) '" will be deleted;'; + put '%put NOTE- ;' /; + put 'drop table ' fileshort ';'; + end; + put "quit;" /; + + /* delete libraries */ + EOF = 0; + do until(EOF); + set &filesWithCodes. end = EOF; + if not (upcase(type)=:'LIBNAME') then continue; + put '%put NOTE- Element of type ' type 'generated from the file "' file +(-1) '" will be cleared;'; + put '%put NOTE- ;' /; + put 'libname ' fileshort ' clear;'; + end; + put "run;" /; + + put '%put NOTE: '"Unloading package &packageName., version &packageVersion., license &packageLicense.;"; + put '%put NOTE- *** END ***;'; + put '%put NOTE- ;'; + + put "/* unload.sas end */"; + stop; +run; + +/* package's help */ +data _null_; + /* break if no data */ + if NOBS = 0 then stop; + + file &zipReferrence.(help.sas); + length strX $ 32767; + + put 'filename package list;' /; + put ' %put NOTE- ;'; + put ' %put NOTE: '"Help for package &packageName., version &packageVersion., license &packageLicense.;"; + put ' %put NOTE: ' @; put "*** &packageTitle. ***; "; + put ' %put NOTE- ' @; put "Generated: %sysfunc(datetime(), datetime21.); "; + put ' %put NOTE- ' @; put "Author(s): &packageAuthor.; "; + put ' %put NOTE- ' @; put "Maintainer(s): &packageMaintainer.; "; + put ' %put NOTE- ;'; + put ' %put NOTE- *** START ***;' /; + + /* Use helpKeyword macrovariable to search for content (filename and type) */ + /* put '%local ls_tmp ps_tmp notes_tmp source_tmp; ';*/ + put '%let ls_tmp = %sysfunc(getoption(ls)); '; + put '%let ps_tmp = %sysfunc(getoption(ps)); '; + put '%let notes_tmp = %sysfunc(getoption(notes)); '; + put '%let source_tmp = %sysfunc(getoption(source)); '; + put 'options ls = MAX ps = MAX nonotes nosource; '; + put '%include package(packagemetadata.sas) / nosource2; ' /; + + put 'data _null_; '; + put ' if strip(symget("helpKeyword")) = " " then '; + put ' do until (EOF); '; + put ' infile package(description.sas) end = EOF; '; + put ' input; '; + put ' if upcase(strip(_infile_)) = "DESCRIPTION END:" then printer = 0; '; + put ' if printer then put "*> " _infile_; '; + put ' if upcase(strip(_infile_)) = "DESCRIPTION START:" then printer = 1; '; + put ' end; '; + put ' else stop; '; + put 'run; ' /; + + /* license info */ + put 'data _null_; '; + put ' if upcase(strip(symget("helpKeyword"))) = "LICENSE" then '; + put ' do until (EOF); '; + put ' infile package(license.sas) end = EOF; '; + put ' input; '; + put ' put "*> " _infile_; '; + put ' end; '; + put ' else stop; '; + put 'run; ' /; + + put 'data _%sysfunc(datetime(), hex16.)_; '; + put 'infile cards4 dlm = "/"; '; + put 'input @; '; + put 'if 0 then output; '; + put 'length helpKeyword $ 64; '; + put 'retain helpKeyword "*"; '; + put 'drop helpKeyword; '; + put 'if _N_ = 1 then helpKeyword = strip(symget("helpKeyword")); '; + put 'if FIND(_INFILE_, helpKeyword, "it") or helpKeyword = "*" then '; + put ' do; '; + put ' input (folder order type file fileshort) (: $ 256.); '; + put ' output; '; + put ' end; '; + put 'cards4; '; + + EOFDS = 0; + do until(EOFDS); + /* content is created during package creation */ + set &filesWithCodes. end = EOFDS nobs = NOBS; + select; + when (upcase(type) = "DATA") fileshort2 = fileshort; + when (upcase(type) = "MACRO") fileshort2 = cats('%',fileshort,'()'); + when (upcase(type) = "FUNCTION") fileshort2 = cats(fileshort,'()'); + when (upcase(type) = "FORMAT") fileshort2 = cats('$',fileshort); + otherwise fileshort2 = fileshort; + end; + strX = catx('/', folder, order, type, file, fileshort, fileshort2); + put strX; + end; + + put ";;;;"; + put "run;" /; +/* + put 'proc print;'; + put 'run;'; +*/ + /* loop through content found and print info to the log */ + put 'data _null_; '; + put 'if upcase(strip(symget("helpKeyword"))) in (" " "LICENSE") then do; stop; end; '; + put 'if NOBS = 0 then do; ' / + 'put; put '' *> No help info found. Try %helpPackage(packageName,*) to display all.''; put; stop; ' / + 'end; '; + put ' do until(EOFDS); '; + put ' set _last_ end = EOFDS nobs = NOBS; '; + put ' length memberX $ 1024; '; + put ' memberX = cats("_",folder,".",file); '; + /* inner datastep in call execute to read each embedaded file */ + put ' call execute("data _null_; ");'; + put ' call execute("infile package(" || strip(memberX) || ") end = EOF; ");'; + put ' call execute(" printer = 0; ");'; + put ' call execute(" do until(EOF); ");'; + put ' call execute(" input; ");'; + put ' call execute(" if strip(_infile_) = cat(""/"",""*** "",""HELP END"","" ***"",""/"") then printer = 0; ");'; /* it looks like that because of comments */ + put ' call execute(" if printer then put ""*> "" _infile_; ");'; + put ' call execute(" if strip(_infile_) = cat(""/"",""*** "",""HELP START"","" ***"",""/"") then printer = 1; ");'; /* it looks like that because of comments */ + put ' call execute(" end; ");'; + put ' call execute(" put ""*> "" / ""*> ""; ");'; + put ' call execute(" stop; ");'; + put ' call execute("run; ");'; + put ' if lowcase(type) =: "data" then '; + put ' do; '; + put ' call execute("title ""Dataset " || strip(fileshort) || " from package &packageName. ""; ");'; + put ' call execute("proc contents data = " || strip(fileshort) || "; run; title; ");'; + put ' end; '; + /**/ + put " end; "; + put " stop; "; + put "run; "; + + /* cleanup */ + put "proc delete data = _last_; "; + put "run; "; + put 'options ls = &ls_tmp. ps = &ps_tmp. ¬es_tmp. &source_tmp.; ' /; + + put '%put NOTE: '"Help for package &packageName., version &packageVersion., license &packageLicense.;"; + put '%put NOTE- *** END ***;' /; + put "/* help.sas end */"; + + stop; +run; + +/* create package's content */ +data _null_; + /* break if no data */ + if NOBS = 0 then stop; + + set &filesWithCodes. nobs = NOBS; + + call execute(cat ('filename _IN_ "', catx('/', base, folder, file), '";')); + call execute(cats("filename _OUT_ ZIP '", base, "/%lowcase(&packageName.).zip' member='_", folder, ".", file, "';") ); + call execute('data _null_;'); + call execute(' rc = fcopy("_IN_", "_OUT_");'); + call execute('run;'); + call execute('filename _IN_ clear;'); + call execute('filename _OUT_ clear;'); +run; + +proc sql; + drop table &filesWithCodes.; +quit; +filename &zipReferrence. clear; +%mend GeneratePackge; + + +/* + +options mprint; +ods html; +%GeneratePackge( + testowyPackageName +,0.01 +,author +,contact +,filesLocation=E:\SAS_WORK_5400\testyGeneratePackage +) + +*/ + +/* +TODO: +- modyfikacja helpa, sprawdzanie kodu danje funkcji/makra/typu [v] + +- opcjonalne sortowanie nazw folderow(_) [v] + +- wewnętrzna nazwaz zmiennej z nazwa pakietu (na potrzeby kompilacji) [v] + +- weryfikacja srodaowiska + +- weryfikacja "niepustosci" obowiazkowych argumentow [v] + +- dodac typ "clear" do czyszczenia po plikach 'exec' [v] + +- doadc sprawdzanie liczby wywołan procedury fcmp, format i slowa '%macro(' w plikach z kodami + +- syspackages - makrozmienna z lista zaladowanych pakietow + +- dodac typ "imp", "ds2", "proto" + +-lista wymaganych komponentow potrzebnych do działania SASa (na bazie proc SETINIT) +*/ + +/* + +%include "C:\SAS_PACKAGES\generatePackage.sas"; + +ods html; +%generatePackge(filesLocation=C:\SAS_PACKAGES\SQLinDS) +*/ + +/* +*"C:\SAS_PACKAGES\testyGeneratoraPakietow"; + +libname packages "E:\SAS_WORK_5400\testyGeneratePackage"; +filename packages "E:\SAS_WORK_5400\testyGeneratePackage"; + +%include packages(loadpackage.sas); + +dm 'log;clear'; +%loadpackage(testowypackagename) + + +*/ +/* + +%let helpKeyword=*; +%helpPackage(testowypackagename) +%unloadPackage(testowypackagename) + + +filename package ZIP "E:\SAS_WORK_5400\testyGeneratePackage\testowypackagename.zip"; + +%put %sysfunc(pathname(package)); + +%include package(load.sas); +%help()??? +%include package(unload.sas); + +filename package ZIP "C:\SAS_PACKAGES\testowypackagename.zip"; +%include package(load.sas); +%include package(unload.sas); + +filename package ZIP "C:\SAS_PACKAGES\macroarray.zip"; +%include package(load.sas); +%include package(unload.sas); +*/ diff --git a/license.sas b/license.sas new file mode 100644 index 0000000..62c5ba6 --- /dev/null +++ b/license.sas @@ -0,0 +1,19 @@ +Copyright (c) 2019 Bartosz Jablonski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/listpackages.sas b/listpackages.sas new file mode 100644 index 0000000..75ab797 --- /dev/null +++ b/listpackages.sas @@ -0,0 +1,128 @@ +/*** HELP START ***/ + +/**############################################################################**/ +/* */ +/* Copyright Bartosz Jablonski, Jully 2019. */ +/* */ +/* Code is free and open source. If you want - you can use it. */ +/* I tested it the best I could */ +/* but it comes with absolutely no warranty whatsoever. */ +/* If you cause any damage or something - it will be your own fault. */ +/* You've been warned! You are using it on your own risk. */ +/* However, if you decide to use it don't forget to mention author: */ +/* Bartosz Jablonski (yabwon@gmail.com) */ +/* */ +/* Here is the official version: */ +/* + Copyright (c) 2019 Bartosz Jablonski (yabwon@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ +/**#############################################################################**/ + +/* Macros to list SAS packages in packsges' folder */ +/* A SAS package is a zip file containing a group + of SAS codes (macros, functions, datasteps generating + data, etc.) wrapped up together and %INCLUDEed by + a single load.sas file (also embeaded inside the zip). +*/ +/* + * Example 1: + + filename packages "C:\SAS_PACKAGES"; + %listPackages() + +*/ +/*** HELP END ***/ + + +%macro listPackages(); + +%local ls_tmp ps_tmp notes_tmp source_tmp; +%let filesWithCodes = WORK._%sysfunc(datetime(), hex16.)_; + +%local ls_tmp ps_tmp notes_tmp source_tmp; +%let ls_tmp = %sysfunc(getoption(ls)); +%let ps_tmp = %sysfunc(getoption(ps)); +%let notes_tmp = %sysfunc(getoption(notes)); +%let source_tmp = %sysfunc(getoption(source)); +options NOnotes NOsource ls=MAX ps=MAX; + +data _null_; + base = "%sysfunc(pathname(packages))"; + + if base = " " then + do; + put "NOTE: The filereference PACKAGES is not assigned."; + stop; + end; + + length folder file $ 256 folderRef fileRef $ 8; + + folderRef = "_%sysfunc(datetime(), hex6.)0"; + + rc=filename(folderRef, base); + folderid=dopen(folderRef); + + put; + put "/*" 100*"+" ; + do i=1 to dnum(folderId); drop i; + folder = dread(folderId, i); + + fileRef = "_%sysfunc(datetime(), hex6.)1"; + rc = filename(fileRef, catx("/", base, folder)); + fileId = dopen(fileRef); + + EOF = 0; + if fileId = 0 and lowcase(scan(folder, -1, ".")) = 'zip' then + do; + file = catx('/',base, folder); + length nn $ 96; + nn = repeat("*", (96-lengthn(file))); + + putlog " "; + put " * " file @; put nn /; + + infile package ZIP FILEVAR=file member="description.sas" end=EOF; + + do until(EOF); + input; + if lowcase(scan(_INFILE_,1,":")) in ("package" "title" "version" "author" "maintainer" "license") then + do; + _INFILE_ = scan(_INFILE_,1,":") !! ":" !! scan(_INFILE_,2,":"); + putlog " * " _INFILE_; + end; + if strip(_INFILE_) = "DESCRIPTION START:" then leave; + end; + end; + + rc = dclose(fileId); + rc = filename(fileRef); + end; + + putlog " "; + put 100*"+" "*/"; + rc = dclose(folderid); + rc = filename(folderRef); + stop; +run; + +options ls = &ls_tmp. ps = &ps_tmp. ¬es_tmp. &source_tmp.; +%mend listPackages; + diff --git a/loadpackage.sas b/loadpackage.sas new file mode 100644 index 0000000..ee5b1e9 --- /dev/null +++ b/loadpackage.sas @@ -0,0 +1,199 @@ +/*** HELP START ***/ + +/**############################################################################**/ +/* */ +/* Copyright Bartosz Jablonski, Jully 2019. */ +/* */ +/* Code is free and open source. If you want - you can use it. */ +/* I tested it the best I could */ +/* but it comes with absolutely no warranty whatsoever. */ +/* If you cause any damage or something - it will be your own fault. */ +/* You've been warned! You are using it on your own risk. */ +/* However, if you decide to use it don't forget to mention author: */ +/* Bartosz Jablonski (yabwon@gmail.com) */ +/* */ +/* Here is the official version: */ +/* + Copyright (c) 2019 Bartosz Jablonski (yabwon@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ +/**#############################################################################**/ + +/* Macros to load or to unload SAS packages */ +/* A SAS package is a zip file containing a group + of SAS codes (macros, functions, datasteps generating + data, etc.) wrapped up together and %INCLUDEed by + a single load.sas file (also embeaded inside the zip). +*/ +/* +TODO: +- makro for testing avaliable packages in the packages' folder [DONE] checkuot: %listPackages() +*/ +/*** HELP END ***/ + +/*** HELP START ***/ + +%macro loadPackage( + packageName /* name of a package, e.g. myPackageFile.zip, not null */ +, path = %sysfunc(pathname(packages)) /* location of a package, by default it looks for location of "packages" library */ +, options = %str(LOWCASE_MEMNAME) /* possible options for ZIP filename */ +, source2 = /*source2*/ /* option to print out details, null by default */ +)/secure; +/*** HELP END ***/ + %local ls_tmp ps_tmp notes_tmp source_tmp; + %let ls_tmp = %sysfunc(getoption(ls)); + %let ps_tmp = %sysfunc(getoption(ps)); + %let notes_tmp = %sysfunc(getoption(notes)); + %let source_tmp = %sysfunc(getoption(source)); + options NOnotes NOsource ls=MAX ps=MAX; + + filename package ZIP + /* put location of package myPackageFile.zip here */ + "&path./%lowcase(&packageName.).zip" %unquote(&options.) + ; + %if %sysfunc(fexist(package)) %then + %do; + %include package(packagemetadata.sas) / &source2.; + filename package clear; + options ls = &ls_tmp. ps = &ps_tmp. ¬es_tmp. &source_tmp.; + filename package ZIP + "&path./%lowcase(&packageName.).zip" %unquote(&options.) + ENCODING = + %if %bquote(&packageEncoding.) NE %then &packageEncoding. ; + %else utf8 ; + ; + %include package(load.sas) / &source2.; + %end; + %else %put ERROR:[&sysmacroname] File "&path./&packageName..zip" does not exist; + filename package clear; + options ls = &ls_tmp. ps = &ps_tmp. ¬es_tmp. &source_tmp.; +%mend loadPackage; + +/*** HELP START ***/ + +%macro unloadPackage( + packageName /* name of a package, e.g. myPackageFile.zip, not null */ +, path = %sysfunc(pathname(packages)) /* location of a package, by default it looks for location of "packages" library */ +, options = %str(LOWCASE_MEMNAME) /* possible options for ZIP filename */ +, source2 = /*source2*/ /* option to print out details, null by default */ +)/secure; +/*** HELP END ***/ + %local ls_tmp ps_tmp notes_tmp source_tmp; + %let ls_tmp = %sysfunc(getoption(ls)); + %let ps_tmp = %sysfunc(getoption(ps)); + %let notes_tmp = %sysfunc(getoption(notes)); + %let source_tmp = %sysfunc(getoption(source)); + options NOnotes NOsource ls=MAX ps=MAX; + + filename package ZIP + /* put location of package myPackageFile.zip here */ + "&path./%lowcase(&packageName.).zip" %unquote(&options.) + ; + %if %sysfunc(fexist(package)) %then + %do; + %include package(packagemetadata.sas) / &source2.; + filename package clear; + options ls = &ls_tmp. ps = &ps_tmp. ¬es_tmp. &source_tmp.; + filename package ZIP + "&path./%lowcase(&packageName.).zip" %unquote(&options.) + ENCODING = + %if %bquote(&packageEncoding.) NE %then &packageEncoding. ; + %else utf8 ; + ; + %include package(unload.sas) / &source2.; + %end; + %else %put ERROR:[&sysmacroname] File "&path./&packageName..zip" does not exist; + filename package clear; + options ls = &ls_tmp. ps = &ps_tmp. ¬es_tmp. &source_tmp.; +%mend unloadPackage; + +/*** HELP START ***/ + +%macro helpPackage( + packageName /* name of a package, e.g. myPackageFile.zip, not null */ +, helpKeyword /* phrase to search, * means print all help */ +, path = %sysfunc(pathname(packages)) /* location of a package, by default it looks for location of "packages" library */ +, options = %str(LOWCASE_MEMNAME) /* possible options for ZIP filename */ +, source2 = /*source2*/ /* option to print out details, null by default */ +)/secure; +/*** HELP END ***/ + %local ls_tmp ps_tmp notes_tmp source_tmp; + %let ls_tmp = %sysfunc(getoption(ls)); + %let ps_tmp = %sysfunc(getoption(ps)); + %let notes_tmp = %sysfunc(getoption(notes)); + %let source_tmp = %sysfunc(getoption(source)); + options NOnotes NOsource ls=MAX ps=MAX; + + filename package ZIP + /* put location of package myPackageFile.zip here */ + "&path./%lowcase(&packageName.).zip" %unquote(&options.) + ; + %if %sysfunc(fexist(package)) %then + %do; + %include package(packagemetadata.sas) / &source2.; + filename package clear; + options ls = &ls_tmp. ps = &ps_tmp. ¬es_tmp. &source_tmp.; + filename package ZIP + "&path./%lowcase(&packageName.).zip" %unquote(&options.) + ENCODING = + %if %bquote(&packageEncoding.) NE %then &packageEncoding. ; + %else utf8 ; + ; + %include package(help.sas) / &source2.; + %end; + %else %put ERROR:[&sysmacroname] File "&path./&packageName..zip" does not exist; + filename package clear; + options ls = &ls_tmp. ps = &ps_tmp. ¬es_tmp. &source_tmp.; +%mend helpPackage; + + +/*** HELP START ***/ + +/* + * Filenames references "packages" and "package" are keywords; + * the first one should be used to point folder with packages; + * the second is used internaly by macros; + + * Example 1: + * assuming that _THIS_FILE_ and the SQLinDS package (sqlinds.zip file) + * are located in the "C:/SAS_PACKAGES/" folder + * coppy the following code into autoexec.sas + * or run it in your SAS session +**/ +/* + +filename packages "C:/SAS_PACKAGES"; +%include packages(loadpackage.sas); + +%loadpackage(SQLinDS) +%helpPackage(SQLinDS) +%unloadPackage(SQLinDS) + +optional: + +libname packages "C:/SAS_PACKAGES/"; +%include "%sysfunc(pathname(packages))/loadpackage.sas"; + +%loadPackage(SQLinDS) +%helpPackage(SQLinDS) +%unloadPackage(SQLinDS) + +*/ +/*** HELP END ***/ diff --git a/macroarray.zip b/macroarray.zip new file mode 100644 index 0000000..0a42d9f Binary files /dev/null and b/macroarray.zip differ diff --git a/sqlinds.zip b/sqlinds.zip new file mode 100644 index 0000000..10e113e Binary files /dev/null and b/sqlinds.zip differ