a4_p0001
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
* acl4のプログラムのページ0001
-(by [[K]], 2026.02.02)
** (1) #defineしかできない簡易プリプロセッサ
-[[a4_0007]]までの関数があれば、そこそこ面白いことができ...
** (2) p0001a0.txt を使ってテスト
#define Sqr(x) (x)*(x)
#define Diff(x, y) (x)-(y)
x = Sqr(Diff(9, 5));
y = Diff(Sqr(5), Sqr(3));
>p0001a p0001a0.txt
x = ((9)-(5))*((9)-(5));
y = ((5)*(5))-((3)*(3));
p0001a.c(181): malloc_debugList()
-こんなふうにちゃんと動きます。もちろんいろいろ足りない部...
-Windows上でa_DbgLv=0でコンパイルした場合、p0001a.exeは12...
-これに #if や #include をつけて、さらに細かいところをち...
** (3) p0001a.c
#define a_Version 1
#include <acl4.c>
class_(Def) {
SetElm elm[1];
char *q;
intptr_t n;
};
void define1(VecChr *tmp, Token0 *t0, VecChr *args, int ...
void define0(Set0 *set, Token0 *t0, VecChr *linBuf, int c)
// #defineの登録処理.
{
VecChr args[1], tmp[1]; VecChr_ini4(args, tmp, 0, 0);
char *k = Token1_get(t0);
intptr_t kn = t0->len, argsN = 0xff;
if (k[kn] == '(') {
t0->s++; parseArgs(t0, args);
if (t0->len == 0) goto fin;
argsN = args->n / (2 * sizeof (char *));
}
char *t = Token1_get(t0);
VecChr_resize(_arg_ tmp, linBuf->p + linBuf->n - t);
memcpy(tmp->p, t, tmp->n);
define1(tmp, t0, args, c);
Def *d = malloc_(_arg_ sizeof (Def));
d->elm->k = malloc_(_arg_ kn + 1);
d->elm->n = kn + 1;
((unsigned char *) d->elm->k)[0] = (unsigned char) a...
memcpy((char *) d->elm->k + 1, k, kn);
d->q = malloc_(_arg_ tmp->n);
d->n = tmp->n;
memcpy(d->q, tmp->p, tmp->n);
Set0_add(set, d->elm);
fin:
VecChr_din4(args, tmp, 0, 0);
}
void define1(VecChr *tmp, Token0 *t0, VecChr *args, int c)
// #defineの引数を [01 01] とか [01 02] などに置換する.
{
int i, n = (int) (args->n / (2 * sizeof (char *)));
Set0 set[1]; Set0_ini(set); SetElm elm[256];
char mark[2]; mark[0] = c;
char **ap = (char **) args->p, *t;
if (n + c > 256) errExit("define1: too many args (c=...
for (i = 0; i < n; i++) {
elm[i].k = ap[i * 2];
elm[i].n = ap[i * 2 + 1] - ap[i * 2];
Set0_add(set, &elm[i]);
}
t0->s = tmp->p; t0->s1 = tmp->p + tmp->n;
for (;;) {
t = Token1_get(t0);
if (t0->len == 0) break;
if (t0->len >= 2 && t[0] == '/' && t[1] == '/') {
tmp->n = t - tmp->p; // コメントが後続してい...
break;
}
}
while (tmp->n > 0 && ((unsigned char *) tmp->p)[tmp-...
t0->s = tmp->p; t0->s1 = tmp->p + tmp->n;
for (;;) {
t = Token1_get(t0);
if (t0->len == 0) break;
SetElm *e = Set0_findKn(set, t, t0->len);
if (e != NULL) {
mark[1] = (unsigned char) (c + (e - elm));
intptr_t pos0 = t - tmp->p;
VecChr_replace(tmp, pos0, t0->len, mark, 2);...
t0->s = tmp->p + pos0 + t0->len;
t0->s1 = tmp->p + tmp->n;
}
}
Set0_din(set);
}
void define2(Set0 *set, Token0 *t0, VecChr *linBuf, int c)
// 一般行に対して#defineの登録内容を適用する.
{
VecChr args[1], tmp[1]; VecChr_ini4(args, tmp, 0, 0);
char *p = linBuf->p;
for (t0->s = p;;) {
char *t = Token1_get(t0);
if (t0->len == 0) break;
if (t0->len == 2 && t[0] == '#' && t[1] == '#') ...
intptr_t pos0 = t - p, pos1 = pos0 + 2;
while (pos0 > 0 && p[pos0 - 1] <= ' ') pos0--;
while (pos1 < linBuf->n && p[pos1] <= ' ') p...
VecChr_replace(linBuf, pos0, pos1 - pos0, NU...
t0->s = p;
t0->s1 = p + linBuf->n;
continue;
}
if (t0->cTyp != 3) continue;
intptr_t kn = t0->len + 1;
unsigned char *k = malloc_(_arg_ kn);
memcpy(k + 1, t, kn); k[0] = 0xff;
intptr_t pos0 = t - p;
Def *d = Set0_findKn(set, k, kn); // 引数なしマ...
if (d != NULL) {
VecChr_replace(linBuf, pos0, t0->len, d->q, ...
nxt:
p = linBuf->p;
t0->s = p + pos0;
t0->s1 = p + linBuf->n;
free_(_arg_ k, kn);
continue;
}
if (t[t0->len] == '(') {
const char *t0s = t0->s++;
t = parseArgs(t0, args);
k[0] = (unsigned char) (args->n / (2 * sizeo...
d = Set0_findKn(set, k, kn); // 引数付きマク...
if (d != NULL) {
VecChr_resize(_arg_ tmp, d->n);
memcpy(tmp->p, d->q, d->n);
for (;;) {
p = memchr(tmp->p, c, tmp->n);
if (p == NULL) break;
int i = ((unsigned char *) p)[1] - c;
char **ap = (char **) args->p;
VecChr_replace(tmp, p - tmp->p, 2, a...
}
VecChr_replace(linBuf, pos0, t + 1 - (li...
goto nxt;
}
t0->s = t0s;
}
free_(_arg_ k, kn);
}
VecChr_din4(args, tmp, 0, 0);
}
void define3(Set0 *set)
{
intptr_t i, n = set->tbl->n / sizeof (Def *);
Def **tbl = (Def **) set->tbl->p;
for (i = 0; i < n; i++) {
free_(_arg_ (char *) tbl[i]->elm->k, tbl[i]->el...
free_(_arg_ tbl[i]->q, tbl[i]->n);
free_(_arg_ tbl[i], sizeof (Def));
}
Set0_din(set);
}
int main(int argc, const char **argv)
{
VecChr src[1], linBuf[1], tmp[1]; VecChr_ini4(src, l...
VecChr_readFileAll_errChk(src, argv[1]); VecChr_eras...
Set0 set[1]; Set0_ini(set);
Token0Table t0t[1]; Token0Table_ini(t0t);
Token0 t0[1]; t0->tbl = t0t;
char *s = src->p, *s1 = src->p + src->n, *t;
for (;;) {
s = VecChr_gets(linBuf, s, s1); // 1行をlinBufに...
if (linBuf->n == 0) break;
for (;;) { // 末尾が "\\\n"であれば、後続行を接続.
char *p1 = linBuf->p + linBuf->n;
if (!(linBuf->n >= 2 && p1[-2] == '\\' && p1...
s = VecChr_gets(tmp, s, s1);
VecChr_replace(linBuf, linBuf->n - 2, 2, tmp...
}
t0->s = linBuf->p; t0->s1 = linBuf->p + linBuf->n;
t = Token1_get(t0);
if (t0->c == '#') { // #で始まる行は、プリプロセ...
t = Token1_get(t0);
if (t0->len == 6 && memcmp(t, "define", 6) =...
define0(set, t0, linBuf, 1); continue;
}
continue;
} else { // #で始まらない行は一般行.
define2(set, t0, linBuf, 1);
printf("%.*s", (int) linBuf->n, linBuf->p);
}
}
define3(set);
VecChr_din4(src, linBuf, tmp, 0);
a_malloc_debugList(_arg);
return 0;
}
** (4) 説明
-mainはまあ難しいことはないと思うので、説明を省略します。
--setは連想コンテナですが、この中にdefineの定義内容を貯め...
--素早く辞書引きしたいので連想コンテナに入れています。
-define0は、#defineの登録処理をします。
--まず引数があれば、それはparseArgsで解析してしまいます。...
--次に置換内容が書かれているわけですが、それをlinBufから...
--そしてargsとともにdefine1に渡して整形します。
--整形が終わったら、(引数の数, define名)をkeyとして、整形...
-define1は、上記で言及した整形処理をやります。
--整形処理というのは、こういうことです。
--[1]もしコメントが後続している場合は、邪魔なので切り取る。
--[2]引数部分を [01 xx] の2バイトに置き換える。
(例) #define Diff(x, y) (x)-(y)
→ ([01 01])-([01 02])
--なぜ2バイトなのかというと、1バイトでは普通の文字と衝突...
--01は「次が引数番号だよ」ということを表すマークで、xxが...
--最初にargsをsetに登録していきます。このsetは#define登録...
--整形処理が終わったら、args早引き用setは不要なので処分し...
-define2はマクロを適用していく処理ですが、コメントを多く...
-define3はsetを開放するための処理をまとめたものです。
** (99) 更新履歴
-2026.02.02(月) 初版
終了行:
* acl4のプログラムのページ0001
-(by [[K]], 2026.02.02)
** (1) #defineしかできない簡易プリプロセッサ
-[[a4_0007]]までの関数があれば、そこそこ面白いことができ...
** (2) p0001a0.txt を使ってテスト
#define Sqr(x) (x)*(x)
#define Diff(x, y) (x)-(y)
x = Sqr(Diff(9, 5));
y = Diff(Sqr(5), Sqr(3));
>p0001a p0001a0.txt
x = ((9)-(5))*((9)-(5));
y = ((5)*(5))-((3)*(3));
p0001a.c(181): malloc_debugList()
-こんなふうにちゃんと動きます。もちろんいろいろ足りない部...
-Windows上でa_DbgLv=0でコンパイルした場合、p0001a.exeは12...
-これに #if や #include をつけて、さらに細かいところをち...
** (3) p0001a.c
#define a_Version 1
#include <acl4.c>
class_(Def) {
SetElm elm[1];
char *q;
intptr_t n;
};
void define1(VecChr *tmp, Token0 *t0, VecChr *args, int ...
void define0(Set0 *set, Token0 *t0, VecChr *linBuf, int c)
// #defineの登録処理.
{
VecChr args[1], tmp[1]; VecChr_ini4(args, tmp, 0, 0);
char *k = Token1_get(t0);
intptr_t kn = t0->len, argsN = 0xff;
if (k[kn] == '(') {
t0->s++; parseArgs(t0, args);
if (t0->len == 0) goto fin;
argsN = args->n / (2 * sizeof (char *));
}
char *t = Token1_get(t0);
VecChr_resize(_arg_ tmp, linBuf->p + linBuf->n - t);
memcpy(tmp->p, t, tmp->n);
define1(tmp, t0, args, c);
Def *d = malloc_(_arg_ sizeof (Def));
d->elm->k = malloc_(_arg_ kn + 1);
d->elm->n = kn + 1;
((unsigned char *) d->elm->k)[0] = (unsigned char) a...
memcpy((char *) d->elm->k + 1, k, kn);
d->q = malloc_(_arg_ tmp->n);
d->n = tmp->n;
memcpy(d->q, tmp->p, tmp->n);
Set0_add(set, d->elm);
fin:
VecChr_din4(args, tmp, 0, 0);
}
void define1(VecChr *tmp, Token0 *t0, VecChr *args, int c)
// #defineの引数を [01 01] とか [01 02] などに置換する.
{
int i, n = (int) (args->n / (2 * sizeof (char *)));
Set0 set[1]; Set0_ini(set); SetElm elm[256];
char mark[2]; mark[0] = c;
char **ap = (char **) args->p, *t;
if (n + c > 256) errExit("define1: too many args (c=...
for (i = 0; i < n; i++) {
elm[i].k = ap[i * 2];
elm[i].n = ap[i * 2 + 1] - ap[i * 2];
Set0_add(set, &elm[i]);
}
t0->s = tmp->p; t0->s1 = tmp->p + tmp->n;
for (;;) {
t = Token1_get(t0);
if (t0->len == 0) break;
if (t0->len >= 2 && t[0] == '/' && t[1] == '/') {
tmp->n = t - tmp->p; // コメントが後続してい...
break;
}
}
while (tmp->n > 0 && ((unsigned char *) tmp->p)[tmp-...
t0->s = tmp->p; t0->s1 = tmp->p + tmp->n;
for (;;) {
t = Token1_get(t0);
if (t0->len == 0) break;
SetElm *e = Set0_findKn(set, t, t0->len);
if (e != NULL) {
mark[1] = (unsigned char) (c + (e - elm));
intptr_t pos0 = t - tmp->p;
VecChr_replace(tmp, pos0, t0->len, mark, 2);...
t0->s = tmp->p + pos0 + t0->len;
t0->s1 = tmp->p + tmp->n;
}
}
Set0_din(set);
}
void define2(Set0 *set, Token0 *t0, VecChr *linBuf, int c)
// 一般行に対して#defineの登録内容を適用する.
{
VecChr args[1], tmp[1]; VecChr_ini4(args, tmp, 0, 0);
char *p = linBuf->p;
for (t0->s = p;;) {
char *t = Token1_get(t0);
if (t0->len == 0) break;
if (t0->len == 2 && t[0] == '#' && t[1] == '#') ...
intptr_t pos0 = t - p, pos1 = pos0 + 2;
while (pos0 > 0 && p[pos0 - 1] <= ' ') pos0--;
while (pos1 < linBuf->n && p[pos1] <= ' ') p...
VecChr_replace(linBuf, pos0, pos1 - pos0, NU...
t0->s = p;
t0->s1 = p + linBuf->n;
continue;
}
if (t0->cTyp != 3) continue;
intptr_t kn = t0->len + 1;
unsigned char *k = malloc_(_arg_ kn);
memcpy(k + 1, t, kn); k[0] = 0xff;
intptr_t pos0 = t - p;
Def *d = Set0_findKn(set, k, kn); // 引数なしマ...
if (d != NULL) {
VecChr_replace(linBuf, pos0, t0->len, d->q, ...
nxt:
p = linBuf->p;
t0->s = p + pos0;
t0->s1 = p + linBuf->n;
free_(_arg_ k, kn);
continue;
}
if (t[t0->len] == '(') {
const char *t0s = t0->s++;
t = parseArgs(t0, args);
k[0] = (unsigned char) (args->n / (2 * sizeo...
d = Set0_findKn(set, k, kn); // 引数付きマク...
if (d != NULL) {
VecChr_resize(_arg_ tmp, d->n);
memcpy(tmp->p, d->q, d->n);
for (;;) {
p = memchr(tmp->p, c, tmp->n);
if (p == NULL) break;
int i = ((unsigned char *) p)[1] - c;
char **ap = (char **) args->p;
VecChr_replace(tmp, p - tmp->p, 2, a...
}
VecChr_replace(linBuf, pos0, t + 1 - (li...
goto nxt;
}
t0->s = t0s;
}
free_(_arg_ k, kn);
}
VecChr_din4(args, tmp, 0, 0);
}
void define3(Set0 *set)
{
intptr_t i, n = set->tbl->n / sizeof (Def *);
Def **tbl = (Def **) set->tbl->p;
for (i = 0; i < n; i++) {
free_(_arg_ (char *) tbl[i]->elm->k, tbl[i]->el...
free_(_arg_ tbl[i]->q, tbl[i]->n);
free_(_arg_ tbl[i], sizeof (Def));
}
Set0_din(set);
}
int main(int argc, const char **argv)
{
VecChr src[1], linBuf[1], tmp[1]; VecChr_ini4(src, l...
VecChr_readFileAll_errChk(src, argv[1]); VecChr_eras...
Set0 set[1]; Set0_ini(set);
Token0Table t0t[1]; Token0Table_ini(t0t);
Token0 t0[1]; t0->tbl = t0t;
char *s = src->p, *s1 = src->p + src->n, *t;
for (;;) {
s = VecChr_gets(linBuf, s, s1); // 1行をlinBufに...
if (linBuf->n == 0) break;
for (;;) { // 末尾が "\\\n"であれば、後続行を接続.
char *p1 = linBuf->p + linBuf->n;
if (!(linBuf->n >= 2 && p1[-2] == '\\' && p1...
s = VecChr_gets(tmp, s, s1);
VecChr_replace(linBuf, linBuf->n - 2, 2, tmp...
}
t0->s = linBuf->p; t0->s1 = linBuf->p + linBuf->n;
t = Token1_get(t0);
if (t0->c == '#') { // #で始まる行は、プリプロセ...
t = Token1_get(t0);
if (t0->len == 6 && memcmp(t, "define", 6) =...
define0(set, t0, linBuf, 1); continue;
}
continue;
} else { // #で始まらない行は一般行.
define2(set, t0, linBuf, 1);
printf("%.*s", (int) linBuf->n, linBuf->p);
}
}
define3(set);
VecChr_din4(src, linBuf, tmp, 0);
a_malloc_debugList(_arg);
return 0;
}
** (4) 説明
-mainはまあ難しいことはないと思うので、説明を省略します。
--setは連想コンテナですが、この中にdefineの定義内容を貯め...
--素早く辞書引きしたいので連想コンテナに入れています。
-define0は、#defineの登録処理をします。
--まず引数があれば、それはparseArgsで解析してしまいます。...
--次に置換内容が書かれているわけですが、それをlinBufから...
--そしてargsとともにdefine1に渡して整形します。
--整形が終わったら、(引数の数, define名)をkeyとして、整形...
-define1は、上記で言及した整形処理をやります。
--整形処理というのは、こういうことです。
--[1]もしコメントが後続している場合は、邪魔なので切り取る。
--[2]引数部分を [01 xx] の2バイトに置き換える。
(例) #define Diff(x, y) (x)-(y)
→ ([01 01])-([01 02])
--なぜ2バイトなのかというと、1バイトでは普通の文字と衝突...
--01は「次が引数番号だよ」ということを表すマークで、xxが...
--最初にargsをsetに登録していきます。このsetは#define登録...
--整形処理が終わったら、args早引き用setは不要なので処分し...
-define2はマクロを適用していく処理ですが、コメントを多く...
-define3はsetを開放するための処理をまとめたものです。
** (99) 更新履歴
-2026.02.02(月) 初版
ページ名: