It looks like:
1- Macro variables don't like storing non-printable characters.
2- SQL in V9.1 doesn't like a missing 2nd parameter in the compress function
3- Even if the 2nd parameter is not missing, the 3rd parameter 'c' is not honoured in SQL V9.1
So you must store hex values instead of actual values in your macro variable.
You can do this with a data step or with a macro:
[pre]
data _null_;
length TXT $64;
do I=0 to 31;
TXT=put(I,hex2.)||TXT;
end;
call symput('CTRL_CHAR1',TXT);
run;
%macro concat_ctrl;
%global CTRL_CHAR2;
%do i=0 %to 31;
%let CTRL_CHAR2=&CTRL_CHAR2%sysfunc(putn(&i,hex2.));
%end;
%mend;
%concat_ctrl;
ods html;
proc sql; * '21'x is the ! character;
select compress('210A21'x, "&CTRL_CHAR1"x) as GOOD_DATA_VAR from sashelp.class(obs=1);
select compress('210A21'x, "&CTRL_CHAR2"x) as GOOD_MACRO_VAR from sashelp.class(obs=1);
select compress('210A21'x, ' ','c') as BAD_C_PARAM from sashelp.class(obs=1);
quit;
data TEST;
GOOD_C_PARAM=compress('210A21'x, , 'c');
proc print noobs;
run;
ods html close;
[/pre]
yields (note how the non-printable character 0A (in the middle) is still in the 3rd output):
[pre]
GOOD_DATA_VAR
!!
GOOD_MACRO_VAR
!!
BAD_C_PARAM
! !
GOOD_C_PARAM
!!
[/pre]