summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/statrep/sas
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/statrep/sas
Initial commit
Diffstat (limited to 'macros/latex/contrib/statrep/sas')
-rw-r--r--macros/latex/contrib/statrep/sas/statrep_macros.sas1523
-rw-r--r--macros/latex/contrib/statrep/sas/statrep_tagset.sas566
2 files changed, 2089 insertions, 0 deletions
diff --git a/macros/latex/contrib/statrep/sas/statrep_macros.sas b/macros/latex/contrib/statrep/sas/statrep_macros.sas
new file mode 100644
index 0000000000..3681c4b653
--- /dev/null
+++ b/macros/latex/contrib/statrep/sas/statrep_macros.sas
@@ -0,0 +1,1523 @@
+ /*---------------------------------------------*/
+ /* The WRITE macro displays one or more pieces */
+ /* of output (tables, notes, graphs, and so */
+ /* on) that were captured into an ODS document */
+ /* by the OUTPUT macro. */
+ /*---------------------------------------------*/
+%macro write(fname, /* is a required keyword that specifies the */
+ /* first level of the output file name. This */
+ /* name will appear at the end of the \Listing */
+ /* or \Graphic tag in the LaTeX file. The */
+ /* following examples show where the fname */
+ /* keyword, in this case 'crsi1a', is */
+ /* specified in the WRITE macro and in the */
+ /* \Listing tag: */
+ /* */
+ /* %*;%write(crsi1a, objects=inertias) */
+ /* \Listing[caption={... caption ...}]{crsi1a} */
+ /* */
+ dest=, /* specifies destination: latex or listing. */
+ /* Null uses the defaultdests macro. */
+ /* */
+ width=, /* specifies the width of graphs. */
+ /* Example: WIDTH=5.4in. */
+ height=, /* specifies the height of graphs. */
+ /* Example: HEIGHT=4in. */
+ /* */
+ dpi=, /* specifies DPI (dots per inch) for ODS */
+ /* Graphics. You typically would not use this */
+ /* option except when you would otherwise run */
+ /* out of memory. The default is 300 DPI, and */
+ /* a reasonable alternative for ODS graphs */
+ /* with large file sizes is 100 DPI. More */
+ /* details follow. */
+ /* */
+ /* This option controls the DPI for ODS */
+ /* Graphics. Use the DPI= option in the */
+ /* OUTPUT macro to control the DPI for GRSEG */
+ /* graphics. */
+ /* */
+ /* If DPI= is specified, that DPI is used. */
+ /* If DPI= is not specified, and if a macro */
+ /* variable DefaultDPI is defined, its value */
+ /* is used as the DPI. If DPI= is not */
+ /* specified and the macro variable DefaultDPI */
+ /* is not defined or if its value is null, */
+ /* then the default DPI, 300, is used. */
+ /* */
+ /* In other words, the default DPI is 300. */
+ /* However, you can set the default DPI to */
+ /* (say) 100 by putting the following at the */
+ /* top of your first Sascode block, beginning */
+ /* in column 1: */
+ /* */
+ /* %*;%let defaultdpi=100; */
+ /* */
+ /* Since the %LET statement is preceded by a */
+ /* null macro comment (%*;) beginning in */
+ /* column 1, it will not show up in the */
+ /* SAS code listing, but it will affect the */
+ /* capture program and change the default */
+ /* DPI for the duration of the running of the */
+ /* program. You can change the default DPI at */
+ /* any time with a %LET statement. */
+ /* */
+ /* With GRSEG graphics, 100 DPI is not */
+ /* available, so this specification creates */
+ /* graphs at 96 DPI. */
+ /* */
+ store=, /* specifies the name of the ODS document */
+ /* that is created by the OUTPUT macro. This */
+ /* is the ODS document that the WRITE macro */
+ /* will process. By default, when null, the */
+ /* current document from the last OUTPUT macro */
+ /* is used. If you are processing the last */
+ /* document created, you can omit specifying */
+ /* the STORE= option. To use some other */
+ /* document, specify STORE=documentlabel. */
+ /* */
+ pattern=, /* provides an optional additional selection */
+ /* criterion. Specify part of a path, for */
+ /* example, a group name. Then only objects */
+ /* whose name includes this group name are */
+ /* used. Comparisons are not case sensitive. */
+ /* The macro looks for an appearance of the */
+ /* PATTERN=value anywhere in the path. For */
+ /* example, PATTERN=fit, will match */
+ /* "Reg.m2.Fit.Population.ParameterEstimates" */
+ /* and anything else with "fit" in it */
+ /* including paths that contain "fitplot", */
+ /* "fitness", "outfit" and so on. */
+ /*---------------------------------------------*/
+ firstobj=, /* specifies the first data object. */
+ lastobj=, /* specifies the last data object. */
+ objects=, /* specifies the list of data objects. */
+ /* */
+ /* To specify which objects go into a section */
+ /* of output, specify one of the following */
+ /* combinations: */
+ /* * FIRSTOBJ=, */
+ /* * LASTOBJ=, */
+ /* * FIRSTOBJ= and LASTOBJ=, */
+ /* * OBJECTS=, */
+ /* * none of the above. */
+ /* */
+ /* If FIRSTOBJ= is specified and LASTOBJ= is */
+ /* not specified, then the last object is the */
+ /* last object produced by the procedure. If */
+ /* LASTOBJ= is specified and FIRSTOBJ= is not */
+ /* specified, then the default first object is */
+ /* the first object produced by the procedure. */
+ /* If OBJECTS= is specified, then only objects */
+ /* in that list are used. If none of these */
+ /* options is specified then, all objects are */
+ /* used. */
+ /* */
+ /* The term "object" used in this */
+ /* discussion refers to notes, tables, and */
+ /* graphs. Specify the first or last object */
+ /* or list of objects (tables, notes, graphs). */
+ /* All object name comparisons are case */
+ /* insensitive. */
+ /* */
+ /* All selections are based on paths instead */
+ /* of label paths. You can specify the last m */
+ /* levels of the path. Assuming that you have */
+ /* one model and one ANOVA table, any of the */
+ /* following specifications for the ANOVA */
+ /* object are equivalent, along with many */
+ /* other possibilities: */
+ /* */
+ /* Reg.MODEL1.Fit.Population.ANOVA */
+ /* reg.model1.fit.population.anova */
+ /* reg#1.model1#1.fit#1.population#1.anova#1 */
+ /* reg#1.model1.fit.population#1.anova#1 */
+ /* MODEL1.Fit.Population.ANOVA */
+ /* Fit.Population.ANOVA */
+ /* Population.ANOVA */
+ /* ANOVA */
+ /* ANOVA#1 */
+ /* */
+ /* Typically, you need to specify only the */
+ /* last level. If an object appears more than */
+ /* once, then you might need to specify more */
+ /* levels. The #n notation is allowed, even */
+ /* in cases where it does not work in an ODS */
+ /* SELECT statement. You must specify a name, */
+ /* using the #n notation that matches the name */
+ /* (or the last few levels of the name) as it */
+ /* appears in the ODS document. For example, */
+ /* if there are multiple residual panels, you */
+ /* can specify OBJECTS=residualplot and */
+ /* OBJECTS=residualplot#2. The object list */
+ /* produced by the macro will show every place */
+ /* that a #2 or #n (n > 1) is required. */
+ /* */
+ /* If you run a procedure more than once for */
+ /* this ODS document, then you need #2 on the */
+ /* procedure name for the second group. For */
+ /* example, here are the fully-qualified names */
+ /* from a set of two PROC REG runs: */
+ /* */
+ /* Reg.MODEL1.Fit.Fail.NObs */
+ /* Reg.MODEL1.Fit.Fail.ANOVA */
+ /* Reg.MODEL1.Fit.Fail.FitStatistics */
+ /* Reg.MODEL1.Fit.Fail.ParameterEstimates */
+ /* Reg#2.MODEL1.Fit.Fail.NObs */
+ /* Reg#2.MODEL1.Fit.Fail.ANOVA */
+ /* Reg#2.MODEL1.Fit.Fail.FitStatistics */
+ /* Reg#2.MODEL1.Fit.Fail.ParameterEstimates */
+ /* */
+ /* The order in which objects come out is */
+ /* determined by the order in which they are */
+ /* generated, not the order in which they are */
+ /* specified in the OBJECTS= option. */
+ /* */
+ /* If you specify OBJECTS=, then you can also */
+ /* specify where page breaks can occur. By */
+ /* default, breaks might occur between the */
+ /* bottom of a table and the top of the note */
+ /* or table that comes after it. If you want */
+ /* anything different to occur, use left and */
+ /* right angled brackets, <>, to start and end */
+ /* a new group and suppress normal page */
+ /* breaking in between. After a <, no default */
+ /* page breaking occurs until a > is hit. A */
+ /* page break occurs at the > and then in the */
+ /* default places after that. You can use */
+ /* "< list >" in pairs (for example, "<ANOVA */
+ /* FitStatistics>" to keep certain objects */
+ /* together. You can instead use > to cause */
+ /* page breaks in addition to the default page */
+ /* breaks. You can also use < to designate */
+ /* page breaks and suppress all default page */
+ /* breaking. A break always occurs before and */
+ /* after a graph regardless of what <> */
+ /* specification you use. */
+ /*---------------------------------------------*/
+ pagesize=, /* specifies the page size. The default is */
+ /* the page size currently in effect. This */
+ /* specification lasts for the duration of */
+ /* this step. The current page size is */
+ /* restored at the end. */
+ linesize=, /* specifies the line size. The default is */
+ /* the line size currently in effect. This */
+ /* specification lasts for the duration of */
+ /* this step. The current line size is */
+ /* restored at the end. */
+ /* */
+ options=, /* specifies one or more binary options: */
+ /* */
+ /* LIST - do not run PROC DOCUMENT for */
+ /* each group of objects. Just */
+ /* list the contents of the */
+ /* document. */
+ /* */
+ /* TABLE - (or TABLES) selects only tables */
+ /* and notes (more specifically, */
+ /* anything but graphs). */
+ /* */
+ /* GRAPH - only selects graphs. */
+ /* */
+ /* NOPAGE - no page breaks at the top of */
+ /* tables. */
+ /* */
+ /* NEWPAGE - forces a page break on the first */
+ /* object. */
+ /* */
+ /* AUTOPAGE - same page breaks that the */
+ /* procedure makes. There is a */
+ /* page break on the first object */
+ /* and where the proc forces a new */
+ /* page. AUTOPAGE is the default. */
+ /* */
+ /* ONEBOX - is used with the \Listing tag */
+ /* and specifies that only one */
+ /* block of tables is made. This */
+ /* option strips out all '<>' */
+ /* characters from the OBJECTS= */
+ /* list and adds a '<' to the */
+ /* beginning of the list. With */
+ /* FIRSTOBJ= or LASTOBJ= or no */
+ /* OBJECTS= list, the effect is the */
+ /* same even though the mechanism */
+ /* is different. If anything other */
+ /* than only tables or a single */
+ /* graph is input, an error is */
+ /* issued along with the object */
+ /* list. */
+ /* */
+ /* SKIPFIRST- deletes the first object that */
+ /* would otherwise be selected. */
+ /* Typical usage is with FIRST= */
+ /* to select every object after the */
+ /* one that was named. */
+ /* */
+ /* SKIPLAST - deletes the last object that */
+ /* would otherwise be selected. */
+ /* Typical usage is with LAST= to */
+ /* select every object before the */
+ /* one that was named. */
+ /* */
+ /* Example: OPTIONS=TABLE ONEBOX. */
+ /* */
+ style=, /* specifies the ODS style for ODS Graphics. */
+ /* Use the STYLE= option in the OUTPUT macro */
+ /* to control the style for GRSEG graphics. */
+ /* If STYLE= is specified, that style is used. */
+ /* If STYLE= is not specified, and if a macro */
+ /* variable DefaultStyle is defined, its value */
+ /* is used as the style. If STYLE= is not */
+ /* specified and the macro variable */
+ /* DefaultStyle is not defined or if its value */
+ /* is null, then the default style (which is */
+ /* the HTMLBLUE style) is used. */
+ /* */
+ /* In other words, the default style is the */
+ /* HTMLBLUE style. However, you can set the */
+ /* default style to (say) LISTING by putting */
+ /* the following line at the top of your first */
+ /* Sascode block, beginning in column 1: */
+ /* */
+ /* %*;%let defaultstyle=listing; */
+ /* */
+ /* Since this line begins with a null macro */
+ /* comment (%*;) that begins in column 1, it */
+ /* will not show up in the SAS code listing, */
+ /* but it will affect the capture program and */
+ /* change the default style for the duration */
+ /* of the running of the program. */
+ /* */
+ type=);; /* specifies the type of objects to select. */
+ /* \Listing specifies TYPE=LISTING, which is */
+ /* an alias for OPTIONS=TABLE. */
+ /* \Graphic specifies TYPE=GRAPH, which is an */
+ /* alias for OPTIONS=GRAPH. */
+ /*---------------------------------------------*/
+
+%local i j k flow error savenote holdlast allobjflag firstflag onlylist
+ lastflag rangeflag objflag ngroups h onebox isgraph savesize
+ left tyw stw grw abnormal selecttype savetime kl kh jl jh ls
+ pagebreak gdevice skipfirst skiplast;
+
+%let abnormal = 0;
+%let error = 0;
+%let savenote = %sysfunc(getoption(notes));
+%let savetime = %sysfunc(getoption(stimer));
+%let savesize = ls=%sysfunc(getoption(ls)) ps=%sysfunc(getoption(ps));
+%let holdlast = &syslast;
+%let graphtype = %qlowcase(&graphtype);
+%if %nrbquote(&graphtype) ne pdf %then %let graphtype = png;
+
+options nostimer %if &pagesize ne %then ps=&pagesize;
+ %if &linesize ne %then ls=&linesize;;
+
+%if %symexist(adsflow) %then %let flow = %lowcase(&adsflow);
+
+* Set the default style using STYLE= and a DefaultStyle macro variable.;
+%if &style eq %then %let style = &defaultstyle;
+
+* Set the default DPI using DPI= and a DefaultDPI macro variable.;
+%if &dpi eq %then %let dpi = &defaultDPI;
+
+%let gdevice = %substr(png300, 1, 3 * (1 + (&dpi eq 300)));
+%if %nrbquote(&graphtype) eq pdf %then %let gdevice = pdf;
+
+* Find out what is in the document. Store the list in a SAS data set.;
+%if %symexist(documentlabel) %then %do;
+ %if %nrbquote(&store) eq %then %let store = &documentLabel;
+ %end;
+
+%if %nrbquote(&store) eq %then %do;
+ %put ERROR: No ODS document available.;
+ %let error = 1;
+ %goto veryend;
+ %end;
+%else %put NOTE: Processing document &store..;
+
+%if not %index(&flow, notes) %then %do; options nonotes; %end;
+
+ods document close; run;
+ods _all_ close;
+
+proc document name=&store;
+ ods output properties=_ads_doclist(where=(not (type eq "Dir" or
+ (type =: 'R' and index(type, 'p.')))));
+ list / details levels=all;
+ run; quit;
+
+%if &syserr > 4 %then %let error = 1; %if &error %then %goto veryend;
+ods listing;
+
+data _null_;
+ call symputx('ls', getoption('ls'), 'L');
+ if 0 then set _ads_doclist nobs=nprts;
+ if nprts eq 0 then do;
+ put "ERROR: Document &store does not exist.";
+ call symputx('error', '1', 'L');
+ end;
+
+ length fname $ 40 c $ 1;
+ fname = symget('fname');
+ c = substr(fname, length(fname), 1);
+ if '0' le c le '9' then do;
+ put 'ERROR: The name ' fname 'is invalid. It must not end in a numeral.';
+ call symputx('error', '1', 'L');
+ end;
+ if _error_ then call symputx('error', '1', 'L');
+ stop;
+ run;
+
+%if &syserr > 4 %then %let error = 1; %if &error %then %goto veryend;
+
+* Basic option setting, checking, and processing.;
+data _null_;
+ length c $ 1 c2 $ 2 firstobj lastobj options type $ 200 objects $ 32500;
+
+ w = symget('width');
+ if w = ' ' then w = '6.4in';
+ h = symget('height');
+ if h = ' ' then
+ call symputx('h', trim(put(0.75 * input(translate(lowcase(w), ' ',
+ 'incm'), 12.), best12.)) || substr(w, length(w) - 1, 2), 'L');
+ else call symputx('h', trim(h), 'L');
+
+ options = lowcase(symget('defaultdests'));
+ options = compbl(options);
+ call symputx('defaultdests', options, 'G');
+ i = index(options, 'listing'); if i then substr(options, i, 7) = ' ';
+ i = index(options, 'latex'); if i then substr(options, i, 5) = ' ';
+
+ if options ne ' ' then do;
+ put 'ERROR: %LET ' "DEFAULTDESTS=&defaultdests is invalid.";
+ put 'WARNING: Choose from: listing latex.';
+ call symputx('error', '1', 'L');
+ end;
+
+ options = lowcase(symget('dest'));
+ options = compbl(options);
+
+ if not (options eq ' ' or options eq 'listing' or options eq 'latex') then do;
+ put "ERROR: DESTS=&dest is invalid.";
+ put 'WARNING: Choose from: listing latex.';
+ call symputx('error', '1', 'L');
+ end;
+ if options eq ' ' then options = symget('defaultdests');
+ call symputx('dest', options, 'L');
+
+ * Flag which options were specified.;
+
+ type = lowcase(symget('type'));
+ options = lowcase(symget('options'));
+
+ tx = index(type , 'tables'); if tx then substr(type , tx, 6) = ' ';
+ tt = index(type , 'table'); if tt then substr(type , tt, 5) = ' ';
+ tl = index(type , 'listing'); if tl then substr(type , tl, 7) = ' ';
+ t1 = index(type , 'graphics'); if t1 then substr(type , t1, 8) = ' ';
+ t2 = index(type , 'graphic'); if t2 then substr(type , t2, 7) = ' ';
+ t3 = index(type , 'graphs'); if t3 then substr(type , t3, 6) = ' ';
+ t4 = index(type , 'graph'); if t4 then substr(type , t4, 5) = ' ';
+ no = index(options, 'nopage'); if no then substr(options, no, 6) = ' ';
+ nw = index(options, 'newpage'); if nw then substr(options, nw, 7) = ' ';
+ ap = index(options, 'autopage'); if ap then substr(options, ap, 8) = ' ';
+ li = index(options, 'listing'); if li then substr(options, li, 7) = ' ';
+ ls = index(options, 'list'); if ls then substr(options, ls, 4) = ' ';
+ ty = index(options, 'tables'); if ty then substr(options, ty, 6) = ' ';
+ ta = index(options, 'table'); if ta then substr(options, ta, 5) = ' ';
+ ob = index(options, 'onebox'); if ob then substr(options, ob, 6) = ' ';
+ g1 = index(options, 'graphics'); if g1 then substr(options, g1, 8) = ' ';
+ g2 = index(options, 'graphic'); if g2 then substr(options, g2, 7) = ' ';
+ g3 = index(options, 'graphs'); if g3 then substr(options, g3, 6) = ' ';
+ g4 = index(options, 'graph'); if g4 then substr(options, g4, 5) = ' ';
+ sf = index(options, 'skipfirst'); if sf then substr(options, sf, 9) = ' ';
+ sl = index(options, 'skiplast'); if sl then substr(options, sl, 8) = ' ';
+
+ if options ne ' ' then do;
+ options = compbl(options);
+ put 'WARNING: WRITE macro OPTIONS=' options 'is invalid and is ignored.';
+ end;
+
+ if type ne ' ' then do;
+ type = compbl(type);
+ put 'WARNING: WRITE macro TYPE=' type 'is invalid and is ignored.';
+ end;
+
+ table = ta or ty or li or tt or tx or tl;
+ graph = g1 or g2 or g3 or g4 or t1 or t2 or t3 or t4;
+
+ if no then call symputx('pagebreak', 'nopage');
+ else if nw then call symputx('pagebreak', 'newpage');
+ else call symputx('pagebreak', 'autopage');
+
+ call symputx('onlylist', ls ne 0, 'L');
+ call symputx('onebox', ob, 'L');
+ call symputx('isgraph', graph, 'L');
+ call symputx('selecttype', ob or table or graph, 'L');
+ call symputx('skipfirst', sf ne 0, 'L');
+ call symputx('skiplast', sl ne 0, 'L');
+
+ if table and graph then do;
+ put "ERROR: TYPE=&type and OPTIONS=&options conflict.";
+ put "ERROR: Both tables and graphs were selected.";
+ call symputx('error', '1', 'L');
+ end;
+
+ * Process object names.;
+ firstobj = symget('firstobj');
+ lastobj = symget('lastobj');
+ objects = lowcase(symget('objects'));
+ if ob then objects = '<' || compbl(translate(objects, ' ', '<>'));
+
+ call symputx('ngroups', '0', 'L');
+ call symputx('pattern', lowcase(symget('pattern')), 'L');
+ call symputx('firstobj', lowcase(firstobj), 'L');
+ call symputx('lastobj', lowcase(lastobj), 'L');
+ call symputx('objects', objects, 'L');
+
+ if (firstobj ne ' ' or lastobj ne ' ') and objects ne ' ' then do;
+ put 'ERROR: OBJECTS= may not be specified with FIRSTOBJ= and LASTOBJ=.';
+ call symputx('error', '1', 'L');
+ end;
+
+ * Remove extra spaces and funkiness around < and >.;
+ if objects ne ' ' then do;
+ objects = ' ' || compbl(objects);
+
+ * Get rid of trailing open brackets.;
+ done = 0;
+ do i = 1 to 32500 until(done);
+ l = length(objects);
+ if substr(objects, l, 1) eq '<' then substr(objects, l, 1) = ' ';
+ else done = 1;
+ end;
+
+ * Get rid of multiple contiguous brackets.;
+ c = ' ';
+ done = 0;
+ do i = 1 to 32500 until(done);
+ if i gt length(objects) then done = 1;
+ else do;
+ c2 = substr(objects, i, 1);
+ if (c eq '<' and c2 eq '<') or
+ (c eq '>' and c2 eq '>') then substr(objects, i, 1) = ' ';
+ c2 = substr(objects, i, 1);
+ if not (c2 eq ' ' or c2 eq '<' or c2 eq '>') then c = ' ';
+ else if c2 eq '<' or c2 eq '>' then c = c2;
+ end;
+ end;
+ objects = ' ' || compbl(objects);
+
+ * Move brackets next to names.
+ For example, change '< name' to '<name' and 'name >' to 'name>'.;
+ done = 0;
+ do i = 1 to 32500 until(done);
+ if i gt length(objects) then done = 1;
+ else do;
+ c2 = substr(objects, i, 2);
+ if c2 eq '< ' then substr(objects, i, 2) = ' <';
+ if c2 eq ' >' then substr(objects, i, 2) = '> ';
+ c2 = substr(objects, i, 1);
+ if c2 eq '<' then do;
+ c = substr(objects, i - 1, 1);
+ if c ne ' ' then objects = substr(objects, 1, i - 1) ||
+ ' <' || substr(objects, i + 1);
+ i + 1;
+ end;
+ else if c2 eq '>' then do;
+ c = substr(objects, i + 1, 1);
+ if c ne ' ' then objects = substr(objects, 1, i - 1) ||
+ '> ' || substr(objects, i + 1);
+ i + 1;
+ end;
+ end;
+ end;
+
+ * Get rid of null bracket groups.;
+ done = 0;
+ do i = 1 to 32500 until(done);
+ if i gt length(objects) then done = 1;
+ else do;
+ c2 = substr(objects, i, 2);
+ if c2 eq '<>' then substr(objects, i, 2) = ' ';
+ end;
+ end;
+ objects = compbl(left(objects));
+
+ * Get rid of leading close brackets.;
+ if objects =: '>' then objects = substr(objects, 2);
+
+ call symputx('objects', left(compbl(objects)), 'L');
+ end;
+
+ call symputx('allobjflag', (firstobj eq ' ' and lastobj eq ' ' and
+ objects eq ' '), 'L');
+ call symputx('firstflag', (firstobj eq ' ' and lastobj ne ' '), 'L');
+ call symputx('lastflag' , (firstobj ne ' ' and lastobj eq ' '), 'L');
+ call symputx('rangeflag', (firstobj ne ' ' and lastobj ne ' '), 'L');
+ call symputx('objflag' , (objects ne ' '), 'L');
+
+ if _error_ then call symputx('error', '1', 'L');
+ run;
+
+%if &syserr > 4 %then %let error = 1; %if &error %then %goto veryend;
+
+data _ads_doclist(drop=i p);
+ set _ads_doclist;
+
+ /*-------------Translate: Special characters not shown-------------
+ English German Spanish French Italian
+ Batch Batch Batch Traitement par lots Batch
+ Crosstab Kreuztabelle TablaCruzada Table a double entr*e Campi incr.
+ Dir Dir Dir Rép. Dir
+ File file Archivo Fichier File
+ Graph Grafik Gr*fico Graphique Grafico
+ Note Hinweis Nota Note Nota
+ Report Bericht Informe Rapport Report
+ Table Tabelle Tabla Tableau Tabella
+ Text Text Texto Texte Testo
+ Tree Baum *rbol Arbre Struttura
+ */
+
+ if trim(type) in ('Hinweis', 'Nota') then type = 'Note';
+ else if type =: 'Kreuz' or type =: 'Tabla' or type =: 'Campi' or
+ index(trim(type), 'double') then type = 'Crosstab';
+ else if type =: 'Tab' then type = 'Table';
+ else if type =: 'Gra' then type = 'Graph';
+ else if type =: 'Traite' then type = 'Batch';
+ else if type =: 'Te' then type = 'Text';
+ else if type =: 'Fi' or type =: 'fi' or type =: 'Archi' then type = 'File';
+ else if trim(type) in ('Bericht', 'Informe', 'Rapport') then type ='Report';
+ else if trim(type) in ('Baum', 'Arbre', 'Struttura') or index(type, 'rbol')
+ then type ='Tree';
+
+ ObjNum = _n_;
+ * The variable ourpath is used for group subsetting and display in the SAS log.
+ It is not used for actual selection (beyond group selection).;
+ ourpath = substr(translate(path, '.', '\'), 2);
+ do i = 1 to length(ourpath) until(p eq 0);
+ p = index(ourpath, '#1.');
+ if p then substr(ourpath, p, 3) = '. ';
+ end;
+ ourpath = compress(ourpath, ' ');
+ p = length(ourpath) - 1;
+ if substr(ourpath, p, 2) eq '#1' then substr(ourpath, p, 2) = ' ';
+
+ if _error_ then call symputx('error', '1', 'L');
+ run;
+
+%if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+
+* Get object names specified in FIRSTOBJ=, LAST=, and OBJECTS= for error checking.;
+%if not &allobjflag %then %do;
+ data _ads_objects(keep=object);
+ length l $ 32500 object $ 200;
+ l = symget('firstobj') || ' ' || symget('lastobj') || ' ' || symget('objects');
+ do i = 1 to 32500 until(object eq ' ');
+ object = scan(l, i, ' <>');
+ if object ne ' ' then output;
+ end;
+
+ if _error_ then call symputx('error', '1', 'L');
+ run;
+
+ %if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+
+ * Make sure every specified name is referenced.;
+ data _null_;
+ set _ads_objects;
+ length object holdobj $ 200;
+ holdobj = object;
+
+ * Store object name with pounds and such to match document.;
+ %ads_expand_obj(object, holdobj)
+
+ match = 0;
+ do i = 1 to nprts until(match);
+ set _ads_doclist nobs=nprts point=i;
+
+ * If object has n levels, store in pathpart the last n levels from path.;
+ %ads_extr_path(pathpart, path, holdobj)
+ match = (pathpart eq object);
+ end;
+ if not match then do;
+ put 'ERROR: Object ' holdobj 'not found.';
+ call symputx('error', '1', 'L');
+ end;
+
+ if _error_ then call symputx('error', '1', 'L');
+ run;
+
+ %if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+ %end;
+
+* Extract the relevant tables and notes from the list.;
+data _ads_select(keep=path type left right object ourpath label pagebreak);
+ length objlist $ 32500 fullqualobj object firstlist lastlist $ 200;
+ retain object firstlist lastlist objlist ' ' inflag 0 objind 1;
+ set _ads_doclist;
+
+ if type eq 'Report' and label =: 'Data Set ' and path =: '\Print'
+ then label = substr(label, 10);
+ else do;
+ label = ' ';
+ if type eq 'Report' then type = 'rpt';
+ end;
+
+ left = 0; right = 0; fullqualobj = ' ';
+
+ if _n_ eq 1 then do;
+ firstlist = symget('firstobj');
+ lastlist = symget('lastobj');
+ objlist = symget('objects');
+ end;
+
+ * Perform preliminary subsetting based on group patterns.;
+ %if %nrbquote(&pattern) ne %then %do;
+ if index(lowcase(ourpath), "&pattern");
+ %end;
+
+ righttype = 1;
+ if &selecttype then righttype = (( &isgraph and type eq 'Graph') or
+ (not &isgraph and type ne 'Graph'));
+
+ %* Are only the last ones selected (FIRSTOBJ= specified)?;
+ %if &lastflag and not &allobjflag %then %do;
+ %ads_extr_path(pathpart, path, firstlist)
+ %ads_expand_obj(fullqualobj, firstlist)
+ if pathpart eq fullqualobj then inflag = 1;
+ if inflag and righttype then output;
+ %end;
+
+ %* Are only the first ones selected (LASTOBJ= specified)?;
+ %else %if &firstflag and not &allobjflag %then %do;
+ if _n_ eq 1 then inflag = 1;
+ %ads_extr_path(pathpart, path, lastlist)
+ %ads_expand_obj(fullqualobj, lastlist)
+ if inflag and righttype then output;
+ if pathpart eq fullqualobj then inflag = 0;
+ %end;
+
+ %* Is a range being selected (FIRSTOBJ= and LASTOBJ= specified)?;
+ %else %if &rangeflag and not &allobjflag %then %do;
+ %ads_extr_path(pathpart, path, firstlist)
+ %ads_expand_obj(fullqualobj, firstlist)
+ if pathpart eq fullqualobj then inflag = 1;
+ %ads_extr_path(pathpart, path, lastlist)
+ %ads_expand_obj(fullqualobj, lastlist)
+ if inflag and righttype then output;
+ if pathpart eq fullqualobj then inflag = 0;
+ %end;
+
+ %* Is a list being selected (OBJECTS= specified)?;
+ %else %if &objflag and not &allobjflag %then %do;
+ do i = 1 to 32500 until(object eq ' ');
+ object = scan(objlist, i, ' ');
+
+ if object ne ' ' then do;
+
+ * For an object has n levels,
+ store in pathpart the last n levels from the path.;
+ %ads_extr_path(pathpart, path, object)
+
+ left = 0; right = 0;
+ if substr(object, 1, 1) eq '<' then do;
+ left = 1;
+ object = substr(object, 2);
+ end;
+ if substr(object, length(object), 1) eq '>' then do;
+ right = 1;
+ object = substr(object, 1, length(object) - 1);
+ end;
+
+ * Store the object name with pounds and such to match the document.;
+ %ads_expand_obj(fullqualobj, object)
+
+ if fullqualobj eq pathpart then do;
+ if righttype then output;
+ object = ' ';
+ end;
+ end;
+ end;
+ %end;
+
+ %* Is everything selected?;
+ %else %do;
+ if righttype then output;
+ %end;
+
+ if _error_ then call symputx('error', '1', 'L');
+ run;
+
+%if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+
+
+* Omit the first or last object from the selection list with SKIPFIRST or SKIPLAST.;
+%if &skipfirst or &skiplast %then %do;
+ data _ads_select;
+ set _ads_select end=eof;
+
+ %if &skipfirst %then %do; if _n_ = 1 then delete; %end;
+ %if &skiplast %then %do; if eof then delete; %end;
+
+ if _error_ then call symputx('error', '1', 'L');
+ run;
+
+ %if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+ %end;
+
+* Set page breaks.;
+data _ads_select(keep=path type left right object ourpath group label pagebreak);
+ set _ads_select end=eof;
+ retain Group 1 oldgroup anyleft 0;
+ if type in ('Graph', 'Report', 'rpt') then do;
+ left = 1; right = 1;
+ if type eq 'Graph' then ngraphs + 1;
+ end;
+ if left then do;
+ group = oldgroup + (not &onebox);
+ if &onebox and group eq 0 then group = 1;
+ anyleft = 1;
+ end;
+ oldgroup = group;
+ output;
+ if right then anyleft = 0;
+
+ other + (type in ('Note', 'Report', 'rpt'));
+ tabtype = (type in ('Table', 'Tree', 'Batch', 'Crosstab', 'Text'));
+ if tabtype then ntabs + 1;
+ if right or (not anyleft and tabtype) then group = oldgroup + (not &onebox);
+
+ if eof and &onebox and &isgraph and ((ntabs + other) or ngraphs ne 1) then do;
+ put 'ERROR: The Graphic tag must select '
+ 'only one graph and nothing ' "else in document &store..";
+ call symputx('onlylist', '1', 'L');
+ call symputx('abnormal', '1', 'L');
+ end;
+
+ if eof and &onebox and not &isgraph and ((ntabs + other) lt 1 or ngraphs)
+ then do;
+ put 'ERROR: The Listing tag must select tables and no graphs '
+ "in document &store..";
+ call symputx('onlylist', '1', 'L');
+ call symputx('abnormal', '1', 'L');
+ end;
+
+ if not &onlylist and eof and
+ not &onebox and (ntabs + other) and ngraphs then do;
+ put 'ERROR: You may request either tables or graphs but not both '
+ "in document &store..";
+ call symputx('onlylist', '1', 'L');
+ call symputx('abnormal', '1', 'L');
+ end;
+
+ if _error_ then call symputx('error', '1', 'L');
+ run;
+
+%if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+
+%if %index(&flow, print) %then %do;
+ proc print; var path type group object; run;
+ proc print; var ourpath type group object; run;
+ %end;
+
+* Check for objects that match multiple document pieces.;
+%if not &allobjflag %then %do;
+ proc sort data=_ads_select out=_ads_objects;
+ by object;
+ run;
+
+ %if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+
+ data _null_;
+ set _ads_objects;
+ by object;
+ if object ne ' ' and not (first.object and last.object) then do;
+ put 'ERROR: Multiple matches. Object ' object
+ 'matches ' ourpath +(-1)'.';
+ call symputx('error', '1', 'L');
+ end;
+ if _error_ then call symputx('error', '1', 'L');
+ run;
+
+ %if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+ %end;
+
+* Clear out titles, subtitles, and footnotes as necessary. Build rendering code.;
+options nosource;
+
+data _null_;
+ length list $ 32500;
+ retain list ' ' forcepage &&__New_&store;
+ set _ads_select end=end;
+ by group;
+ if _n_ eq 1 then call execute("proc document name=&store;");
+
+ list = trim(list) || ' or _path_ = "' || trim(path) || '"';
+
+ %if &pagebreak eq autopage %then %do; /* default */
+ first = pagebreak;
+ if type ne 'Graph' then do;
+ first = (first or forcepage);
+ forcepage = 0;
+ end;
+ %end;
+ %else %if &pagebreak eq nopage %then %do;
+ first = 0;
+ %end;
+ %else %do; /* new page */
+ first = ((_n_ eq 1) or pagebreak);
+ %end;
+
+ if first and type ne 'Graph' then put 'Note: New page for ' path;
+
+ if first then call execute("obfootn " || path || ';');
+ else if end then call execute('obtitle ' || path || '; obstitle ' ||
+ path || '; run; quit;');
+ else call execute('obfootn ' || path || '; obstitle ' || path ||
+ '; obtitle ' || path || ';');
+
+ if last.group then do;
+ list = substr(list, 5);
+ call symputx('_list' || left(put(group, 5.)), trim(list), 'L');
+ call symputx('_gtype' || left(put(group, 5.)), put(type, $1.), 'L');
+ call symputx('ngroups', group, 'L');
+ if type eq 'Report' then
+ call symputx('_data' || left(put(group, 5.)), trim(label), 'L');
+ list = ' ';
+ end;
+
+ if _error_ then call symputx('error', '1', 'L');
+ run;
+
+%if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+
+options source &savenote;
+
+%let __new_&store = 0;
+
+%if &onebox and &ngroups ne 1 and not &abnormal %then %do;
+ %if &isgraph %then %let i = Graphic;
+ %else %let i = Listing;
+ %put ERROR: There must be exactly one group of objects with &i..;
+ %let onlylist = 1;
+ %let abnormal = 1;
+ %end;
+
+* Render each group of data objects.;
+%if not &onlylist %then %do;
+ ods _all_ close;
+ ods graphics / reset=index imagename="";
+
+ %let kl = 0; %let kh = 0;
+ %do i = 1 %to &ngroups;
+
+ %if %symexist(_list&i) %then %do;
+ %if &kl eq 0 %then %let jl = ; %else %let jl = &kl;
+ %if &kh eq 0 %then %let jh = ; %else %let jh = &kh;
+ %let kl = %eval(&kl + 1);
+ %let kh = %eval(&kh + 1);
+
+ %if &&_gtype&i eq G %then %do; /* if graph replay */
+ %if %nrbquote(&graphtype) eq pdf %then %do;
+ %if (%nrbquote(&sysver) < 9.3) %then %do;
+ %put WARNING: ODS PDF Graphics are unavailable in SAS 9.2;
+ %put WARNING: Generating PNG format in "png" directory.;
+ %let graphtype=png;
+ %let graphicdir=png;
+ %end;
+ %end;
+
+ ods listing style=&style image_dpi=&dpi gpath="&graphicdir";
+ ods graphics / reset=index imagename="&fname&jl" &odsgraphopts
+ %if %nrbquote(&width) ne %then width=&width;
+ %if %nrbquote(&height) ne %then height=&height;
+ %if %nrbquote(&graphtype) eq pdf %then outputfmt=pdf;;
+
+ %if %sysprod(graph) = 1 %then %do;
+ goptions dev=&gdevice fileonly gsfname=gsasfile gsfmode=replace
+ hsize=
+ %if %nrbquote(&width) ne %then &width;
+ %else 6.4in;
+ vsize=&h border;
+ %end;
+ filename gsasfile "&graphicdir/&fname&jl..&graphtype";
+ %put NOTE: Writing Graph file: &graphicdir/&fname&jl..&graphtype;
+ %end;
+ %else %do;
+ %if %index(&dest, listing) %then %do;
+ ods listing file="&listingdir/_tmp";
+ %end;
+ %if %index(&dest, latex) %then %do;
+ ods tagsets.statrep style=&latexstyle
+ file="&latexdir/&fname&jh..tex" (notop nobot)
+ stylesheet="&rootdir/sas.sty"
+ newfile=output ;
+ %end;
+ %end;
+ %if not %index(&flow, notes) %then %do; options nonotes; %end;
+ proc document name=&store;
+ replay ^(where=(&&_list&i)) / levels=all;
+ run; quit;
+ %if &syserr > 4 %then %let error = 1;
+ %if &error %then %goto endit;
+ options &savenote;
+ %if &&_gtype&i eq G %then %do; /* if graph replay */
+ filename gsasfile "&graphicdir/_tmp.&graphtype";
+ %end;
+ ods _all_ close;
+ ods graphics / reset=index imagename="" reset=width reset=height;
+ %if &&_gtype&i ne G and /* if not graph */
+ %index(&dest, listing) %then %do;
+ /* break up big listing files */
+ options nonotes;
+ data _null_;
+ retain kl &jl;
+ length fn $ 200;
+ infile "&listingdir/_tmp" lrecl=%eval(&ls+1) pad;
+ input line $char%eval(&ls+1).;
+ page = substr(line, 1, 1) eq '0C'x;
+ if _n_ eq 1 or page then do;
+ fn = "&listingdir/&fname";
+ if page then line = substr(line, 2);
+ if kl then fn = compress(fn || put(kl, 5.) || '.lst');
+ else fn = compress(fn || '.lst');
+ kl + 1;
+ call symputx('kl', kl, 'L');
+ put 'Note: Writing Listing file : ' fn;
+ end;
+ file x filevar=fn nopad;
+ l = length(line);
+ put line $varying. l;
+ if _error_ then call symputx('error', '1', 'L');
+ run;
+ %if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+ options &savenote;
+ %end;
+ %end;
+ %end;
+ ods listing;
+%end;
+
+%if &ngroups eq 0 %then %do;
+ %put ERROR: No objects selected.;
+ %let error = 1;
+ %goto endit;
+ %end;
+
+%if not %index(&flow, notes) %then %do; options nonotes; %end;
+
+proc sort data=_ads_doclist; by path; run;
+
+%if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+
+proc sort data=_ads_select; by path; run;
+
+%if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+
+data _ads_doclist;
+ merge _ads_doclist(in=dl) _ads_select(keep=path group in=s);
+ by path;
+ if s then Status = 'Selected';
+ if _error_ then call symputx('error', '1', 'L');
+ run;
+
+%if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+
+proc sort data=_ads_doclist; by objnum; run;
+
+%if &syserr > 4 %then %let error = 1; %if &error %then %goto endit;
+
+%endit:;
+
+* Get some formatting information for rendering the document contents list.;
+data _null_;
+ set _ads_doclist end=eof;
+ left = max(left, length(ourpath));
+ tyw = max(tyw, length(type));
+ if eof then do;
+ left + 1; tyw + 1; stw = 9; grw = 5;
+ atright = min(&ls - tyw - stw - grw - 1, left + 3);
+ call symputx('atright', atright, 'L');
+ call symputx('tyw', tyw, 'L');
+ call symputx('stw', stw, 'L');
+ call symputx('grw', grw, 'L');
+ end;
+ if _error_ then call symputx('error', '1', 'L');
+ run;
+
+%if &syserr > 4 %then %let error = 1;
+
+* Render the document contents list, wrapping the path if necessary.;
+data _null_;
+ length p $ 500;
+ status = ' '; group = .;
+ file log;
+ set _ads_doclist;
+ ghead = 'Group'; thead = 'Type'; shead = 'Status';
+ if _n_ eq 1 then put / 'Objects'
+ @&atright thead $&tyw..
+ @%eval(&atright+&tyw) shead $&stw..
+ @%eval(&atright+&tyw+&stw) ghead $&grw.. /;
+ do j = 1 to 100 while(ourpath ne ' ');
+ do l = &atright - 2 to &atright / 2 by -1
+ while(not (substr(ourpath, l, 1) in ('.', ' ')));
+ end;
+ p = substr(ourpath, 1, l);
+ if j eq 1 then
+ put p $%eval(&atright-2). +1 type $&tyw.. status $&stw.. group 3.;
+ else put p $%eval(&atright-2).;
+ ourpath = substr(ourpath, l + 1);
+ end;
+ if _error_ then call symputx('error', '1', 'L');
+ run;
+
+%if &syserr > 4 %then %let error = 1;
+
+%veryend:;
+
+* Clean up.;
+%if not %index(&flow, notes) %then %do; options nonotes; %end;
+proc datasets nolist; delete _ads_select _ads_doclist _ads_objects; run; quit;
+
+%if &syserr > 4 %then %let error = 1;
+
+%let syslast = &holdlast;
+%if &error or &abnormal %then %put ERROR: Macro write ended abnormally.;
+run;
+
+filename __f1 "&listingdir/_tmp";
+filename __f2 "&graphicdir/_tmp.&graphtype";
+data _null_; rc = fdelete('__f1'); rc = fdelete('__f2'); run;
+
+options obs=max nosyntaxcheck &savenote &savetime &savesize;
+%mend;
+
+*------------------------------------------------------------------------;
+
+ /*---------------------------------------------*/
+ /* The OUTPUT macro opens an ODS document and */
+ /* captures output until it encounters an */
+ /* ENDOUTPUT macro or a WRITE macro. */
+ /*---------------------------------------------*/
+%macro output(label, /* is a required keyword that specifies the */
+ /* ODS document name. This is used in the */
+ /* STORE= option in the WRITE macro and in */
+ /* \Listing and \Graphic tags. */
+ /* */
+ style=, /* specifies the ODS style for GRSEG graphics. */
+ /* Use the STYLE= option in the WRITE macro to */
+ /* control the style for ODS Graphics. If */
+ /* STYLE= is specified, that style is used. */
+ /* If STYLE= is not specified, and if a macro */
+ /* variable DefaultStyle is defined, its value */
+ /* is used as the style. If STYLE= is not */
+ /* specified and the macro variable */
+ /* DefaultStyle is not defined or if its value */
+ /* is null, then the default style (which is */
+ /* the HTMLBLUE style) is used. */
+ /* */
+ /* In other words, the default style is the */
+ /* HTMLBLUE style. However, you can set the */
+ /* default style to (say) LISTING by putting */
+ /* the following line at the top of your first */
+ /* Sascode block, beginning in column 1: */
+ /* */
+ /* %*;%let defaultstyle=listing; */
+ /* */
+ /* Since this line begins with a null macro */
+ /* comment (%*;) in column 1, it will not show */
+ /* up in the SAS code listing, but it will */
+ /* affect the capture program and change the */
+ /* default style for the duration of the */
+ /* running of the program. */
+ /* */
+ dpi=);; /* specifies DPI (dots per inch) for GRSEG */
+ /* graphics. You typically would not use this */
+ /* except when you would otherwise run out of */
+ /* memory. The default is 300 DPI, and a */
+ /* reasonable alternative for GRSEG graphs */
+ /* with a large file size is 96 DPI. More */
+ /* details follow. */
+ /* */
+ /* With GRSEG graphics, you do not have */
+ /* continuous control over DPI as you do with */
+ /* ODS Graphics. With the macro default DPI */
+ /* of 300, you get 300 DPI. Otherwise, you */
+ /* get the device default of 96 DPI. */
+ /* */
+ /* This option controls the DPI for GRSEG */
+ /* graphics. Use the DPI= option in the WRITE */
+ /* macro to control the style for ODS */
+ /* Graphics. If DPI= is specified, that DPI */
+ /* is used. If DPI= is not specified, and if */
+ /* a macro variable DefaultDPI is defined, its */
+ /* value is used as the DPI. If DPI= is not */
+ /* specified and the macro variable DefaultDPI */
+ /* is not defined or if its value is null, */
+ /* then the default DPI (300) is used. */
+ /* */
+ /* In other words, the default DPI is 300. */
+ /* However, you can set the default DPI for */
+ /* GRSEG graphics to 96 by putting the */
+ /* following line at the top of your first */
+ /* Sascode block, beginning in column 1: */
+ /* */
+ /* %*;%let defaultdpi=100; */
+ /* */
+ /* This is not a typo. If you set the default */
+ /* DPI to anything other than 300, you get 96 */
+ /* DPI with GRSEG graphics and the specified */
+ /* value with ODS Graphics. With ODS */
+ /* Graphics, the values of 300 and 100 are */
+ /* most commonly used. */
+ /* */
+ /* Since the %LET statement is preceded by a */
+ /* null macro comment (%*;) in column 1, it */
+ /* will not show up in the SAS code listing, */
+ /* but it will affect the capture program and */
+ /* change the default DPI for the duration of */
+ /* the running of the program. You can change */
+ /* DPI at any time with one of these */
+ /* statements. */
+ /*---------------------------------------------*/
+
+%local log lst savenote gdevice;
+
+* Set the default style using STYLE= and a DefaultStyle macro variable;
+%if &style eq %then %let style = &defaultstyle;
+
+* Set the default DPI using DPI= and a DefaultDPI macro variable;
+%if &dpi eq %then %let dpi = &defaultDPI;
+
+%let graphtype = %qlowcase(&graphtype);
+%if %nrbquote(&graphtype) ne pdf %then %let graphtype = png;
+%let gdevice = %substr(png300, 1, 3 * (1 + (&dpi eq 300)));
+%if %nrbquote(&graphtype) eq pdf %then %let gdevice = pdf;
+
+%if not (&dpi eq 96 or &dpi eq 100 or &dpi eq 300)
+ %then %put NOTE: DPI=96 will be used for GRSEG graphics.;
+
+%let savenote = %sysfunc(getoption(notes));
+%if %sysfunc(symexist(_ads_debug)) %then %do;
+ %let log = 0;
+ %let lst = 0;
+ %let _ads_debug = %lowcase(&_ads_debug);
+ %if %index(&_ads_debug, flowall) %then %do;
+ %let log = 1;
+ %let lst = 1;
+ %end;
+ %else %if %index(&_ads_debug, flowlog) %then %let log = 1;
+ %else %if %index(&_ads_debug, flowlst) %then %let lst = 1;
+ %if &log or &lst %then %do;
+ ods listing;
+ data _null_;
+ %if &log %then %do; put "Begin Sascode block ""&label""."; %end;
+ %if &lst %then %do;
+ file print;
+ put _page_;
+ put "Begin Sascode block ""&label"".";
+ %end;
+ run;
+ %end;
+ %end;
+
+run; quit;
+
+options nonotes;
+libname mydir '.';
+options nodate nonumber obs=max nosyntaxcheck;
+%global documentlabel;
+
+ods _all_ close;
+ods document close;
+
+data _null_; call symputx("__New_&label", '1', 'G'); run;
+
+proc datasets nolist nowarn;
+ delete gseg(memtype=catalog);
+ run; quit;
+
+proc datasets nolist nowarn library=sasuser;
+ delete __&label(memtype=catalog);
+ run; quit;
+
+* Select the style for GRSEG graphics.;
+ods listing style=&style file="&listingdir/_tmp";
+ods listing select none;
+filename __f "&listingdir/_tmp";
+data _null_; rc = fdelete('__f'); run;
+
+* Set the global label, and open the ODS Document.;
+%let documentLabel = &label;
+ods document name = &label(write) cat=sasuser.__&label;
+
+* Specify 300 DPI for GRSEG graphics (gdevice = png or png300).;
+%if %sysprod(graph) = 1 %then %do;
+ goptions dev=&gdevice fileonly gsfname=gsasfile gsfmode=replace border;
+%end;
+filename gsasfile "&graphicdir/_tmp.&graphtype";
+options &savenote;
+%mend;
+
+*------------------------------------------------------------------------;
+
+ /*---------------------------------------------*/
+ /* The ENDOUTPUT macro ends output capture. */
+ /*---------------------------------------------*/
+%macro endoutput(label);;/* specifies the ODS document name. This is */
+ /* used only to display program flow */
+ /* information in the SAS log when the macro */
+ /* variable _ads_debug is defined. */
+ /*---------------------------------------------*/
+
+run; quit;
+options obs=max nosyntaxcheck;
+ods document close;
+
+%local log lst;
+
+%if %sysfunc(symexist(_ads_debug)) %then %do;
+ %let log = 0;
+ %let lst = 0;
+ %let _ads_debug = %lowcase(&_ads_debug);
+ %if %index(&_ads_debug, flowall) %then %do;
+ %let log = 1;
+ %let lst = 1;
+ %end;
+ %else %if %index(&_ads_debug, flowlog) %then %let log = 1;
+ %else %if %index(&_ads_debug, flowlst) %then %let lst = 1;
+ %if &log or &lst %then %do;
+ ods listing;
+ data _null_;
+ %if &log %then %do; put "End Sascode block ""&label""."; %end;
+ %if &lst %then %do;
+ file print;
+ put "End Sascode block ""&label"".";
+ put _page_;
+ %end;
+ run;
+ %end;
+ %end;
+ods _all_ close;
+%mend;
+
+*------------------------------------------------------------------------;
+
+ /*---------------------------------------------*/
+ /* The STARTLIST macro starts the capture of */
+ /* listing output. Use this macro when you */
+ /* want to program your own output capture */
+ /* (for example, when you want to show only */
+ /* part of a table). */
+ /*---------------------------------------------*/
+%macro startlist(fname, /* is a required keyword that specifies the */
+ /* first level of the output file name. This */
+ /* name will appear at the end of the \Listing */
+ /* tag. */
+ /* */
+ pagesize=, /* specifies page size. The default is the */
+ /* page size currently in effect. This */
+ /* specification lasts for the duration of */
+ /* this step. The current page size is */
+ /* restored at the end. */
+ linesize=);;/* specifies line size. The default is the */
+ /* line size currently in effect. This */
+ /* specification lasts for the duration of */
+ /* this step. The current line size is */
+ /* restored at the end. */
+ /*---------------------------------------------*/
+
+%global _ads_printfname _ads_savesize;
+%let _ads_printfname = &fname;
+%let _ads_savesize = ls=%sysfunc(getoption(ls)) ps=%sysfunc(getoption(ps));
+quit;
+ods _all_ close;
+ods document close;
+options nodate nonumber %if &pagesize ne %then ps=&pagesize;
+ %if &linesize ne %then ls=&linesize;;
+ods listing file="&listingdir/_tmp";
+%mend;
+
+ /*---------------------------------------------*/
+%macro endlist;; /* The ENDLIST macro ends the capture of */
+ /* listing output. */
+ /*---------------------------------------------*/
+%local ls savenote;
+run;
+ods _all_ close;
+%let ls = %sysfunc(getoption(ls));
+%let savenote = %sysfunc(getoption(notes));
+
+options nonotes;
+data _null_;
+ retain kl 0;
+ length fn $ 40;
+ infile "&listingdir/_tmp" lrecl=%eval(&ls+1) pad;
+ input line $char%eval(&ls+1).;
+ page = substr(line, 1, 1) eq '0C'x;
+ if _n_ eq 1 or page then do;
+ ext = 'lst';;
+ fn = ext || "/&_ads_printfname";
+ if page then line = substr(line, 2);
+ if kl then fn = compress(fn || put(kl, 5.) || '.' || ext);
+ else fn = compress(fn || '.' || ext);
+ kl + 1;
+ put 'Note: Writing Print file: ' fn;
+ end;
+ file x filevar=fn nopad;
+ l = length(line);
+ put line $varying. l;
+ run;
+
+options &savenote &_ads_savesize;
+
+filename __f "&listingdir/_tmp";
+data _null_; rc = fdelete('__f'); run;
+%mend;
+
+*------------------------------------------------------------------------;
+
+ /*---------------------------------------------*/
+ /* The STARTLOG macro starts the capture of */
+ /* the SAS log. */
+ /*---------------------------------------------*/
+%macro startlog(fname);; /* is a required keyword that specifies the */
+ /* first level of the output file name. This */
+ /* name will appear at the end of the \Listing */
+ /* tag. */
+ /*---------------------------------------------*/
+%global __fname __ls;
+%let __fname=&fname;
+%let __ls = %sysfunc(getoption(ls));
+
+options nostimer nosource2 nosource;
+proc printto log="&listingdir/__tmp" new; run;
+%mend;
+
+
+ /*---------------------------------------------*/
+ /* The ENDLOG macro ends the capture of the */
+ /* SAS log. */
+ /*---------------------------------------------*/
+%macro endlog(store=1, /* set STORE=0 to capture messages only and */
+ /* not code. */
+ range=1);; /* Specify a Boolean expression to select only */
+ /* certain observations. Examples: */
+ /* RANGE=_n_ < 5, */
+ /* RANGE=not index(line, 'ERROR'). */
+ /*---------------------------------------------*/
+
+%local savenote;
+%let savenote = %sysfunc(getoption(stimer)) %sysfunc(getoption(source2))
+ %sysfunc(getoption(source));
+
+proc printto log=log; run;
+
+options stimer source2 source;
+
+data _null_;
+ infile "&listingdir/__tmp" lrecl=%eval(&__ls+4) pad;
+ input line $char&__ls..;
+ if anycntrl(line) = 0;
+ %if &store %then %do;
+ if index(line, '%endlog') = 0;
+ %end;
+ %else %do;
+ if not (n(input(scan(line, 1, ' +'), ?? 12.)) and
+ compress(line, ' 0123456789') =: '+');
+ %end;
+ if &range;
+ file "&listingdir/&__fname..lst" lrecl=%eval(&__ls+4);
+ put line $char&__ls..;
+ run;
+
+filename __f "&listingdir/__tmp";
+data _null_; rc = fdelete('__f'); run;
+
+options &savenote;
+%mend;
+
+*------------------------------------------------------------------------;
+
+* This utility macro stores in the out macro variable the
+ object name with pounds and such to match the name in the document.;
+%macro ads_expand_obj(out, in);
+ length _w $ 200;
+ &out = ' ';
+ do _j = 1 to 32500 until(_w = ' ');
+ _w = scan(&in, _j, '.');
+ if _w ne ' ' then do;
+ if not index(_w, '#') then _w = trim(_w) || '#1';
+ &out = trim(&out) || '\' || _w;
+ end;
+ end;
+ &out = substr(&out, 3);
+ %mend;
+
+* This utility macro stores in the out macro variable the last n levels
+ (for an object with n levels) from the path.;
+%macro ads_extr_path(out, path, object);
+ _levs = 1 + length(&object) - length(compress(&object, '.'));
+ call scan(&path, -_levs, _p, _len, '\');
+ &out = lowcase(substr(&path, max(_p, 1)));
+ if substr(&out, 1, 1) eq '\' then &out = substr(&out, 2);
+ %mend;
+
+*------------------------------------------------------------------------;
+
+* 'this macro creates a directory if needed and deletes files with the
+given extension to insure the directory exists and is empty of output files.;
+
+%macro cleandir(droot, dname, ext);
+ %local saveopts;
+ %let saveopts = %sysfunc(getoption(notes));
+ options nonotes;
+ data _null_;
+ length ext $ 5 ;
+ droot = symget('droot');
+ dname = symget('dname');
+ ext = cats('.', upcase(symget('ext')));
+ dpath = cats(droot, '/', dname);
+
+ rc = filename('dref', droot);
+ rc = fexist('dref');
+ if rc eq 0 then do;
+ put 'ERROR: Directory ' droot 'not found.';
+ stop;
+ end;
+
+ rc = filename('dref', dpath);
+ rc = fexist('dref');
+ if rc eq 0 then do;
+ dpath = dcreate(dname, droot);
+ rc2 = filename('dreff', dpath);
+ rc2 = fexist('dreff');
+ if rc2 eq 0 then do;
+ put 'ERROR: Directory ' dpath 'not created.';
+ stop;
+ end;
+ else do;
+ put 'Note: Directory ' dpath 'created.';
+ end;
+ end;
+ else do;
+ rc = filename('dreff', dpath);
+ did = dopen('dreff');
+ if rc or not did then do;
+ put 'ERROR: Directory ' dpath 'not found.';
+ stop;
+ end;
+ do i = 1 to dnum(did); /* Loops through entire directory */
+ file = dread(did, i);
+ if index(upcase(file), ext) then do; /* file ends in dot extension */
+ rc = filename('fref', cats(dpath, '/', file));
+ rc = fdelete('fref');
+ end;
+ end;
+ rc = dclose(did);
+ end;
+ run;
+ options &saveopts;
+%mend cleandir;
+
+
diff --git a/macros/latex/contrib/statrep/sas/statrep_tagset.sas b/macros/latex/contrib/statrep/sas/statrep_tagset.sas
new file mode 100644
index 0000000000..819157c07d
--- /dev/null
+++ b/macros/latex/contrib/statrep/sas/statrep_tagset.sas
@@ -0,0 +1,566 @@
+proc template;
+ define style styles.StatRep;
+ parent = styles.statistical;
+ class colors /
+ 'link2' = cx0000FF
+ 'link1' = cx800080
+ 'docbg' = cxFFFFFF
+ 'contentbg' = cxFFFFFF
+ 'systitlebg' = cxFFFFFF
+ 'titlebg' = cxFFFFFF
+ 'proctitlebg' = cxFFFFFF
+ 'headerbg' = cxFFFFFF
+ 'captionbg' = cxFFFFFF
+ 'captionfg' = cx000000
+ 'bylinebg' = cxFFFFFF
+ 'notebg' = cxFFFFFF
+ 'tablebg' = cxFFFFFF
+ 'batchbg' = cxFFFFFF
+ 'systitlefg' = cx000000
+ 'titlefg' = cx000000
+ 'proctitlefg' = cx000000
+ 'bylinefg' = cx000000
+ 'notefg' = cx000000;
+ class Header /
+ color = cx000000
+ backgroundcolor = cxFFFFFF
+ bordercolor = cxB0B7BB
+ bordercollapse = collapse;
+ class RowHeader /
+ color = cx000000
+ backgroundcolor = cxFFFFFF
+ bordercolor = cxB0B7BB
+ bordercollapse = collapse;
+ class Footer /
+ color = cx000000
+ backgroundcolor = cxFFFFFF
+ bordercolor = cxB0B7BB
+ bordercollapse = collapse;
+ class RowFooter /
+ color = cx000000
+ backgroundcolor = cxFFFFFF
+ bordercolor = cxB0B7BB
+ bordercollapse = collapse;
+ class batch /
+ borderwidth = 0px;
+ class Data /
+ font = fonts('DocFont')
+ backgroundcolor = _undef_
+ bordercolor = cx919191
+ bordercollapse = collapse;
+ class DataEmphasis /
+ font = fonts('DocFont')
+ backgroundcolor = _undef_
+ bordercolor = cx919191
+ bordercollapse = collapse;
+ end;
+run;
+
+proc template;
+define tagset Tagsets.StatRep;
+ notes "This is the StatRep LaTeX definition";
+
+ define event initialize;
+ trigger set_options;
+ end;
+
+ define event set_options;
+ set $options["junk" ] "junk" /if ^$options;
+ unset $cell_align;
+
+ do /if cmp( $options["CELL_ALIGN"], "yes");
+ set $cell_align "True";
+ done;
+
+ end;
+
+ define event title_format_section;
+ put value;
+ end;
+
+ define event cell_is_empty;
+ put " ";
+ end;
+
+ define event list;
+ start:
+ put "\begin{itemize}" NL;
+
+ finish:
+ put "\end{itemize}" NL;
+ end;
+
+ define event list_item;
+ put "\item ";
+ end;
+
+ define event list_entry;
+ put "\item ";
+ end;
+
+ define event image;
+ put "\sasgraph{";
+ put BASENAME /if ^exists( NOBASE);
+ put URL;
+ put "}" NL;
+ end;
+
+ define event line;
+ put "\rule{\linewidth}{" colwidth;
+ put "pt}" NL;
+ end;
+
+ define event text;
+ start:
+ put "\par " NL;
+ end;
+
+ define event paragraph;
+ start:
+ put VALUE;
+ put NL;
+ put NL;
+ end;
+
+ define event preformat;
+ start:
+ put "\verb?" NL;
+
+ finish:
+ put "?" NL;
+ end;
+
+ define event center;
+ start:
+ put "\begin{center}" NL;
+
+ finish:
+ put "\end{center}" NL;
+ end;
+
+ define event styles;
+ start:
+ put NL;
+ put "\RequirePackage[T1]{fontenc}" NL;
+ put "\RequirePackage{times}" NL;
+ put "\RequirePackage{fancyvrb}" NL;
+ put "\RequirePackage{array}" NL;
+ put "\RequirePackage{graphicx}" NL;
+ put NL;
+ put "\newbox\sas@fig" NL;
+ put "\newlength\sas@figwidth" NL;
+ put NL;
+ put "\newif\ifsas@color" NL;
+ put "\sas@colorfalse" NL;
+ put NL;
+ put "\DeclareOption{color}{\sas@colortrue}" NL;
+ put "\ProcessOptions" NL;
+ put NL;
+
+ finish:
+ put %nrstr("%% Set cell padding") NL;
+ put "\renewcommand{\arraystretch}{1.3}" NL NL;
+ put %nrstr("%% Headings") NL;
+ put %nrstr("\newcommand{\sasheading}[3][c]{{%%") NL;
+ put %nrstr(" \if#1r\flushright\else\if#1l\flushleft\else\centering\fi\fi%%") NL;
+ put %nrstr(" {\csname sasS#2\endcsname #3}\mbox{}\\[0.1\baselineskip]%%") NL;
+ put %nrstr(" \if#1r\endflushright\else\if#1l\endflushleft\else\fi\fi%%") NL;
+ put "}}" NL;
+ put NL;
+ put "\newcommand{\sasbyline}[2][c]{\sasheading[#1]{byline}{#2}}" NL;
+ put "\newcommand{\sassystemtitle}[2][c]{\sasheading[#1]{systemtitle}{#2}}" NL;
+ put "\newcommand{\sassystemfooter}[2][c]{\sasheading[#1]{systemfooter}{#2}}" NL;
+ put "\newcommand{\sasproctitle}[2][c]{\sasheading[#1]{proctitle}{#2}}" NL;
+ put "\newcommand{\sascaption}[2][l]{\marginpar[#1]{\fbox{\parbox{0.7in}{\sasScaption{#2}}}}}" NL;
+ put NL;
+ put %nrstr("%% Declare new verbatim type") NL;
+ put %nrstr("\DefineVerbatimEnvironment{sasverbatim}{BVerbatim}%%") NL;
+ put " {fontsize=\footnotesize," NL;
+ put " commandchars=\\\{\}," NL;
+ put " formatcom=\sasSbatch}" NL;
+ put NL;
+ put %nrstr("%% Declare new column types") NL;
+ put "\newcolumntype{S}[2]{>{\csname sasS#1\endcsname}#2}" NL;
+ put "\newcolumntype{d}{r}" NL;
+ put NL;
+ put %nrstr("%% Set warning box style") NL;
+ put "\newlength\notewidth" NL;
+ put "\setlength\notewidth{4in}" NL;
+ put "\newcommand*{\saswarn}[2][c]{\sasmsg{warn}{#1}{#2}}" NL;
+ put "\newcommand*{\saserror}[2][c]{\sasmsg{error}{#1}{#2}}" NL;
+ put "\newcommand*{\sasnote}[2][c]{\sasmsg{note}{#1}{#2}}" NL;
+ put "\newcommand*{\sasfatal}[2][c]{\sasmsg{fatal}{#1}{#2}}" NL;
+ put %nrstr("\newcommand*{\sasmsg}[3]{%%") NL;
+ put %nrstr(" \ifsas@color\let\columncolor\undefined\fi%%") NL;
+ put %nrstr(" \begin{center}%%") NL;
+ put %nrstr(" \begin{tabular}{ll}\hline%%") NL;
+ put %nrstr(" \multicolumn{1}{|S{#1banner}{p{0.7in}}|}{#1} & %%") NL;
+ put %nrstr(" \multicolumn{1}{|S{#1content}{p{\notewidth}}|}{#3{\newline}}\\\hline%%") NL;
+ put %nrstr(" \end{tabular}%%") NL;
+ put %nrstr(" \end{center}%%") NL;
+ put %nrstr(" \ifsas@color\let\columncolor\sascolumncolor\fi%%") NL;
+ put "}" NL;
+ put NL;
+ put "\ifsas@color\RequirePackage{colortbl}\fi" NL;
+ put NL;
+ put %nrstr("%% Hack colortbl to allow \columncolor in macros") NL;
+ put "\let\CT@extract@org\CT@extract" NL;
+ put "\def\CT@extract{\futurelet\CT@NEXT\CT@extract@next}" NL;
+ put %nrstr("\def\CT@extract@next{%%") NL;
+ put " \ifx\CT@NEXT\csname" NL;
+ put %nrstr(" \@ReturnAfterFi{%%") NL;
+ put " \expandafter\expandafter\expandafter" NL;
+ put %nrstr(" }%%") NL;
+ put " \fi" NL;
+ put " \CT@extract@org" NL;
+ put "}" NL;
+ put "\long\def\@ReturnAfterFi#1\fi{\fi#1}" NL;
+ put "" NL;
+ put "\ifsas@color" NL;
+ put "" NL;
+ put " \newcommand{\foreground}[1]{\color[rgb]{#1}}" NL;
+ put " \newcommand{\sascolumncolor}[2][]{}" NL;
+ put " \let\columncolor\sascolumncolor" NL;
+ put " \newcommand{\documentforeground}[1]{\AtBeginDocument{\color[rgb]{#1}}}" NL;
+ put " \newcommand{\documentbackground}[1]{\AtBeginDocument{\pagecolor[rgb]{#1}}}" NL;
+ put " \def\sastable{\let\columncolor\undefined\tabular}" NL;
+ put " \def\endsastable{\endtabular\let\columncolor\sascolumncolor}" NL;
+ put " \def\stackedcell{\bgroup\renewcommand{\arraystretch}{1}\tabular}" NL;
+ put " \def\endstackedcell{\endtabular\egroup}" NL;
+ put NL;
+ put "\else" NL;
+ put NL;
+ put " \providecommand{\foreground}[1]{}" NL;
+ put " \providecommand{\color}[2][]{}" NL;
+ put " \newcommand{\sascolumncolor}[2][]{}" NL;
+ put " \let\columncolor\sascolumncolor" NL;
+ put " \newcommand{\documentforeground}[1]{}" NL;
+ put " \newcommand{\documentbackground}[1]{}" NL;
+ put " \def\sastable{\tabular}" NL;
+ put " \def\endsastable{\endtabular}" NL;
+ put " \def\stackedcell{\bgroup\renewcommand{\arraystretch}{1}\tabular}" NL;
+ put " \def\endstackedcell{\endtabular\egroup}" NL;
+ put "" NL;
+ put "\fi" NL;
+ put NL;
+ put %nrstr("%%\let\sasgraph\includegraphics") NL;
+ put %nrstr("%% Scale graphics so they always fit on the page") NL;
+ put %nrstr("\newcommand\sasgraph[2][]{%%") NL;
+ put %nrstr(" \savebox{\sas@fig}{\includegraphics[#1]{#2}}%%") NL;
+ put %nrstr(" \settowidth{\sas@figwidth}{\usebox{\sas@fig}}%%") NL;
+ put %nrstr(" \ifthenelse{\lengthtest{\sas@figwidth > \textwidth}}{%%") NL;
+ put %nrstr(" \resizebox{0.95\textwidth}{!}{\usebox{\sas@fig}}}{%%") NL;
+ put " \usebox{\sas@fig}}" NL;
+ put "}" NL;
+ put NL;
+ end;
+
+ define event style_class;
+ start:
+ put "\def\sasS" lowcase(HTMLCLASS) %nrstr("{%%") NL;
+ put " " FONT_SIZE %nrstr("%%") NL /if exists( FONT_SIZE);
+ put " " FONT_WEIGHT %nrstr("%%") NL /if exists( FONT_WEIGHT);
+ put " " FONT_STYLE %nrstr("%%") NL /if exists( FONT_STYLE);
+ put " " FONT_FACE %nrstr("%%") NL /if exists( FONT_FACE);
+ put " \color[rgb]{" FOREGROUND %nrstr("}%%") NL /if exists( foreground);
+ put " \columncolor[rgb]{" BACKGROUND %nrstr("}%%") NL /if exists( background);
+ set $foreground foreground /if cmp( htmlclass, "body");
+ set $background background /if cmp( htmlclass, "body");
+
+ finish:
+ put "}" NL;
+ end;
+
+ define event caption;
+ start:
+ set $sascaption "true";
+ block table;
+ block row;
+ block colspecs;
+ block colspec_entry;
+ put "\sascaption[";
+ put "l" /if cmp( TYPE, "L");
+ put "r" /if cmp( TYPE, "R");
+ put "b" /if cmp( TYPE, "B");
+ put "t" /if cmp( TYPE, "T");
+ put "]{";
+
+ finish:
+ put "}" NL;
+ unblock table;
+ unblock row;
+ unblock colspecs;
+ unblock colspec_entry;
+ set $sascaption "false";
+ end;
+
+ define event table;
+ start:
+ put NL;
+ put NL;
+ put "\begin{sastable}";
+
+ trigger alignment;
+
+ finish:
+ put "\end{sastable}" NL;
+ put NL;
+ end;
+
+ define event verbatim_text;
+ put VALUE;
+ put NL;
+ end;
+
+ define event verbatim_container;
+ start:
+ put NL;
+ put NL;
+ put "\begin{center}" NL /if cmp( just, "c");
+ put "\begin{sasverbatim}" NL;
+
+ finish:
+ put "\end{sasverbatim}" NL;
+ put "\end{center}" NL /if cmp( just, "c");
+ put NL;
+ end;
+
+ define event alignment;
+ start:
+ put "[c]" /if cmp( just, "c");
+ put "[c]" /if cmp( just, "d");
+ put "[r]" /if cmp( just, "r");
+ put "[l]" /if cmp( just, "l");
+ flush;
+ end;
+
+ define event colspecs;
+ start:
+ put "{";
+
+ finish:
+ put "}\hline" NL;
+ end;
+
+ define event colspec_entry;
+ put just /if ^cmp( just, "d");
+ put "r" /if cmp( just, "d");
+ end;
+
+ define event row;
+
+ finish:
+ put NL "\\\hline" NL;
+ end;
+
+ define event rowspanfillsep;
+ put %nrstr(" & ") NL;
+ end;
+
+ define event rowspancolspanfill;
+ put " ";
+ put "\multicolumn{";
+ put colspan;
+ put "1" /if ^exists( colspan);
+ put "}";
+ put "{|S{";
+ put lowcase(HTMLCLASS);
+ put "data" /if ^htmlclass;
+ put "}{";
+ put just;
+ put "}|}{~}";
+ end;
+
+ define event header;
+ start:
+
+ trigger data;
+
+ finish:
+
+ trigger data;
+ end;
+
+ define event data;
+ start:
+ put VALUE /if cmp( $sascaption, "true");
+ break /if cmp( $sascaption, "true");
+ put %nrstr(" & ") NL /if ^cmp( COLSTART, "1");
+ put " ";
+ put "\multicolumn{";
+ put colspan;
+ put "1" /if ^colspan;
+ put "}";
+ put "{";
+ put "|" /if ^$instacked;
+ put "S{";
+ put lowcase(HTMLCLASS);
+ put "}{";
+ put just;
+ put "}";
+ put "|" /if ^$instacked;
+ put "}";
+ put "{";
+ put tranwrd(VALUE,"-","$-$") /if contains( lowcase(HTMLCLASS), "data");
+ put VALUE /if ^contains( lowcase(HTMLCLASS), "data");
+
+ finish:
+ break /if cmp( $sascaption, "true");
+ put "}";
+ end;
+
+ define event data_note;
+ start:
+
+ trigger data;
+
+ finish:
+
+ trigger data;
+ end;
+
+ define event stacked_cell;
+ start:
+ put NL;
+ put "\begin{stackedcell}";
+
+ trigger alignment;
+
+ finish:
+ put "\end{stackedcell}" NL;
+ end;
+
+ define event stacked_value;
+ start:
+ unset $instacked;
+ set $instacked "true";
+
+ trigger data;
+
+ finish:
+
+ trigger data;
+ unset $instacked;
+ end;
+
+ define event stacked_value_header;
+ start:
+
+ trigger stacked_value;
+
+ finish:
+
+ trigger stacked_value;
+ end;
+
+ define event stacked_cell_colspecs;
+ start:
+ put "{";
+
+ finish:
+ put "}" NL;
+ end;
+
+ define event stacked_cell_colspec_entry;
+ put just /if ^cmp( just, "d");
+ put "r" /if cmp( just, "d");
+ end;
+
+ define event stacked_cell_row;
+
+ finish:
+ put NL "\\" NL;
+ end;
+
+ define event put_value;
+ put VALUE;
+ end;
+
+ define event put_value_cr;
+ put VALUE NL;
+ end;
+
+ define event byline;
+ put NL;
+ put "\sasbyline";
+
+ trigger alignment;
+ put "{";
+ put VALUE;
+ put "}" NL;
+ end;
+
+ define event proc_title;
+ put "\sasproctitle";
+
+ trigger alignment;
+ put "{";
+ put VALUE;
+ put "}" NL;
+ end;
+
+ define event note;
+ put "\sasnote";
+
+ trigger alignment;
+ put "{";
+ put VALUE;
+ put "}" NL;
+ end;
+
+ define event Error;
+ put "\saserror";
+
+ trigger alignment;
+ put "{";
+ put VALUE;
+ put "}" NL;
+ end;
+
+ define event Warn;
+ put "\saswarn";
+
+ trigger alignment;
+ put "{";
+ put VALUE;
+ put "}" NL;
+ end;
+
+ define event Fatal;
+ put "\sasfatal";
+
+ trigger alignment;
+ put "{";
+ put VALUE;
+ put "}" NL;
+ end;
+
+ define event system_title;
+ put "\sassystemtitle";
+
+ trigger alignment;
+ put "{";
+ put VALUE;
+ put "}" NL;
+ end;
+
+ define event system_footer;
+ put "\sassystemfooter";
+
+ trigger alignment;
+ put "{";
+ put VALUE;
+ put "}" NL;
+ end;
+
+ image_formats = "png,pdf";
+ split = " {\newline} ";
+ nobreakspace = "~";
+ mapsub = %nrstr("/\%%/\$/\&/\{/\}/\~/\^/\#/{\textunderscore}/{\textbackslash}/");
+ map = %nrstr("%%$&{}~^#_\");
+ output_type = "latex";
+ stacked_columns = OFF;
+ embedded_stylesheet;
+ private;
+end;
+run;