Commits

Anonymous committed 68031f3

initial refactoring for go13linker work

  • Participants
  • Parent commits 7326da9
  • Branches go13linker

Comments (0)

Files changed (143)

 misc/osx/*.pkg
 misc/osx/*.dmg
 src/cmd/?a/y.output
-src/cmd/?l/enam.c
+src/liblink/anames?.c
 src/cmd/cc/y.output
 src/cmd/cgo/zdefaultcc.go
 src/cmd/dist/dist.dSYM

File include/link.h

+// Derived from Inferno utils/6l/l.h and related files.
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/l.h
+//
+//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//	Portions Copyright © 1997-1999 Vita Nuova Limited
+//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//	Portions Copyright © 2004,2006 Bruce Ellis
+//	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+typedef	struct	Addr	Addr;
+typedef	struct	Prog	Prog;
+typedef	struct	LSym	LSym;
+typedef	struct	Reloc	Reloc;
+typedef	struct	Auto	Auto;
+typedef	struct	Hist	Hist;
+typedef	struct	Hist2	Hist2;
+typedef	struct	Link	Link;
+typedef	struct	Plist	Plist;
+typedef	struct	LinkArch	LinkArch;
+typedef	struct	Library	Library;
+
+typedef	struct	Pcln	Pcln;
+typedef	struct	Pcdata	Pcdata;
+
+struct	Addr
+{
+	vlong	offset;
+
+	union
+	{
+		char	sval[8];
+		float64	dval;
+		Prog*	branch;	// for 5g, 6g, 8g
+	} u;
+
+	LSym*	sym;
+	LSym*	gotype;
+	short	type;
+	uint8	index;
+	int8	scale;
+	int8	reg;	// for 5l
+	int8	name; // for 5l
+	int8	class;	// for 5l
+	uint8	etype; // for 5g, 6g, 8g
+	int32	offset2;	// for 5l, 8l
+	struct Node*	node; // for 5g, 6g, 8g
+	int64	width; // for 5g, 6g, 8g
+};
+
+struct	Reloc
+{
+	int32	off;
+	uchar	siz;
+	uchar	done;
+	int32	type;
+	int64	add;
+	int64	xadd;
+	LSym*	sym;
+	LSym*	xsym;
+};
+
+struct	Prog
+{
+	vlong	pc;
+	int32	lineno;
+	Prog*	link;
+	short	as;
+	uchar	reg; // arm only
+	uchar	scond; // arm only
+	Addr	from;
+	Addr	to;
+	
+	// for 5g, 6g, 8g internal use
+	uint32	loc;	// TODO: merge with pc?
+	void*	opt;
+
+	// for 5l, 6l, 8l internal use
+	Prog*	forwd;
+	Prog*	pcond;
+	Prog*	comefrom;	// 6l, 8l
+	Prog*	pcrel;	// 5l
+	int32	spadj;
+	uchar	mark;
+	uchar	back;	// 6l, 8l
+	char	ft;	/* 6l, 8l oclass cache */
+	char	tt;	// 6l, 8l
+	uchar	optab;	// 5l
+
+	char	width;	/* fake for DATA */
+	char	mode;	/* 16, 32, or 64 */
+};
+
+struct	LSym
+{
+	char*	name;
+	char*	extname;	// name used in external object files
+	short	type;
+	short	version;
+	uchar	dupok;
+	uchar	reachable;
+	uchar	cgoexport;
+	uchar	special;
+	uchar	stkcheck;
+	uchar	hide;
+	uchar	leaf;	// arm only
+	uchar	fnptr;	// arm only
+	int16	symid;	// for writing .5/.6/.8 files
+	int32	dynid;
+	int32	sig;
+	int32	plt;
+	int32	got;
+	int32	align;	// if non-zero, required alignment in bytes
+	int32	elfsym;
+	int32	args;	// size of stack frame incoming arguments area
+	int32	locals;	// size of stack frame locals area (arm only?)
+	vlong	value;
+	vlong	size;
+	LSym*	hash;	// in hash table
+	LSym*	allsym;	// in all symbol list
+	LSym*	next;	// in text or data list
+	LSym*	sub;	// in SSUB list
+	LSym*	outer;	// container of sub
+	LSym*	gotype;
+	LSym*	reachparent;
+	LSym*	queue;
+	char*	file;
+	char*	dynimplib;
+	char*	dynimpvers;
+	struct Section*	sect;
+	Hist2*	hist;	// for ATEXT
+	
+	// STEXT
+	Auto*	autom;
+	Prog*	text;
+	Pcln*	pcln;
+
+	// SDATA, SBSS
+	uchar*	p;
+	int32	np;
+	int32	maxp;
+	Reloc*	r;
+	int32	nr;
+	int32	maxr;
+};
+
+// LSym.type
+enum
+{
+	Sxxx,
+
+	/* order here is order in output file */
+	/* readonly, executable */
+	STEXT,
+	SELFRXSECT,
+	
+	/* readonly, non-executable */
+	STYPE,
+	SSTRING,
+	SGOSTRING,
+	SGOFUNC,
+	SRODATA,
+	SFUNCTAB,
+	STYPELINK,
+	SSYMTAB, // TODO: move to unmapped section
+	SPCLNTAB,
+	SELFROSECT,
+	
+	/* writable, non-executable */
+	SMACHOPLT,
+	SELFSECT,
+	SMACHO,	/* Mach-O __nl_symbol_ptr */
+	SMACHOGOT,
+	SNOPTRDATA,
+	SINITARR,
+	SDATA,
+	SWINDOWS,
+	SBSS,
+	SNOPTRBSS,
+	STLSBSS,
+
+	/* not mapped */
+	SXREF,
+	SMACHOSYMSTR,
+	SMACHOSYMTAB,
+	SMACHOINDIRECTPLT,
+	SMACHOINDIRECTGOT,
+	SFILE,
+	SFILEPATH,
+	SCONST,
+	SDYNIMPORT,
+	SHOSTOBJ,
+
+	SSUB = 1<<8,	/* sub-symbol, linked from parent via ->sub list */
+	SMASK = SSUB - 1,
+	SHIDDEN = 1<<9, // hidden or local symbol
+};
+
+struct	Auto
+{
+	LSym*	asym;
+	Auto*	link;
+	int32	aoffset;
+	int16	type;
+	LSym*	gotype;
+};
+
+enum
+{
+	LINKHASH = 100003,
+};
+
+struct	Hist
+{
+	Hist*	link;
+	char*	name;
+	int32	line;
+	int32	offset;
+};
+
+struct	Plist
+{
+	LSym*	name;
+	Prog*	firstpc;
+	int	recur;
+	Plist*	link;
+};
+
+struct	Library
+{
+	char *objref;	// object where we found the reference
+	char *srcref;	// src file where we found the reference
+	char *file;	// object file
+	char *pkg;	// import path
+};
+
+struct Pcdata
+{
+	uchar *p;
+	int n;
+	int m;
+};
+
+struct Pcln
+{
+	Pcdata pcsp;
+	Pcdata pcfile;
+	Pcdata pcline;
+	Pcdata *pcdata;
+	int npcdata;
+	LSym **funcdata;
+	int64 *funcdataoff;
+	int nfuncdata;
+	
+	LSym **file;
+	int nfile;
+	int mfile;
+
+	LSym *lastfile;
+	int lastindex;
+};
+
+enum
+{
+	LinkMaxHist = 40,
+};
+
+// TODO: Replace uses of Hist2 with Hist and delete this.
+struct Hist2
+{
+	int32 line;
+	int32 off;
+	LSym *file;
+};
+
+// symbol version, incremented each time a file is loaded.
+// version==1 is reserved for savehist.
+enum
+{
+	HistVersion = 1,
+};
+
+// Link holds the context for writing object code from a compiler
+// to be linker input or for reading that input into the linker.
+struct	Link
+{
+	int32	thechar; // '5' (arm), '6' (amd64), etc.
+	char*	thestring; // full name of architecture ("arm", "amd64", ..)
+	int32	goarm; // for arm only, GOARM setting
+	int	headtype;
+	int	linkmode;
+
+	LinkArch*	arch;
+	int32	(*ignore)(char*);	// do not emit names satisfying this function
+	int32	debugasm;	// -S flag in compiler
+	int32	debugline;	// -L flag in compiler
+	int32	debughist;	// -O flag in linker
+	int32	debugread;	// -W flag in linker
+	int32	debugvlog;	// -v flag in linker
+	int32	debugstack;	// -K flag in linker
+	int32	debugzerostack;	// -Z flag in linker
+	int32	debugdivmod;	// -M flag in 5l
+	int32	debugfloat;	// -F flag in 5l
+	int32	debugpcln;	// -O flag in linker
+	int32	flag_shared;	// -shared flag in linker
+	int32	iself;
+	Biobuf*	bso;	// for -v flag
+	char*	pathname;
+	int32	windows;
+
+	// hash table of all symbols
+	LSym*	hash[LINKHASH];
+	LSym*	allsym;
+	int32	nsymbol;
+
+	// file-line history
+	Hist*	hist;
+	Hist*	ehist;
+	
+	// all programs
+	Plist*	plist;
+	Plist*	plast;
+	
+	// code generation
+	LSym*	sym_div;
+	LSym*	sym_divu;
+	LSym*	sym_mod;
+	LSym*	sym_modu;
+	LSym*	symmorestack[10];
+	LSym*	gmsym;
+	LSym*	plan9tos;
+	Prog*	curp;
+	Prog*	printp;
+	Prog*	blitrl;
+	Prog*	elitrl;
+	int	rexflag;
+	int	asmode;
+	uchar*	andptr;
+	uchar	and[100];
+	int32	instoffset;
+	int32	autosize;
+	int32	armsize;
+
+	// for reading input files (during linker)
+	vlong	pc;
+	char**	libdir;
+	int32	nlibdir;
+	int32	maxlibdir;
+	Library*	library;
+	int	libraryp;
+	int	nlibrary;
+	int	tlsoffset;
+	void	(*diag)(char*, ...);
+	void	(*dwarfaddfrag)(int, char*);
+	LSym*	histfrog[LinkMaxHist];
+	int	histfrogp;
+	int	histgen;
+	Auto*	curauto;
+	Auto*	curhist;
+	LSym*	cursym;
+	int	version;
+	LSym*	textp;
+	LSym*	etextp;
+	Hist2*	histcopy;
+	Hist2*	hist2;
+	int32	nhist2;
+	int32	maxhist2;
+	int32	histdepth;
+	int32	nhistfile;
+	LSym*	filesyms;
+};
+
+// LinkArch is the definition of a single architecture.
+struct LinkArch
+{
+	char*	name; // "arm", "amd64", and so on
+
+	void	(*addstacksplit)(Link*, LSym*);
+	void	(*assemble)(Link*, LSym*);
+	int	(*datasize)(Prog*);
+	void	(*follow)(Link*, LSym*);
+	int	(*iscall)(Prog*);
+	int	(*isdata)(Prog*);
+	void	(*ldobj)(Link*, Biobuf*, char*, int64, char*);
+	void	(*nopout)(Prog*);
+	Prog*	(*prg)(void);
+	void	(*progedit)(Link*, Prog*);
+	void	(*settextflag)(Prog*, int);
+	int	(*symtype)(Addr*);
+	int	(*textflag)(Prog*);
+	void	(*zfile)(Biobuf*, char*, int);
+	void	(*zhist)(Biobuf*, int, vlong);
+	void	(*zprog)(Link*, Biobuf*, Prog*, int, int, int, int);
+	void (*zname)(Biobuf*, LSym*, int);
+
+	int	minlc;
+	int	ptrsize;
+	
+	// TODO: Give these the same values on all systems.
+	int	D_ADDR;
+	int	D_BRANCH;
+	int	D_CONST;
+	int	D_EXTERN;
+	int	D_FCONST;
+	int	D_NONE;
+	int	D_PCREL;
+	int	D_SCONST;
+	int	D_SIZE;
+
+	int	ACALL;
+	int	AFUNCDATA;
+	int	AJMP;
+	int	ANOP;
+	int	APCDATA;
+	int	ARET;
+	int	ATEXT;
+	int	AUSEFIELD;
+};
+
+/* executable header types */
+enum {
+	Hunknown = 0,
+	Hdarwin,
+	Hdragonfly,
+	Helf,
+	Hfreebsd,
+	Hlinux,
+	Hnetbsd,
+	Hopenbsd,
+	Hplan9,
+	Hwindows,
+};
+
+enum
+{
+	LinkAuto = 0,
+	LinkInternal,
+	LinkExternal,
+};
+
+extern	uchar	fnuxi8[8];
+extern	uchar	fnuxi4[4];
+extern	uchar	inuxi1[1];
+extern	uchar	inuxi2[2];
+extern	uchar	inuxi4[4];
+extern	uchar	inuxi8[8];
+
+// asm5.c
+void	span5(Link *ctxt, LSym *s);
+
+// asm6.c
+void	span6(Link *ctxt, LSym *s);
+
+// asm8.c
+void	span8(Link *ctxt, LSym *s);
+
+// data.c
+vlong	addaddr(Link *ctxt, LSym *s, LSym *t);
+vlong	addaddrplus(Link *ctxt, LSym *s, LSym *t, vlong add);
+vlong	addaddrplus4(Link *ctxt, LSym *s, LSym *t, vlong add);
+vlong	addpcrelplus(Link *ctxt, LSym *s, LSym *t, vlong add);
+Reloc*	addrel(LSym *s);
+vlong	addsize(Link *ctxt, LSym *s, LSym *t);
+vlong	adduint16(Link *ctxt, LSym *s, uint16 v);
+vlong	adduint32(Link *ctxt, LSym *s, uint32 v);
+vlong	adduint64(Link *ctxt, LSym *s, uint64 v);
+vlong	adduint8(Link *ctxt, LSym *s, uint8 v);
+vlong	adduintxx(Link *ctxt, LSym *s, uint64 v, int wid);
+void	mangle(char *file);
+void	savedata(Link *ctxt, LSym *s, Prog *p, char *pn);
+vlong	setaddr(Link *ctxt, LSym *s, vlong off, LSym *t);
+vlong	setaddrplus(Link *ctxt, LSym *s, vlong off, LSym *t, vlong add);
+vlong	setuint16(Link *ctxt, LSym *s, vlong r, uint16 v);
+vlong	setuint32(Link *ctxt, LSym *s, vlong r, uint32 v);
+vlong	setuint64(Link *ctxt, LSym *s, vlong r, uint64 v);
+vlong	setuint8(Link *ctxt, LSym *s, vlong r, uint8 v);
+vlong	setuintxx(Link *ctxt, LSym *s, vlong off, uint64 v, vlong wid);
+void	symgrow(Link *ctxt, LSym *s, int32 siz);
+
+// go.c
+void*	emallocz(long n);
+void*	erealloc(void *p, long n);
+char*	estrdup(char *p);
+char*	expandpkg(char *t0, char *pkg);
+
+// ieee.c
+void	double2ieee(uint64 *ieee, double native);
+
+// ld.c
+void	addhist(Link *ctxt, int32 line, int type);
+void	addlib(Link *ctxt, char *src, char *obj);
+void	addlibpath(Link *ctxt, char *srcref, char *objref, char *file, char *pkg);
+void	collapsefrog(Link *ctxt, LSym *s);
+void	copyhistfrog(Link *ctxt, char *buf, int nbuf);
+int	find1(int32 l, int c);
+Hist2*	gethist(Link *ctxt);
+void	linkgetline(Link *ctxt, Hist2 *h, int32 line, LSym **f, int32 *l);
+void	histtoauto(Link *ctxt);
+void	mkfwd(LSym*);
+void	nuxiinit(void);
+void	savehist(Link *ctxt, int32 line, int32 off);
+Prog*	copyp(Link*, Prog*);
+Prog*	appendp(Link*, Prog*);
+vlong	atolwhex(char*);
+
+// obj.c
+int	linklinefmt(Link *ctxt, Fmt *fp);
+void	linklinehist(Link *ctxt, int lineno, char *f, int offset);
+Plist*	linknewplist(Link *ctxt);
+void	linkouthist(Link *ctxt, Biobuf *b);
+void	linkprfile(Link *ctxt, int32 l);
+void	linkwritefuncs(Link *ctxt, Biobuf *b);
+
+// pass.c
+Prog*	brchain(Link *ctxt, Prog *p);
+Prog*	brloop(Link *ctxt, Prog *p);
+void	linkpatch(Link *ctxt, LSym *sym);
+
+// pcln.c
+void	linkpcln(Link*, LSym*);
+
+// rdobj5.c
+void	ldobj5(Link *ctxt, Biobuf *f, char *pkg, int64 len, char *pn);
+void	nopout5(Prog *p);
+
+// rdobj6.c
+void	ldobj6(Link *ctxt, Biobuf *f, char *pkg, int64 len, char *pn);
+void	nopout6(Prog *p);
+
+// rdobj8.c
+void	ldobj8(Link *ctxt, Biobuf *f, char *pkg, int64 len, char *pn);
+void	nopout8(Prog *p);
+
+// sym.c
+LSym*	linklookup(Link *ctxt, char *name, int v);
+Link*	linknew(LinkArch*);
+LSym*	linknewsym(Link *ctxt, char *symb, int v);
+LSym*	linkrlookup(Link *ctxt, char *name, int v);
+int	linksymfmt(Fmt *f);
+
+extern	char*	anames5[];
+extern	char*	anames6[];
+extern	char*	anames8[];
+
+extern	LinkArch	link386;
+extern	LinkArch	linkamd64;
+extern	LinkArch	linkarm;
 typedef s64int int64;
 typedef u64int uint64;
 
+typedef float float32;
+typedef double float64;
 
 #undef _NEEDUCHAR
 #undef _NEEDUSHORT

File src/cmd/5a/a.h

 // THE SOFTWARE.
 
 #include <bio.h>
+#include <link.h>
 #include "../5l/5.out.h"
-
+ 
 #ifndef	EXTERN
 #define	EXTERN	extern
 #endif
 #define	ungetc	ccungetc
 
 typedef	struct	Sym	Sym;
-typedef	struct	Gen	Gen;
 typedef	struct	Io	Io;
-typedef	struct	Hist	Hist;
 
 #define	MAXALIGN	7
 #define	FPCHIP		1
 };
 #define	I	((Io*)0)
 
-EXTERN	struct
-{
-	Sym*	sym;
-	short	type;
-} h[NSYM];
-
-struct	Gen
-{
-	Sym*	sym;
-	int32	offset;
-	int32	offset2;
-	short	type;
-	short	reg;
-	short	name;
-	double	dval;
-	char	sval[8];
-};
-
-struct	Hist
-{
-	Hist*	link;
-	char*	name;
-	int32	line;
-	int32	offset;
-};
-#define	H	((Hist*)0)
-
 enum
 {
 	CLAST,
 EXTERN	Sym*	hash[NHASH];
 EXTERN	char**	Dlist;
 EXTERN	int	nDlist;
-EXTERN	Hist*	ehist;
 EXTERN	int	newflag;
-EXTERN	Hist*	hist;
 EXTERN	char*	hunk;
 EXTERN	char**	include;
 EXTERN	Io*	iofree;
 EXTERN	int32	nhunk;
 EXTERN	int	ninclude;
 EXTERN	int32	nsymb;
-EXTERN	Gen	nullgen;
+EXTERN	Addr	nullgen;
 EXTERN	char*	outfile;
 EXTERN	int	pass;
-EXTERN	char*	pathname;
 EXTERN	int32	pc;
 EXTERN	int	peekc;
 EXTERN	int32	stmtline;
 EXTERN	char*	thestring;
 EXTERN	int32	thunk;
 EXTERN	Biobuf	obuf;
+EXTERN	Link*	ctxt;
 
 void*	alloc(int32);
 void*	allocn(void*, int32, int32);
 void	cinit(void);
 void	pinit(char*);
 void	cclean(void);
-int	isreg(Gen*);
-void	outcode(int, int, Gen*, int, Gen*);
-void	zname(char*, int, int);
-void	zaddr(Gen*, int);
-void	ieeedtod(Ieee*, double);
+int	isreg(Addr*);
+void	outcode(int, int, Addr*, int, Addr*);
 int	filbuf(void);
 Sym*	getsym(void);
 void	domacro(void);
 void	macprag(void);
 void	macif(int);
 void	macend(void);
-void	outhist(void);
 void	dodefine(char*);
 void	prfile(int32);
 void	linehist(char*, int);

File src/cmd/5a/a.y

 	int32	lval;
 	double	dval;
 	char	sval[8];
-	Gen	gen;
+	LAddr	addr;
 }
 %left	'|'
 %left	'^'
 %token	<sym>	LNAME LLAB LVAR
 %type	<lval>	con expr oexpr pointer offset sreg spreg creg
 %type	<lval>	rcon cond reglist
-%type	<gen>	gen rel reg regreg freg shift fcon frcon
-%type	<gen>	imm ximm name oreg ireg nireg ioreg imsr
+%type	<addr>	gen rel reg regreg freg shift fcon frcon
+%type	<addr>	imm ximm name oreg ireg nireg ioreg imsr
 %%
 prog:
 |	prog
  */
 |	LTYPE8 cond ioreg ',' '[' reglist ']'
 	{
-		Gen g;
+		LAddr g;
 
 		g = nullgen;
 		g.type = D_CONST;
 	}
 |	LTYPE8 cond '[' reglist ']' ',' ioreg
 	{
-		Gen g;
+		LAddr g;
 
 		g = nullgen;
 		g.type = D_CONST;
  */
 |	LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
 	{
-		Gen g;
+		LAddr g;
 
 		g = nullgen;
 		g.type = D_CONST;
 		if(pass == 2)
 			yyerror("undefined label: %s", $1->name);
 		$$.type = D_BRANCH;
-		$$.sym = $1;
 		$$.offset = $2;
 	}
 |	LLAB offset
 	{
 		$$ = nullgen;
 		$$.type = D_BRANCH;
-		$$.sym = $1;
 		$$.offset = $1->value + $2;
 	}
 
 	{
 		$$ = nullgen;
 		$$.type = D_SCONST;
-		memcpy($$.sval, $2, sizeof($$.sval));
+		memcpy($$.u.sval, $2, sizeof($$.u.sval));
 	}
 |	fcon
 
 	{
 		$$ = nullgen;
 		$$.type = D_FCONST;
-		$$.dval = $2;
+		$$.u.dval = $2;
 	}
 |	'$' '-' LFCONST
 	{
 		$$ = nullgen;
 		$$.type = D_FCONST;
-		$$.dval = -$3;
+		$$.u.dval = -$3;
 	}
 
 reglist:
 		$$ = nullgen;
 		$$.type = D_OREG;
 		$$.name = $3;
-		$$.sym = S;
+		$$.sym = nil;
 		$$.offset = $1;
 	}
 |	LNAME offset '(' pointer ')'
 		$$ = nullgen;
 		$$.type = D_OREG;
 		$$.name = $4;
-		$$.sym = $1;
+		$$.sym = linklookup(ctxt, $1->name, 0);
 		$$.offset = $2;
 	}
 |	LNAME '<' '>' offset '(' LSB ')'
 		$$ = nullgen;
 		$$.type = D_OREG;
 		$$.name = D_STATIC;
-		$$.sym = $1;
+		$$.sym = linklookup(ctxt, $1->name, 1);
 		$$.offset = $4;
 	}
 

File src/cmd/5a/lex.c

 
 	thechar = '5';
 	thestring = "arm";
+	ctxt = linknew(&linkarm);
+	ctxt->diag = yyerror;
 
 	ensuresymb(NSYMB);
 	memset(debug, 0, sizeof(debug));
 		p = ARGF();
 		setinclude(p);
 		break;
+
 	case 't':
 		thechar = 't';
 		thestring = "thumb";
 		break;
+
+	case 'S':
+		ctxt->debugasm++;
+		break;
 	} ARGEND
 	if(*argv == 0) {
 		print("usage: %ca [-options] file.s\n", thechar);
 		errorexit();
 	}
 	Binit(&obuf, of, OWRITE);
+	Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
+	Bprint(&obuf, "\n!\n");
 
-	pass = 1;
-	pinit(file);
-
-	Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
-
-	for(i=0; i<nDlist; i++)
-		dodefine(Dlist[i]);
-	yyparse();
-	if(nerrors) {
+	for(pass = 1; pass <= 2; pass++) {
+		pinit(file);
+		for(i=0; i<nDlist; i++)
+			dodefine(Dlist[i]);
+		yyparse();
 		cclean();
-		return nerrors;
+		if(nerrors)
+			return nerrors;
 	}
 
-	Bprint(&obuf, "\n!\n");
-
-	pass = 2;
-	outhist();
-	pinit(file);
-	for(i=0; i<nDlist; i++)
-		dodefine(Dlist[i]);
-	yyparse();
-	cclean();
-	return nerrors;
+	linkouthist(ctxt, &obuf);
+	linkwritefuncs(ctxt, &obuf);
+	Bflush(&obuf);
+	return 0;
 }
 
 struct
 	Sym *s;
 	int i;
 
-	nullgen.sym = S;
-	nullgen.offset = 0;
 	nullgen.type = D_NONE;
 	nullgen.name = D_NONE;
 	nullgen.reg = NREG;
-	if(FPCHIP)
-		nullgen.dval = 0;
-	for(i=0; i<sizeof(nullgen.sval); i++)
-		nullgen.sval[i] = 0;
 
 	nerrors = 0;
 	iostack = I;
 		s->type = itab[i].type;
 		s->value = itab[i].value;
 	}
-
-	pathname = allocn(pathname, 0, 100);
-	if(getwd(pathname, 99) == 0) {
-		pathname = allocn(pathname, 100, 900);
-		if(getwd(pathname, 999) == 0)
-			strcpy(pathname, "/???");
-	}
 }
 
 void
 }
 
 int
-isreg(Gen *g)
+isreg(Addr *g)
 {
 
 	USED(g);
 void
 cclean(void)
 {
-
 	outcode(AEND, Always, &nullgen, NREG, &nullgen);
-	Bflush(&obuf);
-}
-
-void
-zname(char *n, int t, int s)
-{
-
-	BPUTC(&obuf, ANAME);
-	BPUTC(&obuf, t);	/* type */
-	BPUTC(&obuf, s);	/* sym */
-	while(*n) {
-		BPUTC(&obuf, *n);
-		n++;
-	}
-	BPUTC(&obuf, 0);
-}
-
-void
-zaddr(Gen *a, int s)
-{
-	int32 l;
-	int i;
-	char *n;
-	Ieee e;
-
-	BPUTC(&obuf, a->type);
-	BPUTC(&obuf, a->reg);
-	BPUTC(&obuf, s);
-	BPUTC(&obuf, a->name);
-	BPUTC(&obuf, 0);
-	switch(a->type) {
-	default:
-		print("unknown type %d\n", a->type);
-		exits("arg");
-
-	case D_NONE:
-	case D_REG:
-	case D_FREG:
-	case D_PSR:
-	case D_FPCR:
-		break;
-
-	case D_REGREG:
-	case D_REGREG2:
-		BPUTC(&obuf, a->offset);
-		break;
-
-	case D_CONST2:
-		l = a->offset2;
-		BPUTLE4(&obuf, l);
-		// fall through
-	case D_OREG:
-	case D_CONST:
-	case D_BRANCH:
-	case D_SHIFT:
-		l = a->offset;
-		BPUTLE4(&obuf, l);
-		break;
-
-	case D_SCONST:
-		n = a->sval;
-		for(i=0; i<NSNAME; i++) {
-			BPUTC(&obuf, *n);
-			n++;
-		}
-		break;
-
-	case D_FCONST:
-		ieeedtod(&e, a->dval);
-		BPUTLE4(&obuf, e.l);
-		BPUTLE4(&obuf, e.h);
-		break;
-	}
 }
 
 static int bcode[] =
 	ANOP,
 };
 
+static Prog *lastpc;
+
 void
-outcode(int a, int scond, Gen *g1, int reg, Gen *g2)
+outcode(int a, int scond, Addr *g1, int reg, Addr *g2)
 {
-	int sf, st, t;
-	Sym *s;
+	Prog *p;
+	Plist *pl;
 
 	/* hack to make B.NE etc. work: turn it into the corresponding conditional */
 	if(a == AB){
 
 	if(pass == 1)
 		goto out;
-jackpot:
-	sf = 0;
-	s = g1->sym;
-	while(s != S) {
-		sf = s->sym;
-		if(sf < 0 || sf >= NSYM)
-			sf = 0;
-		t = g1->name;
-		if(h[sf].type == t)
-		if(h[sf].sym == s)
-			break;
-		zname(s->name, t, sym);
-		s->sym = sym;
-		h[sym].sym = s;
-		h[sym].type = t;
-		sf = sym;
-		sym++;
-		if(sym >= NSYM)
-			sym = 1;
-		break;
-	}
-	st = 0;
-	s = g2->sym;
-	while(s != S) {
-		st = s->sym;
-		if(st < 0 || st >= NSYM)
-			st = 0;
-		t = g2->name;
-		if(h[st].type == t)
-		if(h[st].sym == s)
-			break;
-		zname(s->name, t, sym);
-		s->sym = sym;
-		h[sym].sym = s;
-		h[sym].type = t;
-		st = sym;
-		sym++;
-		if(sym >= NSYM)
-			sym = 1;
-		if(st == sf)
-			goto jackpot;
-		break;
-	}
-	BPUTC(&obuf, a);
-	BPUTC(&obuf, scond);
-	BPUTC(&obuf, reg);
-	BPUTLE4(&obuf, stmtline);
-	zaddr(g1, sf);
-	zaddr(g2, st);
+	
+	p = malloc(sizeof *p);
+	memset(p, 0, sizeof *p);
+	p->as = a;
+	p->lineno = stmtline;
+	p->scond = scond;
+	p->from = *g1;
+	p->reg = reg;
+	p->to = *g2;
+
+	if(lastpc == nil) {
+		pl = linknewplist(ctxt);
+		pl->firstpc = p;
+	} else
+		lastpc->link = p;
+	lastpc = p;	
 
 out:
 	if(a != AGLOBL && a != ADATA)
 		pc++;
 }
 
-void
-outhist(void)
-{
-	Gen g;
-	Hist *h;
-	char *p, *q, *op, c;
-	int n;
- 	char *tofree;
- 	static int first = 1;
- 	static char *goroot, *goroot_final;
- 
- 	if(first) {
- 		// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
- 		first = 0;
- 		goroot = getenv("GOROOT");
- 		goroot_final = getenv("GOROOT_FINAL");
- 		if(goroot == nil)
- 			goroot = "";
- 		if(goroot_final == nil)
- 			goroot_final = goroot;
- 		if(strcmp(goroot, goroot_final) == 0) {
- 			goroot = nil;
- 			goroot_final = nil;
- 		}
- 	}
- 
- 	tofree = nil;
-	g = nullgen;
-	c = '/';
-	for(h = hist; h != H; h = h->link) {
-		p = h->name;
- 		if(p != nil && goroot != nil) {
- 			n = strlen(goroot);
- 			if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
- 				tofree = smprint("%s%s", goroot_final, p+n);
- 				p = tofree;
- 			}
- 		}
-		op = 0;
-		if(systemtype(Windows) && p && p[1] == ':'){
-			c = p[2];
-		} else if(p && p[0] != c && h->offset == 0 && pathname){
-			if(systemtype(Windows) && pathname[1] == ':') {
-				op = p;
-				p = pathname;
-				c = p[2];
-			} else if(pathname[0] == c){
-				op = p;
-				p = pathname;
-			}
-		}
-		while(p) {
-			q = strchr(p, c);
-			if(q) {
-				n = q-p;
-				if(n == 0){
-					n = 1;	/* leading "/" */
-					*p = '/';	/* don't emit "\" on windows */
-				}
-				q++;
-			} else {
-				n = strlen(p);
-				q = 0;
-			}
-			if(n) {
-				BPUTC(&obuf, ANAME);
-				BPUTC(&obuf, D_FILE);	/* type */
-				BPUTC(&obuf, 1);	/* sym */
-				BPUTC(&obuf, '<');
-				Bwrite(&obuf, p, n);
-				BPUTC(&obuf, 0);
-			}
-			p = q;
-			if(p == 0 && op) {
-				p = op;
-				op = 0;
-			}
-		}
-		g.offset = h->offset;
-
-		BPUTC(&obuf, AHISTORY);
-		BPUTC(&obuf, Always);
-		BPUTC(&obuf, 0);
-		BPUTLE4(&obuf, h->line);
-		zaddr(&nullgen, 0);
-		zaddr(&g, 0);
-
-		if(tofree) {
-			free(tofree);
-			tofree = nil;
-		}
-	}
-}
-
 #include "../cc/lexbody"
 #include "../cc/macbody"

File src/cmd/5a/y.tab.c

-/* A Bison parser, made by GNU Bison 2.5.  */
+/* A Bison parser, made by GNU Bison 2.3.  */
 
-/* Bison implementation for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
-   
-   This program is free software: you can redistribute it and/or modify
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-   
+   the Free Software Foundation; either version 2, 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 General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.5"
+#define YYBISON_VERSION "2.3"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 /* Pure parsers.  */
 #define YYPURE 0
 
-/* Push parsers.  */
-#define YYPUSH 0
-
-/* Pull parsers.  */
-#define YYPULL 1
-
 /* Using locations.  */
 #define YYLSP_NEEDED 0
 
 
 
-/* Copy the first part of user declarations.  */
-
-/* Line 268 of yacc.c  */
-#line 31 "a.y"
-
-#include <u.h>
-#include <stdio.h>	/* if we don't, bison will, and a.h re-#defines getc */
-#include <libc.h>
-#include "a.h"
-#include "../../pkg/runtime/funcdata.h"
-
-
-/* Line 268 of yacc.c  */
-#line 80 "y.tab.c"
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-
 /* Tokens.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
 
 
 
+/* Copy the first part of user declarations.  */
+#line 31 "a.y"
+
+#include <u.h>
+#include <stdio.h>	/* if we don't, bison will, and a.h re-#defines getc */
+#include <libc.h>
+#include "a.h"
+#include "../../pkg/runtime/funcdata.h"
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
+#line 39 "a.y"
 {
-
-/* Line 293 of yacc.c  */
-#line 39 "a.y"
-
 	Sym	*sym;
 	int32	lval;
 	double	dval;
 	char	sval[8];
-	Gen	gen;
-
-
-
-/* Line 293 of yacc.c  */
-#line 226 "y.tab.c"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
+	Addr	addr;
+}
+/* Line 193 of yacc.c.  */
+#line 212 "y.tab.c"
+	YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
 
+
 /* Copy the second part of user declarations.  */
 
 
-/* Line 343 of yacc.c  */
-#line 238 "y.tab.c"
+/* Line 216 of yacc.c.  */
+#line 225 "y.tab.c"
 
 #ifdef short
 # undef short
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static int
-YYID (int yyi)
+YYID (int i)
 #else
 static int
-YYID (yyi)
-    int yyi;
+YYID (i)
+    int i;
 #endif
 {
-  return yyi;
+  return i;
 }
 #endif
 
 #    define alloca _alloca
 #   else
 #    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef EXIT_SUCCESS
-#      define EXIT_SUCCESS 0
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
 #     endif
 #    endif
 #   endif
 #  ifndef YYSTACK_ALLOC_MAXIMUM
 #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
 #  endif
-#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+#  if (defined __cplusplus && ! defined _STDLIB_H \
        && ! ((defined YYMALLOC || defined malloc) \
 	     && (defined YYFREE || defined free)))
 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef EXIT_SUCCESS
-#    define EXIT_SUCCESS 0
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
 #   endif
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
-#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
 #  ifndef YYFREE
 #   define YYFREE free
-#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
 {
-  yytype_int16 yyss_alloc;
-  YYSTYPE yyvs_alloc;
-};
+  yytype_int16 yyss;
+  YYSTYPE yyvs;
+  };
 
 /* The size of the maximum gap between one aligned stack and the next.  */
 # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
      ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
       + YYSTACK_GAP_MAXIMUM)
 
-# define YYCOPY_NEEDED 1
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
-	Stack = &yyptr->Stack_alloc;					\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (YYID (0))
-
-#endif
-
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
 /* Copy COUNT objects from FROM to TO.  The source and destination do
    not overlap.  */
 # ifndef YYCOPY
       while (YYID (0))
 #  endif
 # endif
-#endif /* !YYCOPY_NEEDED */
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (YYID (0))
+
+#endif
 
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  2
      141,   148,   155,   162,   169,   176,   185,   197,   201,   205,
      212,   219,   225,   231,   240,   247,   254,   261,   265,   269,
      273,   280,   302,   310,   319,   326,   335,   346,   352,   355,
-     359,   364,   365,   368,   374,   383,   391,   397,   402,   407,
-     413,   416,   422,   430,   434,   443,   449,   450,   451,   452,
-     457,   463,   469,   475,   476,   479,   480,   488,   497,   498,
-     507,   508,   514,   517,   518,   519,   521,   529,   537,   546,
-     552,   558,   564,   572,   578,   586,   587,   591,   599,   600,
-     606,   607,   615,   616,   619,   625,   633,   641,   649,   659,
-     662,   666,   672,   673,   674,   677,   678,   682,   686,   690,
-     694,   700,   703,   709,   710,   714,   718,   722,   726,   730,
-     734,   738,   742,   746
+     359,   364,   365,   368,   374,   382,   389,   395,   400,   405,
+     411,   414,   420,   428,   432,   441,   447,   448,   449,   450,
+     455,   461,   467,   473,   474,   477,   478,   486,   495,   496,
+     505,   506,   512,   515,   516,   517,   519,   527,   535,   544,
+     550,   556,   562,   570,   576,   584,   585,   589,   597,   598,
+     604,   605,   613,   614,   617,   623,   631,   639,   647,   657,
+     660,   664,   670,   671,   672,   675,   676,   680,   684,   688,
+     692,   698,   701,   707,   708,   712,   716,   720,   724,   728,
+     732,   736,   740,   744
 };
 #endif
 
   "LSP", "LSB", "LFP", "LPC", "LTYPEX", "LTYPEPC", "LTYPEF", "LR", "LREG",
   "LF", "LFREG", "LC", "LCREG", "LPSR", "LFCR", "LCOND", "LS", "LAT",
   "LFCONST", "LSCONST", "LNAME", "LLAB", "LVAR", "':'", "'='", "';'",
-  "','", "'['", "']'", "'('", "')'", "'$'", "'~'", "$accept", "prog",
-  "$@1", "line", "$@2", "$@3", "inst", "cond", "comma", "rel", "ximm",
-  "fcon", "reglist", "gen", "nireg", "ireg", "ioreg", "oreg", "imsr",
-  "imm", "reg", "regreg", "shift", "rcon", "sreg", "spreg", "creg",
-  "frcon", "freg", "name", "offset", "pointer", "con", "oexpr", "expr", 0
+  "','", "'['", "']'", "'('", "')'", "'$'", "'~'", "$accept", "prog", "@1",
+  "line", "@2", "@3", "inst", "cond", "comma", "rel", "ximm", "fcon",
+  "reglist", "gen", "nireg", "ireg", "ioreg", "oreg", "imsr", "imm", "reg",
+  "regreg", "shift", "rcon", "sreg", "spreg", "creg", "frcon", "freg",
+  "name", "offset", "pointer", "con", "oexpr", "expr", 0
 };
 #endif
 
        4,     3,     3,     3
 };
 
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
-   Performed when YYTABLE doesn't specify something else to do.  Zero
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If YYTABLE_NINF, syntax error.  */
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
 #define YYTABLE_NINF -64
 static const yytype_int16 yytable[] =
 {
      202,   203,   204,   198,   199,   200,   201,   202,   203,   204
 };
 
-#define yypact_value_is_default(yystate) \
-  ((yystate) == (-128))
-
-#define yytable_value_is_error(yytable_value) \
-  YYID (0)
-
 static const yytype_int16 yycheck[] =
 {
       28,    29,    45,    60,     0,   132,    27,    15,    16,    37,
 
 /* Like YYERROR except do call yyerror.  This remains here temporarily
    to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  However,
-   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
-   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
-   discussed.  */
+   Once GCC version 2 has supplanted version 1, this can go.  */
 
 #define YYFAIL		goto yyerrlab
-#if defined YYFAIL
-  /* This is here to suppress warnings from the GCC cpp's
-     -Wunused-macros.  Normally we don't worry about that warning, but
-     some users do, and we want to make it easy for users to remove
-     YYFAIL uses, which will produce warnings from Bison 2.5.  */
-#endif
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
     {								\
       yychar = (Token);						\
       yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
       YYPOPSTACK (1);						\
       goto yybackup;						\
     }								\
 #endif
 
 
-/* This macro is provided for backward compatibility. */
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)			\
+     fprintf (File, "%d.%d-%d.%d",			\
+	      (Loc).first_line, (Loc).first_column,	\
+	      (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
 #endif
 
 
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
 #else
 static void
-yy_stack_print (yybottom, yytop)
-    yytype_int16 *yybottom;
-    yytype_int16 *yytop;
+yy_stack_print (bottom, top)
+    yytype_int16 *bottom;
+    yytype_int16 *top;
 #endif
 {
   YYFPRINTF (stderr, "Stack now");
-  for (; yybottom <= yytop; yybottom++)
-    {
-      int yybot = *yybottom;
-      YYFPRINTF (stderr, " %d", yybot);
-    }
+  for (; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
   YYFPRINTF (stderr, "\n");
 }
 
   /* The symbols being reduced.  */
   for (yyi = 0; yyi < yynrhs; yyi++)
     {
-      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      fprintf (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
 		       &(yyvsp[(yyi + 1) - (yynrhs)])
 		       		       );
-      YYFPRINTF (stderr, "\n");
+      fprintf (stderr, "\n");
     }
 }
 
 # define YYMAXDEPTH 10000
 #endif
 
+
 
 #if YYERROR_VERBOSE
 
 }
 # endif
 
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
-   about the unexpected token YYTOKEN for the state stack whose top is
-   YYSSP.
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
 
-   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
-   not large enough to hold the message.  In that case, also set
-   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
-   required number of bytes is too large to store.  */
-static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
-                yytype_int16 *yyssp, int yytoken)
-{
-  YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
-  YYSIZE_T yysize = yysize0;
-  YYSIZE_T yysize1;
-  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-  /* Internationalized format string. */
-  const char *yyformat = 0;
-  /* Arguments of yyformat. */
-  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-  /* Number of reported tokens (one for the "unexpected", one per
-     "expected"). */
-  int yycount = 0;
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
 
-  /* There are many possibilities here to consider:
-     - Assume YYFAIL is not used.  It's too flawed to consider.  See
-       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
-       for details.  YYERROR is fine as it does not invoke this
-       function.
-     - If this state is a consistent state with a default action, then
-       the only way this function was invoked is if the default action
-       is an error action.  In that case, don't check for expected
-       tokens because there are none.
-     - The only way there can be no lookahead present (in yychar) is if
-       this state is a consistent state with a default action.  Thus,
-       detecting the absence of a lookahead is sufficient to determine
-       that there is no unexpected or expected token to report.  In that
-       case, just report a simple "syntax error".
-     - Don't assume there isn't a lookahead just because this state is a
-       consistent state with a default action.  There might have been a
-       previous inconsistent state, consistent state with a non-default
-       action, or user semantic action that manipulated yychar.
-     - Of course, the expected token list depends on states to have
-       correct lookahead information, and it depends on the parser not
-       to perform extra reductions after fetching a lookahead from the
-       scanner and before detecting a syntax error.  Thus, state merging
-       (from LALR or IELR) and default reductions corrupt the expected
-       token list.  However, the list is correct for canonical LR with
-       one exception: it will still contain any token that will not be
-       accepted due to an error action in a later state.
-  */
-  if (yytoken != YYEMPTY)
-    {
-      int yyn = yypact[*yyssp];
-      yyarg[yycount++] = yytname[yytoken];
-      if (!yypact_value_is_default (yyn))
-        {
-          /* Start YYX at -YYN if negative to avoid negative indexes in
-             YYCHECK.  In other words, skip the first -YYN actions for
-             this state because they are default actions.  */
-          int yyxbegin = yyn < 0 ? -yyn : 0;
-          /* Stay within bounds of both yycheck and yytname.  */
-          int yychecklim = YYLAST - yyn + 1;
-          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-          int yyx;
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+	 constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+		    + sizeof yyexpecting - 1
+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+		       * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
 
-          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
-                && !yytable_value_is_error (yytable[yyx + yyn]))
-              {
-                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-                  {
-                    yycount = 1;
-                    yysize = yysize0;
-                    break;
-                  }
-                yyarg[yycount++] = yytname[yyx];
-                yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-                if (! (yysize <= yysize1
-                       && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-                  return 2;
-                yysize = yysize1;
-              }
-        }
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+	 YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	  {
+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+	      {
+		yycount = 1;
+		yysize = yysize0;
+		yyformat[sizeof yyunexpected - 1] = '\0';
+		break;
+	      }
+	    yyarg[yycount++] = yytname[yyx];
+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+	    yysize_overflow |= (yysize1 < yysize);
+	    yysize = yysize1;
+	    yyfmt = yystpcpy (yyfmt, yyprefix);
+	    yyprefix = yyor;
+	  }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+	return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+	{
+	  /* Avoid sprintf, as that infringes on the user's name space.
+	     Don't have undefined behavior even if the translation
+	     produced a string with the wrong number of "%s"s.  */
+	  char *yyp = yyresult;
+	  int yyi = 0;
+	  while ((*yyp = *yyf) != '\0')
+	    {
+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		{
+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+		  yyf += 2;
+		}
+	      else
+		{
+		  yyp++;
+		  yyf++;
+		}
+	    }
+	}
+      return yysize;
     }
-
-  switch (yycount)
-    {
-# define YYCASE_(N, S)                      \
-      case N:                               \
-        yyformat = S;                       \
-      break
-      YYCASE_(0, YY_("syntax error"));
-      YYCASE_(1, YY_("syntax error, unexpected %s"));
-      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
-      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
-      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
-      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
-    }
-
-  yysize1 = yysize + yystrlen (yyformat);
-  if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-    return 2;
-  yysize = yysize1;
-
-  if (*yymsg_alloc < yysize)
-    {
-      *yymsg_alloc = 2 * yysize;
-      if (! (yysize <= *yymsg_alloc
-             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
-        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
-      return 1;
-    }
-
-  /* Avoid sprintf, as that infringes on the user's name space.
-     Don't have undefined behavior even if the translation
-     produced a string with the wrong number of "%s"s.  */
-  {
-    char *yyp = *yymsg;
-    int yyi = 0;
-    while ((*yyp = *yyformat) != '\0')
-      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
-        {
-          yyp += yytnamerr (yyp, yyarg[yyi++]);
-          yyformat += 2;
-        }
-      else
-        {
-          yyp++;
-          yyformat++;
-        }
-  }
-  return 0;
 }
 #endif /* YYERROR_VERBOSE */
+
 
 /*-----------------------------------------------.
 | Release the memory associated to this symbol.  |
 	break;
     }
 }
-
+
 
 /* Prevent warnings from -Wmissing-prototypes.  */
+
 #ifdef YYPARSE_PARAM
 #if defined __STDC__ || defined __cplusplus
 int yyparse (void *YYPARSE_PARAM);
 #endif /* ! YYPARSE_PARAM */
 
 
-/* The lookahead symbol.  */
+
+/* The look-ahead symbol.  */
 int yychar;
 
-/* The semantic value of the lookahead symbol.  */
+/* The semantic value of the look-ahead symbol.  */
 YYSTYPE yylval;
 
 /* Number of syntax errors so far.  */
 int yynerrs;
 
 
+
 /*----------.
 | yyparse.  |
 `----------*/
 #endif
 #endif
 {
-    int yystate;
-    /* Number of tokens to shift before error messages enabled.  */
-    int yyerrstatus;
-
-    /* The stacks and their tools:
-       `yyss': related to states.
-       `yyvs': related to semantic values.
-
-       Refer to the stacks thru separate pointers, to allow yyoverflow
-       to reallocate them elsewhere.  */
-
-    /* The state stack.  */
-    yytype_int16 yyssa[YYINITDEPTH];
-    yytype_int16 *yyss;
-    yytype_int16 *yyssp;
-
-    /* The semantic value stack.  */
-    YYSTYPE yyvsa[YYINITDEPTH];
-    YYSTYPE *yyvs;
-    YYSTYPE *yyvsp;
-
-    YYSIZE_T yystacksize;
-
+  
+  int yystate;
   int yyn;
   int yyresult;
-  /* Lookahead token as an internal (translated) token number.  */
-  int yytoken;
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Look-ahead token as an internal (translated) token number.  */
+  int yytoken = 0;
 #if YYERROR_VERBOSE
   /* Buffer for error messages, and its allocated size.  */
   char yymsgbuf[128];
   YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
 #endif
 
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  yytype_int16 yyssa[YYINITDEPTH];
+  yytype_int16 *yyss = yyssa;
+  yytype_int16 *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  YYSTYPE *yyvsp;
+
+
+
 #define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
 
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
   /* The number of symbols on the RHS of the reduced rule.
      Keep to zero when no symbol should be popped.  */
   int yylen = 0;
 
-  yytoken = 0;
-  yyss = yyssa;
-  yyvs = yyvsa;
-  yystacksize = YYINITDEPTH;
-
   YYDPRINTF ((stderr, "Starting parse\n"));