← 都来码 / Dolaima← 例程索引pascal/test/libs.pas原文

pascal/test/libs.pas · 4706 字节 · 下载原文

{ 共享库一览 —— 用 **Pascal** 把四个共享库各叫一遍
  Shared libraries tour -- calling all four shared libraries from **Pascal**

  ◆ 这份例程在练什么
  * What this example exercises

  共享库是**一次投入、22 门语言都受益**的那种东西:regex(正则)· dbf(dBASE 数据文件)
  · sql(跑在 .dbf 上的查询)· turtle(海龟作图)。它们**不是 Pascal 的库**,
  而是每一门语言都能调的同一份实现 —— 这份例程就是"从 Pascal 这边调得动"的活证据。
  The shared libraries are one investment serving all 22 languages: regex, dbf (dBASE data
  files), sql (queries over .dbf) and turtle. They are not Pascal libraries -- they are one
  implementation every language can call. This example is the living proof that Pascal can.

    regex  : 模式 abc 在 xxabcyy 里**找得到**吗(1 = 找得到)
    dbf    : 现建一张两字段的表、塞两条记录,再看一眼记录数
    sql    : 在刚建的那张表上跑一句 SELECT ... WHERE
    turtle : 抬笔走 50 步,看它的坐标(不写屏幕,所以**不需要开窗口**)

  ◆ 为什么全程只调"返回整数"的那些接口
  * Why only the integer-returning calls

  Pascal 的字符串字面量**取不到可写地址**,而 dbf_get / sql_cell 这类要调用方给 dst。
  所以这里走另一条路:**要缓冲区的地方用 alloc 自己拿一块**(见下面 rec 那几行),
  取值一律用"只问长度"的形态(dbf_fname(h, 0, 0))。
  Pascal string literals give no writable address, and dbf_get / sql_cell need a caller-supplied
  dst. So: take a buffer yourself with alloc (see the rec lines below), and use the
  "length only" form of the accessors (dbf_fname(h, 0, 0)).

  ◆ 本前端的一条写法要求(实测)
  * One writing requirement of this frontend (measured)

    库函数**不需要**声明文件、也**不写 uses** —— 裸调即可(demo_std.pas 里的规矩照旧:
    字符串不用 + 拼,要拼就把几个值分别写进同一个 writeln 实参表)。
    Library functions need **no** declaration file and **no** uses clause -- call them bare.
    (The rule from demo_std.pas still stands: + does not concatenate strings; to join values,
    pass them as separate writeln arguments.)

  ⚠ 跑一次会在**本文件所在目录**建一个 libdemo.dbf(这就是 dbf 那一半在演示的事)。
  ⚠ Running this creates a small libdemo.dbf **next to this file** -- that is the point of it.
}

program libs;

var
  h, rec : integer;

begin
  { ── regex:模式匹配 ── }
  writeln('REGEX_HIT=', re_test('abc', 'xxabcyy'));
  writeln('REGEX_MISS=', re_test('abc', 'xxabxyy'));
  writeln('REGEX_VALID=', re_is_valid('(a|b)+'));

  { ── dbf:建表 → 塞两条 → 读记录数 ──
    字段类型用**字符的字节值**:'C' = 67(字符型)· 'N' = 78(数字型)——
    Pascal 没有字符字面量,所以这里直接写数字。
    Field types are the byte value of the character: 'C' = 67, 'N' = 78 -- Pascal has no
    character literal, so the number goes in directly. }
  h := dbf_new('libdemo.dbf');
  dbf_addfield(h, 'NAME', 67, 8, 0);
  dbf_addfield(h, 'AGE', 78, 3, 0);
  dbf_build(h);

  rec := alloc(64);
  dbf_mkrec(h, rec);
  dbf_put(h, rec, 0, 'Alice');
  dbf_put(h, rec, 1, '30');
  dbf_add(h, rec);
  dbf_mkrec(h, rec);
  dbf_put(h, rec, 0, 'Bob');
  dbf_put(h, rec, 1, '7');
  dbf_add(h, rec);
  dbf_flush(h);

  writeln('DBF_ROWS=', dbf_records(h));
  writeln('DBF_FIELDS=', dbf_fields(h));
  writeln('DBF_FIELD0_LEN=', dbf_fname(h, 0, 0));
  dbf_close(h);

  { ── sql:在刚建的表上查 ── }
  writeln('SQL_ROWS=', sql_run('libdemo.dbf', 'SELECT * FROM t WHERE AGE > 20'));
  writeln('SQL_COLS=', sql_cols());
  writeln('SQL_COL0_LEN=', sql_colname(0, 0));

  { ── turtle:抬笔走 50 步(落笔会去画屏幕,那要窗口)── }
  turtle_reset();
  turtle_pen_up();
  turtle_forward(50);
  writeln('TURTLE_X=', turtle_x());
  writeln('TURTLE_Y=', turtle_y());

{ ── sed:sed 的替换规则(s / y 两条命令,依附 regex 库)—— 缓冲区那一半只有 C 拿得到,
     这里压的是「只问长度」那一支(cap 传 0)与对账用的 sed_count。
}
writeln('SED_COUNT=', sed_count('s/a/X/g', 'banana'));
writeln('SED_LEN=', sed_sub('s/a/X/g', 'banana', 0, 0));
  writeln('DONE=', 1);
end.

{ 期望(scripts/lib-examples-check.sh 按这一行比对):
EXPECT: REGEX_HIT=1|REGEX_MISS=0|REGEX_VALID=1|DBF_ROWS=2|DBF_FIELDS=2|DBF_FIELD0_LEN=4|SQL_ROWS=1|SQL_COLS=2|SQL_COL0_LEN=4|TURTLE_X=0|TURTLE_Y=50|SED_COUNT=3|SED_LEN=6|DONE=1
}