/* ------------------------------------------------------------------------ */
/* */
/* [ctoh.c] Creates an Interface File from a C-Source */
/* */
/* Copyright (c) 1994 by D\olle, Manns */
/* ------------------------------------------------------------------------ */
/* [*.h] files should now look like */
/* */
/* Header ... */
/* */
/* #ifndef __MODNAME */
/* #define __MODNAME */
/* */
/* Includes ... */
/* */
/*+++ #ifdef __cplusplus */
/*+++ extern "C" { */
/*+++ #endif */
/* */
/* Signature ... */
/* */
/*+++ #ifdef __cplusplus */
/*+++ } */
/*+++ #endif */
/* #endif __MODNAME */
#include "stdosx.h"
#include "pathes.h"
#include "sink.h"
#include "dicts.h"
#include "line_scn.h"
#include "com_get.h"
#include "hmap.h"
#include "hset.h"
#include "symbols.h"
#include "ctoh_cim.h"
#include "binimg.h"
#include "scn_base.h"
#include "ccnv_lim.h"
static long pgmtim; /* the start time of this program */
static string null_line = "";
static string scan_line = (string)NULL;
static string line = (string)NULL;
static symbol ccls = (symbol)NULL;
static string cfid = (string)NULL;
static string lnam = (string)NULL;
static string hnam = (string)NULL;
static string cnam = (string)NULL;
static string enam = (string)NULL;
static FILE *SysIn = (FILE*)NULL;
static FILE *SysOut = (FILE*)NULL;
static FILE *SysExp = (FILE*)NULL;
static FILE *SysDoc = (FILE*)NULL;
static long lineno = 0; /* current line number */
static bool Patched = False; /* c/h patched in header comment */
static bool IncludeSeen = False; /* passed any includes */
static bool Shift = False; /* between '{' ... '}' */
static bool OnOff = True; /* 'INTERFACE_ON/OFF' */
static bool mainSeen = False; /* 'main' seen */
#define GenExp CTX_EVAL(string ,"exp")
#define GenApi CTX_EVAL(string ,"api")
static symbol ApiSym = (symbol)NULL;
#define CTypConv CTX_EVAL(bool,"ct")
static Scn_T pScn = (Scn_T)NULL;
#define DROOT CTX_EVAL(string ,"DROOT")
#define GET_REFERENCE(a,b) (getReference((void**)(a),(void (*)(void**))(b)))
#define PUT_REFERENCE(a,b) (putReference((void*)(a),(void (*)(void*))(b)))
#define LineLength 78
#define CommentMargin 40
#define HTML_DOCTYPE \
""
bool beginswith(string key)
{
return strncmp(line,key,strlen(key)) == 0;
}
bool endswith(string key)
{ int len = strlen(line), klen = strlen(key);
if( len < klen ) return False;
return strncmp(line+len-klen,key,klen) == 0;
}
void patchhead(void)
{ int fidlen = strlen(cfid), i, len = strlen(line);
for (i = 0; i < len; i++)
{
if (line[i] == '[' && strncmp(cfid,line+i+1,fidlen) == 0)
{ int j, k;
for( j=fidlen-1; j > 0; --j )
if( line[i+j] == '.' )
{
line[i+j+1] = 'h'; Patched = True; break;
}
k = i + fidlen + 1;
if( line[k] == '(' )
{ string s; int clslen = 0;
for( k=k+1; k < len; ++k )
if( line[k] == ')' )
{ ++k; break; }
else
{
if( isalpha(line[k]) || line[k] == '_' ) ++clslen;
else
{
fprintf(STDERR,"Warnung: %s bad module name.\n",cfid);
return;
}
}
s = SubStrCopy(line+i+fidlen+2,clslen);
ccls = stringToSymbol(s);
FreeMem(s);
}
if( line[k] != ']' )
{
fprintf(STDERR,"Warnung: %s missing closing bracket.\n",cfid);
return;
}
}
}
}
bool getline(void)
{
if( scan_line != NULL ) FreeMem(scan_line);
if ((scan_line = Line_get(SysIn)) == NULL)
{
line = null_line; return False;
}
else line = scan_line;
lineno += 1;
if (!Patched) patchhead();
if (line[0] == '{') Shift = True;
if (line[0] == '}') Shift = False;
mainSeen |= beginswith("main") || beginswith("int main");
return True;
}
static string convBlock(string szBlock)
/* C-Header-Block-Filter */
{ string szResult, szTxt;
Sink pSnk;
Scn_Stream pStream;
if (strstr(szBlock,"/*NOCONVERSION*/"))
return StrCopy(szBlock);
pSnk = Sink_open();
pStream = Stream_string(pScn, szBlock);
Stream_defEofId(pStream, -1);
Stream_defErrId(pStream, 0);
Stream_defTokId(pStream, "Ide", 1);
Stream_defTokId(pStream, "Inc", 2);
Stream_defTokId(pStream, "Com", 3);
Stream_defTokId(pStream, "Other", 4);
for(Stream_next(pStream); Stream_ctid(pStream) >= 0; Stream_next(pStream))
{
szTxt = symbolToString(Stream_csym(pStream));
if (Stream_ctid(pStream) == 1)
{
if( !strcmp(szTxt,"byte") ) Sink_printf(pSnk,"c_byte");
else
if( !strcmp(szTxt,"word") ) Sink_printf(pSnk,"c_word");
else
if( !strcmp(szTxt,"string") ) Sink_printf(pSnk,"c_string");
else
if( !strcmp(szTxt,"bool") ) Sink_printf(pSnk,"c_bool");
else
if( !strcmp(szTxt,"False") ) Sink_printf(pSnk,"C_False");
else
if( !strcmp(szTxt,"True") ) Sink_printf(pSnk,"C_True");
else Sink_printf(pSnk,"%s",szTxt);
}
else Sink_printf(pSnk,"%s",szTxt);
}
szResult = Sink_close(pSnk);
Stream_close(pStream);
Stream_free(pStream);
return szResult;
}
static bool Funpossible;
bool CppFunDef(void)
/* ob 'line' eine Methodendefinition einleitet */
{ int len = strlen(line), i;
/* assumes isLetter(line[0]) */
for( i=1; i < len-1; ++i )
{
if( line[i] == ':' && line[i+1] == ':' ) return( True );
if( ! ( islower(line[i]) ||
isupper(line[i]) ||
isdigit(line[i]) ||
line[i] == '*' ||
line[i] == '&' ||
line[i] == '_' ||
line[i] == ' ' ) ) return( False );
}
return( False );
}
bool BlockStart(void)
/* whether 'line' starts an interface block */
{
Funpossible = False;
if (Shift) return False;
if (!OnOff) return False;
if (beginswith("ExternalType"))
{
strncpy(line,"Abstract",8);
return True;
}
if (beginswith("ExternalDecl"))
{
strncpy(line,"AbstractType",12);
return True;
}
//18.10.98 _DLL_EXPORT_ startet einen Interface-Block !
if( beginswith("_DLL_EXPORT_") ||
(
( islower(line[0]) || isupper(line[0]) )
&& !beginswith("ConcreteType")
&& !beginswith("ConcreteImp")
&& !beginswith("static")
&& !beginswith("struct")
&& !beginswith("union")
&& !beginswith("typedef")
/* C++ - Rules */
&& !beginswith("class")
&& !beginswith("template")
&& !beginswith("inline")
&& !beginswith("namespace")
&& !beginswith("using")
&& !CppFunDef()
)
)
{
//Funpossible = (line[strlen(line)-1] == ')');
Funpossible = True;
return True;
}
if (beginswith("#include") && !IncludeSeen)
{ IncludeSeen = True; return True; }
if (beginswith("/*I-") || beginswith("/*I="))
{ line[2] = ' '; return True; }
return False;
}
static string replaceDocBlock(string block)
{ MAP(symbol,symbol) m = MAP_newPrimMap();
string res = (string)NULL;
MAP_dfndom(m,stringToSymbol("<"),stringToSymbol("<"));
MAP_dfndom(m,stringToSymbol(">"),stringToSymbol(">"));
MAP_dfndom(m,stringToSymbol("/*NOCONVERSION*/"),stringToSymbol(""));
res = Line_replace(block,m);
MAP_freeMap(m);
return res;
}
void writeDocFun
(
FILE* fp_doc, long idx, string funtyp, string funhdr, string funcom
)
/* writes a function declaration to the current document file */
/*
idx = -1 ==> multi line function definition in 'funhdr' or
end of single line function definitions
idx >= 0 ==> single line function definition [idx] in
'funtyp', 'funhdr', 'funcom'
*/
{ string dfuntyp, dfunhdr, dfuncom, t, t1, t2, t3;
if( idx == 0 || ( idx == -1 && funhdr != (string)NULL ) )
{
//if( idx == 0 ) fprintf(fp_doc,"
\n");
fprintf(fp_doc,"
");
if( funtyp != (string)NULL )
{
dfuntyp = replaceDocBlock(funtyp);
fprintf(fp_doc,"%s ",dfuntyp); FreeMem(dfuntyp); } else fprintf(fp_doc,"\n",t1); } FreeMem(t1); if( t2 != (string)NULL ) FreeMem(t2); fprintf(fp_doc,""); t1 = Line_withoutCCom(dfunhdr); t = Line_clip(t1); if( t1 != dfunhdr ) FreeMem(t1); t1 = strstr(t,"#define "); if( t1 != (string)NULL ) *t1 = '\0'; t2 = Line_getCFunNam(t); if( t1 != (string)NULL ) *t1 = '#'; t1 = t; if( t2 != (string)NULL ) { t3 = strstr(t1,t2); while( t < t3 ) { fprintf(fp_doc,"%c",*t); t += 1; } fprintf(fp_doc,"%s",t2); fprintf(fp_doc,"%s\n",t3+strlen(t2)); } else { fprintf(fp_doc,"%s | ");
if( funcom != (string)NULL )
{
dfuncom = replaceDocBlock(funcom);
fprintf ( fp_doc,"%s\n",dfuncom);
FreeMem(dfuncom);
}
else
{
t1 = Line_withCComText(dfunhdr);
if( t1 != (string)NULL )
{ Sink snk; PIT itr;
snk = Sink_open();
itr = PIT_make(t1); PIT_sep(itr,"\n");
while( ( t = PIT_read(itr) ) != NULL )
{
if( *t == '*' )
fprintf(fp_doc,"%s \n",t+1); else Sink_printf(snk,"%s \n",t); } t2 = Sink_close(snk); fprintf(fp_doc,"%s",t2); PIT_drop(itr); FreeMem(t1); FreeMem(t2); } else fprintf(fp_doc," "); } FreeMem(dfunhdr); } if( idx == -1 ) { fprintf(fp_doc,"\n"); fprintf(fp_doc," |
"); while( ( t1 += 1 ) < t2 ) { fprintf(fp_doc,"%c",*t1); } fprintf(fp_doc,"\n"); fprintf(fp_doc," | "); t1 = Line_withCComText(t); fprintf(fp_doc,"%s\n",t1==(string)NULL?"abstract type":t1); if( t1 != (string)NULL ) FreeMem(t1); fprintf(fp_doc,"\n"); } } PIT_drop(itr); fprintf(fp_doc," |
%s\n",dblock); FreeMem(dblock); } } } #define MaxFuncs 100 static struct { string typ; string fun; string com; bool ext; int ltyp; int lfun; int lcom; } Func[MaxFuncs]; static int topFunc = 0; static int ltyp = 0; static int lfun = 0; static int lcom = 0; void flushFuncs(void) { int i, xltyp, xlfun, xlcom; if (topFunc == 0) return; for (i = 0; i < topFunc; i++) { xltyp = (Func[i].ltyp==-1)?ltyp:Func[i].ltyp; xlfun = (Func[i].lfun==-1)?lfun:Func[i].lfun; xlcom = (Func[i].lcom==-1)?lcom:Func[i].lcom; xlcom = MAX(xlcom,MIN(LineLength-CommentMargin+1,LineLength-xltyp-1-xlfun-2)-6); if( Func[i].ext == False ) fprintf ( SysOut, "%s%*s %s;%*s/* %s%*s */\n", Func[i].typ, xltyp-strlen(Func[i].typ),"", Func[i].fun, xlfun-strlen(Func[i].fun)+ LineLength-xltyp-1-xlfun-1-xlcom-6,"", Func[i].com, xlcom-strlen(Func[i].com),"" ); else fprintf ( SysOut,"%s%s;\n\n", ( i>0&&Func[i-1].ext==False ) ? "\n" : "", Func[i].fun ); if( SysDoc != (FILE*)NULL ) { writeDocFun(SysDoc,i,Func[i].typ,Func[i].fun,Func[i].com); } if( Func[i].typ != (string)NULL ) FreeMem(Func[i].typ); FreeMem(Func[i].fun); if( Func[i].com != (string)NULL ) FreeMem(Func[i].com); } fprintf(SysOut,"\n"); if( SysDoc != (FILE*)NULL ) { writeDocFun(SysDoc,-1,(string)NULL,(string)NULL,(string)NULL); } topFunc = 0; ltyp = 0; lfun = 0; lcom = 0; } void genFunExport(string CDecl) { string nam, t; if( strstr(CDecl,"_NO_DLL_EXPORT_") == CDecl ) return; t = strstr(CDecl,"#define"); if( t != (string)NULL ) *t = '\0'; nam = Line_getCFunNam(CDecl); if( t != (string)NULL ) *t = '#'; if( nam != (string)NULL ) { fprintf(SysExp,"/EXPORT:%s\n",nam); FreeMem(nam); } } void pushFuncLine(string h, string c) { int i, xltyp, xlfun, xlcom; string typ, fun; if(topFunc >= MaxFuncs) flushFuncs(); if( GenExp ) genFunExport(h); for (i = 0; h[i] != 0 && h[i] != ' ' && h[i] != '('; i++); if (h[i] != 0 && h[i] != '(') { h[i] = 0; typ = StrCopy(h); i+=1; } else { i = 0; typ = StrCopy(""); } while(h[i]==' ') i+=1; fun = StrCopy(h+i); FreeMem(h); xltyp = strlen(typ); xlfun = strlen(fun); xlcom = strlen(c); if (MAX(xltyp,ltyp)+1 + MAX(xlfun,lfun)+2 + MAX(xlcom,lcom)+6 > LineLength) { //flushFuncs(); for( i=topFunc-1; i >= 0; --i ) { if( Func[i].ltyp == -1 ) { Func[i].ltyp = ltyp; Func[i].lfun = lfun; Func[i].lcom = lcom; } } ltyp = 0; lfun = 0; lcom = 0; } ltyp = MAX(xltyp,ltyp); lfun = MAX(xlfun,lfun); lcom = MAX(xlcom,lcom); Func[topFunc].ltyp = -1; Func[topFunc].lfun = -1; Func[topFunc].lcom = -1; Func[topFunc].typ = typ; Func[topFunc].fun = fun; Func[topFunc].com = c; Func[topFunc].ext = False; topFunc += 1; } void pushExtFuncLine(string fun) { if(topFunc >= MaxFuncs) flushFuncs(); Func[topFunc].ltyp = -1; Func[topFunc].lfun = -1; Func[topFunc].lcom = -1; Func[topFunc].typ = (string)NULL; Func[topFunc].fun = StrCopy(fun); Func[topFunc].com = (string)NULL; Func[topFunc].ext = True; topFunc += 1; } void copyBlock(bool skipFirst, bool DocBlock, bool forcedDocBlock) { Sink snk = (Sink)NULL, ext = (Sink)NULL; string temp = (string)NULL, s = (string)NULL, t; bool expflg = ( !skipFirst && beginswith("_DLL_EXPORT_") ), extflg = False; if (Funpossible && !skipFirst && (line[strlen(line)-1] == ')')) /* a simple function definition? */ { int lft, rgh; if( strlen(symbolToString(ApiSym)) > 0 && expflg ) { s = line + strlen("_DLL_EXPORT_"); temp = Str_printf("_DLL_API_%s %s",symbolToString(ApiSym),s); } else temp = Str_printf("%s",line); if( CTypConv ) { t = convBlock(temp); FreeMem(temp); temp = t; } if( getline() && CTypConv ) { t = convBlock(line); FreeMem(line); scan_line = line = t; } if ( strstr(temp,"//") != (string)NULL || !( line[0] == '{' || (beginswith("/*") && strcmp(line+strlen(line)-2,"*/") == 0) ) || ( line[0] != '{' && strlen(temp) + strlen(line) + 2 > LineLength ) ) { goto Ordinary; } if(line[0] == '{') pushFuncLine(temp,StrCopy("")); else { for (lft = 2; line[lft] == ' '; lft+=1); for (rgh = strlen(line)-3; line[rgh] == ' '; rgh-=1); if (rgh < lft) rgh = lft-1; line[rgh+1] = 0; pushFuncLine(temp,StrCopy(line+lft)); } while( line[0] != 0 && line[0] != '{') getline(); return; Ordinary: if( GenExp && line[0] != 0 ) { if( line[0] == '{' ) genFunExport(temp); else { ext = Sink_open(); Sink_printf(ext,"%s\n",temp); } } if (line[0] == 0 || line[0] == '{') { t = Str_printf("%s\n",temp); if( line[0] == '{' ) { pushExtFuncLine(t); } else { flushFuncs(); fprintf(SysOut,"%s",t); if( DocBlock ) writeDocBlock(SysDoc,t,forcedDocBlock); } FreeMem(temp); FreeMem(t); return; } } /* multiline function headers, macro definitions, ... */ snk = Sink_open(); if( temp != (string)NULL ) { Sink_printf(snk,"%s\n",temp); FreeMem(temp); } if (!skipFirst) Sink_printf(snk,"%s\n",line); if( GenExp && Funpossible && !skipFirst && !beginswith("/*") && !beginswith("//") && !beginswith("#") ) { extflg = True; if( ext == (Sink)NULL ) ext = Sink_open(); Sink_printf(ext,"%s\n",line); } while(getline() && line[0] != 0 && line[0] != '{' ) { if( extflg &= ( !beginswith("/*") && !beginswith("//") && !beginswith("#") )) Sink_printf(ext,"%s\n",line); if (beginswith("ExternalType")) { strncpy(line,"Abstract",8); } else if (beginswith("ExternalDecl")) { strncpy(line,"AbstractType",12); } Sink_printf(snk,"%s\n",line); } temp = Sink_close(snk); if( GenExp && Funpossible && !skipFirst ) { t = Sink_close(ext); if( line[0] == '{' ) genFunExport(t); FreeMem(t); } if( CTypConv ) { t = convBlock(temp); FreeMem(temp); temp = t; } if( strlen(symbolToString(ApiSym)) > 0 && expflg && s == (string)NULL ) { t = Str_printf ( "_DLL_API_%s %s%s", symbolToString(ApiSym),temp + strlen("_DLL_EXPORT_"), ( line[0] == '{' ) ? "" : "\n" ); } else t = Str_printf("%s%s",temp,( line[0] == '{' ) ? "" : "\n"); if( line[0] == '{' ) { if( Funpossible && !skipFirst ) pushExtFuncLine(t); else { flushFuncs(); fprintf(SysOut,"%s;\n\n",t); if( DocBlock ) writeDocBlock(SysDoc,t,forcedDocBlock); } } else { flushFuncs(); fprintf(SysOut,"%s",t); if( DocBlock ) writeDocBlock(SysDoc,t,forcedDocBlock); } FreeMem(temp); FreeMem(t); } void skipDoc(void) { while(getline() && strcmp(line,"#endif") != 0) /* skip */; } void copyDoc ( string szStartTagOri, string szStartTagNew, string szEndTag ) { string dline, t1, t2; bool pretag = ( strstr(szStartTagOri,"!!") != (string)NULL ); if( SysDoc != (FILE*)NULL ) { fprintf(SysDoc,"
"); } if( !strcmp(szStartTagOri,szStartTagNew) ) { fprintf(SysOut,"%s\n",line); } else { fprintf(SysOut,"%s",szStartTagNew); fprintf(SysOut,"%s\n",line+strlen(szStartTagOri)); } t2 = strstr(line,szEndTag); if( SysDoc != (FILE*)NULL ) { dline = pretag?replaceDocBlock(line):StrCopy(line); t2 = strstr(dline,szEndTag); if( t2 != (string)NULL) { t1 = dline+strlen(szStartTagOri); while( t1 < t2 ) { fprintf(SysDoc,"%c",*t1); t1 += 1; } fprintf(SysDoc,"\n"); } else fprintf(SysDoc,"%s\n",dline+strlen(szStartTagOri)); FreeMem(dline); } if( t2 == (string)NULL) { while(getline() ) { fprintf(SysOut,"%s\n",line); if( (t2=strstr(line,szEndTag)) != (string)NULL) { if( SysDoc != (FILE*)NULL ) { dline = pretag?replaceDocBlock(line):StrCopy(line); t1 = dline; t2 = strstr(dline,szEndTag); while( t1 < t2 ) { fprintf(SysDoc,"%c",*t1); t1 += 1; } fprintf(SysDoc,"\n"); FreeMem(dline); } break; } else if( SysDoc != (FILE*)NULL ) { dline = pretag?replaceDocBlock(line):StrCopy(line); fprintf(SysDoc,"%s\n",dline); FreeMem(dline); } } } fprintf(SysOut,"\n"); if( SysDoc != (FILE*)NULL ) { if( pretag ) fprintf(SysDoc,""); fprintf(SysDoc,"\n"); } } void copyToI(string szEndTag, bool forcedDocBlock) { Sink pSnk = (Sink)NULL; string dline, szIBlock, szCnvIBlock; if( CTypConv ) pSnk = Sink_open(); if( forcedDocBlock ) fprintf(SysDoc,"
\n"); while(getline() && strcmp(line,szEndTag) != 0) { if( CTypConv ) Sink_printf(pSnk,"%s\n",line); else { fprintf(SysOut,"%s\n",line); if( forcedDocBlock ) { dline = replaceDocBlock(line); fprintf(SysDoc,"%s\n",dline); FreeMem(dline); } } } if( CTypConv ) { szIBlock = Sink_close(pSnk); szCnvIBlock = convBlock(szIBlock); fprintf(SysOut,"%s\n",szCnvIBlock); if( forcedDocBlock ) { dline = replaceDocBlock(szCnvIBlock); fprintf(SysDoc,"%s\n",dline); FreeMem(dline); } FreeMem(szIBlock); FreeMem(szCnvIBlock); } else fprintf(SysOut,"\n"); if( forcedDocBlock ) fprintf(SysDoc,"\n"); } void printCLinkageOn(void) { fprintf(SysOut,"\n"); fprintf(SysOut,"#ifdef __cplusplus\n"); fprintf(SysOut,"extern \"C\" {\n"); fprintf(SysOut,"#endif\n"); fprintf(SysOut,"\n\n"); } void convertText(void) { bool CLinkageFlag = False; Patched = False; lineno = 0; IncludeSeen = False; Funpossible = False; Shift = False; OnOff = True; /* INTERFACE_ON ! */ mainSeen = False; if (getline()) copyBlock(False,False,False); if (!Patched) fprintf(STDERR,"Warning: %s missing header comment.\n",cfid); Patched = True; fprintf(SysOut,"/* File generated by 'ctoh'. Don't change manually. */\n"); fprintf(SysOut,"\n"); fprintf(SysOut,"#ifndef %s_INCL\n",symbolToString(ccls)); fprintf(SysOut,"#define %s_INCL\n",symbolToString(ccls)); fprintf(SysOut,"\n\n"); if( strlen(symbolToString(ApiSym)) > 0 ) { fprintf(SysOut,"#ifndef _DLL_API_%s\n",symbolToString(ApiSym)); fprintf(SysOut,"#ifdef _DLL_DFN_%s\n",symbolToString(ApiSym)); fprintf ( SysOut,"#define _DLL_API_%s _DLL_EXPORT_DECL_\n",symbolToString(ApiSym) ); fprintf(SysOut,"#else\n"); fprintf(SysOut,"#ifndef _NO_DLL_%s\n",symbolToString(ApiSym)); fprintf(SysOut,"#define _DLL_API_%s _DLL_IMPORT_\n",symbolToString(ApiSym)); fprintf(SysOut,"#endif\n"); fprintf(SysOut,"#endif\n"); fprintf(SysOut,"#endif\n"); fprintf(SysOut,"\n"); } while (getline()) { if( CLinkageFlag == False && IncludeSeen == True ) { printCLinkageOn(); CLinkageFlag = True; } if(BlockStart()) { if( CLinkageFlag == False && Funpossible == True ) { printCLinkageOn(); CLinkageFlag = True; } copyBlock(False,(SysDoc!=(FILE*)NULL),False); } else if(beginswith("/*!!")) { flushFuncs(); copyDoc("/*!!","/* ","*/"); } else if(beginswith("/*!")) { flushFuncs(); copyDoc("/*!","/* ","*/"); } else if(strcmp(line,"/*INTERFACE*/") == 0) copyBlock(True,(SysDoc!=(FILE*)NULL),False); else if(strcmp(line,"/*DOC_INTERFACE*/") == 0) { copyBlock(True,(SysDoc!=(FILE*)NULL),True); } else if(strcmp(line,"/*INTERFACE_OFF*/") == 0) { OnOff = False; } else if(strcmp(line,"/*INTERFACE_ON*/") == 0) { OnOff = True; } else if(strcmp(line,"/*INTERFACE_GROUP*/") == 0) { flushFuncs(); } else if(strcmp(line,"#ifdef INTERFACE") == 0) { flushFuncs(); copyToI("#endif",False); } else if(strcmp(line,"#ifdef DOC_INTERFACE") == 0) { flushFuncs(); copyToI("#endif",(SysDoc!=(FILE*)NULL)); } else if(strcmp(line,"/*INTERFACE_COPY_ON*/") == 0) { flushFuncs(); copyToI("/*INTERFACE_COPY_OFF*/",False); } else if(strcmp(line,"/*DOC_INTERFACE_COPY_ON*/") == 0) { flushFuncs(); copyToI("/*DOC_INTERFACE_COPY_OFF*/",(SysDoc!=(FILE*)NULL)); } else if(strcmp(line,"#ifdef DOCUMENT") == 0) { skipDoc(); } else if( CLinkageFlag == False && strcmp(line,"/*INTERFACE_LINKAGE_ON*/") == 0 ) { flushFuncs(); printCLinkageOn(); CLinkageFlag = True; } } flushFuncs(); fprintf(SysOut,"\n"); if( CLinkageFlag == True ) { fprintf(SysOut,"#ifdef __cplusplus\n"); fprintf(SysOut,"}\n"); fprintf(SysOut,"#endif\n\n"); } fprintf(SysOut,"#endif\n"); } #define tnam "____ctoh.___" ConcreteType( ModuleInfo ) { symbol Path; /* only in 'newmap' ( C-Path; Base is dom ) */ symbol hext; symbol scls; long Ctim; long Htim; short prog; /* mainflag */ }; ModuleInfo mi_Copy(ModuleInfo mi) { ModuleInfo res = New(ModuleInfo); res->Path = mi->Path; res->hext = mi->hext; res->scls = mi->scls; res->Ctim = mi->Ctim; res->Htim = mi->Htim; res->prog = mi->prog; return res; } void mi_Free(ModuleInfo mi) { FreeMem(mi); } MAPTY glotyp; MAPTY clstyp; MAP(symbol, ModuleInfo) newmap; MAP(symbol, ModuleInfo) oldmap; MAP(symbol, HS_Set) clsmap; MAP(symbol, long ) oldtim; MAP(symbol, long ) newtim; int errcnt; bool validModule(symbol Cpath, symbol BaseSy, long Ctime, long Htime) { bool res = False; if (MAP_defined(oldmap,BaseSy)) { ModuleInfo mi = MAP_apply(ModuleInfo,oldmap,BaseSy); res = (mi->Path == Cpath && mi->Ctim == Ctime && mi->Htim == Htime); if (res) { ccls = mi->scls; mainSeen = mi->prog; } mi_Free(mi); } return res; } void addModule(symbol ModSy, ModuleInfo mi) { if (MAP_defined(newmap,ModSy)) { ModuleInfo mo = MAP_apply(ModuleInfo,newmap,ModSy); fprintf ( STDERR,"Module [%s.c(xx)] both in dictionary '%s' and in '%s'.\n", symbolToString(ModSy), symbolToString(mi->Path), symbolToString(mo->Path) ); mi_Free(mo); errcnt += 1; MAP_upddom(newmap,ModSy,mi); } else MAP_dfndom(newmap,ModSy,mi); } void PutMi(void) /* put module info to [$PRJ/ctoh.cth] */ { symbol fsy; MAPIT itr; putBgn("PRJ","ctoh.cth",""); putHeader("[ctoh.cth] Binary image for 'ctoh'\n","cth",3,0); putWord((short)MAP_count(newmap)); MAP_forItr(fsy,itr,newmap) { ModuleInfo mi = MAP_apply(ModuleInfo,newmap,fsy); putSymbol(fsy); PUT_REFERENCE(mi->Path,putSymbol); PUT_REFERENCE(mi->hext,putSymbol); PUT_REFERENCE(mi->scls,putSymbol); putLong(mi->Ctim); putLong(mi->Htim); putWord(mi->prog); mi_Free(mi); } putWord((short)MAP_count(newtim)); MAP_forItr(fsy,itr,newtim) { long tim = MAP_apply(long,newtim,fsy); putSymbol(fsy); putLong(tim); } putEnd(); } void GetMi(void) /* get module info from [$PRJ/ctoh.cth] */ { short i,size; { string tmp = MkPath("PRJ","ctoh.cth","",'p'); if (!IsPath(tmp)) { FreeMem(tmp); return; } else FreeMem(tmp); } getBgn("PRJ","ctoh.cth",""); getHeader("cth",3,0); getWord(&size); for (i = 0; i < size; i++) { symbol fsy; ConcreteImp(ModuleInfo) mi; getSymbol(&fsy); GET_REFERENCE(&mi.Path,getSymbol); GET_REFERENCE(&mi.hext,getSymbol); GET_REFERENCE(&mi.scls,getSymbol); getLong(&mi.Ctim); getLong(&mi.Htim); getWord(&mi.prog); MAP_dfndom(oldmap,fsy,&mi); } getWord(&size); for (i = 0; i < size; i++) { symbol fsy; long tim; getSymbol(&fsy); getLong(&tim); MAP_dfndom(oldtim,fsy,tim); } getEnd(); } bool FileEqual(string fna, string fnb) /* whether files 'fna' and 'fnb' are binary equal */ { FILE* fa = OpnFile(fna,"rb"); FILE* fb = OpnFile(fnb,"rb"); int ca, cb; for ( ca = fgetc(fa), cb = fgetc(fb); ca != EOF && cb != EOF && ca == cb; ca = fgetc(fa), cb = fgetc(fb) ); fclose(fa); fclose(fb); return ca == cb; } /* ----------------- Handling Multiple Implementations --------------------- */ string normalize_header_line(string line, string cfid, bool *hl) /* returns a line, normalizing header line if '*hl == True' */ { if (!*hl || line == NULL) return line; { int i,j,k,m, len = strlen(line), blen = strlen(cfid); string ext; for (i = 0; i < len; i++) { if (strncmp(cfid,line+i,blen) == 0) { if (line[i+blen] != '(') return line; for( j=blen-1; j > 0 && line[i+j] != '.' ; --j ); ext = SubStrCopy(line+i+j,blen-j); for( j=0; line[i+blen+1+j] != 0 && line[i+blen+1+j] != ')'; ++j ) line[i+j] = line[i+blen+1+j]; for( k=0; k < strlen(ext); k++) line[i+j+k] = ext[k]; line[i+j+k] = ']'; for(m = 1; m < j+2; m++) line[i+j+k+m] = ' '; FreeMem(ext); *hl = False; return line; } } } return line; } string Line_get_normal(FILE* f, string cfid, bool *hl) { return normalize_header_line(Line_get(f), cfid, hl); } bool FileNormalEqual(string fna, string cna, string fnb, string cnb) /* whether files 'fna' and 'fnb' are binary equal */ { FILE* fa = OpnFile(fna,"rt"); FILE* fb = OpnFile(fnb,"rt"); string sa, sb; bool ha = True, hb = True; long lna=1,lnb=1; bool res; for ( sa = Line_get_normal(fa,cna,&ha), sb = Line_get_normal(fb,cnb,&hb); sa != NULL && sb != NULL && strcmp(sa,sb) == 0; sa = Line_get_normal(fa,cna,&ha), sb = Line_get_normal(fb,cnb,&hb) ) { FreeMem(sa); FreeMem(sb); lna+=1; lnb+=1; }; fclose(fa); fclose(fb); res = ((sa == sb) || strcmp(sa,sb) == 0); if (sa != NULL) FreeMem(sa); if (sb != NULL) FreeMem(sb); if (!res) { fprintf(STDERR,"files %s(%ld), %s(%ld) differ.\n",fna,lna,fnb,lnb); errcnt += 1; } return res; } void FileNormalize(string fna, string cna, string fnb) /* normalizes header of file 'fna' */ { FILE* fa; FILE* fb; string sa; bool ha = True; if (strcmp(fna,fnb) == 0) return; fa = OpnFile(fna,"rt"); fb = OpnFile(tnam,"wt"); for ( sa = Line_get_normal(fa,cna,&ha); sa != NULL; sa = Line_get_normal(fa,cna,&ha) ) { fprintf(fb,"%s\n",sa); FreeMem(sa); }; fclose(fa); fclose(fb); if (IsPath(fnb) && FileEqual(fnb,tnam)) remove(tnam); else { remove(fnb); rename(tnam,fnb); fprintf(STDOUT,"-> %s\n",fnb); } } void editClass(symbol sclass, symbol BaseSy) /* adds/updates current class 'sclass' */ { HS_Set cset; if( ! MAP_defined(clsmap,sclass) ) { cset = HS_CREATE_ADTSET(symbol); MAP_dfndom(clsmap,sclass,cset); MAP_dfndom ( newtim, sclass, MAP_defined(oldtim,sclass)?MAP_apply(long,oldtim,sclass):0L ); } else cset = MAP_apply(HS_Set,clsmap,sclass); HS_SET_ELM(BaseSy,cset); } void multipleH(bool Force) /* handles multiple Implementations */ { MAPIT itr; symbol dom; HMP_Rng rng; MAP_forItrAsg(dom,rng,itr,clsmap) { HS_Itr hit; symbol elm; long youngest = 0L; bool ok = True; symbol hext = (symbol)NULL; symbol firstH = (symbol)NULL; string s1; HS_FORALL(elm,hit,rng) { ModuleInfo mi = MAP_apply(ModuleInfo,newmap,elm); youngest = MAX(youngest,mi->Htim); if( hext == (symbol)NULL ) hext = mi->hext; else { if( hext != mi->hext ) { fprintf ( STDERR,"different Header Types for Class '%s'.\n", symbolToString(dom) ); errcnt += 1; } } if( firstH == (symbol)NULL ) firstH = (symbol)elm; FreeMem(mi); } s1 = MkPath("HPATH",symbolToString(dom),symbolToString(hext),'e'); if ( Force || pgmtim <= youngest || !IsPath(s1) || PathMTime(s1) != MAP_apply(long,newtim,dom) ) { string s3=Str_printf("%s%s",symbolToString(firstH),symbolToString(hext)); string s4=Str_printf("%s%s",symbolToString(dom),symbolToString(hext)); string s2 = MkPath ( "HPATH",symbolToString(firstH),symbolToString(hext),'e' ); FileNormalize(s2,s3,s1); HS_FORALL(elm,hit,rng) { string s5 = MkPath ( "HPATH",symbolToString(elm),symbolToString(hext),'e' ); string s6 = Str_printf("%s%s",symbolToString(elm),symbolToString(hext)); ok &= FileNormalEqual(s1,s4,s5,s6); FreeMem(s5); FreeMem(s6); } FreeMem(s2); FreeMem(s3); FreeMem(s4); } MAP_upddom(newtim,dom,ok?PathMTime(s1):-1L); FreeMem(s1); } } FILE* BeginDocFile(string Dpath, string BaseName, string Ext) { FILE* fp_doc = (FILE*)NULL; if( *Dpath != '\0' ) { string dnam, title, tmp; title = Com_GetEx(cnam); tmp = strstr(title,"#"); if( tmp == (string)NULL ) { dnam = MkPath(Dpath,BaseName,".htm",'d'); fp_doc = OpnFile(dnam,"w"); if( fp_doc != (FILE*)NULL ) { fprintf(fp_doc,"%s\n",HTML_DOCTYPE); fprintf ( fp_doc, "\n\n
"); t = dline + 3 + pretag; while ( t < t1 ) { fprintf(SysDoc,"%c",*t); ++t; } } else { snk = Sink_open(); if( pretag ) Sink_printf(snk,"
%s\n",dline+4); else Sink_printf(snk,"%s\n",dline+3); comblk = True; } FreeMem(dline); } else if( beginswith("#ifndef") && strstr(line,"_INCL") != (string)NULL ) /* skip */; else if( beginswith("#define") && strstr(line,"_INCL") != (string)NULL ) /* skip */; else if( strstr(line,"/*_INCL*/") != (string)NULL || strstr(line,"//_INCL") != (string)NULL ) /* skip */; else if( beginswith("/* -") || beginswith("/* =") || beginswith("#include") || beginswith("AbstractType") ) { dline = replaceDocBlock(line); writeDocBlock(SysDoc, dline, True); FreeMem(dline); } else { dline = replaceDocBlock(line); fprintf(SysDoc,"
%s",dline); FreeMem(dline); } } ++lineno; FreeMem(line); } EndDocFile(SysDoc); fclose(SysIn); FreeMem(cnam); } void ctoh ( symbol CpathSy, string Hpath, string BaseName, string Ext, bool Force, string Dpath ) { string Cpath = symbolToString(CpathSy); string HExt = StrCopy(Ext); symbol BaseSy = stringToSymbol(BaseName); long Ctime, Htime; ConcreteImp(ModuleInfo) mi; ccls = BaseSy; cnam = MkPath(Cpath,BaseName,Ext,'d'); HExt[1] = 'h'; hnam = MkPath(Hpath,BaseName,HExt,'d'); cfid = Str_printf("%s%s",BaseName,Ext); lnam = StrToUpper(StrCopy(BaseName)); Ctime = PathMTime(cnam); Htime = IsPath(hnam) ? PathMTime(hnam) : 0L; if (validModule(CpathSy,BaseSy,Ctime,Htime) && !Force) goto Done; SysDoc = BeginDocFile(Dpath,BaseName,Ext); SysIn = OpnFile(cnam,"r"); SysOut = OpnFile(tnam,"w"); if( GenExp ) { enam = MkPath(Hpath,BaseName,".exp",'d'); SysExp = OpnFile(enam,"w"); } convertText(); if( GenExp ) { fclose(SysExp); FreeMem(enam); } fclose(SysOut); fclose(SysIn); EndDocFile(SysDoc); if (mainSeen) { if( ccls != BaseSy ) { fprintf(STDERR,"Program [%s.c(xx)] with multiple Headers.\n",BaseName); errcnt += 1; } remove(tnam); } else { if (!Force && Htime != 0 && FileEqual(hnam,tnam)) remove(tnam); else { remove(hnam); rename(tnam,hnam); Htime = PathMTime(hnam); fprintf(STDOUT,"-> %s%s\n",BaseName,HExt); } } Done: mi.Path = CpathSy; mi.hext = stringToSymbol(HExt); mi.scls = ccls; mi.Ctim = Ctime; mi.Htim = Htime; mi.prog = mainSeen; addModule(BaseSy,&mi); if( !mainSeen ) editClass(ccls,BaseSy); FreeMem(cnam); FreeMem(hnam); FreeMem(cfid); FreeMem(lnam); FreeMem(HExt); } void RemoveOldH(void) /* removes all H-files in [$HPATH] no occuring in [ctoh.cth] */ { DII dii; PIT pit; string srcpath; pit = PIT_make(CTX_EVAL(string,"HPATH")); while( ( srcpath = PIT_read(pit) ) != NULL ) { DII_FORALL(dii,srcpath,"*.h") { string base = DII_get_base(dii); if( !MAP_defined(newmap,stringToSymbol(base)) && !MAP_defined(clsmap,stringToSymbol(base)) ) { string tmp = Str_printf("%s/%s.h",srcpath,base); printf("-- %s.h\n",base); remove(tmp); FreeMem(tmp); } FreeMem(base); } DII_FORALL(dii,srcpath,"*.hxx") { string base = DII_get_base(dii); if( !MAP_defined(newmap,stringToSymbol(base)) && !MAP_defined(clsmap,stringToSymbol(base)) ) { string tmp = Str_printf("%s/%s.hxx",srcpath,base); printf("-- %s.hxx\n",base); remove(tmp); FreeMem(tmp); } FreeMem(base); } } PIT_drop(pit); } int main(int argc, string argv[]) { DII dii; PIT pit; string srcpath, srclib, tmp; MAPIT itr; HMP_Dom dom; HMP_Rng rng; CTX_init_ctoh(argc,argv); bug0(strcmp(CTX_EVAL(string,"PRJ"),""),"Variable PRJ undefiniert"); initSymbols(); MAP_init(); pgmtim = time(NULL); errcnt = 0; glotyp = MAP_newTyp(primCopy,primFree,primEqual,primHash, mi_Copy,mi_Free); clstyp = MAP_newTyp(primCopy,primFree,primEqual,primHash, primCopy,primFree); newmap = MAP_newMap( glotyp ); oldmap = MAP_newMap( glotyp ); clsmap = MAP_newMap( clstyp ); oldtim = MAP_newMap( clstyp ); newtim = MAP_newMap( clstyp ); GetMi(); if( CTypConv ) Scn_get_ccnv(&pScn); pit = PIT_make(CTX_EVAL(string,"CPATH")); while( ( srcpath = PIT_read(pit) ) != NULL ) { symbol psy; ApiSym = stringToSymbol(GenApi); tmp = strstr(srcpath,"~"); if( tmp != (string)NULL ) { srclib = srcpath; srcpath = tmp + 1; *tmp = '\0'; ApiSym = stringToSymbol(srclib); } psy = stringToSymbol(srcpath); DII_FORALL(dii,srcpath,"*.c") { string base = DII_get_base(dii); ctoh ( psy, CTX_EVAL(string,"HPATH"), base, ".c", CTX_EVAL(bool ,"force"), CTX_EVAL(string,"DPATH") ); FreeMem(base); } DII_FORALL(dii,srcpath,"*.cxx") { string base = DII_get_base(dii); ctoh ( psy, CTX_EVAL(string,"HPATH"), base, ".cxx", CTX_EVAL(bool ,"force"), CTX_EVAL(string,"DPATH") ); FreeMem(base); } DII_FORALL(dii,srcpath,"*.cpp") { string base = DII_get_base(dii); ctoh ( psy, CTX_EVAL(string,"HPATH"), base, ".cpp", CTX_EVAL(bool ,"force"), CTX_EVAL(string,"DPATH") ); FreeMem(base); } if( *(CTX_EVAL(string,"DPATH")) != '\0' ) { DII_FORALL(dii,srcpath,"*.h") { string base = DII_get_base(dii); htod ( psy, base, ".h", CTX_EVAL(string,"DPATH") ); FreeMem(base); } } } PIT_drop(pit); multipleH(CTX_EVAL(bool,"force")); PutMi(); if( CTypConv ) Scn_free(pScn); RemoveOldH(); MAP_freeMap(newmap); MAP_freeMap(oldmap); MAP_forItrAsg(dom,rng,itr,clsmap) HS_DROP_SET(rng); MAP_freeMap(clsmap); MAP_freeMap(oldtim); MAP_freeMap(newtim); MAP_freeTyp(glotyp); MAP_freeTyp(clstyp); MAP_quit(); freeSymbols(); CTX_quit(); if (errcnt > 0) { fprintf(STDERR,"total %d error(s).\n",errcnt); STD_ERREXIT; } BUG_CORE; return(0); }