/* preprocess.c */
#include "config.h"
#include "object.h"
#include "file.h"
#include "token.h"
#include "construct.h"
#include "instr.h"
extern char expand_buf[EBUFSIZ+1];
extern char tmpbuf[EBUFSIZ+1];
extern char name_buf[MAX_TOK_LEN+1];
extern char string_buf[MAX_STR_LEN+1];
#define isstart(c) (isalpha(c) || ((c)=='_'))
#define iscname(c) (isstart(c) || isdigit(c))
#define getch() *((file_info->expanded)++)
#define ungetch() --(file_info->expanded)
char *make_include_name(char *name)
{
static char nbuf[MAX_STR_LEN];
int c,n;
c=0;
n=strlen(name);
if (n<3) return "";
if ((*name=='<') && (name[n-1]=='>')) {
strcpy(nbuf,INCLUDE_PATH);
c=strlen(INCLUDE_PATH);
nbuf[c++]='/';
} else
if (!((*name=='\"') && (name[n-1]=='\"')))
return "";
if (c+n-1>MAX_STR_LEN) return "";
strncpy(nbuf+c,name+1,n-2);
nbuf[c+n-2]='\0';
return nbuf;
}
char *find_parm(struct define *def, char *name)
{
struct parm *curr;
curr=def->params;
while (curr) {
if (!strcmp(curr->name,name))
return curr->exp;
curr=curr->next;
}
return NULL;
}
void add_expand_buf(char *s1, char *s2)
{
int counter;
counter=0;
if (s1==expand_buf)
counter=strlen(s1);
else
while ((*s1) && (counter<EBUFSIZ))
expand_buf[counter++]=*(s1++);
while ((*s2) && (counter<EBUFSIZ))
expand_buf[counter++]=*(s2++);
expand_buf[counter]='\0';
}
void free_parm_exp(struct define *def)
{
struct parm *curr;
curr=def->params;
while (curr) {
if (curr->exp) {
FREE(curr->exp);
curr->exp=NULL;
}
curr=curr->next;
}
}
int preprocess(filptr *file_info)
{
int counter,c,done;
struct define *currdef,*prevdef;
struct parm *currparm,*nextparm;
FILE *tmp;
struct file_stack *tmp2;
counter=0;
c=fgetc(file_info->curr_file);
while ((c!=EOF) && (!isspace(c)) && (counter<MAX_TOK_LEN)) {
name_buf[counter++]=c;
c=fgetc(file_info->curr_file);
}
if ((c!=EOF) && (!(isspace(c))))
return 1;
name_buf[counter]='\0';
if (!strcmp(name_buf,"undef")) {
while ((c!=EOF) && isspace(c)) c=fgetc(file_info->curr_file);
counter=0;
while ((c!=EOF) && (!isspace(c)) && (counter<MAX_TOK_LEN)) {
name_buf[counter++]=c;
c=fgetc(file_info->curr_file);
}
name_buf[counter]='\0';
ungetc(c,file_info->curr_file);
currdef=file_info->defs;
prevdef=NULL;
while (currdef)
if (!strcmp(currdef->name,name_buf)) {
if (prevdef)
prevdef->next=currdef->next;
else
file_info->defs=currdef->next;
FREE(currdef->name);
FREE(currdef->definition);
currparm=currdef->params;
while (currparm) {
nextparm=currparm->next;
FREE(currparm->name);
if (currparm->exp)
FREE(currparm->exp);
FREE(currparm);
currparm=nextparm;
}
FREE(currdef);
} else
currdef=currdef->next;
return 0;
} else if (!strcmp(name_buf,"include")) {
counter=0;
while ((c!=EOF) && isspace(c)) c=fgetc(file_info->curr_file);
counter=0;
while ((c!=EOF) && (!isspace(c)) && (counter<MAX_STR_LEN)) {
string_buf[counter++]=c;
c=fgetc(file_info->curr_file);
}
string_buf[counter]='\0';
ungetc(c,file_info->curr_file);
if (!(tmp=open_file(make_include_name(string_buf),"r",NULL))) {
set_c_err_msg("couldn't open include file");
return 1;
}
tmp2=(struct file_stack *) MALLOC(sizeof(struct file_stack));
tmp2->file_ptr=file_info->curr_file;
tmp2->previous=file_info->previous;
file_info->previous=tmp2;
file_info->curr_file=tmp;
ungetc('\n',tmp);
return 0;
} else if (!strcmp(name_buf,"define")) {
counter=0;
while ((c!=EOF) && isspace(c)) c=fgetc(file_info->curr_file);
counter=0;
if (!isstart(c)) return 1;
while ((c!=EOF) && iscname(c) && (counter<MAX_TOK_LEN)) {
name_buf[counter++]=c;
c=fgetc(file_info->curr_file);
}
name_buf[counter]='\0';
currdef=(struct define *) MALLOC(sizeof(struct define));
currdef->name=copy_string(name_buf);
currdef->has_paren=0;
currdef->params=NULL;
currparm=NULL;
if (c=='(') {
currdef->has_paren=1;
c=fgetc(file_info->curr_file);
while (c!=EOF) {
while ((c!=EOF) && (c!='\n') && isspace(c))
c=fgetc(file_info->curr_file);
counter=0;
if (c=='\n') {
currdef->params=currparm;
currdef->next=file_info->defs;
file_info->defs=currdef;
currdef->definition=copy_string("");
set_c_err_msg("malformed #define");
return 1;
}
if (c==')') {
c=fgetc(file_info->curr_file);
break;
}
while ((c!=EOF) && (iscname(c)) && (counter<MAX_TOK_LEN)) {
name_buf[counter++]=c;
c=fgetc(file_info->curr_file);
}
name_buf[counter]='\0';
nextparm=(struct parm *) MALLOC(sizeof(struct parm));
nextparm->next=currparm;
nextparm->name=copy_string(name_buf);
nextparm->exp=NULL;
currparm=nextparm;
while ((c!=EOF) && (c!='\n') && (isspace(c)))
c=fgetc(file_info->curr_file);
if ((c!=',') && (c!=')')) {
currdef->params=currparm;
currdef->next=file_info->defs;
currdef->definition=copy_string("");
file_info->defs=currdef;
set_c_err_msg("malformed #define");
return 1;
}
if (c==',') c=fgetc(file_info->curr_file);
}
c=fgetc(file_info->curr_file);
} else
ungetc(c,file_info->curr_file);
while (currparm) {
nextparm=currparm->next;
currparm->next=currdef->params;
currdef->params=currparm;
currparm=nextparm;
}
currdef->next=file_info->defs;
file_info->defs=currdef;
while ((c!=EOF) && (c!='\n') && (isspace(c))) c=fgetc(file_info->curr_file);
counter=0;
while ((c!=EOF) && (c!='\n') && (counter<EBUFSIZ)) {
if (c=='\\') {
c=fgetc(file_info->curr_file);
if (c=='\n') {
if (!(file_info->previous))
++(file_info->phys_line);
c=' ';
} else {
ungetc(c,file_info->curr_file);
c='\\';
}
}
if (c=='/') {
c=fgetc(file_info->curr_file);
if (c=='*') {
while (c!=EOF) {
c=fgetc(file_info->curr_file);
if (c=='*') {
c=fgetc(file_info->curr_file);
if (c=='/') {
c=' ';
break;
} else {
ungetc(c,file_info->curr_file);
}
} else if (c=='\n')
if (!(file_info->previous))
++(file_info->phys_line);
}
} else {
ungetc(c,file_info->curr_file);
c='/';
}
}
if ((c!=EOF) && (c!='\n') && (isspace(c))) {
expand_buf[counter++]=' ';
while ((c!=EOF) && (c!='\n') && (isspace(c)))
c=fgetc(file_info->curr_file);
} else if ((c!=EOF) && (c!='\n')) {
expand_buf[counter++]=c;
c=fgetc(file_info->curr_file);
}
}
ungetc(c,file_info->curr_file);
expand_buf[counter]='\0';
currdef->definition=copy_string(expand_buf);
return 0;
} else
return 1;
}
void expand_def(struct define *def, char *buf)
{
char *s,*s2;
int counter,counter2;
s=def->definition;
counter=0;
while ((*s) && (counter<EBUFSIZ)) {
if (isstart(*s)) {
counter2=0;
while ((counter2<MAX_TOK_LEN) && (iscname(*s)))
name_buf[counter2++]=*(s++);
name_buf[counter2]='\0';
if (!(s2=find_parm(def,name_buf)))
s2=name_buf;
while ((*s2) && (counter<EBUFSIZ))
buf[counter++]=*(s2++);
} else
buf[counter++]=*(s++);
}
buf[counter]='\0';
}
void expand_exp(struct define *def, filptr *file_info)
{
char c;
int done,paren_counter,in_string,counter;
struct parm *currparm;
if (def->has_paren) {
do {
c=getch();
} while (c && isspace(c));
if (c!='(')
return;
paren_counter=0;
in_string=0;
currparm=def->params;
do {
do {
c=getch();
} while (c && isspace(c));
if (c==')')
break;
if (!currparm) {
free_parm_exp(def);
return;
}
counter=0;
while (c && (counter<EBUFSIZ)) {
if (c=='\"')
in_string=(!in_string);
else if (c=='(' && (!in_string))
paren_counter++;
else if (c==')' && (!in_string))
if (!paren_counter) {
ungetch();
break;
} else
paren_counter--;
else if (c==',' && (!paren_counter) && (!in_string))
break;
else if (c=='\\' && in_string) {
c=getch();
if (counter<(EBUFSIZ-1))
tmpbuf[counter++]='\\';
}
tmpbuf[counter++]=c;
c=getch();
}
tmpbuf[counter]='\0';
currparm->exp=copy_string(tmpbuf);
currparm=currparm->next;
} while (c);
if (!c) {
free_parm_exp(def);
return;
}
strcpy(tmpbuf,file_info->expanded);
expand_def(def,expand_buf);
add_expand_buf(expand_buf,tmpbuf);
file_info->expanded=expand_buf;
free_parm_exp(def);
} else {
strcpy(tmpbuf,file_info->expanded);
add_expand_buf(def->definition,tmpbuf);
file_info->expanded=expand_buf;
}
}
void expand(struct define *def, filptr *file_info)
{
int c,paren_counter,in_string,counter;
struct parm *currparm;
if (def->has_paren) {
do {
c=fgetc(file_info->curr_file);
if (c=='\n')
if (!(file_info->previous))
++(file_info->phys_line);
} while ((c!=EOF) && isspace(c));
if (c!='(')
return;
paren_counter=0;
in_string=0;
currparm=def->params;
do {
do {
c=fgetc(file_info->curr_file);
if (c=='\n')
if (!(file_info->previous))
++(file_info->phys_line);
} while ((c!=EOF) && isspace(c));
if (c==')')
break;
if (!currparm) {
free_parm_exp(def);
return;
}
counter=0;
while ((c!=EOF) && (counter<EBUFSIZ)) {
if (c=='\n') {
if (!(file_info->previous))
++(file_info->phys_line);
c=' ';
}
if (c=='\"')
in_string=(!in_string);
else if (c=='(' && (!in_string))
paren_counter++;
else if (c==')' && (!in_string))
if (!paren_counter) {
ungetc(c,file_info->curr_file);
break;
} else
paren_counter--;
else if (c==',' && (!paren_counter) && (!in_string))
break;
else if (c=='\\' && in_string) {
c=fgetc(file_info->curr_file);
if (counter<(EBUFSIZ-1))
tmpbuf[counter++]='\\';
}
tmpbuf[counter++]=c;
c=fgetc(file_info->curr_file);
}
tmpbuf[counter]='\0';
currparm->exp=copy_string(tmpbuf);
currparm=currparm->next;
} while (c!=EOF);
if (c==EOF) {
free_parm_exp(def);
return;
}
expand_def(def,expand_buf);
file_info->expanded=expand_buf;
free_parm_exp(def);
} else {
strcpy(expand_buf,def->definition);
file_info->expanded=expand_buf;
}
}