Вот кстати тот самый простой сишный препроцессор (minicpp), написанный мной для виндовой версии Tunguska CC (компилятор троичного языка си для тунгуски) в 2008 году:Shaos wrote:Есть компилятор си-подобного языка в байткод, интерпретатор и транслятор байт-кода, а также простой сишный препроцессор (#ifdef, #define и т.д.).
Code: Select all
/* minicpp.c - Alexander Shabarshin <ashabarshin@gmail.com>
* Mini C preprocessor (public domain)
* 21 Nov 2008 - first version
*/
#include <stdio.h>
#include <string.h>
#include "my_text.h"
#define LINESZ 256
Text* macros = NULL;
int miniparse(char* file);
int main(int argc, char** argv)
{
int r = 0;
if(argc<1) return -1;
macros = TextNew();
r = miniparse(argv[1]);
// TextList(macros);
TextDel(macros);
return r;
}
int miniparse(char* file)
{
Line *s,*l;
Text *t;
int i,j,k;
int f_com = 0;
int f_if = 0;
int err = 0;
char c,*p,*q,*qq,*qqq,str[64],st[LINESZ],st2[LINESZ];
printf("# 1 "%s"\n",file);
t = TextNew();
if(t==NULL) return -2;
TextLoad(t,file);
if(t->num<=0) return -3;
j = 0;
for(s=t->first;s!=NULL;s=s->next)
{
p = s->str;
while(*p==' '||*p=='\t') p++;
for(q=p;*q;q++)
{
if(!f_com&&q[0]=='/'&&q[1]=='/'){*q=0;break;}
if(!f_com&&q[0]=='/'&&q[1]=='*')
{
k = strlen(q);
q[0] = ' ';
q[1] = ' ';
for(i=2;i<k;i++)
{
if(q[i]=='*'&&q[i+1]=='/')
{
q[i] = ' ';
q[i+1] = ' ';
break;
}
q[i] = ' ';
}
if(i==k){*q=0;f_com=1;break;}
}
if(f_com&&q[0]=='*'&&q[1]=='/'){p=&q[2];f_com=0;}
}
if(f_com < 2)
{
q--;
while(*q==' '||*q=='\t'){*q=0;q--;}
if(f_com==1) f_com++;
}
else *p = 0;
if(!*p) continue;
if(*p=='#')
{
if(!strncmp(p,"#include",8))
{
p = &p[8];
while(*p==' '||*p=='\t') p++;
if(/**p=='<'||*/*p=='"')
{
c = *p;
if(c=='<') c='>';
p++;
q = strchr(p,c);
if(q==NULL) err++;
else *q = 0;
err += miniparse(p);
}
continue;
}
else if(!strncmp(p,"#define",7))
{
p = &p[7];
while(*p==' '||*p=='\t') p++;
i = 0;
while(*p!=' '&&*p!='\t'&&*p!=0)
{
str[i++] = *p;
p++;
}
while(*p==' '||*p=='\t') p++;
k = i;
if(!*p) str[i] = 0;
else
{
str[i++] = '=';
while(*p)
{
str[i++] = *p;
p++;
}
str[i] = 0;
}
l = TextAdd(macros,str);
if(l==NULL) return -4;
l->type = 100 - k;
TextSort(macros,TextFldTyp);
continue;
}
else if(!strncmp(p,"#ifdef",6))
{
p = &p[6];
while(*p==' '||*p=='\t') p++;
i = 0;
while(*p!=' '&&*p!='\t'&&*p!=0)
{
str[i++] = *p;
p++;
}
str[i] = 0;
for(l=macros->first;l!=NULL;l=l->next)
{
strncpy(st,l->str,LINESZ);
q = strchr(st,'=');
if(q!=NULL) *q = 0;
if(!strcmp(st,str)) break;
}
if(l!=NULL) f_if = 2;
else f_if = 1;
continue;
}
else if(!strncmp(p,"#ifndef",7))
{
p = &p[7];
while(*p==' '||*p=='\t') p++;
i = 0;
while(*p!=' '&&*p!='\t'&&*p!=0)
{
str[i++] = *p;
p++;
}
str[i] = 0;
for(l=macros->first;l!=NULL;l=l->next)
{
strncpy(st,l->str,LINESZ);
q = strchr(st,'=');
if(q!=NULL) *q = 0;
if(!strcmp(st,str)) break;
}
if(l!=NULL) f_if = 1;
else f_if = 2;
continue;
}
else if(!strncmp(p,"#else",5))
{
if(f_if==1) f_if = 2;
else if(f_if==2) f_if = 1;
continue;
}
else if(!strncmp(p,"#endif",6))
{
f_if = 0;
continue;
}
}
if(f_if==1) continue;
i = 0;
while(*p)
{
for(l=macros->first;l!=NULL;l=l->next)
{
q = strchr(l->str,'=');
if(q==NULL)
{
if(!strncmp(p,l->str,strlen(l->str)))
{
p = &p[strlen(l->str)];
l = NULL;
break;
}
}
else
{
strncpy(st2,l->str,LINESZ);
q = strchr(st2,'=');
*q = 0;
q++;
if(!strncmp(p,st2,strlen(st2))) break;
}
}
if(l==NULL)
{
st[i++] = *p;
p++;
}
else
{
qq = strchr(st2,'(');
if(qq==NULL)
{
strcpy(&st[i],q);
i += strlen(q);
p = &p[strlen(st2)];
}
else
{
*qq = 0;
qq++;
qqq = strchr(qq,')');
if(qqq!=NULL) *qqq = 0;
/* not yet ready to handle this */
err++;
}
}
}
st[i] = 0;
printf("%s\n",st);
j++;
}
TextDel(t);
return err;
}
