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
}