- Processing on disk occurred during summarization. Peak disk usage was approximately nnn Mbytes. Adjusting SUMSIZE may improve performance.
- NOTE: 要約化中にディスク処理が発生しました。 ディスクの最大使用はおよそ 2454 M バイトです。 SUMSIZE の調整によって、パフォーマンスを改善できるかもしれません。
SASプログラムとログを解析するユーティリティを開発するための備忘録です。This is a memo to develop utility that analyzes the SAS log.
2013年11月5日火曜日
NOTE: 要約化中にディスク処理が発生しました。
時間が出来たときに、ツールで以下のメッセージを捕捉するように修正する。
Calls a specific routine or module that resides in an external dynamic link library (DLL).
SASからWindowsのAPIを呼び出す方法を整理しています。
その理由を列挙しますと
VBScriptから制御する手もありますが、古いデータセットから順に移行したり、停止の制御を考えるとSAS1本でやるのが良さそうです。
基本はDLLを呼び出すためのI/Fを"The SASCBTBL Attribute Table"で定義して、MODULE関数で呼び出します。この仕組みが繊細で、定義を間違えるとSAS.EXEが落ちます。WinAPIの型を調べて、変数を割り当てるのは面倒な作業です。
その理由を列挙しますと
- SASのバージョンアップの作業で、Xステートメントが規制されている
- SASデータセットをCOPYプロシージャで移行するとタイムスタンプが維持できない
- タイムスタンプが変わると元ファイルが更新されたときに再転送が必要かわからない
- DOS窓からの実行だと遅い
VBScriptから制御する手もありますが、古いデータセットから順に移行したり、停止の制御を考えるとSAS1本でやるのが良さそうです。
基本はDLLを呼び出すためのI/Fを"The SASCBTBL Attribute Table"で定義して、MODULE関数で呼び出します。この仕組みが繊細で、定義を間違えるとSAS.EXEが落ちます。WinAPIの型を調べて、変数を割り当てるのは面倒な作業です。
2013年11月4日月曜日
SASからCopyFileAを呼び出して、ファイルをコピー
SASからWindowsのAPIをコールするサンプルコードです。バージョンアップによるデータの引越しで、今回はWinAPIを使ったツールを作る予定です。動作確認したのは、Windows7+SAS9.2です。
ネットにはいくつか見本が転がっていますが、PDFで文字が化けていたり、APIがまったく変わってしまったようなものもあります。素直に動くものが少ないので、いくつかの手本を元に作成しました。APIの定義をテキストで別に用意している例が多いのですが、カタログを使った例がまとまりが良いです。
ネットにはいくつか見本が転がっていますが、PDFで文字が化けていたり、APIがまったく変わってしまったようなものもあります。素直に動くものが少ないので、いくつかの手本を元に作成しました。APIの定義をテキストで別に用意している例が多いのですが、カタログを使った例がまとまりが良いです。
/*
*++
* WinAPI(CopyFileA)を呼び出して、ファイルをコピー
*--
*/
filename winapi catalog 'WORK.Windows.WINAPI.SOURCE';
data _null_;
file winapi;
input;
put _infile_;
cards4;
routine CopyFileA
module=KERNEL32
minarg=3 maxarg=3 stackpop=called
returns=ushort
;
arg 1 input char format=$cstr200.; * FROM ;
arg 2 input char format=$cstr200.; * TO ;
arg 3 input num format=pib4. byvalue;
* 1=Do Not Overwrite Existing ;
* 0=Overwrite Existing File ;
;;;;
run;
filename winapi;
filename sascbtbl catalog 'WORK.Windows.WINAPI.SOURCE';
data _null_;
rc = modulen('*e', 'CopyFileA', 'c:\temp\foo.txt', 'c:\temp\foo_copy.txt', 0);
put _all_;
run;
filename sascbtbl clear;
SASからSetFileTimeを呼び出して、ファイルのタイムスタンプを設定
コードに間違いがあったので修正しました。
SASからWindowsのAPIをコールするサンプルコードです。バージョンアップによるデータの引越しで、今回はWinAPIを使ったツールを作る予定です。動作確認したのは、Windows7+SAS9.2です。ネットにはいくつか見本が転がっていますが、PDFでうまく転記できなかったり、APIがまったく変わってしまったようなものもありました。
SASからWindowsのAPIをコールするサンプルコードです。バージョンアップによるデータの引越しで、今回はWinAPIを使ったツールを作る予定です。動作確認したのは、Windows7+SAS9.2です。ネットにはいくつか見本が転がっていますが、PDFでうまく転記できなかったり、APIがまったく変わってしまったようなものもありました。
/*
*++
* WinAPI(SetFileTime)を呼び出して、ファイルのタイプスタンプを更新
*--
*/
filename winapi catalog 'WORK.Windows.WINAPI.SOURCE';
data _null_;
file winapi;
input;
put _infile_;
cards4;
routine CreateFileA
module=Kernel32
minarg=7
maxarg=7
stackpop=called
returns=long
;
arg 1 char input format=$cstr260.; * LPCTSTR lpFileName;
arg 2 num input format=pib4. byvalue; * DWORD dwDesiredAccess;
arg 3 num input format=pib4. byvalue; * DWORD dwShareMode;
arg 4 num input format=pib4. byvalue; * LPSECURITY_ATTRIBUTES lpSecurityAttributes (set to null,pass 0 byvalue);
arg 5 num input format=pib4. byvalue; * DWORD dwCreationDispostion;
arg 6 num input format=pib4. byvalue; * DWORD dwFlagsAndAttributes (set to zero);
arg 7 num input format=pib4. byvalue; * HANDLE hTemplateFile (ignored);
*-------------------------------------------------------------;
routine CloseHandle
module=Kernel32
minarg=1
maxarg=1
stackpop=called
returns=long
;
arg 1 num input format=pib4. byvalue; * HANDLE hObject;
*-------------------------------------------------------------;
routine SystemTimeToFileTime
minarg=9
maxarg=9
stackpop=called
module=Kernel32
returns=long
;
arg 1 num input fdstart format=pib2.; * WORD wYear ;
arg 2 num input format=pib2.; * WORD wMonth ;
arg 3 num input format=pib2.; * WORD wDayOfWeek ;
arg 4 num input format=pib2.; * WORD wDay ;
arg 5 num input format=pib2.; * WORD wHour ;
arg 6 num input format=pib2.; * WORD wMinute ;
arg 7 num input format=pib2.; * WORD wSecond ;
arg 8 num input format=pib2.; * WORD wMilliseconds ;
arg 9 num output fdstart format=pib8.;
*-------------------------------------------------------------;
routine LocalFileTimeToFileTime
minarg=2
maxarg=2
stackpop=called
module=kernel32
returns=long
;
arg 1 input fdstart num format=pib8.; * lpLocalFileTime // converted file time;
arg 2 output fdstart num format=pib8.; * lpFileTime, // UTC file time to convert;
*-------------------------------------------------------------;
routine SetFileTime
minarg=4
maxarg=4
stackpop=called
module=Kernel32
returns=long
;
arg 1 num input byvalue format=pib4.; * HANDLE hFindFile // file search handle ;
arg 2 num input fdstart format=pib8.; * CONST FILETIME * lpCreationTime, // pointer to creation file time ;
arg 3 num input fdstart format=pib8.; * CONST FILETIME * lpModifiedTime, // pointer to creation file time ;
arg 4 num input fdstart format=pib8.; * CONST FILETIME * lpAccessedTime, // pointer to creation file time ;
;;;;
run;
filename winapi;
filename sascbtbl catalog 'WORK.Windows.WINAPI.SOURCE';
%macro touch(path=, year=);
data _null_ ;
GENERIC_READ = 080000100x; /* GENRIC_READ + FILE_WRITE_ATTRIBUTES(0x0100) */
FILE_SHARE_READ = 1;
OPEN_EXISTING = 3;
length path $260;
path = "&path";
HANDLE = modulen('CreateFileA', path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0,0);
If HANDLE >= 1 Then Do;
cdt_n = datetime();
MINUTE = Minute( cdt_n);
HOUR = Hour( cdt_n);
DAY = DAY( DatePart( cdt_n) );
DAYOFWK = WeekDay( DatePart( cdt_n) );
MONTH = MONTH( DatePart( cdt_n) );
YEAR = &year;
SECONDS = 0;
MSECONDS = 0;
CREATED = .;
CREATED1 = .;
rc = ModuleN('SystemTimeToFileTime', YEAR, MONTH, DAYOFWK, DAY, HOUR, MINUTE, SECONDS, MSECONDS, CREATED);
rc = ModuleN('LocalFileTimeToFileTime', CREATED, CREATED1);
put rc= created= created1=;
ACCESSE1 = CREATED1;
WRITTEN1 = CREATED1;
rc = ModuleN('SetFileTime', HANDLE, CREATED1, ACCESSE1, WRITTEN1);
put rc=;
rc = Modulen('CloseHandle', HANDLE);
put rc=;
end;
run;
%mend;
%touch(path=c:\temp\foo.txt, year=2009);
filename sascbtbl clear;
2013年9月23日月曜日
Delphi for Lex(6)
メモです。
集合型の演算でマッチングの文字列を計算していることがわかり、Unicodeの多彩な文字をどうやって吸収するか検討しています。アイディアとしては、- パターンを保持する集合型を文字列に変える
- パターンを保持する集合型を正規表現に変える
- 今のCClassを拡張して日本語の文字を識別する部分を作る
Unicodeの文字を判定する、IsControlやIsNumberを試してみたが、"1"も"1"同じ数値として判定されてしまう。if ByteType(S, i) <> mbSingleByte という条件判定で使うが、SをAnsiStringに型変換する必要がある。
2013年9月19日木曜日
Lex for Delphi(5)
忙しいなかやる気を持続させるために、まめにBlogに書き込んでします。いま一度、字句解析のコードを修正前後で比較します。文字の集合型で表している部分を、文字列に直します。元のプログラムはASCIIで#0...#255の範囲を想定しています。Unicode対応するときに、集合型から文字列に置き換えるだけでよいのか、検証していきます。
正規表現で「以下の文字を含まない」とか「改行以外の文字」を表すときに、Unicodeだとうまく集合型に収まらないのでなんらか工夫が必要だと認識しました。
2013年9月18日水曜日
Lex for Delphi(4)
考えを整理するために、修正すべきコードwriteccを貼り付けます。
実装でわかっていないのは、字句定義で"\t"としたときに、引数ccにはどのようなコード値で表されるかです。集合型から文字列に変えるのですが、ASCIIのコード値(#9)は、そのままUnicodeのコード値と同じで良いのか?BOMとか、非表示の文字を読み込んだらどうなるのか?さっぱりわかっていません。週末にでも、テストコードを書いて検証します。
function charStr(c: char): string;
begin
case c of
#0..#31, (* nonprintable characters *)
#127..#255: Result := '#' + intStr(Ord(c));
'''': Result := '''''''''';
else Result := '''' + c + '''';
end;
end(*charStr*);
procedure writecc(var f: Text; cc: CClass);
(* print the given character class *)
const
MaxChar = #255;
var
c1, c2: char;
col: integer;
tag: string;
Quit: boolean;
begin
Write(f, '[ ');
col := 0;
c1 := chr(0);
Quit := False;
while not Quit do
begin
if c1 in cc then
begin
if col > 0 then
begin
Write(f, ',');
Inc(col);
end;
if col > 40 then
{ insert line break }
begin
writeln(f);
Write(f, ' ': 12);
col := 0;
end;
c2 := c1;
while (c2 < MaxChar) and (succ(c2) in cc) do
c2 := succ(c2);
if c1 = c2 then
tag := charStr(c1)
else if c2 = succ(c1) then
tag := charStr(c1) + ',' + charStr(c2)
else
tag := charStr(c1) + '..' + charStr(c2);
Write(f, tag);
col := col + length(tag);
c1 := c2;
end;
Quit := c1 = MaxChar;
if not Quit then
c1 := Succ(c1);
end; { of while }
Write(f, ' ]');
end(*writecc*);
引数ccで渡された集合型の文字を、印字可能なものならばそのまま出力、印字できない文字ならば数値化しています。
文字の範囲を0から255のコードを前提とした実装です。ASCIIで連続したコード値であれば、'A'...'Z'の形式で出力します。実装でわかっていないのは、字句定義で"\t"としたときに、引数ccにはどのようなコード値で表されるかです。集合型から文字列に変えるのですが、ASCIIのコード値(#9)は、そのままUnicodeのコード値と同じで良いのか?BOMとか、非表示の文字を読み込んだらどうなるのか?さっぱりわかっていません。週末にでも、テストコードを書いて検証します。
登録:
投稿
(
Atom
)
