見出し画像

Notes C API探訪: @式のデコンパイル

コンパイルしてバイナリ形式になった@式は、式ハンドルとして扱います。元のテキスト形式からは独立した状態になるわけです。バイナリ形式の@式からテキスト形式の@式を得る、デコンパイルするための関数が用意されています。

NSFFormulaDecompile

NSFFormulaDecompile関数は、ロックしたバイナリ形式のポインタを渡すと、デコンパイルされてテキスト形式の文字列を得られます。

#include <nsfsearch.h>
STATUS LNPUBLIC NSFFormulaDecompile(
  char far *pFormulaBuffer,
  BOOL fSelectionFormula,
  DHANDLE far *rethFormulaText,
  WORD far *retFormulaTextLength);

pFormulaBufferは、式ハンドルのロック済みバイナリ形式のポインタを指定します。
fSelectionFormulaは、ビューの選択式アイテム「$Formula」のデコンパイル時にはTRUEを指定します。
rethFormulaTextは、テキスト形式のデータ(LMBCS文字列)を持つメモリハンドルを返す変数へのポインタを指定します。
retFormulaTextLengthは、返ってきたハンドルが持つメモリサイズを返す変数へのポインタを指定します。データタイププレフィックスはないので、この長さがそのままLMBCS文字列の長さになります。

サンプルコード

#include <iostream>
#include "logger.h"

#ifdef NT
#pragma pack(push, 1)
#endif

#include <nsfsearc.h>
#include <osmem.h>

#ifdef NT
#pragma pack(pop)
#endif

FORMULAHANDLE compileFormula(const char *text);

void nsfFormulaDecompile() {
 FORMULAHANDLE hFormula = compileFormula("@adjust(@now;1;2;3;4;5;6)");
 if (hFormula == NULLHANDLE) {
   return;
 }
 void *pFormula = OSLockObject(hFormula);
 DHANDLE hText = NULLHANDLE;
 WORD len = 0;
 STATUS status = NSFFormulaDecompile(
       reinterpret_cast<char*>(pFormula),
       FALSE,
       &hText,
       &len);
 if (ERR(status) != NOERROR) {
   logger::printStatusMessage(status);
 }
 else {
   char *pText = reinterpret_cast<char*>(OSLockObject(hText));
   std::cout << "Decompiled: '" << std::string(pText, len) << "'."
             << std::endl;
   OSUnlockObject(hText);
   OSMemFree(hText);
 }
 OSUnlockObject(hFormula);
 OSMemFree(hFormula);
}

FORMULAHANDLE compileFormula(const char *text) {
 FORMULAHANDLE hFormula = NULLHANDLE;
 STATUS compileStatus = NOERROR;
 WORD wLen = 0, wLine = 0, wColumn = 0, wOffset = 0, wOffsetLen = 0;
 std::cout << "Formula is '" << text << "'." << std::endl;
 STATUS status = NSFFormulaCompile(
       nullptr, 0,
       text, static_cast<WORD>(strlen(text)),
       &hFormula,
       &wLen,
       &compileStatus,
       &wLine,
       &wColumn,
       &wOffset,
       &wOffsetLen);
 if (ERR(status) != NOERROR) {
   logger::printStatusMessage(status);
   logger::printStatusMessage(compileStatus);
   std::cout << "Line=" << wLine
             << ", Column=" << wColumn
             << ", Offset=" << wOffset
             << ", OffsetLen=" << wOffsetLen
             << "\n===> "
             << std::string(text).substr(wOffset, wOffsetLen)
             << std::endl;
 }
 return hFormula;
}

関数nsfFormulaDecompileを実行すると、まずテキスト形式の@式をコンパイルしてハンドルを得ます。次にそのハンドルをロックして実ポインタを得ます。実ポインタをデコンパイルすると、テキストハンドルが得られるので、そのハンドルをロックし、その実ポインタからテキストを取得し、標準出力に表示します。あとは、テキストハンドル、@式ハンドルの後始末をして終了します。

@Now関数と@Adjust関数を用いた@式をコンパイルし、デコンパイルした結果は以下の通りです。

Formula is '@adjust(@now;1;2;3;4;5;6)'.
Decompiled: '@Adjust(@Now;1;2;3;4;5;6)'.

小文字で書かれた関数の頭文字が大文字に直っている様子がわかります。@関数は、コンパイルしてしまうと大文字小文字を維持できないんですね。

まとめ

デコンパイルの機会は、ほとんどが「この@式は何か」を表示する、内容を示すということになるでしょう。データベースの解析を進める上では、強力なツールの一つです。

注意: コードの利用においてチブル・システムズは一切の責任を負いません。自己責任でご利用をお願いいたします。

この記事が気に入ったらサポートをしてみませんか?