ref: 94443daf8e248e65afc8d3f17f26efea22748b51
dir: /utils/c2l/out.c/
#include "cc.h"
#define INCREMENT 8
#define DEVNULL "/dev/null"
static int indent = 0;
static int fd = -1;
static int nf = 0;
static int mylineno = 1;
typedef struct Com{
int lno;
char *s;
Node *n;
int tba;
struct Com *nxt;
} Com;
Com *hdc, *curc;
typedef struct File{
char *s;
char *f;
char *m;
int b;
int loc;
int in;
int tg;
Node *n;
Com *c;
struct File *nxt;
} File;
typedef struct Create{
char *s;
struct Create *nxt;
} Create;
File *fs;
Create *cs;
static void genmsg(void);
static int isloc(void);
static void
addcreate(char *s)
{
Create *c;
if(strcmp(s, DEVNULL) == 0)
return;
c = (Create*)malloc(sizeof(Create));
c->s = malloc(strlen(s)+1);
strcpy(c->s, s);
c->nxt = cs;
cs = c;
}
static int
created(char *s)
{
Create *c;
for(c = cs; c != nil; c = c->nxt)
if(strcmp(s, c->s) == 0)
return 1;
return 0;
}
int
dolog(void)
{
if(justcode)
return 0;
return domod || !doinc || inmain;
}
static char*
curf(void)
{
File *f;
for(f = fs; f != nil; f = f->nxt)
if(f->f != nil)
return f->s;
return nil;
}
static char*
curm(void)
{
File *f;
for(f = fs; f != nil; f = f->nxt)
if(f->f != nil)
return f->m;
return nil;
}
void
setmod(Sym *s)
{
if(domod && s->mod == nil && ism() && !(doloc && !isloc()))
s->mod = curm();
}
char *
outmod(char *buf, int up)
{
char *s, *t;
s = curf();
if(s == nil)
return "";
t = strchr(s, '.');
if(t != nil)
*t = '\0';
strcpy(buf, s);
if(t != nil)
*t = '.';
if(up == 1 || (up < 0 && ism()))
buf[0] = toupper(buf[0]);
return buf;
}
int
ism(void)
{
return !isb();
}
int
isb(void)
{
File *f;
for(f = fs; f != nil; f = f->nxt)
if(f->f != nil)
return f->b;
return 0;
}
static int
isloc(void)
{
File *f;
for(f = fs; f != nil; f = f->nxt)
if(f->f != nil)
return f->loc;
return 0;
}
static File*
pushf(void)
{
static File zfile;
File *f;
f = (File*)malloc(sizeof(File));
*f = zfile;
f->s = nil;
f->f = nil;
f->m = nil;
f->nxt = fs;
fs = f;
return f;
}
static void
popf(void)
{
File *f;
f = fs;
fs = fs->nxt;
if(f->s != nil)
free(f->s);
free(f);
}
static void
setf(File *f, char *s)
{
int n;
char *t;
if(s != nil){
t = strrchr(s, '/');
f->loc = t == nil;
if(t != nil)
s = t+1;
n = strlen(s);
f->s = malloc(n+1);
strcpy(f->s, s);
s = f->s;
if(n > 2 && s[n-2] == '.'){
f->m = malloc(n-1);
strncpy(f->m, s, n-2);
if(s[n-1] == 'h')
s[n-1] = 'm';
else if(s[n-1] == 'c'){
s[n-1] = 'b';
f->b = 1;
}
else
s = nil;
}
else
s = nil;
if(s == nil){
free(f->s);
if(f->m != nil)
free(f->m);
f->s = nil;
f->m = nil;
}
}
f->f = f->s;
if(f->s != nil && nf > 0){
if(doinc || doloc && !f->loc)
f->f = DEVNULL;
else if(!domod)
f->f = nil;
}
}
void
outpush0(char *s, Node *n)
{
File *f;
f = pushf();
setf(f, s);
if(f->f != nil){
nf++;
f->tg = taggen;
taggen = 0;
f->n = n;
f->c = hdc;
hdc = nil;
}
}
void
outpop0(int lno)
{
File *f;
USED(lno);
f = fs;
if(f->f != nil){
nf--;
taggen = f->tg;
f->n->left = (void*)hdc;
hdc = f->c;
}
popf();
}
void
outpush2(char *s, Node *n)
{
File *f;
f = pushf();
setf(f, s);
if(f->f != nil){
if(fd >= 0){
newsec(0);
close(fd);
close(1);
fd = -1;
}
if(created(f->f))
f->f = DEVNULL; /* don't overwrite original if included again */
fd = create(f->f, OWRITE, 0664);
if(fd >= 0)
addcreate(f->f);
mydup(fd, 1);
nf++;
f->tg = taggen;
taggen = 0;
f->c = hdc;
if(n != Z)
hdc = (void*)n->left;
else
hdc = nil;
f->in = indent;
indent = 0;
genmsg();
pgen(f->b);
}
}
void
outpop2(int lno)
{
File *f, *g;
f = fs;
if(f->f != nil){
if(fd >= 0){
newsec(0);
output(lno, 1);
epgen(f->b);
close(fd);
close(1);
fd = -1;
}
for(g = fs->nxt; g != nil; g = g->nxt){
if(g->f != nil){
fd = open(g->f, OWRITE);
seek(fd, 0, 2);
mydup(fd, 1);
break;
}
}
nf--;
taggen = f->tg;
hdc = f->c;
indent = f->in;
}
popf();
}
static void
xprint(char *s)
{
if(nerrors == 0)
print(s);
}
static int tot = 0;
static void
doindent(int d)
{
int i;
for(i = 0; i < d/8; i++)
xprint("\t");
for(i = 0; i < d%8; i++)
xprint(" ");
}
void
incind(void)
{
indent += INCREMENT;
}
void
decind(void)
{
indent -= INCREMENT;
}
int
zeroind(void)
{
int i = indent;
indent = 0;
return i;
}
void
restoreind(int i)
{
indent = i;
}
void
newline0(void)
{
xprint("\n");
tot = 0;
mylineno++;
}
void
newline(void)
{
if(!outcom(1)){
xprint("\n");
mylineno++;
}
tot = 0;
}
static void
lprint(char *s)
{
if(tot == 0) {
doindent(indent);
tot += indent;
}
xprint(s);
tot += strlen(s);
}
void
prline(char *s)
{
xprint(s);
xprint("\n");
mylineno++;
}
void
prdelim(char *s)
{
if(*s == '%'){
if(*++s == '=')
lprint("%%=");
else
lprint("%%");
return;
}
lprint(s);
}
void
prkeywd(char *kw)
{
lprint(kw);
}
void
prid(char *s)
{
lprint(s);
}
static void
priddol(char *s, int dol)
{
char *t;
char buf[128];
if(dol){
t = strchr(s, '$');
if(t != nil)
*t = '_';
lprint(s);
if(t != nil){
strcpy(buf, s);
while(slookup(buf)->type != T){
strcat(buf, "x");
lprint("x");
}
*t = '$';
}
}
else
lprint(s);
}
void
prsym(Sym *s, int mod)
{
char buf[128];
int c;
if(mod && s->mod && strcmp(s->mod, curm()) != 0 && (!s->limbo || s->class == CEXTERN)){
c = isconsym(s);
if(c >= 0){
if(c){
s->mod[0] = toupper(s->mod[0]);
lprint(s->mod);
s->mod[0] = tolower(s->mod[0]);
}
else
lprint(s->mod);
lprint("->");
usemod(s, !c);
}
}
if(s->lname)
prid(s->lname);
else{
priddol(s->name, s->class == CSTATIC);
if(s->lkw){
strcpy(buf, s->name);
for(;;){
strcat(buf, "x");
lprint("x");
s = slookup(buf);
if(s->type == T)
break;
}
}
}
}
int
arrow(Sym *s)
{
if(s->mod && strcmp(s->mod, curm()) != 0)
return isconsym(s) >= 0;
return 0;
}
void
prsym0(Sym *s)
{
int c;
if(s->mod && strcmp(s->mod, curm()) != 0){
c = isconsym(s);
if(c >= 0)
usemod(s, !c);
}
}
static int
isprintable(int c)
{
if(c >= 0x20 && c <= 0x7e)
return 1;
return c == '\0' || c == '\n' || c == '\t' || c == '\b' || c == '\r' || c == '\f' || c == '\a' || c == '\v';
}
static int
hex(int c)
{
if(c < 10)
return c+'0';
return c+'a'-10;
}
void
prchar0(vlong x, int quote)
{
int c, e, i = 0;
static char buf[16];
if(quote)
buf[i++] = '\'';
c = x;
if(c < 0 || c > 255 || !isprintable(c)){
if(c&0xffff0000)
diag(Z, "character too big");
buf[i++] = '\\';
buf[i++] = 'u';
buf[i++] = hex((c>>12)&0xf);
buf[i++] = hex((c>>8)&0xf);
buf[i++] = hex((c>>4)&0xf);
buf[i++] = hex((c>>0)&0xf);
}
else{
e = 0;
switch(c){
case '\n': e = 'n'; break;
case '\t': e = 't'; break;
case '\b': e = 'b'; break;
case '\r': e = 'r'; break;
case '\f': e = 'f'; break;
case '\a': e = 'a'; break;
case '\v': e = 'v'; break;
case '"': if(!quote) e = '"'; break;
case '\'': if(quote) e = '\''; break;
case '\\': e = '\\'; break;
case '%': buf[i++] = c; break;
case 0: e = '0'; if(strings) prcom("nul byte in string ?", Z); break;
}
if(e != 0){
buf[i++] = '\\';
c = e;
}
buf[i++] = c;
}
if(quote)
buf[i++] = '\'';
buf[i] = '\0';
lprint(buf);
}
void
prchar(vlong x)
{
prchar0(x, 1);
}
void
prstr(char *s)
{
uchar *t;
Rune r;
t = (uchar*)s;
lprint("\"");
while(*t != 0){
if(*t & 0x80){
t += chartorune(&r, (char*)t);
prchar0(r, 0);
}
else
prchar0(*t++, 0);
}
lprint("\"");
}
void
prlstr(Rune *s)
{
lprint("\"");
while(*s != 0)
prchar0(*s++, 0);
lprint("\"");
}
void
prreal(double x, char *s, int b)
{
static char buf[128];
if(b != KDEC)
diag(Z, "not base 10 in prreal");
if(s != nil)
lprint(s);
else{
sprint(buf, "%f", x);
lprint(buf);
}
}
void
prnum(vlong x, int b, Type *t)
{
static char buf[128];
int w;
vlong m;
w = 4;
if(t != T)
w = ewidth[t->etype];
m = MASK(8*w);
if(b == KHEX)
sprint(buf, "16r%llux", x&m);
else if(b == KOCT)
sprint(buf, "8r%lluo", x&m);
else
sprint(buf, "%lld", x);
lprint(buf);
}
char *cb;
int cn, csz;
static void
outcom0(Com *c)
{
Node *n;
char *s, *t, *u;
s = c->s;
n = c->n;
if(comm && c->tba){
t = strchr(s, '\n');
*t = '\0';
fprint(2, "%s:%d: %s", curf(), mylineno, s);
*t = '\n';
if(n != Z){
mydup(2, 1);
expgen(n);
mydup(fd, 1);
}
fprint(2, "\n");
}
while(*s != '\0'){
t = strchr(s, '\n');
*t = '\0';
if(tot != 0)
prdelim("\t");
prdelim("# ");
while((u = strchr(s, '%')) != nil){
/* do not let print interpret % ! */
*u = 0;
lprint(s);
*u = '%';
lprint("%%");
s = u+1;
}
lprint(s);
if(n == Z)
newline0();
*t = '\n';
s = t+1;
}
if(n != Z){
expgen(n);
newline0();
}
}
int
outcom(int f)
{
int lno, nl;
Com *c;
nl = 0;
lno = pline+f;
c = hdc;
while(c != nil && c->lno < lno){
/* print("outcom: %d < %d (f=%d)\n", c->lno, lno, f); */
nl = 1;
outcom0(c);
hdc = hdc->nxt;
free(c->s);
free(c);
c = hdc;
}
return nl;
}
void
startcom(int lno)
{
Com *c, **ac;
c = (Com *)malloc(sizeof(Com));
c->lno = lno;
c->s = nil;
c->n = Z;
c->tba = 0;
c->nxt = nil;
for(ac = &hdc; *ac != nil && (*ac)->lno <= lno; ac = &(*ac)->nxt)
;
c->nxt = *ac;
curc = *ac = c;
}
void
addcom(int rr)
{
int i, nb;
char *ncb;
char s[UTFmax];
Rune r[1];
if(rr >= Runeself){
r[0] = rr;
nb = runetochar(s, r);
}
else{
nb = 1;
s[0] = rr;
}
if(cn+nb-1 >= csz){
csz += 32;
ncb = malloc(csz);
memcpy(ncb, cb, cn);
free(cb);
cb = ncb;
}
for(i = 0; i < nb; i++)
cb[cn++] = s[i];
}
void
endcom(void)
{
char *s;
addcom('\n');
addcom('\0');
s = malloc(strlen(cb)+1);
strcpy(s, cb);
curc->s = s;
/* print("com %d %s\n", curc->lno, s); */
cn = 0;
}
void
linit()
{
csz = 32;
cb = malloc(csz);
sysinit();
}
static void
genmsg(void)
{
prline("#");
prline("# initially generated by c2l");
prline("#");
prline("");
}
void
prcom(char *s, Node *n)
{
Com *c;
startcom(pline);
c = curc;
sprint(cb, "TBA %s", s);
cn = strlen(cb);
c->n = n;
c->tba = 1;
endcom();
}
void
output(long lno, int com)
{
/* print("output(%ld)\n", lno); */
pline = lno;
if(com)
outcom(0);
}
int
exists(char *f)
{
int fd;
fd = open(f, OREAD);
close(fd);
return fd >= 0;
}