* acpp0
-(by [[K]], 2024.09.02)

** (0)
-C言語のプリプロセッサより前にこれを使うことで、プリプロセッサを拡張します。
-以下が使えるようになります。
--#include_once
--#longdef
--#endlongdef
--#longuse

** (1) ver.1.10 [2024.09.15] (250行)
** (1) ver.1.20 [2024.09.20] (248行)

 #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