summaryrefslogtreecommitdiff
path: root/utils/vl
diff options
context:
space:
mode:
authorforsyth <forsyth@lavoro.terzarima.net>2013-06-03 21:01:14 +0000
committerforsyth <forsyth@lavoro.terzarima.net>2013-06-03 21:01:14 +0000
commit45a20ab721a513710138340faff3d59a31c3e01e (patch)
treeeea29d2684c51cc73725b8992a2125bede48e118 /utils/vl
parentcd8e99851af33e52bcdf8faf34f9d4e62fa0cbaf (diff)
sync compilers with Plan 9
remove 1[acl] 2[acl]
Diffstat (limited to 'utils/vl')
-rw-r--r--utils/vl/Nt.c77
-rw-r--r--utils/vl/Plan9.c57
-rw-r--r--utils/vl/Posix.c80
-rw-r--r--utils/vl/asm.c123
-rw-r--r--utils/vl/compat.c23
-rw-r--r--utils/vl/l.h15
-rw-r--r--utils/vl/list.c2
-rw-r--r--utils/vl/mkfile8
-rw-r--r--utils/vl/obj.c125
-rw-r--r--utils/vl/span.c2
10 files changed, 202 insertions, 310 deletions
diff --git a/utils/vl/Nt.c b/utils/vl/Nt.c
deleted file mode 100644
index 73c6f795..00000000
--- a/utils/vl/Nt.c
+++ /dev/null
@@ -1,77 +0,0 @@
-#include <windows.h>
-#include "l.h"
-
-/*
- * fake malloc
- */
-void*
-malloc(uint n)
-{
- void *p;
-
- while(n & 7)
- n++;
- while(nhunk < n)
- gethunk();
- p = hunk;
- nhunk -= n;
- hunk += n;
- return p;
-}
-
-void
-free(void *p)
-{
- USED(p);
-}
-
-void*
-calloc(uint m, uint n)
-{
- void *p;
-
- n *= m;
- p = malloc(n);
- memset(p, 0, n);
- return p;
-}
-
-void*
-realloc(void *p, uint n)
-{
- void *new;
-
- new = malloc(n);
- if(new && p)
- memmove(new, p, n);
- return new;
-}
-
-#define Chunk (1*1024*1024)
-
-void*
-mysbrk(ulong size)
-{
- void *v;
- static int chunk;
- static uchar *brk;
-
- if(chunk < size) {
- chunk = Chunk;
- if(chunk < size)
- chunk = Chunk + size;
- brk = VirtualAlloc(NULL, chunk, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- if(brk == 0)
- return (void*)-1;
- }
- v = brk;
- chunk -= size;
- brk += size;
- return v;
-}
-
-double
-cputime(void)
-{
- return ((double)0);
-}
diff --git a/utils/vl/Plan9.c b/utils/vl/Plan9.c
deleted file mode 100644
index f4cf23f4..00000000
--- a/utils/vl/Plan9.c
+++ /dev/null
@@ -1,57 +0,0 @@
-#include "l.h"
-
-/*
- * fake malloc
- */
-void*
-malloc(ulong n)
-{
- void *p;
-
- while(n & 7)
- n++;
- while(nhunk < n)
- gethunk();
- p = hunk;
- nhunk -= n;
- hunk += n;
- return p;
-}
-
-void
-free(void *p)
-{
- USED(p);
-}
-
-void*
-calloc(ulong m, ulong n)
-{
- void *p;
-
- n *= m;
- p = malloc(n);
- memset(p, 0, n);
- return p;
-}
-
-void*
-realloc(void *p, ulong n)
-{
- USED(p);
- USED(n);
- fprint(2, "realloc called\n");
- abort();
- return 0;
-}
-
-void*
-mysbrk(ulong size)
-{
- return sbrk(size);
-}
-
-void
-setmalloctag(void*, ulong)
-{
-}
diff --git a/utils/vl/Posix.c b/utils/vl/Posix.c
deleted file mode 100644
index 7c3a661f..00000000
--- a/utils/vl/Posix.c
+++ /dev/null
@@ -1,80 +0,0 @@
-#include "l.h"
-#include <sys/types.h>
-#include <sys/times.h>
-#undef getwd
-#include <unistd.h> /* For sysconf() and _SC_CLK_TCK */
-
-/*
- * fake malloc
- */
-void*
-malloc(size_t n)
-{
- void *p;
-
- while(n & 7)
- n++;
- while(nhunk < n)
- gethunk();
- p = hunk;
- nhunk -= n;
- hunk += n;
- return p;
-}
-
-void
-free(void *p)
-{
- USED(p);
-}
-
-void*
-calloc(size_t m, size_t n)
-{
- void *p;
-
- n *= m;
- p = malloc(n);
- memset(p, 0, n);
- return p;
-}
-
-void*
-realloc(void *p, size_t n)
-{
- fprint(2, "realloc called\n", p, n);
- abort();
- return 0;
-}
-
-void*
-mysbrk(ulong size)
-{
- return (void*)sbrk(size);
-}
-
-double
-cputime(void)
-{
-
- struct tms tmbuf;
- double ret_val;
-
- /*
- * times() only fials if &tmbuf is invalid.
- */
- (void)times(&tmbuf);
- /*
- * Return the total time (in system clock ticks)
- * spent in user code and system
- * calls by both the calling process and its children.
- */
- ret_val = (double)(tmbuf.tms_utime + tmbuf.tms_stime +
- tmbuf.tms_cutime + tmbuf.tms_cstime);
- /*
- * Convert to seconds.
- */
- ret_val *= sysconf(_SC_CLK_TCK);
- return ret_val;
-
-}
diff --git a/utils/vl/asm.c b/utils/vl/asm.c
index 1e7039f1..527b8de5 100644
--- a/utils/vl/asm.c
+++ b/utils/vl/asm.c
@@ -84,6 +84,12 @@ long BADOFFSET = -1;
}
void
+cput(long l)
+{
+ CPUT(l);
+}
+
+void
objput(long l) /* emit long in byte order appropriate to object machine */
{
LPUT(l);
@@ -96,11 +102,55 @@ objhput(short s)
}
void
+wput(long l)
+{
+
+ cbp[0] = l>>8;
+ cbp[1] = l;
+ cbp += 2;
+ cbc -= 2;
+ if(cbc <= 0)
+ cflush();
+}
+
+void
+wputl(long l)
+{
+
+ cbp[0] = l;
+ cbp[1] = l>>8;
+ cbp += 2;
+ cbc -= 2;
+ if(cbc <= 0)
+ cflush();
+}
+
+void
lput(long l) /* emit long in big-endian byte order */
{
LBEPUT(l);
}
+void
+lputl(long l) /* emit long in big-endian byte order */
+{
+ LLEPUT(l);
+}
+
+void
+llput(vlong v)
+{
+ lput(v>>32);
+ lput(v);
+}
+
+void
+llputl(vlong v)
+{
+ lputl(v);
+ lputl(v>>32);
+}
+
long
entryvalue(void)
{
@@ -391,64 +441,7 @@ asmb(void)
lput(0x80L); /* flags */
break;
case 5:
- /* first part of ELF is byte-wide parts, thus no byte-order issues */
- strnput("\177ELF", 4); /* e_ident */
- CPUT(1); /* class = 32 bit */
- CPUT(little? 1: 2); /* data: 1 = LSB, 2 = MSB */
- CPUT(1); /* version = 1 */
- strnput("", 9); /* reserved for expansion */
- /* entire remainder of ELF file is in target byte order */
-
- /* file header part of ELF header */
- objhput(2); /* type = EXEC */
- objhput(8); /* machine = MIPS */
- objput(1L); /* version = CURRENT */
- objput(entryvalue()); /* entry vaddr */
- objput(52L); /* offset to first phdr */
- objput(0L); /* offset to first shdr */
- objput(0L); /* flags (no MIPS flags defined) */
- objhput(52); /* Ehdr size */
- objhput(32); /* Phdr size */
- objhput(3); /* # of Phdrs */
- objhput(0); /* Shdr size */
- objhput(0); /* # of Shdrs */
- objhput(0); /* Shdr string size */
-
- /* "Program headers" - one per chunk of file to load */
-
- /*
- * include ELF headers in text -- 8l doesn't,
- * but in theory it aids demand loading.
- */
- objput(1L); /* text: type = PT_LOAD */
- objput(0L); /* file offset */
- objput(INITTEXT-HEADR); /* vaddr */
- objput(INITTEXT-HEADR); /* paddr */
- objput(HEADR+textsize); /* file size */
- objput(HEADR+textsize); /* memory size */
- objput(0x05L); /* protections = RX */
- objput(0x1000L); /* page-align text off's & vaddrs */
-
- objput(1L); /* data: type = PT_LOAD */
- objput(HEADR+textsize); /* file offset */
- objput(INITDAT); /* vaddr */
- objput(INITDAT); /* paddr */
- objput(datsize); /* file size */
- objput(datsize+bsssize); /* memory size */
- objput(0x06L); /* protections = RW */
- if(INITDAT % 4096 == 0 && (HEADR + textsize) % 4096 == 0)
- objput(0x1000L); /* page-align data off's & vaddrs */
- else
- objput(0L); /* do not claim alignment */
-
- objput(0L); /* P9 symbols: type = PT_NULL */
- objput(HEADR+textsize+datsize); /* file offset */
- objput(0L);
- objput(0L);
- objput(symsize); /* symbol table size */
- objput(lcsize); /* line number size */
- objput(0x04L); /* protections = R */
- objput(0L); /* do not claim alignment */
+ elf32(MIPS, little? ELFDATA2LSB: ELFDATA2MSB, 0, nil);
break;
case 6:
break;
@@ -616,12 +609,12 @@ asmlc(void)
if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
if(p->as == ATEXT)
curtext = p;
- if(debug['L'])
+ if(debug['V'])
Bprint(&bso, "%6lux %P\n",
p->pc, p);
continue;
}
- if(debug['L'])
+ if(debug['V'])
Bprint(&bso, "\t\t%6ld", lcsize);
v = (p->pc - oldpc) / MINLC;
while(v) {
@@ -629,7 +622,7 @@ asmlc(void)
if(v < 127)
s = v;
CPUT(s+128); /* 129-255 +pc */
- if(debug['L'])
+ if(debug['V'])
Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
v -= s;
lcsize++;
@@ -643,7 +636,7 @@ asmlc(void)
CPUT(s>>16);
CPUT(s>>8);
CPUT(s);
- if(debug['L']) {
+ if(debug['V']) {
if(s > 0)
Bprint(&bso, " lc+%ld(%d,%ld)\n",
s, 0, s);
@@ -658,14 +651,14 @@ asmlc(void)
}
if(s > 0) {
CPUT(0+s); /* 1-64 +lc */
- if(debug['L']) {
+ if(debug['V']) {
Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
Bprint(&bso, "%6lux %P\n",
p->pc, p);
}
} else {
CPUT(64-s); /* 65-128 -lc */
- if(debug['L']) {
+ if(debug['V']) {
Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
Bprint(&bso, "%6lux %P\n",
p->pc, p);
@@ -678,7 +671,7 @@ asmlc(void)
CPUT(s);
lcsize++;
}
- if(debug['v'] || debug['L'])
+ if(debug['v'] || debug['V'])
Bprint(&bso, "lcsize = %ld\n", lcsize);
Bflush(&bso);
}
diff --git a/utils/vl/compat.c b/utils/vl/compat.c
index 5e676913..fa93a42a 100644
--- a/utils/vl/compat.c
+++ b/utils/vl/compat.c
@@ -4,7 +4,7 @@
* fake malloc
*/
void*
-malloc(long n)
+malloc(ulong n)
{
void *p;
@@ -25,7 +25,7 @@ free(void *p)
}
void*
-calloc(long m, long n)
+calloc(ulong m, ulong n)
{
void *p;
@@ -36,9 +36,9 @@ calloc(long m, long n)
}
void*
-realloc(void *p, long n)
+realloc(void*, ulong)
{
- fprint(2, "realloc called\n", p, n);
+ fprint(2, "realloc called\n");
abort();
return 0;
}
@@ -48,3 +48,18 @@ mysbrk(ulong size)
{
return sbrk(size);
}
+
+void
+setmalloctag(void *v, ulong pc)
+{
+ USED(v, pc);
+}
+
+int
+fileexists(char *s)
+{
+ uchar dirbuf[400];
+
+ /* it's fine if stat result doesn't fit in dirbuf, since even then the file exists */
+ return stat(s, dirbuf, sizeof(dirbuf)) >= 0;
+}
diff --git a/utils/vl/l.h b/utils/vl/l.h
index 75243ad8..c8f9b868 100644
--- a/utils/vl/l.h
+++ b/utils/vl/l.h
@@ -1,11 +1,14 @@
#include <lib9.h>
#include <bio.h>
#include "../vc/v.out.h"
+#include "../8l/elf.h"
#ifndef EXTERN
#define EXTERN extern
#endif
+#define LIBNAMELEN 300
+
typedef struct Adr Adr;
typedef struct Sym Sym;
typedef struct Autom Auto;
@@ -186,6 +189,7 @@ EXTERN int HEADTYPE; /* type of header */
EXTERN long INITDAT; /* data location */
EXTERN long INITRND; /* data round above text location */
EXTERN long INITTEXT; /* text location */
+EXTERN long INITTEXTP; /* text location (physical) */
EXTERN char* INITENTRY; /* entry point */
EXTERN long autosize;
EXTERN Biobuf bso;
@@ -266,6 +270,7 @@ int Pconv(Fmt*);
int Sconv(Fmt*);
int aclass(Adr*);
void addhist(long, int);
+void addlibpath(char*);
void addnop(Prog*);
void append(Prog*, Prog*);
void asmb(void);
@@ -278,6 +283,7 @@ void buildop(void);
void buildrep(int, int);
void cflush(void);
int cmp(int, int);
+void cput(long);
int compound(Prog*);
double cputime(void);
void datblk(long, long, int);
@@ -288,7 +294,9 @@ void doprof2(void);
long entryvalue(void);
void errorexit(void);
void exchange(Prog*);
+int fileexists(char*);
int find1(long, int);
+char* findlib(char*);
void follow(void);
void gethunk(void);
void histtoauto(void);
@@ -299,7 +307,10 @@ void ldobj(int, long, char*);
void loadlib(void);
void listinit(void);
Sym* lookup(char*, int);
+void llput(vlong);
+void llputl(vlong);
void lput(long);
+void lputl(long);
void bput(long);
void mkfwd(void);
void* mysbrk(ulong);
@@ -308,7 +319,7 @@ void nocache(Prog*);
void noops(void);
void nuxiinit(void);
void objfile(char*);
-int ocmp(const void*, const void*);
+int ocmp(void*, void*);
long opirr(int);
Optab* oplook(Prog*);
long oprrr(int);
@@ -325,6 +336,8 @@ void sched(Prog*, Prog*);
void span(void);
void strnput(char*, int);
void undef(void);
+void wput(long);
+void wputl(long);
void xdefine(char*, int, long);
void xfol(Prog*);
void xfol(Prog*);
diff --git a/utils/vl/list.c b/utils/vl/list.c
index 9261bc8e..c5033a5b 100644
--- a/utils/vl/list.c
+++ b/utils/vl/list.c
@@ -56,7 +56,7 @@ Aconv(Fmt *fp)
int a;
a = va_arg(fp->args, int);
- s = "???";
+ s = "?";
if(a >= AXXX && a < ALAST)
s = anames[a];
return fmtstrcpy(fp, s);
diff --git a/utils/vl/mkfile b/utils/vl/mkfile
index b84163a6..8e18fced 100644
--- a/utils/vl/mkfile
+++ b/utils/vl/mkfile
@@ -13,6 +13,7 @@ OFILES=\
span.$O\
enam.$O\
$TARGMODEL.$O\
+ elf.$O\
HFILES=\
l.h\
@@ -25,7 +26,12 @@ BIN=$ROOT/$OBJDIR/bin
<$ROOT/mkfiles/mkone-$SHELLTYPE
-CFLAGS= $CFLAGS -I../include
+CFLAGS= $CFLAGS -I../include -I.
enam.$O: ../vc/enam.c
$CC $CFLAGS ../vc/enam.c
+elf.$O: ../ld/elf.c
+ $CC $CFLAGS ../ld/elf.c
+
+$TARGMODEL.$O: ../ld/$TARGMODEL.c
+ $CC $CFLAGS ../ld/$TARGMODEL.c
diff --git a/utils/vl/obj.c b/utils/vl/obj.c
index 8289c588..e80695df 100644
--- a/utils/vl/obj.c
+++ b/utils/vl/obj.c
@@ -11,6 +11,10 @@ char symname[] = SYMDEF;
char thechar = 'v';
char *thestring = "mips";
+char** libdir;
+int nlibdir = 0;
+static int maxlibdir = 0;
+
/*
* -H0 -T0x40004C -D0x10000000 is abbrev unix
* -H1 -T0x80020000 -R4 is bootp() format for 3k
@@ -24,10 +28,18 @@ char *thestring = "mips";
int little;
void
+usage(void)
+{
+ diag("usage: %s [-options] objects", argv0);
+ errorexit();
+}
+
+void
main(int argc, char *argv[])
{
int c;
char *a;
+ char name[LIBNAMELEN];
Binit(&bso, 1, OWRITE);
cout = -1;
@@ -37,6 +49,7 @@ main(int argc, char *argv[])
curtext = P;
HEADTYPE = -1;
INITTEXT = -1;
+ INITTEXTP = -1;
INITDAT = -1;
INITRND = -1;
INITENTRY = 0;
@@ -55,7 +68,7 @@ main(int argc, char *argv[])
if(a)
INITENTRY = a;
break;
- case 'L': /* for little-endian mips */
+ case 'm': /* for little-endian mips */
thechar = '0';
thestring = "spim";
little = 1;
@@ -65,6 +78,11 @@ main(int argc, char *argv[])
if(a)
INITTEXT = atolwhex(a);
break;
+ case 'P':
+ a = ARGF();
+ if(a)
+ INITTEXTP = atolwhex(a);
+ break;
case 'D':
a = ARGF();
if(a)
@@ -81,16 +99,27 @@ main(int argc, char *argv[])
HEADTYPE = atolwhex(a);
/* do something about setting INITTEXT */
break;
+ case 'L':
+ addlibpath(EARGF(usage()));
+ break;
} ARGEND
USED(argc);
- if(*argv == 0) {
- diag("usage: %cl [-options] objects", thechar);
- errorexit();
- }
+ if(*argv == 0)
+ usage();
if(!debug['9'] && !debug['U'] && !debug['B'])
debug[DEFAULT] = 1;
+ a = getenv("ccroot");
+ if(a != nil && *a != '\0') {
+ if(!fileexists(a)) {
+ diag("nonexistent $ccroot: %s", a);
+ errorexit();
+ }
+ }else
+ a = "";
+ snprint(name, sizeof(name), "%s/%s/lib", a, thestring);
+ addlibpath(name);
if(HEADTYPE == -1) {
if(debug['U'])
HEADTYPE = 0;
@@ -150,7 +179,7 @@ main(int argc, char *argv[])
INITRND = 0;
break;
case 5: /* sgi unix elf executable */
- HEADR = rnd(52L+3*32L, 16);
+ HEADR = rnd(Ehdr32sz+3*Phdr32sz, 16);
if(INITTEXT == -1)
INITTEXT = 0x00400000L+HEADR;
if(INITDAT == -1)
@@ -168,6 +197,8 @@ main(int argc, char *argv[])
INITRND = 4096;
break;
}
+ if (INITTEXTP == -1)
+ INITTEXTP = INITTEXT;
if(INITDAT != 0 && INITRND != 0)
print("warning: -D0x%lux is ignored because of -R0x%lux\n",
INITDAT, INITRND);
@@ -195,7 +226,7 @@ main(int argc, char *argv[])
}
cout = create(outfile, 1, 0775);
if(cout < 0) {
- diag("%s: cannot create", outfile);
+ diag("cannot create %s: %r", outfile);
errorexit();
}
nuxiinit();
@@ -212,7 +243,7 @@ main(int argc, char *argv[])
INITENTRY = "_mainp";
if(!debug['l'])
lookup(INITENTRY, 0)->type = SXREF;
- } else
+ } else if(!(*INITENTRY >= '0' && *INITENTRY <= '9'))
lookup(INITENTRY, 0)->type = SXREF;
while(*argv)
@@ -249,6 +280,42 @@ out:
}
void
+addlibpath(char *arg)
+{
+ char **p;
+
+ if(nlibdir >= maxlibdir) {
+ if(maxlibdir == 0)
+ maxlibdir = 8;
+ else
+ maxlibdir *= 2;
+ p = malloc(maxlibdir*sizeof(*p));
+ if(p == nil) {
+ diag("out of memory");
+ errorexit();
+ }
+ memmove(p, libdir, nlibdir*sizeof(*p));
+ free(libdir);
+ libdir = p;
+ }
+ libdir[nlibdir++] = strdup(arg);
+}
+
+char*
+findlib(char *file)
+{
+ int i;
+ char name[LIBNAMELEN];
+
+ for(i = 0; i < nlibdir; i++) {
+ snprint(name, sizeof(name), "%s/%s", libdir[i], file);
+ if(fileexists(name))
+ return libdir[i];
+ }
+ return nil;
+}
+
+void
loadlib(void)
{
int i;
@@ -367,7 +434,8 @@ objfile(char *file)
l |= (e[3] & 0xff) << 16;
l |= (e[4] & 0xff) << 24;
seek(f, l, 0);
- l = read(f, &arhdr, SAR_HDR);
+ /* need readn to read the dumps (at least) */
+ l = readn(f, &arhdr, SAR_HDR);
if(l != SAR_HDR)
goto bad;
if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
@@ -394,7 +462,7 @@ int
zaddr(uchar *p, Adr *a, Sym *h[])
{
int i, c;
- long l;
+ int l;
Sym *s;
Auto *u;
@@ -498,25 +566,24 @@ zaddr(uchar *p, Adr *a, Sym *h[])
void
addlib(char *obj)
{
- char name[1024], comp[256], *p;
- int i;
+ char fn1[LIBNAMELEN], fn2[LIBNAMELEN], comp[LIBNAMELEN], *p, *name;
+ int i, search;
if(histfrogp <= 0)
return;
+ name = fn1;
+ search = 0;
if(histfrog[0]->name[1] == '/') {
sprint(name, "");
i = 1;
- } else
- if(histfrog[0]->name[1] == '.') {
+ } else if(histfrog[0]->name[1] == '.') {
sprint(name, ".");
i = 0;
} else {
- if(debug['9'])
- sprint(name, "/%s/lib", thestring);
- else
- sprint(name, "/usr/%clib", thechar);
+ sprint(name, "");
i = 0;
+ search = 1;
}
for(; i<histfrogp; i++) {
@@ -539,13 +606,25 @@ addlib(char *obj)
memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
memmove(p, thestring, strlen(thestring));
}
- if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
+ if(strlen(fn1) + strlen(comp) + 3 >= sizeof(fn1)) {
diag("library component too long");
return;
}
- strcat(name, "/");
- strcat(name, comp);
+ if(i > 0 || !search)
+ strcat(fn1, "/");
+ strcat(fn1, comp);
}
+
+ cleanname(name);
+
+ if(search){
+ p = findlib(name);
+ if(p != nil){
+ snprint(fn2, sizeof(fn2), "%s/%s", p, name);
+ name = fn2;
+ }
+ }
+
for(i=0; i<libraryp; i++)
if(strcmp(name, library[i]) == 0)
return;
@@ -1017,8 +1096,7 @@ lookup(char *symb, int v)
for(p=symb; c = *p; p++)
h = h+h+h + c;
l = (p - symb) + 1;
- if(h < 0)
- h = ~h;
+ h &= 0xffffff;
h %= NHASH;
for(s = hash[h]; s != S; s = s->link)
if(s->version == v)
@@ -1332,6 +1410,7 @@ nuxiinit(void)
Bflush(&bso);
}
+int
find1(long l, int c)
{
char *p;
diff --git a/utils/vl/span.c b/utils/vl/span.c
index 488c93d3..b28643d2 100644
--- a/utils/vl/span.c
+++ b/utils/vl/span.c
@@ -456,7 +456,7 @@ cmp(int a, int b)
}
int
-ocmp(const void *a1, const void *a2)
+ocmp(void *a1, void *a2)
{
Optab *p1, *p2;
int n;