acpp0
(0)
- C言語のプリプロセッサより前にこれを使うことで、プリプロセッサを拡張します。
- 以下が使えるようになります。
- #include_once
- #longdef
- #endlongdef
- #longuse
(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;
}