1
0
mirror of https://github.com/golang/go synced 2024-10-04 11:11:21 -06:00
go/src/cmd/gc/export.c

490 lines
7.6 KiB
C
Raw Normal View History

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "go.h"
#include "y.tab.h"
void dumpsym(Sym*);
void
addexportsym(Sym *s)
{
Dcl *d, *r;
d = mal(sizeof(*d));
d->dsym = s;
d->dnode = N;
d->lineno = lineno;
r = exportlist;
d->back = r->back;
r->back->forw = d;
r->back = d;
}
void
exportsym(Sym *s)
{
if(s == S)
return;
if(s->export != 0) {
if(s->export != 1)
yyerror("export/package mismatch: %S", s);
return;
}
s->export = 1;
addexportsym(s);
}
void
packagesym(Sym *s)
{
if(s == S)
return;
if(s->export != 0) {
if(s->export != 2)
yyerror("export/package mismatch: %S", s);
return;
}
s->export = 2;
addexportsym(s);
}
2008-09-24 15:12:21 -06:00
int
exportname(char *s)
{
Rune r;
if((uchar)s[0] < Runeself)
return 'A' <= s[0] && s[0] <= 'Z';
chartorune(&r, s);
return isupperrune(r);
}
void
autoexport(Sym *s)
{
if(s == S)
return;
if(dclcontext != PEXTERN)
return;
if(exportname(s->name)) {
exportsym(s);
} else {
packagesym(s);
}
}
2008-09-24 15:12:21 -06:00
void
dumpprereq(Type *t)
2008-09-24 15:12:21 -06:00
{
if(t == T)
return;
if(t->printed || t == types[t->etype])
return;
t->printed = 1;
if(t->sym != S && t->etype != TFIELD)
dumpsym(t->sym);
dumpprereq(t->type);
dumpprereq(t->down);
}
void
dumpexportconst(Sym *s)
{
Node *n;
Type *t;
n = s->oconst;
if(n == N || n->op != OLITERAL)
fatal("dumpexportconst: oconst nil: %S", s);
t = n->type; // may or may not be specified
if(t != T)
dumpprereq(t);
Bprint(bout, "\t");
Bprint(bout, "const %lS", s);
if(t != T)
Bprint(bout, " %#T", t);
Bprint(bout, " = ");
switch(n->val.ctype) {
default:
fatal("dumpexportconst: unknown ctype: %S", s);
case CTINT:
case CTSINT:
case CTUINT:
Bprint(bout, "%B\n", n->val.u.xval);
break;
case CTBOOL:
if(n->val.u.bval)
Bprint(bout, "true\n");
else
Bprint(bout, "false\n");
break;
case CTFLT:
Bprint(bout, "%F\n", n->val.u.fval);
break;
case CTSTR:
Bprint(bout, "\"%Z\"\n", n->val.u.sval);
break;
}
}
void
dumpexportvar(Sym *s)
{
Node *n;
Type *t;
n = s->oname;
2008-07-05 18:43:25 -06:00
if(n == N || n->type == T) {
2008-07-14 21:40:48 -06:00
yyerror("variable exported but not defined: %S", s);
2008-07-05 18:43:25 -06:00
return;
}
t = n->type;
dumpprereq(t);
Bprint(bout, "\t");
if(t->etype == TFUNC)
Bprint(bout, "func ");
else
Bprint(bout, "var ");
Bprint(bout, "%lS %#T\n", s, t);
}
void
dumpexporttype(Sym *s)
{
dumpprereq(s->otype);
Bprint(bout, "\t");
switch (s->otype->etype) {
case TFORW:
case TFORWSTRUCT:
case TFORWINTER:
yyerror("export of incomplete type %T", s->otype);
return;
}
Bprint(bout, "type %#T %l#T\n", s->otype, s->otype);
}
void
dumpsym(Sym *s)
{
Type *f;
if(s->exported != 0)
return;
s->exported = 1;
switch(s->lexical) {
default:
yyerror("unknown export symbol: %S", s);
break;
case LPACK:
2008-07-14 21:40:48 -06:00
yyerror("package export symbol: %S", s);
break;
case LATYPE:
case LBASETYPE:
// TODO(rsc): sort methods by name
for(f=s->otype->method; f!=T; f=f->down)
dumpprereq(f);
dumpexporttype(s);
for(f=s->otype->method; f!=T; f=f->down)
Bprint(bout, "\tfunc (%#T) %hS %#hT\n",
f->type->type->type, f->sym, f->type);
break;
case LNAME:
dumpexportvar(s);
break;
case LACONST:
dumpexportconst(s);
break;
}
}
void
dumptype(Type *t)
{
// no need to re-dump type if already exported
if(t->printed)
return;
// no need to dump type if it's not ours (was imported)
if(t->sym != S && t->sym->otype == t && !t->local)
return;
Bprint(bout, "type %#T %l#T\n", t, t);
}
void
dumpexport(void)
{
Dcl *d;
int32 lno;
2008-06-26 18:54:44 -06:00
lno = lineno;
Bprint(bout, " import\n");
Bprint(bout, "\n$$ // exports\n");
2008-06-12 22:48:56 -06:00
Bprint(bout, " package %s\n", package);
for(d=exportlist->forw; d!=D; d=d->forw) {
2008-06-26 18:54:44 -06:00
lineno = d->lineno;
dumpsym(d->dsym);
}
Bprint(bout, "\n$$ // local types\n");
for(d=typelist->forw; d!=D; d=d->forw) {
lineno = d->lineno;
dumptype(d->dtype);
}
Bprint(bout, "\n$$\n");
2008-06-26 18:54:44 -06:00
lineno = lno;
}
/*
* import
*/
2008-09-24 15:12:21 -06:00
/*
* look up and maybe declare pkg.name, which should match lexical
*/
Sym*
pkgsym(char *name, char *pkg, int lexical)
2008-09-24 15:12:21 -06:00
{
Sym *s;
s = pkglookup(name, pkg);
switch(lexical) {
case LATYPE:
if(s->oname)
yyerror("%s.%s is not a type", name, pkg);
break;
case LNAME:
if(s->otype)
yyerror("%s.%s is not a name", name, pkg);
break;
2008-09-24 15:12:21 -06:00
}
s->lexical = lexical;
return s;
2008-09-24 15:12:21 -06:00
}
/*
* return the sym for ss, which should match lexical
*/
2008-06-11 22:06:26 -06:00
Sym*
importsym(Node *ss, int lexical)
2008-06-11 22:06:26 -06:00
{
Sym *s;
renamepkg(ss);
2008-06-11 22:06:26 -06:00
if(ss->op != OIMPORT)
fatal("importsym: oops1 %N", ss);
2008-06-11 22:06:26 -06:00
s = pkgsym(ss->sym->name, ss->psym->name, lexical);
/* TODO botch - need some diagnostic checking for the following assignment */
2008-06-11 22:06:26 -06:00
s->opackage = ss->osym->name;
if(exportname(ss->sym->name))
s->export = 1;
else
s->export = 2; // package scope
s->imported = 1;
2008-06-11 22:06:26 -06:00
return s;
}
/*
* return the type pkg.name, forward declaring if needed
*/
Type*
pkgtype(char *name, char *pkg)
{
Sym *s;
Type *t;
// botch
// s = pkgsym(name, pkg, LATYPE);
Node *n;
n = nod(OIMPORT, N, N);
n->sym = lookup(name);
n->psym = lookup(pkg);
n->osym = n->psym;
renamepkg(n);
s = importsym(n, LATYPE);
if(s->otype == T) {
t = typ(TFORW);
t->sym = s;
s->otype = t;
}
return s->otype;
}
static int
mypackage(Node *ss)
{
// we import all definitions for sys.
// lowercase ones can only be used by the compiler.
return strcmp(ss->psym->name, package) == 0
|| strcmp(ss->psym->name, "sys") == 0;
}
void
importconst(Node *ss, Type *t, Val *v)
{
Node *n;
Sym *s;
if(!exportname(ss->sym->name) && !mypackage(ss))
return;
n = nod(OLITERAL, N, N);
n->val = *v;
n->type = t;
s = importsym(ss, LACONST);
if(s->oconst != N) {
// TODO: check if already the same.
return;
}
dodclconst(newname(s), n);
if(debug['e'])
print("import const %S\n", s);
}
void
importvar(Node *ss, Type *t)
{
Sym *s;
if(!exportname(ss->sym->name) && !mypackage(ss))
return;
s = importsym(ss, LNAME);
if(s->oname != N) {
if(eqtype(t, s->oname->type, 0))
return;
warn("redeclare import var %S from %T to %T",
s, s->oname->type, t);
}
checkwidth(t);
addvar(newname(s), t, PEXTERN);
if(debug['e'])
print("import var %S %lT\n", s, t);
}
void
importtype(Node *ss, Type *t)
{
Sym *s;
s = importsym(ss, LATYPE);
if(s->otype != T) {
if(eqtype(t, s->otype, 0))
return;
if(s->otype->etype != TFORW) {
warn("redeclare import type %S from %T to %T",
s, s->otype, t);
s->otype = typ(0);
}
}
if(s->otype == T)
s->otype = typ(0);
*s->otype = *t;
s->otype->sym = s;
checkwidth(s->otype);
// If type name should not be visible to importers,
// hide it by setting the lexical type to name.
// This will make references in the ordinary program
// (but not the import sections) look at s->oname,
// which is nil, as for an undefined name.
if(s->export == 2 && !mypackage(ss))
s->lexical = LNAME;
if(debug['e'])
print("import type %S %lT\n", s, t);
}
void
importmethod(Sym *s, Type *t)
{
checkwidth(t);
addmethod(newname(s), t, 0);
}
/*
* ******* import *******
*/
void
checkimports(void)
{
Sym *s;
Type *t, *t1;
uint32 h;
int et;
return;
for(h=0; h<NHASH; h++)
for(s = hash[h]; s != S; s = s->link) {
t = s->otype;
if(t == T)
continue;
et = t->etype;
switch(t->etype) {
case TFORW:
print("ci-1: %S %lT\n", s, t);
break;
case TPTR32:
case TPTR64:
if(t->type == T) {
print("ci-2: %S %lT\n", s, t);
break;
}
t1 = t->type;
if(t1 == T) {
print("ci-3: %S %lT\n", s, t1);
break;
}
et = t1->etype;
if(et == TFORW) {
print("%L: ci-4: %S %lT\n", lineno, s, t);
break;
}
break;
}
}
}
void
renamepkg(Node *n)
{
if(n->psym == pkgimportname)
if(pkgmyname != S)
n->psym = pkgmyname;
}