/*##############################################################################
Copyright (C) 2011 HPCC Systems.
All rights reserved. This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
############################################################################## */
//
// HIDL compiler
#define HIDLVER "1.0"
#include "platform.h"
#include
#include
#include
#include
#include
// TBD should have used yacc/lex - will do so when get time
enum type_kind
{
TK_null,
TK_CHAR,
TK_UNSIGNEDCHAR,
TK_SHORT,
TK_UNSIGNEDSHORT,
TK_INT,
TK_UNSIGNED,
TK_LONG,
TK_UNSIGNEDLONG,
TK_LONGLONG,
TK_UNSIGNEDLONGLONG,
TK_STRUCT,
TK_VOID
};
#define PF_IN 1
#define PF_OUT 2
#define PF_VARSIZE 4
#define PF_PTR 8
#define PF_REF 0x10
#define PF_CONST 0x40
#define PF_SIMPLE 0x80
#define PF_RETURN 0x100
#define PF_STRING 0x200
#define PF_MASK 0x7fff
/*
Allowed Parameter profiles
in T - simple
in T& - ref
in size() T* - sized ptr
inout T& - ref in/out
inout size() T* - size is in only
out T& - ref out only
out size() T* - size is in only
out size() T*& - size out only caller frees
in string const char* - in string
out string char *& - out string (caller frees)
return (implied out):
T - simple return
size() T* - size out only caller frees
*/
const char *type_name[] =
{
"??",
"char",
"unsigned char",
"short",
"unsigned short",
"int",
"unsigned",
"long",
"unsigned long",
"long long",
"unsigned long long",
"",
"void"
};
const char *clarion_type_name[] =
{
"??",
"BYTE",
"BYTE",
"SHORT",
"USHORT",
"LONG",
"ULONG",
"LONG",
"ULONG",
"LONGLONG",
"ULONGLONG",
"",
"BYTE"
};
const int type_size[] =
{
1,
1,
1,
2,
2,
4,
4,
4,
4,
8,
8,
0,
1
};
#define RETURNNAME "_return"
class ParamInfo
{
public:
ParamInfo()
{
name = NULL;
typname=NULL;
size = NULL;
flags = 0;
next = NULL;
kind = TK_null;
sizebytes = NULL;
}
~ParamInfo()
{
free(name);
free(typname);
free(size);
free(sizebytes);
}
char *bytesize(int deref=0)
{
if (!size)
return NULL;
if (sizebytes)
return sizebytes;
char str[1024];
if (type_size[kind]==1)
if (deref) {
strcpy(str,"*");
strcat(str,size);
sizebytes = strdup(str);
return sizebytes;
}
else
return size;
strcpy(str,"sizeof(");
if (kind==TK_STRUCT)
strcat(str,typname);
else
strcat(str,type_name[kind]);
strcat(str,")*(");
if (deref)
strcat(str,"*");
strcat(str,size);
strcat(str,")");
sizebytes = strdup(str);
return sizebytes;
}
int simpleneedsswap()
{
switch(kind) {
case TK_SHORT:
case TK_UNSIGNEDSHORT:
case TK_INT:
case TK_UNSIGNED:
case TK_LONG:
case TK_UNSIGNEDLONG:
case TK_LONGLONG:
case TK_UNSIGNEDLONGLONG:
return 1;
}
return 0;
}
type_kind kind;
char *name;
char *typname;
char *size;
char *sizebytes;
unsigned flags;
ParamInfo *next;
};
#define ForEachParam(pr,pa,flagsset,flagsclear) for (pa=pr->params;pa;pa=pa->next) \
if (((pa->flags&(flagsset))==(flagsset))&((pa->flags&(flagsclear))==0))
#define INDIRECTSIZE(p) ((p->flags&(PF_PTR|PF_REF))==(PF_PTR|PF_REF))
class ProcInfo
{
public:
ProcInfo()
{
name = NULL;
rettype = NULL;
params = NULL;
next = NULL;
async = 0;
virt = 0;
callback = 0;
}
~ProcInfo()
{
free(name);
delete rettype;
while (params) {
ParamInfo *p=params;
params = p->next;
delete p;
}
}
char * name;
ParamInfo * rettype;
ParamInfo * params;
ProcInfo * next;
int async;
int virt;
int callback;
ParamInfo * firstin;
ParamInfo * lastin;
};
class ModuleInfo
{
public:
ModuleInfo(const char *n,size32_t l)
{
name = (char *)malloc(l+1);
memcpy(name,n,l);
name[l] = 0;
version = 0;
procs = NULL;
next = NULL;
}
~ModuleInfo()
{
free(name);
while (procs) {
ProcInfo *p=procs;
procs = p->next;
delete p;
}
}
char *name;
int version;
ProcInfo *procs;
ModuleInfo *next;
};
enum tok_kind {
TOK_null,
TOK_IDENT,
TOK_NUMBER,
TOK_CHARCONST,
TOK_STRCONST,
TOK_LPAREN,
TOK_RPAREN,
TOK_LBRACE,
TOK_RBRACE,
TOK_LBRACKET,
TOK_RBRACKET,
TOK_LANGLE,
TOK_RANGLE,
TOK_STAR,
TOK_AMPERSAND,
TOK_COMMA,
TOK_EQUAL,
TOK_COLON,
TOK_SEMICOLON,
TOK_CONST,
TOK_INT,
TOK_SHORT,
TOK_LONG,
TOK_UNSIGNED,
TOK_FLOAT,
TOK_DOUBLE,
TOK_CHAR,
TOK_VOID,
TOK_MODULE,
TOK_IN,
TOK_INOUT,
TOK_OUT,
TOK_STRING,
TOK_SIZE,
TOK_ASYNC,
TOK_CALLBACK,
TOK_VIRTUAL,
TOK_EOF
};
static const struct tokdef { tok_kind k; const char *n; } symbols[] =
{
{TOK_MODULE,"module"},
{TOK_CONST, "const"},
{TOK_VOID, "void"},
{TOK_CHAR, "char"},
{TOK_INT, "int"},
{TOK_UNSIGNED, "unsigned"},
{TOK_SHORT, "short"},
{TOK_LONG, "long"},
{TOK_FLOAT, "float"},
{TOK_DOUBLE, "double"},
{TOK_IN, "in"},
{TOK_OUT, "out"},
{TOK_INOUT, "inout"},
{TOK_STRING, "string"},
{TOK_SIZE,"size"},
{TOK_ASYNC,"async"},
{TOK_CALLBACK,"callback"},
{TOK_VIRTUAL,"virtual"},
{TOK_EOF, "??????"},
};
class token {
public:
tok_kind kind;
const char *str; //in buffer
size32_t len;
char *copystr() { char *ret=(char *)malloc(len+1); memcpy(ret,str,len); ret[len] = 0; return ret; }
int integer()
{
size32_t l=len;
if (l>15)
l = 15;
char num[16];
memcpy(num,str,l);
num[l] = 0;
return atoi(num);
}
};
class HIDLcompiler
{
protected:
const char *start;
const char *s;
int lineno;
token t;
int outfile;
void error(const char *err)
{
printf("ERROR: line %d: %s\n",lineno,err);
const char *sp=s;
while ((sp!=start)&&((s-sp<10)||(*(sp-1)!='\n')))
sp--;
printf("Near the end of:\n-----\n");
char *ln = (char *)malloc(s-sp+1);
memcpy(ln,sp,s-sp);
ln[s-sp] = 0;
printf("%s\n-----\n",ln);
free(ln);
exit(1);
}
int parse_strconst()
{
t.str = s+1;
do {
s++;
if (*s=='\\')
s++;
if (*s==0) {
error("\" expected");
return 0;
}
} while (*s!='"');
t.kind = TOK_STRCONST;
t.len = s-t.str;
s++;
return 1;
}
int parse_chrconst()
{
t.str = s+1;
do {
s++;
if (*s=='\\')
s++;
if (*s==0)
return 0;
} while (*s!='\'');
t.kind = TOK_CHARCONST;
t.len = s-t.str;
s++;
return 1;
}
int parse_int()
{
t.str = s;
do {
s++;
if (*s=='\\')
s++;
if (*s==0)
return 0;
} while (isalnum(*s));
t.kind = TOK_NUMBER;
t.len = s-t.str;
return 1;
}
int parse_id()
{
t.str = s;
do {
s++;
if (*s=='\\')
s++;
if (*s==0)
return 0;
} while (isalnum(*s)||(*s=='_'));
t.len = s-t.str;
for (int i=0;symbols[i].k!=TOK_EOF;i++) {
if (memcmp(t.str,symbols[i].n,t.len)==0) {
if (symbols[i].n[t.len]==0) {
t.kind = symbols[i].k;
return 1;
}
}
}
t.kind = TOK_IDENT;
return 1;
}
char *parse_paren_str()
{
int pc = 1;
const char *st=s;
while (1) {
if (*s==')')
if (--pc==0)
break;
else if (*s=='(')
pc++;
else if (*s==0) {
error(") expected");
return NULL;
}
s++;
}
char *ret = (char *)malloc(s-st+1);
memcpy(ret,st,s-st);
ret[s-st] = 0;
return ret;
}
int nexttoken()
{
t.kind = TOK_null;
t.str = NULL;
t.len = 0;
while (1) {
switch (*s) {
case 0: return 0;
case ':': t.kind = TOK_COLON; s++; return 1;
case ';': t.kind = TOK_SEMICOLON; s++; return 1;
case ',': t.kind = TOK_COMMA; s++; return 1;
case '=': t.kind = TOK_EQUAL; s++; return 1;
case '*': t.kind = TOK_STAR; s++; return 1;
case '[': t.kind = TOK_LBRACKET; s++; return 1;
case ']': t.kind = TOK_RBRACKET; s++; return 1;
case '{': t.kind = TOK_LBRACE; s++; return 1;
case '}': t.kind = TOK_RBRACE; s++; return 1;
case '(': t.kind = TOK_LPAREN; s++; return 1;
case ')': t.kind = TOK_RPAREN; s++; return 1;
case '<': t.kind = TOK_LANGLE; s++; return 1;
case '>': t.kind = TOK_RANGLE; s++; return 1;
case '&': t.kind = TOK_AMPERSAND; s++; return 1;
case '"': return parse_strconst();
case '\'': return parse_chrconst();
case ' ':
case '\t':
case '\r':
break;
case '\n':
lineno++;
break;
case '/': if (s[1]=='/') {
do {
s++;
} while ((s[1]!=0)&&(s[1]!='\n'));
}
else if (s[1]=='*') {
do {
s++;
if (*s=='\n')
lineno++;
if (*s==0) {
error("*/ expected");
return 0;
}
} while ((s[0]!='*')||(s[1]!='/'));
}
break;
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': return parse_int();
default:
if (isalpha(*s)||(*s=='_'))
return parse_id();
error("unexpected character");
}
s++;
}
return 0;
}
tok_kind gettoken()
{
if (nexttoken())
return t.kind;
error("Premature EOF");
return TOK_null;
}
int expects(tok_kind k)
{
nexttoken();
return (t.kind==k);
}
int skip_to_module()
{
int i=0;
for (;symbols[i].k!=TOK_MODULE;i++);
const char *m=symbols[i].n;
size32_t l = strlen(m);
while (*s) {
while (isspace(*s))
s++;
if (memcmp(s,m,l)==0) {
if (isspace(s[l])) {
return 1;
}
}
while (*s!='\n') {
if (!*s) {
return 0;
}
s++;
}
lineno++;
s++;
}
return 0;
}
int check_param(ProcInfo *pi,ParamInfo *p)
{
if ((pi->async)&&(p->flags&(PF_OUT|PF_RETURN))) {
error("out parameters not allowed on async procedure");
return 0;
}
if ((p->flags&(PF_CONST&PF_OUT))==(PF_CONST|PF_OUT)) {
error("const not allowed on out parameter");
return 0;
}
switch (p->flags&(PF_IN|PF_OUT|PF_STRING|PF_VARSIZE|PF_PTR|PF_REF|PF_RETURN)) {
case PF_IN: // int T
case (PF_IN|PF_REF): // in T&
case (PF_IN|PF_OUT|PF_REF): // inout T&
case (PF_OUT|PF_REF): // out T&
return 1;
case (PF_IN|PF_PTR|PF_VARSIZE): // in size() T*
case (PF_OUT|PF_PTR|PF_VARSIZE): // out size() T*
case (PF_IN|PF_OUT|PF_PTR|PF_VARSIZE): // inout size() T*
// should check size is in here
return 1;
case (PF_OUT|PF_PTR|PF_REF|PF_VARSIZE): // inout size() T*&
// should check size is out here
return 1;
case (PF_IN|PF_PTR|PF_STRING): // in string const char *
case (PF_OUT|PF_PTR|PF_REF|PF_STRING): // out string char *&
// should check char or unsigned char
return 1;
case (PF_OUT|PF_RETURN): // return simple
return 1;
case (PF_OUT|PF_RETURN|PF_STRING|PF_PTR): // return char *
return 1;
case (PF_OUT|PF_PTR|PF_VARSIZE|PF_RETURN): // return size() T*
// should check size is out here
return 1;
}
printf("Parameter flags %x\n",p->flags);
if (p->flags&PF_RETURN)
error("Invalid return type");
else
error("Invalid parameter combination");
return 0; // TBD
}
ParamInfo *parse_param(ProcInfo *pi,int rettype)
{
ParamInfo *p = new ParamInfo;
while (1) {
switch (t.kind) {
case TOK_IN:
p->flags |= PF_IN;
break;
case TOK_OUT:
p->flags |= PF_OUT;
break;
case TOK_INOUT:
p->flags |= (PF_IN|PF_OUT);
break;
case TOK_STRING:
p->flags |= PF_STRING;
break;
case TOK_SIZE:
if (!expects(TOK_LPAREN)) {
error("( expected");
Error:
delete p;
return NULL;
}
p->size = parse_paren_str();
p->flags |= PF_VARSIZE;
if (!expects(TOK_RPAREN)) {
error(") expected");
goto Error;
}
break;
case TOK_IDENT:
// assume it is a name until the second ID
if (rettype) {
if (p->kind==TK_null) {
p->kind = TK_STRUCT;
p->typname = t.copystr();
}
else if ((p->kind==TK_VOID)&&((p->flags&PF_PTR)==0)) {
delete p;
return NULL;
}
else {
p->flags |= (PF_OUT|PF_RETURN);
p->name = strdup(RETURNNAME);
goto Exit;
}
break;
}
if (p->name) {
if (p->kind==TK_null) {
p->kind = TK_STRUCT;
p->typname = p->name;
}
else {
error("unknown/unexpected ID");
goto Error;
}
}
p->name = t.copystr();
break;
case TOK_COMMA:
case TOK_RPAREN:
if (p->kind==TK_null) {
error("no type specified");
goto Error;
}
if (!p->name) {
error("no name specified");
goto Error;
}
if ((p->flags&(PF_OUT|PF_IN))==0) {
p->flags |= PF_IN;
}
Exit:
if (!check_param(pi,p)) {
goto Error;
}
return p;
case TOK_CHAR:
switch (p->kind) {
case TK_UNSIGNED: p->kind = TK_UNSIGNEDCHAR; break;
case TK_null: p->kind = TK_CHAR; break;
default: {
Error2:
error("invalid type");
goto Error;
}
}
break;
case TOK_SHORT:
switch (p->kind) {
case TK_UNSIGNED: p->kind = TK_UNSIGNEDSHORT; break;
case TK_null: p->kind = TK_SHORT; break;
default:
goto Error2;
}
break;
case TOK_VOID:
p->kind = TK_VOID;
break;
case TOK_INT:
switch (p->kind) {
case TK_UNSIGNED: break;
case TK_SHORT: p->kind = TK_SHORT; break;
case TK_LONG: p->kind = TK_LONG; break;
case TK_null: p->kind = TK_INT; break;
default:
goto Error2;
}
break;
case TOK_UNSIGNED:
switch (p->kind) {
case TK_null: p->kind = TK_UNSIGNED; break;
default:
goto Error2;
}
break;
case TOK_LONG:
switch (p->kind) {
case TK_LONG: p->kind = TK_LONGLONG; break;
case TK_UNSIGNED: p->kind = TK_UNSIGNEDLONG; break;
case TK_UNSIGNEDLONG: p->kind = TK_UNSIGNEDLONGLONG; break;
case TK_null: p->kind = TK_LONG; break;
default:
goto Error2;
}
break;
case TOK_STAR:
if (p->flags&(PF_PTR|PF_REF)) {
Error3:
error("parameter type not supported");
goto Error;
}
p->flags|=PF_PTR;
break;
case TOK_AMPERSAND:
if (p->flags&PF_REF) {
goto Error3;
}
p->flags|=PF_REF;
break;
case TOK_CONST:
p->flags|=PF_CONST;
break;
default:
error("unexpected symbol");
goto Error;
}
gettoken();
}
return NULL;
}
ProcInfo *parse_proc()
{
ProcInfo *pi=new ProcInfo;
while (1) {
switch (t.kind) {
case TOK_ASYNC:
pi->async = 1;
gettoken();
continue;
case TOK_CALLBACK:
pi->callback = 1;
gettoken();
continue;
case TOK_VIRTUAL:
pi->virt = 1;
gettoken();
continue;
}
break;
}
pi->rettype = parse_param(pi,1);
if (pi->async && pi->rettype) {
error("Return not allowed");
Error:
delete pi;
return NULL;
}
if (t.kind!=TOK_IDENT) {
error("Identifier expected");
goto Error;
}
pi->name = t.copystr();
ParamInfo *last = NULL;
if (!expects(TOK_LPAREN)) {
error("parameter definition expected");
goto Error;
}
gettoken();
while (t.kind!=TOK_RPAREN) {
ParamInfo *p=parse_param(pi,0);
if (last)
last->next = p;
else
pi->params = p;
last = p;
if (t.kind==TOK_COMMA)
gettoken();
}
nexttoken();
if (pi->virt&&(t.kind==TOK_EQUAL)) {
if (!expects(TOK_NUMBER)) { // 0 actually
goto Error;
}
nexttoken();
pi->virt = 2;
}
if (t.kind!=TOK_SEMICOLON) {
goto Error;
}
gettoken();
return pi;
}
void out(const char *s,size32_t l)
{
write(outfile,s,l);
}
void outs(const char *s)
{
out(s,strlen(s));
}
void outf(const char *fmt, ...) __attribute__((format(printf, 2, 3)))
{
static char buf[0x4000];
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
outs(buf);
}
void cat_type(char *s,ParamInfo *p,int deref=0,int var=0)
{
if (p==NULL) {
strcat(s,"void");
return;
}
if ((p->flags&PF_CONST)&&!var)
strcat(s,"const ");
if (p->typname)
strcat(s,p->typname);
else
strcat(s,type_name[p->kind]);
if (!deref) {
if (p->flags&PF_PTR)
strcat(s," *");
if (p->flags&PF_REF)
strcat(s," &");
}
}
void out_type(ParamInfo *p,int deref=0,int var=0)
{
char s[256];
s[0] = 0;
cat_type(s,p,deref,var);
outs(s);
}
void typesizeacc(ParamInfo *p,char *accstr,size32_t &acc)
{
if ((p->kind==TK_STRUCT)||(p->flags&(PF_PTR|PF_REF))) {
acc = (acc+3)&~3;
if (*accstr)
strcat(accstr,"+");
strcat(accstr,"sizeof(");
cat_type(accstr,p);
strcat(accstr,")");
}
else {
size32_t sz=type_size[p->kind];
if (sz==2)
acc = (acc+1)&~1;
else if (sz>=4)
acc = (acc+3)&~3;
acc += type_size[p->kind];
}
}
size32_t typesizealign(ParamInfo *p,size32_t &ofs)
{
size32_t ret=0;
if ((p->kind==TK_STRUCT)||(p->flags&(PF_PTR|PF_REF))) {
if (ofs) {
ret = 4-ofs;
ofs = 0;
}
}
else {
size32_t sz=type_size[p->kind];
if (sz==1) {
ret = 0;
ofs = (ofs+1)%4;
}
else if (sz==2) {
ret = (ofs&1);
ofs = (ofs+ret+2)%4;
}
else {
if (ofs) {
ret = 4-ofs;
ofs = 0;
}
}
}
return ret;
}
enum clarion_special_type_enum { cte_normal,cte_longref,cte_constcstr,cte_cstr };
clarion_special_type_enum clarion_special_type(ParamInfo *p)
{
if ((type_size[p->kind]==1)&&((p->flags&(PF_PTR|PF_REF))==PF_PTR)) {
if ((p->flags&PF_CONST)==0)
return cte_cstr;
return cte_constcstr;
}
else if (p->flags&PF_PTR) { // no support - convert to long
return cte_longref;
}
return cte_normal;
}
void out_clarion_type(ParamInfo *p)
{
clarion_special_type_enum cte = clarion_special_type(p);
if (p->flags&PF_REF) {
outs("*");
}
if (cte==cte_longref) {
outs("LONG");
}
else if (cte==cte_cstr) {
outs("*CSTRING");
}
else if (cte==cte_constcstr) {
outs("CONST *CSTRING");
}
else if (p->typname) {
outs(p->typname);
}
else {
outs(clarion_type_name[p->kind]);
}
}
void out_parameter_list(ParamInfo *p,const char *pfx,int forclarion=0)
{
outs("(");
while (p) {
if (forclarion && (clarion_special_type(p)==cte_cstr))
outs("int, ");
out_type(p);
outf(" %s%s",pfx,p->name);
p = p->next;
if (p)
outs(", ");
}
outs(")");
}
void out_clarion_parameter_list(ParamInfo *p)
{
outs("(");
while (p) {
out_clarion_type(p);
outs(" ");
if (clarion_special_type(p)==cte_longref)
outs("REF_");
outs(p->name);
p = p->next;
if (p)
outs(", ");
}
outs(")");
}
void out_method(ProcInfo *pi,const char *classpfx=NULL)
{
if (pi->virt&&!classpfx)
outf("HRPCvirtual%s ",pi->callback?"callback":"");
out_type(pi->rettype);
if (classpfx)
outf(" %s::%s",classpfx,pi->name);
else
outf(" %s",pi->name);
out_parameter_list(pi->params,"");
if ((pi->virt==2)&&!classpfx)
outf(" HRPCpure%s",pi->callback?"callback":"");
}
void write_header_class(ModuleInfo *mi)
{
int hasvirts = 0;
ProcInfo *pi;
for (pi=mi->procs; pi; pi=pi->next) {
if (pi->virt) {
hasvirts = 1;
break;
}
}
outf("#ifdef LOCAL_%s\n",mi->name);
outf("#define %s STUB_%s\n",mi->name,mi->name);
if (hasvirts) {
outs("#define HRPCvirtual virtual\n");
outs("#define HRPCpure =0\n");
outs("#define HRPCvirtualcallback\n");
outs("#define HRPCpurecallback\n");
}
outf("class %s : public HRPCstub\n",mi->name);
outs("#else\n");
if (hasvirts) {
outs("#define HRPCvirtual\n");
outs("#define HRPCpure\n");
outs("#define HRPCvirtualcallback virtual\n");
outs("#define HRPCpurecallback =0\n");
}
outf("class %s : public HRPCmodule\n",mi->name);
outs("#endif\n");
outs("{\npublic:\n");
outf("\t%s();\n",mi->name);
for (pi=mi->procs; pi; pi=pi->next) {
outs("\t");
out_method(pi);
outs(";\n");
}
outf("private:\n");
outf("#ifdef LOCAL_%s\n",mi->name);
outf("\tvoid _stub(HRPCbuffer &_b,HRPCbuffer &_rb,int fn);\n");
outs("#else\n");
outf("\tvoid _callbackstub(HRPCbuffer &_b,HRPCbuffer &_rb,int fn);\n");
outs("#endif\n");
if (hasvirts) {
outs("#undef HRPCvirtual\n");
outs("#undef HRPCpure\n");
outs("#undef HRPCvirtualcallback\n");
outs("#undef HRPCpurecallback\n");
}
outs("};\n");
}
void write_body_struct_elem(ParamInfo *p,int ref)
{
outs("\t");
out_type(p,ref,1);
if (ref&&(p->flags&(PF_REF|PF_PTR))) {
outs(" *");
if ((p->flags&(PF_REF|PF_PTR))==(PF_REF|PF_PTR)) {
outs(" *");
}
}
outf(" %s;\n",p->name);
}
void writeheadsize(ProcInfo *pi)
// used for simple types only at the head of the packet
{
if (pi->lastin) {
char sz[2048];
sz[0] = 0;
size32_t sza=0;
ParamInfo *p=pi->params;
while (1) {
if (p->flags&PF_SIMPLE) {
typesizeacc(p,sz,sza);
}
if(p==pi->lastin)
break;
p = p->next;
}
if (*sz) {
outs(sz);
if (sza)
outf("+%d",sza);
}
else
outf("%d",sza);
}
else
outs("0");
}
void write_offsetof(ModuleInfo *mi,ProcInfo *pi,ParamInfo *p,int inclusive,const char *pfx=NULL)
{
if (p) {
outf("offsetof(const struct HRPC_d_%s__%s,%s%s",mi->name,pi->name,pfx?pfx:"",p->name);
if (inclusive) {
outs(")+sizeof(");
out_type(p);
}
outs(")");
}
else
outf("0");
}
void write_param_convert(ParamInfo *p,int deref=0)
{
outs("(");
out_type(p,1,1);
if (p->flags&(PF_REF|PF_PTR)) {
if (!deref)
outs(" *");
if ((p->flags&(PF_REF|PF_PTR))==(PF_REF|PF_PTR)) {
outs(" *");
}
}
outs(")");
}
int write_body_swapparam(ModuleInfo *mi,ProcInfo *pi)
{
int ret=0;
ParamInfo *p;
ForEachParam(pi,p,PF_IN|PF_SIMPLE,PF_VARSIZE|PF_STRING) {
if(p->simpleneedsswap()) {
if (!ret) {
outs("\tvoid swapparams()\n\t{\n");
ret = 1;
}
outf("\t\t_WINREV%d(%s);\n",type_size[p->kind],p->name);
}
}
if (ret)
outs("\t}\n\n");
return ret;
}
void write_body_pushparam(ModuleInfo *mi,ProcInfo *pi,int swapp)
{
outs("\tvoid pushparams(HRPCbuffer &_b)\n\t{\n");
if (swapp)
outs("\t\t//swapparams();\n");
if (pi->lastin) {
outf("\t\t_b.write(&%s,",pi->firstin->name);
writeheadsize(pi);
outs(");\n");
}
ParamInfo *p;
ForEachParam(pi,p,PF_IN,PF_SIMPLE|PF_VARSIZE|PF_STRING) {
if (p->simpleneedsswap()) {
outf("\t\t//_b.writerev(%s,sizeof(*%s));\n",p->name,p->name);
outf("\t\t_b.write(%s,sizeof(*%s));\n",p->name,p->name);
}
else
outf("\t\t_b.write(%s,sizeof(*%s));\n",p->name,p->name);
}
ForEachParam(pi,p,PF_IN|PF_STRING,PF_SIMPLE|PF_VARSIZE) {
outf("\t\t_b.writestr(%s);\n",p->name);
}
// now dynamic sizes
ForEachParam(pi,p,PF_VARSIZE|PF_IN,0) {
if (INDIRECTSIZE(p)) {
// should handle size32_t* as well as ref
outf("\t\t_b.write(%s,%s);\n",p->name,p->bytesize());
}
else {
outf("\t\t_b.write(%s,%s);\n",p->name,p->bytesize());
}
}
outs("\t}\n\n");
}
void write_body_popparam(ModuleInfo *mi,ProcInfo *pi,int swapp)
{
outs("\tvoid popparams(HRPCbuffer &_b)\n\t{\n");
if (pi->lastin) {
outf("\t\t_b.read(&%s,",pi->firstin->name);
writeheadsize(pi);
outs(");\n");
}
int needensure=0;
ParamInfo *p;
ForEachParam(pi,p,PF_OUT,PF_IN|PF_SIMPLE) {
if (needensure) {
outs("\t\t\t+");
}
else {
outs("\t\t_b.ensure(\n");
outs("\t\t\t");
needensure = 1;
}
if ((p->flags&PF_VARSIZE)&&!(INDIRECTSIZE(p))) {
outf("(%s)\n",p->bytesize());
}
else {
outf("sizeof(*%s)\n",p->name);
}
}
if (needensure) {
outs("\t\t);\n");
}
ForEachParam(pi,p,PF_OUT,PF_IN|PF_SIMPLE|PF_VARSIZE|PF_STRING) {
outf("\t\t%s = ",p->name);
write_param_convert(p);
outf("_b.writeptr(sizeof(*%s));\n",p->name);
}
ForEachParam(pi,p,PF_OUT|PF_STRING,0) {
outf("\t\t%s = ",p->name);
write_param_convert(p);
outf("_b.writeptr(sizeof(*%s));\n",p->name);
outf("\t\t*%s = 0;\n",p->name);
}
ForEachParam(pi,p,PF_IN,PF_SIMPLE|PF_VARSIZE|PF_STRING) {
outf("\t\t%s = ",p->name);
write_param_convert(p);
outf("_b.readptr(sizeof(*%s));\n",p->name);
outf("\t\t\t//_b.readptrrev(sizeof(*%s));\n",p->name);
}
ForEachParam(pi,p,PF_IN|PF_STRING,PF_SIMPLE|PF_VARSIZE) {
outf("\t\t%s = _b.readstrptr();\n",p->name);
}
// now dynamic sizes
ForEachParam(pi,p,PF_VARSIZE|PF_IN,0) {
outf("\t\t%s = ",p->name);
write_param_convert(p);
if (INDIRECTSIZE(p)) {
// should handle size32_t* as well as ref
outs("_b.readptr(sizeof");
write_param_convert(p);
outs(")\n");
}
else {
outf("_b.readptr(%s);\n",p->bytesize());
}
}
ForEachParam(pi,p,PF_OUT|PF_VARSIZE,PF_IN|PF_SIMPLE) {
outf("\t\t%s = ",p->name);
write_param_convert(p);
outs("_b.writeptr(");
if ((p->flags&PF_VARSIZE)&&!(INDIRECTSIZE(p))) {
outf("%s);\n",p->bytesize());
}
else {
outf("sizeof(*%s));\n",p->name);
}
}
if (swapp)
outs("\t\t//swapparams();\n");
outs("\t}\n\n");
}
void write_body_pushreturn(ModuleInfo *mi,ProcInfo *pi)
{
if (!pi->async) {
outs("\tvoid pushreturn(HRPCbuffer &_b)\n\t{\n");
ParamInfo *p;
ForEachParam(pi,p,PF_OUT,PF_SIMPLE|PF_VARSIZE|PF_STRING) {
outf("\t\t_b.write(%s,sizeof(*%s));\n",p->name,p->name);
}
ForEachParam(pi,p,PF_OUT|PF_STRING,0) {
outf("\t\t_b.writestr(*%s);\n",p->name);
outf("\t\tfree(*%s);\n",p->name);
}
// now dynamic sizes
ForEachParam(pi,p,PF_VARSIZE|PF_OUT,0) {
if (INDIRECTSIZE(p)) {
// should handle size32_t* as well as ref
outf("\t\t_b.write(*%s,%s);\n",p->name,p->bytesize(1));
outf("\t\tfree(*%s);\n",p->name);
}
else {
outf("\t\t_b.write(%s,%s);\n",p->name,p->bytesize());
}
}
p = pi->rettype;
if (p) {
if ((p->flags&(PF_PTR|PF_STRING))==(PF_PTR|PF_STRING)) {
outf("\t\t_b.writestr(%s);\n",p->name);
outf("\t\tfree(%s);\n",p->name);
}
else if (p->flags&PF_PTR) {
outf("\t\t_b.write(%s,%s);\n",p->name,p->bytesize(1));
outf("\t\tfree(%s);\n",p->name);
}
else {
outf("\t\t_b.write(&%s,sizeof(%s));\n",p->name,p->name);
}
}
outs("\t}\n\n");
}
}
void write_body_popreturn(ModuleInfo *mi,ProcInfo *pi)
{
if (!pi->async) {
outs("\tvoid popreturn(HRPCbuffer &_b)\n\t{\n");
ParamInfo *p;
ForEachParam(pi,p,PF_OUT,PF_SIMPLE|PF_VARSIZE|PF_RETURN|PF_STRING) {
outf("\t\t_b.read(%s,sizeof(*%s));\n",p->name,p->name);
}
ForEachParam(pi,p,PF_OUT|PF_STRING,0) {
outf("\t\t*%s = _b.readstrdup();\n",p->name);
}
// now dynamic sizes
ForEachParam(pi,p,PF_VARSIZE|PF_OUT,0) {
if (INDIRECTSIZE(p)) {
outf("\t\t*%s = ",p->name);
write_param_convert(p,1);
outf("malloc(%s);\n",p->bytesize(1));
outf("\t\t_b.read(*%s,%s);\n",p->name,p->bytesize(1));
}
else {
outf("\t\t_b.read(%s,%s);\n",p->name,p->bytesize());
}
}
p = pi->rettype;
if (p) {
if ((p->flags&(PF_PTR|PF_STRING))==(PF_PTR|PF_STRING)) {
outf("\t\t%s = _b.readstrdup();\n",p->name);
}
else if (p->flags&PF_PTR) {
outf("\t\t%s = ",p->name);
write_param_convert(p);
outf("malloc(%s);\n",p->bytesize(1));
outf("\t\t_b.read(%s,%s);\n",p->name,p->bytesize(1));
}
else {
outf("\t\t_b.read(&%s,sizeof(%s));\n",p->name,p->name);
}
}
outs("\t}\n\n");
}
}
void write_body_method_structs2(int fn,ModuleInfo *mi,ProcInfo *pi) {
// buffer structure
outf("struct HRPC_d_%s__%s\n{\n",mi->name,pi->name);
ParamInfo *p;
pi->lastin=NULL;
pi->firstin=NULL;
ForEachParam(pi,p,0,0)
p->flags &= ~PF_SIMPLE;
size32_t align=0;
int dummy = 0;
ForEachParam(pi,p,PF_IN,PF_OUT|PF_REF|PF_PTR|PF_VARSIZE) {
p->flags |= PF_SIMPLE;
pi->lastin = p;
if (!pi->firstin)
pi->firstin = p;
size32_t a=typesizealign(p,align);
if (a>0) {
dummy++;
if (a>1)
outf("\tchar __dummy%d[%d];\n",dummy,a);
else
outf("\tchar __dummy%d;\n",dummy,a);
}
write_body_struct_elem(p,0);
}
if (align>0) {
dummy++;
outf("\tchar _dummy%d[%d];\n",dummy,4-align);
align = 0;
}
ForEachParam(pi,p,PF_IN,PF_OUT|PF_SIMPLE) {
write_body_struct_elem(p,1);
}
ForEachParam(pi,p,PF_IN|PF_OUT,PF_SIMPLE) {
write_body_struct_elem(p,1);
}
ForEachParam(pi,p,PF_OUT,PF_IN|PF_SIMPLE) {
write_body_struct_elem(p,1);
}
if (pi->rettype) {
typesizealign(pi->rettype,align);
write_body_struct_elem(pi->rettype,0);
if (align>0) {
dummy++;
outf("\tchar _dummy%d[%d];\n",dummy,4-align);
align = 0;
}
}
int swapp=write_body_swapparam(mi,pi);
write_body_pushparam(mi,pi,swapp);
write_body_popparam(mi,pi,swapp);
if (!pi->async) {
write_body_pushreturn(mi,pi);
write_body_popreturn(mi,pi);
}
// now constructors
outf("\tHRPC_d_%s__%s() {}\n",mi->name,pi->name);
if (pi->params) {
outf("\tHRPC_d_%s__%s",mi->name,pi->name);
out_parameter_list(pi->params,"_");
outs(": ");
ForEachParam(pi,p,0,0) {
outf("%s(",p->name);
if (p->flags&PF_REF) {
outs("&");
}
else if ((p->flags&(PF_PTR&PF_CONST))==(PF_PTR&PF_CONST)) {
write_param_convert(p);
}
outf("_%s)",p->name);
if (p->next)
outs(", ") ;
}
outs("\n\t{\n");
outs("\t};");
}
outs("\n};\n");
}
void write_body_class_stub(ModuleInfo *mi,int cb)
{
outf("void %s::_%sstub(HRPCbuffer &_b,HRPCbuffer &_br,int fn)\n{\n",mi->name,cb?"callback":"");
int fn=0;
int switchdone = 0;
ProcInfo *pi;
for (pi=mi->procs; pi; pi=pi->next) {
fn++;
if (cb!=pi->callback)
continue;
if (!switchdone) {
outs("\tswitch(fn) {\n");
switchdone = 1;
}
outf("\tcase %d: {\n",fn);
outf("\t\t\tHRPC_d_%s__%s _params;\n",mi->name,pi->name,mi->name,pi->name);
outs("\t\t\t_params.popparams(_b);\n");
if (pi->async) {
outs("\t\t\t_returnasync(_br);\n");
}
outs("\t\t\t");
if (pi->rettype) {
outf("_params.%s = ",RETURNNAME);
}
outf("%s(",pi->name);
ParamInfo *p;
ForEachParam(pi,p,0,0) {
if (p->flags&PF_REF)
outs("*");
outf("_params.%s",p->name);
if (p->next)
outs(", ");
}
outs(");\n");
if (!pi->async) {
outs("\t\t\t_returnOK(_br);\n");
outs("\t\t\t_params.pushreturn(_br);\n");
}
outs("\t\t\tbreak;\n");
outs("\t\t}\n");
}
if (switchdone) {
outs("\t}\n");
}
outs("}\n\n");
}
void write_body_class_proxy(ModuleInfo *mi,int cb)
{
int fn = 0;
ProcInfo *pi;
for (pi=mi->procs; pi; pi=pi->next) {
fn++;
if (cb!=pi->callback)
continue;
out_method(pi,mi->name);
outs("\n{\n");
if (pi->callback) {
outs("\tHRPCcallframe _callframe(&_server->Sync(),cbbuff);\n");
}
else {
outs("\tHRPCcallframe _callframe(sync,inbuff);\n");
}
outf("\tHRPC_d_%s__%s _params",mi->name,pi->name);
if (pi->params) {
outs("(");
ParamInfo *p;
ForEachParam(pi,p,0,0) {
outf("%s",p->name);
if (p->next)
outs(", ");
}
outs(")");
}
outs(";\n");
if (pi->callback) {
outs("\t_params.pushparams(cbbuff);\n");
outf("\t_callbackproxy(_callframe,%d);\n",fn);
if (!pi->async)
outs("\t_params.popreturn(cbbuff);\n");
}
else {
outs("\t_params.pushparams(inbuff);\n");
outf("\t_proxy(_callframe,%d);\n",fn);
if (!pi->async)
outs("\t_params.popreturn(inbuff);\n");
}
if (pi->rettype) {
outf("\treturn _params.%s;\n",RETURNNAME);
}
outs("}\n\n");
}
outs("\n\n");
}
void write_body_class(ModuleInfo *mi)
{
outf("// class %s \n\n",mi->name);
outf("static struct HRPCmoduleid _id_%s = { { ",mi->name);
char *mn = mi->name;
for (int i=0;i<8;i++) {
if (i)
outs(", ");
if (*mn) {
outf("'%c'",*mn);
mn++;
}
else
outs("0");
}
outf("}, %d };\n\n",mi->version);
ProcInfo *pi;
int fn=0;
for (pi=mi->procs; pi; pi=pi->next) {
fn++;
write_body_method_structs2(fn,mi,pi);
}
outs("\n");
outf("%s::%s() { _id = &_id_%s; }\n\n",mi->name,mi->name,mi->name);
outf("#ifdef LOCAL_%s // Stub(%s):\n\n",mi->name,mi->name);
write_body_class_stub(mi,0);
write_body_class_proxy(mi,1);
outf("#else // Proxy(%s):\n\n",mi->name);
write_body_class_proxy(mi,0);
write_body_class_stub(mi,1);
outf("#endif // end class %s\n",mi->name);
}
void write_clarion_interface_class(ModuleInfo *mi)
{
outs("extern \"C\" {\n\n");
outs("\n");
outf("// clarion interface class CIC_%s \n",mi->name);
outf("struct HRPCI_%s: public HRPCI_Clarion_Module // interface\n",mi->name);
ProcInfo *pi;
outs("{\n");
for (pi=mi->procs; pi; pi=pi->next) {
if (pi->callback)
continue;
outs("\tvirtual ");
out_type(pi->rettype);
outf(" _stdcall %s",pi->name);
out_parameter_list(pi->params,"",1);
outs("=0;\n");
}
outs("};\n");
outf("#ifndef LOCAL_%s\n\n",mi->name);
outf("class CIC_%s : public HRPCI_%s\n",mi->name,mi->name);
outs("{\n");
outs("public:\n");
outf("\t%s _o;\n",mi->name);
outs("\tmutable unsigned xxcount;\n");
for (pi=mi->procs; pi; pi=pi->next) {
if (pi->callback)
continue;
outs("\t");
out_type(pi->rettype);
outf(" _stdcall %s",pi->name);
out_parameter_list(pi->params,"",1);
outs("\n");
outs("\t{\n");
outs("\t\t");
if (pi->rettype) {
outs("return ");
}
outf("_o.%s(",pi->name);
ParamInfo *p;
ForEachParam(pi,p,0,0) {
outf("%s",p->name);
if (p->next)
outs(", ");
}
outs(");\n");
outs("\t}\n");
}
outf("\tCIC_%s() { xxcount = 0; }\n",mi->name);
outs("\tvoid _stdcall Link() const { ++xxcount; }\n");
outs("\tint _stdcall Release() const {if (xxcount == 0) { delete this; return 1; } --xxcount; return 0; }\n");
outs("\tvoid _stdcall FreeMem(void *p) { free(p); }\n");
outs("};\n");
outf("CIC_%s* PASCAL HRPC_Make_%s(HRPCI_Clarion_Transport *t)\n",mi->name,mi->name);
outs("{\n");
outf("\tCIC_%s *ret=new CIC_%s;\n",mi->name,mi->name);
outs("\tret->_o.UseTransport(t->GetTransport());\n");
outs("\treturn ret;\n");
outs("}\n");
outs("#endif\n");
outs("}\n");
}
void write_example_module(ModuleInfo *mi)
{
outf("void %s_Server()\n",mi->name);
outs("{\n");
outs("\tHRPCserver server(MakeTcpTransport(NULL,PORTNO)); // PORTNO TBD\n");
outf("\t%s stub;\n",mi->name);
outs("\tserver.AttachStub(&stub); // NB a server can service more than one module\n");
outs("\tserver.Listen();\n");
outs("}\n\n");
ProcInfo *pi;
for (pi=mi->procs; pi; pi=pi->next) {
out_method(pi,mi->name);
outs("\n{\n");
outf("\t // TBD\n");
if (pi->rettype) {
outs("\treturn TBD;\n");
}
outs("}\n\n");
}
}
void write_clarion_include_module(ModuleInfo *mi)
{
outf("HRPCI_%s INTERFACE(HRPCI_Clarion_Module)\r\n",mi->name);
ProcInfo *pi;
for (pi=mi->procs; pi; pi=pi->next) {
if (pi->callback)
continue;
outf("%-15s PROCEDURE",pi->name);
out_clarion_parameter_list(pi->params);
if (pi->rettype) {
outs(",");
out_clarion_type(pi->rettype);
}
outs(",PASCAL\r\n");
}
outs(" END\r\n\r\n");
}
public:
void ProcessHIDL(char *sp,int ho,int cppo,int xsvo,int clwo,const char *packagename)
{
lineno = 1;
outfile = ho;
ModuleInfo *first=NULL;
ModuleInfo *last;
ModuleInfo *mi;
outf("// *** Include file generated by HIDL Version %s from %s.hid ***\n",HIDLVER,packagename);
outf("// *** Not to be hand edited (changes will be lost on re-generation) ***\n\n");
outf("#include \"hrpc.hpp\"\n\n");
start = sp;
s = sp;
while (*s) {
const char *p=s;
int eof = !skip_to_module();
out(p,s-p);
if (eof)
break;
gettoken(); // skip module
if (!expects(TOK_IDENT)) {
error("Module name expected");
break;
}
mi = new ModuleInfo(t.str,t.len);
if (first)
last->next = mi;
else {
first = mi;
}
last = mi;
while (1) {
if (gettoken()==TOK_LBRACE)
break;
if (t.kind==TOK_LPAREN) {
if (expects(TOK_NUMBER)) {
mi->version = t.integer();
if ((mi->version>255)||(mi->version<0))
error("version must be in range 0-255");
if (!expects(TOK_RPAREN)) {
error(") expected");
}
}
else
error("Version number expected");
}
else {
error("{ expected");
return;
}
}
ProcInfo *last=NULL;
gettoken();
while (t.kind!=TOK_RBRACE) {
ProcInfo *pi = parse_proc();
if (!pi)
break;
if (last)
last->next = pi;
else
mi->procs = pi;
last = pi;
}
if (!expects(TOK_SEMICOLON)) {
error("; expected after }");
break;
}
write_header_class(mi);
}
outs("//end\r\n"); // CR for Clarion
outfile = cppo;
outf("// *** Source file generated by HIDL Version %s from %s.hid ***\n",HIDLVER,packagename);
outf("// *** Not to be hand edited (changes will be lost on re-generation) ***\n\n");
outf("#include \"%s.hpp\"\n\n",packagename);
for (mi=first;mi;mi=mi->next) {
write_body_class(mi);
write_clarion_interface_class(mi);
}
outs("//end\r\n"); // CR for Clarion
outfile = xsvo;
outs("// Example Server Implementation Template\n");
outf("// Source file generated by HIDL Version %s from %s.hid\n",HIDLVER,packagename);
outs("// *** You should copy this file before changing, as it will be overwritten next time HIDL is run ***\n\n");
outs("#include \n");
outs("#include \n");
outs("#include \n\n");
outs("#include \"hrpcsock.hpp\"// default use TCP/IP sockets\n\n");
outs("// TBD - Add other includes here\n\n");
for (mi=first;mi;mi=mi->next) {
outf("#define LOCAL_%s // implementation of %s\n",mi->name,mi->name);
}
outf("#include \"%s.cpp\"\n\n",packagename);
for (mi=first;mi;mi=mi->next) {
write_example_module(mi);
}
outfile = clwo;
outs("! Clarion HRPC Interfaces\r\n");
outf("! Include file generated by HIDL Version %s from %s.hid\r\n",HIDLVER,packagename);
outs("! *** Not to be hand edited (changes will be lost on re-generation) ***\r\n\r\n");
outf(" OMIT('EndOfInclude',_%s_I_)\r\n",packagename);
outf("_%s_I_ EQUATE(1)\r\n\r\n",packagename);
outs(" INCLUDE('HRPC.INC'),ONCE\r\n\r\n");
for (mi=first;mi;mi=mi->next) {
write_clarion_include_module(mi);
}
outs("\r\n");
outs(" MAP\r\n");
outf(" MODULE('%s')\r\n",packagename);
for (mi=first;mi;mi=mi->next) {
outf(" HRPC_Make_%s(HRPCI_Clarion_Transport transport),*HRPCI_%s,PASCAL,NAME('_HRPC_Make_%s@4')\r\n",mi->name,mi->name,mi->name);
}
outs(" END\r\n\r\n");
outs(" END\r\n\r\n");
outf("\r\nEndOfInclude\r\n");
while (first) {
mi = first;
first = mi->next;
delete mi;
}
}
};
char *gettail(const char *fn)
{
const char *e=NULL;
const char *e1=fn;
while((e1=strchr(e1,'.'))!=NULL)
e = e1++;
const char *s=fn;
const char *s1;
#ifdef _WIN32
if (*s&&s[1]==':')
s+=2;
#endif
for (s1 = s;*s1&&(s1!=e);s1++)
#ifdef _WIN32
if (*s1=='\\')
#else
if (*s1=='/')
#endif
s = s1+1;
size32_t l = s1-s;
char *ret = (char *)malloc(l+1);
memcpy(ret,s,l);
ret[l] = 0;
return ret;
}
char *changeext(const char *fn,const char *ext)
{
char *ret=gettail(fn);
size32_t l = strlen(ret);
ret = (char *)realloc(ret,l+strlen(ext)+2);
ret[l] = '.';
strcpy(ret+l+1,ext);
return ret;
}
int main(int argc, char* argv[])
{
if (argc<2) {
printf("HIDL Compiler Version %s\n\n",HIDLVER);
printf("Usage: HIDL filename.hid [] \n\n");
printf("Output: filename.cpp\n");
printf(" filename.hpp\n");
printf(" filename.xsv\n");
printf(" (the xsv file is an example server implementation template)\n");
return 1;
}
char *path=changeext(argv[1],"hid");
int hi = open(path,_O_RDONLY | _O_BINARY);
if (hi==-1) {
printf("Could not read %s\n",path);
return 1;
}
free(path);
size32_t l = lseek(hi,0,SEEK_END);
lseek(hi,0,SEEK_SET);
char *s = (char *)malloc(l+1);
l = read(hi,s,l);
close(hi);
if (argc>2)
_chdir(argv[2]);
s[l] = 0;
path=changeext(argv[1],"hpp");
int ho = open(path, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY , S_IREAD|S_IWRITE);
if (ho==-1) {
printf("Could not write %s\n",path);
return 1;
}
free(path);
path=changeext(argv[1],"cpp");
int cppo = open(path,_O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY , S_IREAD|S_IWRITE);
if (cppo==-1) {
printf("Could not write %s\n",path);
return 1;
}
free(path);
path=changeext(argv[1],"xsv");
int xsvo = open(path,_O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY , S_IREAD|S_IWRITE);
if (xsvo==-1) {
printf("Could not write %s\n",path);
return 1;
}
free(path);
path=changeext(argv[1],"int");
int clwo = open(path,_O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY , S_IREAD|S_IWRITE);
if (clwo==-1) {
printf("Could not write %s\n",path);
return 1;
}
free(path);
HIDLcompiler hc;
char *package = gettail(argv[1]);
hc.ProcessHIDL(s,ho,cppo,xsvo,clwo,package);
free(package);
free(s);
close(ho);
close(cppo);
close(xsvo);
close(clwo);
return 0;
}