* acl4のページ0008
-(by [[K]], 2026.02.03)
** (1)
#if (a_Version >= 1)
#define Token0_ini1 a_Token0_ini1
#define VecChr_convEsc a_VecChr_convEsc
#define VecChr_iniArg a_VecChr_iniArg
#endif
a_static void a_Token0_ini1(a_Token0 *w)
{
static a_Token0Table t0t[1];
a_Token0Table_ini(t0t);
w->tbl = t0t;
}
a_static void a_VecChr_convEsc(a_VecChr *w)
{
a_VecChr_reserveDiff(w, 4);
memset(w->p + w->n, 0, 4);
char *p, *q, *p1;
p = q = w->p;
p1 = p + w->n;
while (p < p1) {
if (*p == '\\') {
if (p[1] == 'a') { *q++ = '\a'; p += 2; continue; }
if (p[1] == 'b') { *q++ = '\b'; p += 2; continue; }
if (p[1] == 'f') { *q++ = '\f'; p += 2; continue; }
if (p[1] == 'n') { *q++ = '\n'; p += 2; continue; }
if (p[1] == 'r') { *q++ = '\r'; p += 2; continue; }
if (p[1] == 't') { *q++ = '\t'; p += 2; continue; }
if (p[1] == 'v') { *q++ = '\v'; p += 2; continue; }
if (p[1] == 'x') {
*q++ = (char) strtol(p + 1, &p, 16);
if (strchr(",.;:", *p) != NULL) p++;
continue;
}
if ('0' <= p[1] && p[1] <= '7') {
*q++ = (char) strtol(p + 1, &p, 8);
if (strchr(",.;:", *p) != NULL) p++;
continue;
}
p++;
*q++ = *p++;
} else
*q++ = *p++;
}
w->n -= p1 - q;
a_VecChr_reserve0(w);
}
a_static void a_VecChr_iniArg(a_VecChr *w, int argc, const char **argv, int i, int flg)
// flg=1:デフォルトをinlineモードに変更.
// 2:ファイルから読んだ場合にeraseCrする.
// 4:inlineの場合でも、convEscしない.
// 8:fileの場合に、convEscする.
// 16:最初にiniしない.
// 典型値: flg=0(file-bin), flg=2(file-txt)
// flg=1(inline-bin), flg=3(inline-txt)
// file:かinline:か。明示しなければデフォルト値が使われる.
{
if ((flg & 16) == 0)
a_VecChr_ini(w);
if (argc <= i)
a_errExit("VecChr_iniArg: missing args. (i=%d, argc=%d)", i, argc);
w->n = 0;
a_VecChr_puts(w, argv[i], argv[i] + strlen(argv[i]));
if (w->p[0] == 0x22) {
a_VecChr_replace(w, 0, 1, NULL, 0);
if (w->n > 0 && w->p[w->n - 1] == 0x22)
w->n--;
}
if (w->n >= 5 && memcmp(w->p, "file:", 5) == 0) {
a_VecChr_replace(w, 0, 5, NULL, 0);
flg &= ~1;
}
if (w->n >= 7 && memcmp(w->p, "inline:", 7) == 0) {
a_VecChr_replace(w, 0, 7, NULL, 0);
flg |= 1;
}
if ((flg & 1) == 0) {
a_VecChr_reserve0(w);
w->n = 0;
a_VecChr_readFileAll_errChk(w, w->p);
if ((flg & 2) != 0)
a_VecChr_eraseCr(w);
if ((flg & 8) != 0)
flg |= 256;
} else {
if ((flg & 4) == 0)
flg |= 256;
}
if ((flg & 256) != 0)
a_VecChr_convEsc(w);
}
** (2)
-Token0_ini1:
--よく使うのに初期化に2行も書かなきゃいけないのは邪魔だと思ったので作りました。
--これでデフォルト設定のままなら1行で書けるようになりました。
-VecChr_convEsc:
--文字列中の \n などを 0x0a に変換する関数です。主に次の VecChr_iniArg のために作りました。
-VecChr_iniArg:
--コマンドライン引数を簡単に処理するための関数です。
--普通にファイル名を書けばファイルをオープンして中身を全部読み込んで VecChr に格納してくれます。
--それだけではなく、ファイル名を inline:hogehoge とかにすれば、まるで中身が hogehoge のファイルを開いたかのような挙動をします。
--これでちょっとしたテストのためだけにわざわざ小さなファイルを作ったりしないでよくなるのです。
--こういうのがあればきっと便利になるはず、って思って、思い付きで作りました。
--inline指定したときは \n とか \" とかが使えるので、2行以上のファイルやバイナリファイルの代わりだって思いのままです!
** (3) サンプルプログラム: t0008a.c
-acl4ライブラリは以下のようにして利用します。
-[1]まずa4_0001~a4_0008のプログラムをつなげて"acl4.c"として保存します。
-[2]次にacl4を使ったプログラムを書きます。
-[3]コンパイル時に、"acl4.c"のあるパスをインクルードパスの一つとして指定します。
#define a_Version 1
#include <acl4.c>
int main(int argc, const char **argv)
{
VecChr vc[1]; VecChr_iniArg(vc, argc, argv, 1, 3);
fwrite(vc->p, 1, vc->n, stdout);
VecChr_din(vc);
a_malloc_debugList(_arg);
return 0;
}
>t0008a "123\n456\n789\n"
123
456
789
-VecChr_iniArg で flg=3 にしているので、 inline: がデフォルトになっています。
>t0008a file:t0008a.c
#define a_Version 1
#include <acl4.c>
int main(int argc, const char **argv)
{
VecChr vc[1]; VecChr_iniArg(vc, argc, argv, 1, 3);
fwrite(vc->p, 1, vc->n, stdout);
VecChr_din(vc);
a_malloc_debugList(_arg);
return 0;
}
-file: をつけてファイル指定すれば、このようにファイルの内容も取ってこられます(というかこれが本来の動作)。
** (4) サンプルプログラム: t0008b.c
-acl4ライブラリは以下のようにして利用します。
-[1]まずa4_0001~a4_0008のプログラムをつなげて"acl4.c"として保存します。
-[2]次にacl4を使ったプログラムを書きます。
-[3]コンパイル時に、"acl4.c"のあるパスをインクルードパスの一つとして指定します。
#define a_Version 1
#include <acl4.c>
int main(int argc, const char **argv)
{
VecChr vc[1]; VecChr_iniArg(vc, argc, argv, 1, 0);
printf("offset +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF\n");
printf("-------------------------------------------------------------------------\n");
intptr_t i, j;
int i, j;
for (i = 0; i < vc->n; i++) {
if ((i & 15) == 0)
printf("%6X:", i);
printf(" %02X", ((unsigned char *) vc->p)[i]);
if ((i & 15) == 15) {
printf(" ");
for (j = -15; j <= 0; j++) {
int c = ((unsigned char *) vc->p)[i + j];
if (c < 0x20 || 0x7e < c) c = '.';
putchar(c);
}
putchar('\n');
}
}
j = (- vc->n) & 15;
if (j > 0) {
do {
printf(" ");
} while (--j != 0);
printf(" ");
for (i &= -16; i < vc->n; i++) {
int c = ((unsigned char *) vc->p)[i];
if (c < 0x20 || 0x7e < c) c = '.';
putchar(c);
}
putchar('\n');
}
VecChr_din(vc);
a_malloc_debugList(_arg);
return 0;
}
>t0008b t0008a.c
offset +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF
-------------------------------------------------------------------------
0: 23 64 65 66 69 6E 65 20 61 5F 56 65 72 73 69 6F #define a_Versio
10: 6E 20 31 0D 0A 23 69 6E 63 6C 75 64 65 20 3C 61 n 1..#include <a
20: 63 6C 34 2E 63 3E 0D 0A 0D 0A 69 6E 74 20 6D 61 cl4.c>....int ma
30: 69 6E 28 69 6E 74 20 61 72 67 63 2C 20 63 6F 6E in(int argc, con
40: 73 74 20 63 68 61 72 20 2A 2A 61 72 67 76 29 0D st char **argv).
50: 0A 7B 0D 0A 20 20 20 20 56 65 63 43 68 72 20 76 .{.. VecChr v
60: 63 5B 31 5D 3B 20 56 65 63 43 68 72 5F 69 6E 69 c[1]; VecChr_ini
70: 41 72 67 28 76 63 2C 20 61 72 67 63 2C 20 61 72 Arg(vc, argc, ar
80: 67 76 2C 20 31 2C 20 33 29 3B 0D 0A 20 20 20 20 gv, 1, 3);..
90: 66 77 72 69 74 65 28 76 63 2D 3E 70 2C 20 31 2C fwrite(vc->p, 1,
A0: 20 76 63 2D 3E 6E 2C 20 73 74 64 6F 75 74 29 3B vc->n, stdout);
B0: 0D 0A 20 20 20 20 56 65 63 43 68 72 5F 64 69 6E .. VecChr_din
C0: 28 76 63 29 3B 0D 0A 20 20 20 20 61 5F 6D 61 6C (vc);.. a_mal
D0: 6C 6F 63 5F 64 65 62 75 67 4C 69 73 74 28 5F 61 loc_debugList(_a
E0: 72 67 29 3B 0D 0A 20 20 20 20 72 65 74 75 72 6E rg);.. return
F0: 20 30 3B 0D 0A 7D 0D 0A 0;..}..
>t0008b "inline:123\n456\n789\n"
offset +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF
-------------------------------------------------------------------------
0: 31 32 33 0A 34 35 36 0A 37 38 39 0A 123.456.789.
** (5) サンプルプログラム: t0008c.c
-上記2つでサンプルは十分かなと思ったのですが、適当にファイルを作ろうと思って、こんなことをしました。
>t0008a "hello\n" > hello.txt
>t0008b hello.txt
offset +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF
-------------------------------------------------------------------------
0: 68 65 6C 6C 6F 0D 0A hello..
-あっている・・・と思ったら、意図に反して 0D が入っていました。そうです、Windowsでは標準出力はテキストモードなんです。
-そんな余計なことをしないで、そのまま出してくれればいいだけなのに・・・。
-ということで、第1引数の内容をバイナリモードで第2引数の名前のファイルに出力するコマンドを作りました。
#define a_Version 1
#include <acl4.c>
int main(int argc, const char **argv)
{
VecChr vc[1]; VecChr_iniArg(vc, argc, argv, 1, 1);
VecChr_writeFileAll_errChk(vc, argv[2], "wb");
VecChr_din(vc);
a_malloc_debugList(_arg);
return 0;
}
>t0008c "hello\n" hello.txt
>t0008b hello.txt
offset +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF
-------------------------------------------------------------------------
0: 68 65 6C 6C 6F 0A hello.
-今度は意図通りになりました!
** (99) 更新履歴
-2026.02.03(火) 初版