acpp0

(0)

(1) ver.1.10 [2024.09.15] (250行)

#include <acl1Tiny.c>
#include <AMemMan.c>
#include <AMemFile.c>

int cmpCmd(const char *s, const char *cmd)
{
    AInt len = strlen(cmd);
    if (strncmp(s, cmd, len) == 0 && ((unsigned char *) s)[len] <= ' ') return 1;
    return 0;
}

char *skpLf(const char *s)
// 次の行の先頭を得る.
{
    while (*s != 0 && *s != '\n') s++;
    if (*s == '\n') s++;
    return (char *) s;
}

char *skpSpc(const char *s)
{
    while (*s == ' ' || *s == '\t') s++;
    return (char *) s;
}

void commentOut(AMemFile *mp, const char *s0, const char *s, const char *s1)
{
    AMemFile_write(mp, 0, s0, s - s0); // s0からsまでを出力.
    AMemFile_write(mp, 0, "//", 2);
    AMemFile_write(mp, 0, s, s1 - s); // sからs1までを出力.
}

/// includeOnce()関係.

void includeOnce_sub(const char *s, AMemFile *mp, AMemFile *included)
{
    char tmp[1024];
    int i;
    while (*s != 0) {
        const char *s0 = s, *s1 = skpLf(s);
        s = skpSpc(s);
        if (*s == '#') { // これがある方が少し速い.
            if (cmpCmd(s, "#include_once")) {
                const char *s2 = s;
                s = skpSpc(s + 13);
                if (*s == 0x22 || *s == '<') {
                    char c = *s++;
                    if (c == '<') c = '>';
                    commentOut(mp, s0, s2, s1);
                    for (i = 0; s + i < s1 && s[i] != c; i++);
                    sprintf(tmp, "\n%.*s\n", i, s);
                    if (strstr(included->p0, tmp) == 0) {
                        included->p -= 2; // 末尾の"\n\0"を取り除く.
                        AMemFile_write(included, 0, tmp, i + 3); // 末尾の'\0'も書く.
                        tmp[i + 1] = 0;
                        AMemFile *mp1 = AMemFile_open(AMemFile_Text, am0, tmp + 1);
                        includeOnce_sub(mp1->p0, mp, included);
                        AMemFile_dst(mp1);
                    }
                    s = s1;
                    continue;
                }
            }
        }
        AMemFile_write(mp, 0, s0, s1 - s0);
        s = s1;
    }
}

AMemFile *includeOnce(const char *s)
{
    AMemFile *included = AMemFile_newSiz(0, am0, 4096); // ここにインクルード済みのファイル名一覧を追記していく.
    AMemFile_write(included, 0, "\n", 2); // 末尾の'\0'も書き込む.
    AMemFile *mp = AMemFile_new(AMemFile_Text, am0);
    includeOnce_sub(s, mp, included);
    AMemFile_dst(included);
    AMemFile_toReadMode(mp, 0);
    return mp;
}

/// longdef()関係.

char *skpNam(const char *s)
{
    while (*s != 0 && strchr("\t\n\r =(){},", *s) == 0) { s++; }
    return (char *) s;
}

char *skpExpr(const char *s)
{
    int i = 0, n = 0;
    for (;;) {
        if (*s == 0) break;
        if (*s == '(' || *s == '[') n++;
        if (*s == ')' || *s == ']') {
            if (n == 0) break;
            n--;
        }
        if (*s == ',' && n == 0) break;
        s++;
    }
    return (char *) s;
}

char *searchName(void **a, void **a1, AInt len, const char *nam)
{
    while (a < a1) {
        if ((AInt) a[0] == len && memcmp(a[1], nam, len) == 0) {
            if (a[1] == a[2]) { return a[2]; }
            return ((AMemFile *) a[2])->p0;
        }
        a += 3;
    }
    return 0;
}

void longdef_sub(const char *s, AMemFile *mp, char mod, AMemFile *def);

const char *longdef_longdef(const char *nam, AMemFile *mp, AMemFile *def, const char *s1)
{
    AMemFile *mq = 0;
    if (*nam == '@') { nam++; mq = AMemFile_newSiz(0, am0, 4096); }
    const char *s = skpNam(nam);
    AInt namLen = s - nam;
    if (searchName((void **) def->p0, (void **) def->p, namLen, nam) != 0)
        aErrExit("#longdef: double-def: %.*s\n", namLen, nam);
    s = skpSpc(s);
    if (*s != '(') { aErrExit("#longdef: syntax error: %.*s\n", namLen, nam); }
    void *a[3];
    a[0] = (void *) namLen;
    a[1] = (void *) nam;
    a[2] = (void *) nam;
    if (mq != 0) { a[2] = (void *) mq; }
    AMemFile_write(def, 0, (char *) a, sizeof a);
    s = s1;
    while (*s != 0) { // エラーチェックしながら#endlongdefまでを読み飛ばす.
        s = skpSpc(s);
        s1 = skpLf(s);
        if (*s == '#') {
            if (cmpCmd(s, "#longdef")) // #longdef中に#longdefが出てきた.
                aErrExit("not found #endlongdef: %.*s\n", namLen, nam);
            if (cmpCmd(s, "#endlongdef")) break;
        }
        s = s1;
    }
    if (*s == 0) { aErrExit("not found #endlongdef: %.*s\n", namLen, nam); }
    if (mq != 0) {
        for (s = nam; s < s1; ) {
            const char *s0 = s;
            while (s < s1 && *s != '@') s++;
            AMemFile_write(mq, 0, s0, s - s0);
            if (s < s1) {
                s++; // @を読み飛ばす.
                AMemFile_write(mq, 0, nam, namLen); // 代わりに以下を出力.
                AMemFile_write(mq, 0, "_", 1);
            }
        }
        AMemFile_toReadMode(mq, 0);
    }
    return s1;
}

void longdef_longuse(const char *nam, AMemFile *mp, AMemFile *def)
{
    const char *s = skpNam(nam);
    AInt namLen = s - nam;
    const char *p = searchName((void **) def->p0, (void **) def->p, namLen, nam);
    if (p == 0) { aErrExit("#longuse: not found: %.*s\n", namLen, nam); }
    const char *p0 = skpSpc(strchr(p + namLen, '(') + 1), *p1, *s1;
    s = skpSpc(s);
    if (*s != '(') { aErrExit("#longuse: syntax error (1): %.*s\n", namLen, nam); }
    s = skpSpc(s + 1);
    for (p = p0; *p != ')'; ) { // #define出力.
        p1 = skpNam(p);
        s1 = skpExpr(s);
        AMemFile_write(mp, 0, "#define ", 8);
        AMemFile_write(mp, 0, p, p1 - p);
        AMemFile_write(mp, 0, " ", 1);
        AMemFile_write(mp, 0, s, s1 - s);
        AMemFile_write(mp, 0, "\n", 1);
        p = skpSpc(p1);
        s = skpSpc(s1);
        if (*p == ',') p = skpSpc(p + 1);
        if (*s == ',') s = skpSpc(s + 1);
        if (*p != ')' && *s == ')') { aErrExit("#longuse: syntax error (2): %.*s\n", namLen, nam); } // 引数の数があってない.
    }
    if (*s != ')') { aErrExit("#longuse: syntax error (3): %.*s\n", namLen, nam); } // 引数の数があってない.
    longdef_sub(skpLf(p), mp, 1, def);
    for (p = p0; *p != ')'; ) { // #undef出力.
        p1 = skpNam(p);
        AMemFile_write(mp, 0, "#undef ", 7);
        AMemFile_write(mp, 0, p, p1 - p);
        AMemFile_write(mp, 0, "\n", 1);
        p = skpSpc(p1);
        if (*p == ',') { p = skpSpc(p + 1); }
    }
}

void longdef_sub(const char *s, AMemFile *mp, char mod, AMemFile *def)
{
    while (*s != 0) {
        const char *s0 = s, *s1 = skpLf(s);
        s = skpSpc(s);
        if (*s == '#') {
            if (cmpCmd(s, "#longdef")) {
                commentOut(mp, s0, s, s1);
                s = longdef_longdef(skpSpc(s + 8), mp, def, s1);
                continue;
            }
            if (cmpCmd(s, "#endlongdef")) {
                if (mod != 0) { commentOut(mp, s0, s, s1); break; }
                aErrExit("not found #longdef\n");
            }
            if (cmpCmd(s, "#longuse")) {
                commentOut(mp, s0, s, s1);
                longdef_longuse(skpSpc(s + 8), mp, def);
                s = s1; continue;
            }
        }
        AMemFile_write(mp, 0, s0, s1 - s0);
        s = s1;
    }
}

AMemFile *longdef(const char *s)
{
    void **a;
    AMemFile *def = AMemFile_newSiz(0, am0, 4096); // { len, defName },...
    AMemFile *mp = AMemFile_new(AMemFile_Text, am0);
    longdef_sub(s, mp, 0, def);
    for (a = (void **) def->p0; a < (void **) def->p; a += 3) {
        if (a[1] != a[2]) { AMemFile_dst(a[2]); }
    }
    AMemFile_dst(def);
    AMemFile_toReadMode(mp, 0);
    return mp;
}

/// main()関数.

int main(int argc, const char **argv)
{
    if (argc < 3) { aErrExit("usage>acpp0 input-file output-file\n"); }
    AMemFile *mp0 = AMemFile_open(AMemFile_Text, am0, argv[1]);
    AMemFile *mp1 = includeOnce(mp0->p0); AMemFile_dst(mp0);
    AMemFile *mp2 = longdef(mp1->p0);     AMemFile_dst(mp1);
    AMemFile_saveDst(mp2, 0, argv[2]);
    AM_dst(am0);
    return 0;
}

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