acl4のプログラムのページ0001

(1) #defineしかできない簡易プリプロセッサ

(2) 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 c);

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] = argsN;
    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 = 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 mary args (c=%d, n=%d)", c, n);
    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->n - 1] <= ' ') tmp->n--;
    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] = c + (e - elm);
            intptr_t pos0 = t - tmp->p;
            VecChr_replace(tmp, pos0, t0->len, mark, 2); // 変数名を [01 xx] に置換.
            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] <= ' ') pos1++;
            VecChr_replace(linBuf, pos0, pos1 - pos0, NULL, 0); // 長さ0文字の文字列と置換することで削除を実現.
            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, d->n); // 置換する.
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] = args->n / (2 * sizeof (char *));
            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, ap[i * 2], ap[i * 2 + 1] - ap[i * 2]); // 引数を代入.
                }
                VecChr_replace(linBuf, pos0, t + 1 - (linBuf->p + pos0), tmp->p, tmp->n); // 置換する.
                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]->elm->n);
        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, linBuf, tmp, 0);
    VecChr_readFileAll_errChk(src, argv[1]); VecChr_eraseCr(src);
    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 = a_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[-1] == '\n')) break;
            s = VecChr_gets(tmp, s, s1);
            VecChr_replace(linBuf, linBuf->n - 2, 2, tmp->p, tmp->n);
        }
        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) == 0) {
                define0(set, t0, linBuf, 1); continue;
            }
            continue;
        } else { // #で始まらない行は一般行.
            define2(set, t0, linBuf, 1);
            printf("%.*s", linBuf->n, linBuf->p);
        }
    }
    define3(set);
    VecChr_din4(src, linBuf, tmp, 0);
    a_malloc_debugList(_arg);
    return 0;
}

(3) 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()

(4) 説明

(99) 更新履歴


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS