/* headers.c $Log: headers.c,v $ * Revision 5.4.1.3 1994/05/13 15:07:01 demeter * *** empty log message *** * * Revision 5.4.1.2 1994/05/12 16:19:22 demeter * *** empty log message *** * * Revision 5.4.1.1 1994/02/25 14:26:36 demeter * *** empty log message *** * * Revision 5.4 1994/02/25 14:26:35 demeter * *** empty log message *** * * Revision 5.3.1.1 1994/01/26 20:12:45 demeter * *** empty log message *** * * Revision 5.3 1994/01/26 20:12:43 demeter * *** empty log message *** * * Revision 5.2.1.1 1994/01/26 20:12:29 demeter * *** empty log message *** * * Revision 5.2 1994/01/26 20:12:28 demeter * *** empty log message *** * * Revision 5.1.1.3 1993/11/15 15:28:55 demeter * test logging messages again * */ #include #include #include #include #include #include #include #include #include #include "headers.h" #include #include #define FALSE 0 #define TRUE 1 #define NOTDONE 0 #define DONE 1 #define MAXFIELDS 100 #define ENDFILE -1 #define INITCLASSTABLESIZE 300 #define CLASSTABLEINCREMENT 50 #define MAXDEFAULTS 25 #define FILEBUFFSIZE 255 #define TBUFFSIZE 45 #define MAXEXPRESSION 20 #define MAXDIRLEN 1023 #define lasttokenindex(current) (current ? (current - 1) : (TBUFFSIZE - 1)) #define nexttokenindex(current) ((current + 1) % TBUFFSIZE) #define incexpcount() if (++expcount >= MAXEXPRESSION) fatal("Too many arguments") typedef int FLAG; typedef enum classtypes { Construction, Repetition, Alternation } CLASSTYPE; typedef enum scope { pubscope, privscope, protscope } SCOPE; typedef struct ctentry { char *name; CLASSTYPE type; int usedflag; SCOPE lastscope; char *tempfile; } CTENTRY; typedef struct ctable { CTENTRY *entries; int size ; int maxsize; int sorted; } CLASSTABLE; typedef struct expression { TOKEN token; char *string; struct expression *next; } EXPRESSION; typedef struct tokentext { TOKEN token; char string[BUFSIZ]; } TOKENTEXT; char *grammar = "notmod/cds/cd-param-exp"; char *flag = "//++"; char *hext = ".h"; int clean_headers_flag = 0; char *headers_path = "notmod/headers/"; char *cfiles_path = "."; /* current directory*/ char *clean_tag = "-a"; char *currfile; int bracecount; FLAG defaultflag; FLAG inlineflag; FLAG friendflag; FLAG publicflag; FLAG staticflag; FLAG privateflag; FLAG protectedflag; FLAG pureflag; FLAG virtualflag; FLAG nonvirtualflag; CLASSTABLE classtable; /* char *builtinclass[] = { "DemIdent", "DemNumber", "DemReal", "DemString", "DemText" }; */ int expcount; EXPRESSION *expressionlist[MAXEXPRESSION]; EXPRESSION *expressiontails[MAXEXPRESSION]; TOKENTEXT tokenbuff[TBUFFSIZE]; int tbuffhead = 0; char *tmpdir = "notmod/tmp"; enum mv_mode {mv_interactive,mv_silent}; int mv_if_change(enum mv_mode ,char *,char *); void genheaders(FILE*); FILE *xfopen(char *,char *); void fatal(char *s); void clearflags(); void *xmalloc(int); void *xrealloc(void *,int); void buildclasstable(); void addtoclasstable(char* classname,CLASSTYPE ctype); CTENTRY *searchclasstable(char *classname); void skipcomment(); void skipcppcomment(); void skipcharconst(); void skipstring(); void destroyexplist(int); void storetokeninbuffer(TOKEN); void setflagsanddefaults(); void writeprototype(); void builddefaults(); void buildinline(); void writeinlinebody(); void buildexpression(int); void printexpression(FILE*,int); void deleteexpressions(); void makefriend(); char *get_a_cfile(char* ); char *get_a_hfile(); int iscplusplusfile(char * ); int isheaderfile(char * ); void check_headers_path(char *); int IsADirectory (char* path); void check_timestamp(int,char**); void update_headers(); #ifdef __cplusplus extern "C" { void free(void *); void exit(int); int yylex(); int system(const char*); int getpid(); } #else #include void *malloc(int); void *realloc(void *,int); void free(void *); void exit(int); int system(char*); int getpid(); int yylex(); #endif DIR* dir = NULL; int successful = 0; char *mytempnam(char *tmpdir,char *prefix) { static int i = 100000; char *name = (char*)xmalloc(32); sprintf(name,"%s/%s%d",tmpdir,prefix,i); i++; return name; } int mv_if_change(enum mv_mode m,char *newfile,char *oldfile) { FILE *nfp,*ofp; char buf[MAXDIRLEN+1]; char c,nc,oc; int nr,or; assert( (newfile != NULL) && (oldfile != NULL) && (buf != NULL) ); if ((nfp = fopen(newfile,"r")) == NULL) { sprintf(buf,"headers: read %s",newfile); perror(buf); if (unlink(newfile)) { sprintf(buf,"headers: warning : rm %s",newfile); perror(buf); } return 1; } if ((ofp = fopen(oldfile,"r")) == NULL) { if ((ofp = fopen(oldfile,"w"))==NULL) { sprintf(buf,"headers: write %s",oldfile); perror(buf); if (unlink(newfile)) { sprintf(buf,"headers: warning : rm %s",newfile); perror(buf); } return 1; } while (fread(&c,1,1,nfp) == 1) fwrite(&c,1,1,ofp); if (m == mv_interactive) printf("headers: %s created.\n", oldfile); fclose(nfp); fclose(ofp); if (unlink(newfile)) { sprintf(buf,"headers: warning : rm %s",newfile); perror(buf); } return 0; } nr = fread(&nc,1,1,nfp); or = fread(&oc,1,1,ofp); while ( (nr == or) && (nr != 0) && (nc == oc)) { nr = fread(&nc,1,1,nfp); or = fread(&oc,1,1,ofp); } fclose(nfp); fclose(ofp); if ((nr == or) && (nr == 0)) { /* if (m == mv_interactive) printf("headers: %s is up to date.\n", oldfile); */ if (unlink(newfile)) { sprintf(buf,"headers: warning : rm %s",newfile); perror(buf); } return 0; } if ((nfp = fopen(newfile,"r")) == NULL) { sprintf(buf,"headers: open %s",newfile); perror(buf); if (unlink(newfile)) { sprintf(buf,"headers: warning : rm %s",newfile); perror(buf); } return 1; } if ((ofp = fopen(oldfile,"w"))==NULL) { sprintf(buf,"headers: open %s",oldfile); perror(buf); if (unlink(newfile)) { sprintf(buf,"headers: warning : rm %s",newfile); perror(buf); } return 1; } while (fread(&c,1,1,nfp) == 1) fwrite(&c,1,1,ofp); if (m == mv_interactive) printf("headers: %s recreated.\n", oldfile); if (unlink(newfile)) { sprintf(buf,"headers: warning : rm %s",newfile); perror(buf); } fclose(nfp); fclose(ofp); return 0; } int illegal_statements(char *token) { char *terminal_sets = "*terminal_sets*"; return (strncmp(token,terminal_sets,15)); } int isheaderfile(char * name) { int length = strlen(name); return ((length>=2) && (name[length-1] == 'h') && (name[length-2] == '.')); } void opendirforc(char* p) { if (dir != NULL) closedir(dir); dir = opendir(p); successful = dir != NULL; } int iscplusplusfile(char * name) { int length = strlen(name); return (((length>=2) && (name[length-1] == 'C') && (name[length-2] == '.')) || ((length>=3) && (name[length-1] == 'c') && (name[length-2] == 'c') && (name[length-3] == '.')) || ((length>=4) && (name[length-1] == 'x') && (name[length-2] == 'x') && (name[length-3] == 'c') && (name[length-4] == '.'))); } void check_timestamp(int argc, char **argv) { char headerstamp[256]; char *currfile; struct stat stbuf1; struct stat stbuf2; time_t maxctime = 0; time_t minhtime = 0; register int i; FILE *fp; opendirforc(cfiles_path); while (currfile = get_a_cfile(cfiles_path)) { if (stat(currfile,&stbuf1) >= 0) if (stbuf1.st_mtime > maxctime) maxctime = stbuf1.st_mtime; free(currfile); } for (i = 1; i < argc; i++) { opendirforc(argv[i]); while (currfile = get_a_cfile(argv[i])) { if (stat(currfile,&stbuf1) >= 0) if (stbuf1.st_mtime > maxctime) maxctime = stbuf1.st_mtime; free(currfile); } } sprintf(headerstamp,"%sheader-stamp",headers_path); if (access(headerstamp, R_OK | W_OK)) { if (errno != ENOENT) { perror(headerstamp); exit(1); } } else { if (stat(headerstamp,&stbuf2) == 0) minhtime = stbuf2.st_mtime; else { perror(headerstamp); exit(1); } } if (minhtime >= maxctime) { printf("\nAll header files are up to date.\n"); exit(0); } } void create_stamp() { char headerstamp[256]; FILE* fp; sprintf(headerstamp,"%sheader-stamp",headers_path); fp = fopen(headerstamp,"w"); if (fp == NULL) { fprintf(stderr,"headers: unable to create file %s\n",headerstamp); exit(1); } fprintf(fp,"-------------------------------------------------------------------\n"); fprintf(fp,"P L E A S E D O N ' T D E L E T E T H I S F I L E!\n"); fprintf(fp,"-------------------------------------------------------------------\n"); fclose(fp); } main(int argc,char **argv) { int i; FILE *fp; int length; printf("\nCopyright (C) 1991, Northeastern University.\n\ All rights reserved.\n\n"); printf("headers: checking time stamps ...\n"); check_timestamp(argc,argv); if (mkdir(tmpdir,0755) && (errno != EEXIST)) { fprintf(stderr, "headers: unable to create %s/%s for holding temporary files.\n", getcwd(NULL,1023),tmpdir); perror(tmpdir); exit(1); } else if (access(tmpdir, X_OK | R_OK | W_OK )) { fprintf(stderr, "headers: unable to have access to %s/%s for holding temporary files.\n", getcwd(NULL,1023),tmpdir); perror(tmpdir); exit(1); } /* check the cwd is the coreect place to run headers */ check_headers_path(headers_path); /* build class table and initialize the temporary header file for each class */ printf("headers: reading %s ... \n",grammar); buildclasstable(); opendirforc(cfiles_path); while (currfile = get_a_cfile(cfiles_path)) { yylineno = 0; bracecount = 0; printf("headers: reading %s ...\n",currfile); fp = xfopen(currfile,"r"); genheaders(fp); fclose(fp); if (bracecount != 0) fprintf(stderr,"headers: warning: Mismatched curly braces in %s\n",currfile); } for (i = 1; i < argc; i++) { opendirforc(argv[i]); while (currfile = get_a_cfile(argv[i])) { yylineno = 0; bracecount = 0; printf("headers: reading %s ...\n",currfile); fp = xfopen(currfile,"r"); genheaders(fp); fclose(fp); if (bracecount != 0) fprintf(stderr,"headers: warning: Mismatched curly braces in %s/%s\n",argv[i],currfile); } } /* run mv_if_change for each header file */ printf("\n\nheaders: please wait. Updating header files in %s ...\n",headers_path); update_headers(); create_stamp(); printf("\n\n"); return 0; } void update_headers() { static char hfile[FILEBUFFSIZE]; int i; for (i = classtable.size -1; i >= 0 ; i--) { strcpy(hfile,headers_path); strcat(hfile,classtable.entries[i].name); strcat(hfile,hext); mv_if_change(mv_interactive,classtable.entries[i].tempfile,hfile); } } void genheaders(FILE* file) { TOKEN val; yyin = file; clearflags(); while (val = yylex()) { switch(val) { case SEMI : break; case LBRACE : bracecount++; break; case RBRACE : bracecount--; break; case OVERRIDE : /* "//++" */ setflagsanddefaults(); break; case SCOPERESOLUTION : /* "::" */ if (bracecount == 0) writeprototype(); break; case DQUOTE : /* " */ skipstring(); break; case QUOTE : /* ' */ skipcharconst(); break; case BEGINCOMMENT : skipcomment(); break; case CPPCOMMENT : skipcppcomment(); break; } storetokeninbuffer(val); } } FILE *xfopen(char *s,char *p) { FILE *fp; fp = fopen(s,p); if (fp == NULL) { fprintf(stderr,"Can't open file %s. Aborting\n",s); exit(1); } return fp; } void fatal(char *s) { fprintf(stderr,"headers: Fatal error\n"); fprintf(stderr,"File: %s Line: %d\n",currfile,yylineno); fprintf(stderr,"%s\n",s); exit(1); } void clearflags() { defaultflag = FALSE; nonvirtualflag = FALSE; privateflag = FALSE; protectedflag = FALSE; publicflag = FALSE; staticflag = FALSE; inlineflag = FALSE; friendflag = FALSE; pureflag = FALSE; virtualflag = FALSE; } void buildclasstable() { CLASSTYPE ctype; TOKEN val; char *classname; char *dem_terminal; int length; classtable.maxsize = INITCLASSTABLESIZE; classtable.size = 0; currfile = grammar; yylineno = 0; yyin = xfopen(grammar,"r"); classtable.entries = (CTENTRY *) xmalloc(sizeof(CTENTRY)*classtable.maxsize); while(val = yylex()) { /* get classname */ if (val == WS) continue; if (val == SEMI || val == CPPCOMMENT) { skipcppcomment(); continue; } if (val == TERMINAL_SETS) { while (val != DOT) { val = yylex(); continue; /* ignore terminal classes */ length = strlen(yytext); dem_terminal = (char *)xmalloc(length+1); strcpy(dem_terminal,yytext); addtoclasstable(dem_terminal,Construction); val = yylex(); } continue; } if (val != IDENTIFIER) continue; classname = (char *)xmalloc(strlen(yytext)+1); sprintf(classname,"%s",yytext); val = yylex(); while (val == WS) val = yylex(); switch (*yytext) { case '=' : ctype = Construction; break; case '~' : ctype = Repetition; break; case ':' : ctype = Alternation; break; default : /* not a class */ if (illegal_statements(yytext)) fatal("Unknown token"); } addtoclasstable(classname,ctype); while ((val = yylex()) != DOT) { if (val == DQUOTE) skipstring(); else if (val == 0) fatal("Premature end of grammar file"); } } fclose(yyin); } CTENTRY *searchclasstable(char *classname) { int left,size,right,result,middle; left = 0; size = classtable.size; right = size-1; while (!(left > right)) { middle = (left+right)/2; result = strcmp(classname,classtable.entries[middle].name); if (result == 0) return &classtable.entries[middle]; else if (result < 0) left = middle+1; else right = middle-1; } return NULL; } void addtoclasstable(char* classname,CLASSTYPE ctype) { CTENTRY *entry; char *fn,*tmp; int index1,index2; FILE *fp; if (classtable.size >= classtable.maxsize) { classtable.maxsize += CLASSTABLEINCREMENT; classtable.entries = (CTENTRY *) xrealloc(classtable.entries, sizeof(CTENTRY)*classtable.maxsize); } index1 = 0; if (classtable.size > 0) while ((index1 != classtable.size) && (strcmp(classtable.entries[index1].name,classname) > 0)) index1++; if (index1== classtable.size) { entry = &(classtable.entries[index1]); entry->name = (char *)xmalloc(strlen(classname)+1); sprintf(entry->name,"%s",classname); entry->type = ctype; entry->usedflag = FALSE; entry->lastscope = (SCOPE)(protscope + 1); entry->tempfile = mytempnam(tmpdir,"headers"); fp = xfopen(entry->tempfile,"w"); fprintf(fp,"\n"); fclose(fp); classtable.size++; classtable.sorted = TRUE; return; } index2 = classtable.size-1; while (index2 >= index1) { classtable.entries[index2+1].name = classtable.entries[index2].name; classtable.entries[index2+1].type = classtable.entries[index2].type; classtable.entries[index2+1].usedflag = classtable.entries[index2].usedflag; classtable.entries[index2+1].lastscope = classtable.entries[index2].lastscope; classtable.entries[index2+1].tempfile = classtable.entries[index2].tempfile; index2--; } entry = &(classtable.entries[index1]); entry->name = (char *)xmalloc(strlen(classname)+1); sprintf(entry->name,"%s",classname); entry->type = ctype; entry->usedflag = FALSE; entry->lastscope = (SCOPE)(protscope + 1); entry->tempfile = mytempnam(tmpdir,"headers"); fp = xfopen(entry->tempfile,"w"); fprintf(fp,"\n"); fclose(fp); classtable.size++; classtable.sorted = TRUE; } void *xmalloc(int size) { void *p; if ((p = malloc(size)) == NULL) { fprintf(stderr,"headers: malloc(%d) : Memory allocation failure\n",size); exit(1); } return p; } void *xrealloc(void *p,int size) { void *q; /* if ((q = realloc(p,size)) == p) {*/ if ((q = realloc(p,size)) == NULL) { fprintf(stderr,"headers: realloc(%d,%d) %d: Memory allocation failure\n",p,size,q); exit(1); } return q; } void setflagsanddefaults() { TOKEN val; int nlsave = nlflag; nlflag = TRUE; while ((val = yylex()) && val != NEWLINE) { switch(val) { case VIRTUAL : virtualflag = TRUE; break; case NONVIRTUAL : nonvirtualflag = TRUE; break; case PUBLIC : publicflag = TRUE; break; case STATIC : staticflag = TRUE; break; case PRIVATE : privateflag = TRUE; break; case PROTECTED : protectedflag = TRUE; break; case INLINE: inlineflag = TRUE; buildinline(); break; case FRIEND: friendflag = TRUE; makefriend(); break; case DEFAULTS : defaultflag = TRUE; builddefaults(); break; case PURE : pureflag = TRUE; break; case SCOPERESOLUTION : if (pureflag && (bracecount == 0)) writeprototype(); else fatal("no \"pure\" directive, \"::\" unexpected"); break; default: /* just in case we see :: */ if (pureflag) storetokeninbuffer(val); break; } if (friendflag || inlineflag) break; } if (val == 0 && (!friendflag && !inlineflag)) fatal("Premature end of file"); if (publicflag + privateflag + protectedflag > TRUE) fatal("Must be exactly one of public, private, protected"); if (virtualflag + nonvirtualflag > TRUE) fatal("Must be exactly one of virtual, non-virtual"); if (friendflag || inlineflag) clearflags(); nlflag = nlsave; } void builddefaults() { int parencount; int squarecount; TOKEN val; int nlsave = nlflag; char *premsg = "defaults expression list ends prematurely"; nlflag = TRUE; val = yylex(); while (val == WS) val = yylex(); if (val != LPAREN) fatal("\"defaults\" must be followed by defaults list in parentheses"); parencount = 1; expcount = 0; squarecount = 0; while (val = yylex()) { switch(val) { case WS: continue; case LPAREN : parencount++; break; case RPAREN : if (--parencount == 0) { incexpcount(); nlflag = nlsave; return; } break; case LSQUARE : squarecount++; break; case RSQUARE : squarecount--; break; case COMMA : if (parencount == 1 && squarecount == 0) { incexpcount(); continue; } case NEWLINE : fatal(premsg); break; } buildexpression(expcount); } fatal(premsg); } void buildexpression(int expcount) { EXPRESSION *newexp; if (yytext[0] == '=' && yytext[1] == '\0') { destroyexplist(expcount); return; } newexp = (EXPRESSION *)xmalloc(sizeof(EXPRESSION)); newexp->string = (char *)xmalloc(strlen(yytext)+1); strcpy(newexp->string,yytext); if (expressionlist[expcount] == NULL) expressionlist[expcount] = newexp; else expressiontails[expcount]->next = newexp; expressiontails[expcount] = newexp; expressiontails[expcount]->next = NULL; } void deleteexpressions() { int i; for (i = 0; i < expcount; i++) destroyexplist(i); } void destroyexplist(int expnum) { EXPRESSION *eptr,*nptr; eptr = expressionlist[expnum]; while (eptr) { nptr = eptr->next; free(eptr); eptr = nptr; } expressionlist[expnum] = NULL; } void skipcomment() { TOKEN val; while (val = yylex()) { if (val == ENDCOMMENT) return; } fatal("Unterminated comment"); } void skipcppcomment() { TOKEN val; int nlsave = nlflag; nlflag = TRUE; while ((val = yylex()) != NEWLINE) ; nlflag = nlsave; } void skipcharconst() { TOKEN val; while (val = yylex()) { if (val == BACKSLASH) { yylex(); continue; } if (val == QUOTE) return; } } void skipstring() { TOKEN val; while (val = yylex()) { if (val == BACKSLASH) { yylex(); continue; } if (val == DQUOTE) return; } } void storetokeninbuffer(TOKEN val) { TOKENTEXT *t = &tokenbuff[tbuffhead]; t->token = val; strcpy(t->string,yytext); tbuffhead = ++tbuffhead % TBUFFSIZE; } static char lastclass[FILEBUFFSIZE]; static CTENTRY *ctptr; void makefriend() { int foundsemi = 0; int c; FILE *fp = NULL; TOKEN val; static char classname[FILEBUFFSIZE]; classname[0] = '\0'; while ((val = yylex()) != NEWLINE) { if (val == IDENTIFIER && classname[0] == '\0') { strcpy(classname,yytext); strcpy(lastclass,classname); ctptr = searchclasstable(classname); if (!ctptr) { fprintf(stderr,"headers: warning: Class %s not in %s\n",classname,grammar); addtoclasstable(classname,Construction); ctptr = searchclasstable(classname); } fp = xfopen(ctptr->tempfile,"a"); ctptr->usedflag++; fprintf(fp,"friend "); c = getc(yyin); while (c != EOF && c != '\n') { fprintf(fp,"%c",c); if (c == ';') foundsemi = 1; c = getc(yyin); } } } if (foundsemi == 0 && fp) fprintf(fp,";\n"); else if (fp) fprintf(fp,"\n"); if (fp) fclose(fp); deleteexpressions(); return; } void buildinline() { TOKEN val; while (val = yylex()) { switch(val) { case OVERRIDE : /* "//++" */ break; case SCOPERESOLUTION : /* "::" */ if (bracecount == 0) writeinlinebody(); return; default: storetokeninbuffer(val); break; } } } void writeprototype() { int i; TOKEN val; char *classname; int index,cindex,tindex; int retvalfields; static FILE *fp; int parencount; int expsprinted; int tokencount; int nlsave = nlflag; if (pureflag) nlflag = TRUE; cindex = index = lasttokenindex(tbuffhead); classname = tokenbuff[index].string; /* may wish to expand this to allow type qualifiers, like const, etc. */ index = lasttokenindex(index); while ((val = tokenbuff[index].token) == INDIRECTIONS || val == WS) index = lasttokenindex(index); retvalfields = 1; tindex = lasttokenindex(index); if ((val = tokenbuff[tindex].token) == STRUCT || val == LONG || val == SHORT || val == CONST) { index = tindex; retvalfields++; } strcpy(lastclass,classname); ctptr = searchclasstable(classname); if (!ctptr) { fprintf(stderr,"headers: warning: Class %s not in %s\n",classname,grammar); addtoclasstable(classname,Construction); ctptr = searchclasstable(classname); } fp = xfopen(ctptr->tempfile,"a"); ctptr->usedflag++; if (publicflag && ctptr->lastscope != pubscope) { fprintf(fp,"public:\n"); ctptr->lastscope = pubscope; } else if (privateflag && ctptr->lastscope != privscope) { fprintf(fp,"private:\n"); ctptr->lastscope = privscope; } else if (protectedflag && ctptr->lastscope != protscope) { fprintf(fp,"protected:\n"); ctptr->lastscope = protscope; } else if (ctptr->lastscope != pubscope) { fprintf(fp,"public:\n"); ctptr->lastscope = pubscope; } if (staticflag) fprintf(fp,"static "); if (pureflag || virtualflag || (!nonvirtualflag && ctptr->type == Alternation)) { fprintf(fp,"virtual "); } /* print return type */ for (i = 0; i < retvalfields; i++) { if (strcmp(tokenbuff[index].string,"}")!=0) fprintf(fp,"%s ",tokenbuff[index].string); index = nexttokenindex(index); } if (strcmp(tokenbuff[index].string,"}")!=0) while (index != cindex) { if (strcmp(tokenbuff[index].string,"}")!=0) fprintf(fp,"%s",tokenbuff[index].string); index = nexttokenindex(index); } /* now get member function name */ while (yylex() != LPAREN) { fprintf(fp,"%s",yytext); } fprintf(fp,"%s ",yytext); /* and now arguments */ parencount = 1; expsprinted = 0; tokencount = 0; while (val = yylex()) { switch(val) { case RPAREN : if (--parencount == 0) { if (defaultflag && expressionlist[expsprinted]) { fprintf(fp,"= "); printexpression(fp,expsprinted); } else if (tokencount == 0) fprintf(fp,"void "); fprintf(fp,")"); val = yylex(); if (pureflag) { while ( val != NEWLINE ) { if (val == CPPCOMMENT) { char c; while ((c = getc(yyin)) != '\n') ; val = yylex(); break; } if (val == CONST) fprintf(fp," %s ",yytext); val = yylex(); } } else { while ( (val != SEMI) && (val != LBRACE)) { if (val == CPPCOMMENT) { char c; while ((c = getc(yyin)) != '\n') ; val = yylex(); continue; } if (val == CONST) fprintf(fp," %s ",yytext); val = yylex(); } if (val == LBRACE) ungetc('{',yyin); else ungetc(';',yyin); } fprintf(fp,pureflag ? " = 0;\n" : ";\n"); clearflags(); deleteexpressions(); nlflag = nlsave; fclose(fp); return; } break; case LPAREN : parencount++; break; case COMMA : if (defaultflag && expressionlist[expsprinted]) { fprintf(fp,"= "); printexpression(fp,expsprinted); } expsprinted++; break; case NEWLINE : /* can only happen if pure virtual function */ fatal("Pure virtual function must be declared on one line"); break; } tokencount++; fprintf(fp,"%s ",yytext); } fatal("Member function argument list ends prematurely"); } void printexpression(FILE *fp,int index) { EXPRESSION *e = expressionlist[index]; while (e) { fprintf(fp,"%s ",e->string); e = e->next; } } int IsADirectory (char* path) { struct stat filestats; stat(path, &filestats); return filestats.st_mode & S_IFDIR; } char *get_a_cfile(char* p) { struct dirent* d; FILE * fp; if (successful) { for (d = readdir(dir); d != NULL; d = readdir(dir)) { int length = strlen(d->d_name); if (iscplusplusfile(d->d_name)) { char *return_val = (char*)malloc(512); sprintf(return_val,"%s/%s",p,d->d_name); if (fp = fopen(return_val,"r")) { fclose(fp); return return_val; } else { printf("\nError : cannot open %s/%s\n",p,d->d_name); exit(1); } } } closedir(dir); dir = NULL; return NULL; } else { printf("\nError : cannot open directory '%s'.\n",p); return NULL; } } void check_headers_path(char *filename) { FILE* tfp; if (tfp = fopen(headers_path,"r")) if (IsADirectory(filename)) { fclose(tfp); return; } else { printf("Error : %s is a file\n",headers_path); exit(1); } else { printf("Error : %s does not exist.\n",headers_path); exit(1); } } void writeinlinebody() { int i; TOKEN val; char *classname; int index,cindex,tindex; int retvalfields; static FILE *fp; int parencount; int expsprinted; int tokencount; int nlsave = nlflag; if (pureflag) nlflag = TRUE; cindex = index = lasttokenindex(tbuffhead); classname = tokenbuff[index].string; /* may wish to expand this to allow type qualifiers, like const, etc. */ index = lasttokenindex(index); while ((val = tokenbuff[index].token) == INDIRECTIONS || val == WS) index = lasttokenindex(index); retvalfields = 1; tindex = lasttokenindex(index); if ((val = tokenbuff[tindex].token) == STRUCT || val == LONG || val == SHORT || val == CONST) { index = tindex; retvalfields++; } strcpy(lastclass,classname); ctptr = searchclasstable(classname); if (!ctptr) { fprintf(stderr,"headers: warning: Class %s not in %s\n",classname,grammar); addtoclasstable(classname,Construction); ctptr = searchclasstable(classname); } fp = xfopen(ctptr->tempfile,"a"); ctptr->usedflag++; if (publicflag && ctptr->lastscope != pubscope) { fprintf(fp,"public:\n"); ctptr->lastscope = pubscope; } else if (privateflag && ctptr->lastscope != privscope) { fprintf(fp,"private:\n"); ctptr->lastscope = privscope; } else if (protectedflag && ctptr->lastscope != protscope) { fprintf(fp,"protected:\n"); ctptr->lastscope = protscope; } else if (ctptr->lastscope != pubscope) { fprintf(fp,"public:\n"); ctptr->lastscope = pubscope; } if (staticflag) fprintf(fp,"static "); if (pureflag || virtualflag || (!nonvirtualflag && ctptr->type == Alternation)) { fprintf(fp,"virtual "); } /* print return type */ for (i = 0; i < retvalfields; i++) { if (strcmp(tokenbuff[index].string,"}")!=0) fprintf(fp,"%s ",tokenbuff[index].string); else break; index = nexttokenindex(index); } if (strcmp(tokenbuff[index].string,"}")!=0) { while (index != cindex) { if (strcmp(tokenbuff[index].string,"}")!=0) fprintf(fp,"%s",tokenbuff[index].string); else break; index = nexttokenindex(index); } } /* now get member function name */ while ((val = yylex()) != LPAREN) { if (val != OVERRIDE) fprintf(fp,"%s",yytext); } fprintf(fp,"%s ",yytext); /* and now arguments */ parencount = 1; expsprinted = 0; tokencount = 0; while (val = yylex()) { switch(val) { case NEWLINE : fprintf(fp,"\n"); val = yylex(); if ( val == OVERRIDE) break; else { deleteexpressions(); nlflag = nlsave; fclose(fp); return; } default: fprintf(fp,"%s",yytext); } } }