github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/5a/lex.c (about)

     1  // Inferno utils/5a/lex.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/5a/lex.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.	All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  #define	EXTERN
    32  #include <u.h>
    33  #include <libc.h>
    34  #include "a.h"
    35  #include "y.tab.h"
    36  
    37  enum
    38  {
    39  	Plan9	= 1<<0,
    40  	Unix	= 1<<1,
    41  	Windows	= 1<<2,
    42  };
    43  
    44  int
    45  systemtype(int sys)
    46  {
    47  #ifdef _WIN32
    48  	return sys&Windows;
    49  #else
    50  	return sys&Plan9;
    51  #endif
    52  }
    53  
    54  void
    55  main(int argc, char *argv[])
    56  {
    57  	char *p;
    58  	int c;
    59  
    60  	thechar = '5';
    61  	thestring = "arm";
    62  
    63  	ensuresymb(NSYMB);
    64  	memset(debug, 0, sizeof(debug));
    65  	cinit();
    66  	outfile = 0;
    67  	setinclude(".");
    68  	ARGBEGIN {
    69  	default:
    70  		c = ARGC();
    71  		if(c >= 0 || c < sizeof(debug))
    72  			debug[c] = 1;
    73  		break;
    74  
    75  	case 'o':
    76  		outfile = ARGF();
    77  		break;
    78  
    79  	case 'D':
    80  		p = ARGF();
    81  		if(p) {
    82  			if (nDlist%8 == 0) 
    83  				Dlist = allocn(Dlist, nDlist*sizeof(char *), 
    84  					8*sizeof(char *));
    85  			Dlist[nDlist++] = p;
    86  		}
    87  		break;
    88  
    89  	case 'I':
    90  		p = ARGF();
    91  		setinclude(p);
    92  		break;
    93  	case 't':
    94  		thechar = 't';
    95  		thestring = "thumb";
    96  		break;
    97  	} ARGEND
    98  	if(*argv == 0) {
    99  		print("usage: %ca [-options] file.s\n", thechar);
   100  		errorexit();
   101  	}
   102  	if(argc > 1){
   103  		print("can't assemble multiple files\n");
   104  		errorexit();
   105  	}
   106  	if(assemble(argv[0]))
   107  		errorexit();
   108  	exits(0);
   109  }
   110  
   111  int
   112  assemble(char *file)
   113  {
   114  	char *ofile, *p;
   115  	int i, of;
   116  
   117  	ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar)
   118  	strcpy(ofile, file);
   119  	p = utfrrune(ofile, '/');
   120  	if(p) {
   121  		include[0] = ofile;
   122  		*p++ = 0;
   123  	} else
   124  		p = ofile;
   125  	if(outfile == 0) {
   126  		outfile = p;
   127  		if(outfile){
   128  			p = utfrrune(outfile, '.');
   129  			if(p)
   130  				if(p[1] == 's' && p[2] == 0)
   131  					p[0] = 0;
   132  			p = utfrune(outfile, 0);
   133  			p[0] = '.';
   134  			p[1] = thechar;
   135  			p[2] = 0;
   136  		} else
   137  			outfile = "/dev/null";
   138  	}
   139  
   140  	of = create(outfile, OWRITE, 0664);
   141  	if(of < 0) {
   142  		yyerror("%ca: cannot create %s", thechar, outfile);
   143  		errorexit();
   144  	}
   145  	Binit(&obuf, of, OWRITE);
   146  
   147  	pass = 1;
   148  	pinit(file);
   149  
   150  	Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
   151  
   152  	for(i=0; i<nDlist; i++)
   153  		dodefine(Dlist[i]);
   154  	yyparse();
   155  	if(nerrors) {
   156  		cclean();
   157  		return nerrors;
   158  	}
   159  
   160  	Bprint(&obuf, "\n!\n");
   161  
   162  	pass = 2;
   163  	outhist();
   164  	pinit(file);
   165  	for(i=0; i<nDlist; i++)
   166  		dodefine(Dlist[i]);
   167  	yyparse();
   168  	cclean();
   169  	return nerrors;
   170  }
   171  
   172  struct
   173  {
   174  	char	*name;
   175  	ushort	type;
   176  	ushort	value;
   177  } itab[] =
   178  {
   179  	"SP",		LSP,	D_AUTO,
   180  	"SB",		LSB,	D_EXTERN,
   181  	"FP",		LFP,	D_PARAM,
   182  	"PC",		LPC,	D_BRANCH,
   183  
   184  	"R",		LR,	0,
   185  	"R0",		LREG,	0,
   186  	"R1",		LREG,	1,
   187  	"R2",		LREG,	2,
   188  	"R3",		LREG,	3,
   189  	"R4",		LREG,	4,
   190  	"R5",		LREG,	5,
   191  	"R6",		LREG,	6,
   192  	"R7",		LREG,	7,
   193  	"R8",		LREG,	8,
   194  	"R9",		LREG,	9,
   195  	"R10",		LREG,	10,
   196  	"R11",		LREG,	11,
   197  	"R12",		LREG,	12,
   198  	"R13",		LREG,	13,
   199  	"R14",		LREG,	14,
   200  	"R15",		LREG,	15,
   201  
   202  	"F",		LF,	0,
   203  
   204  	"F0",		LFREG,	0,
   205  	"F1",		LFREG,	1,
   206  	"F2",		LFREG,	2,
   207  	"F3",		LFREG,	3,
   208  	"F4",		LFREG,	4,
   209  	"F5",		LFREG,	5,
   210  	"F6",		LFREG,	6,
   211  	"F7",		LFREG,	7,
   212  	"F8",		LFREG,	8,
   213  	"F9",		LFREG,	9,
   214  	"F10",		LFREG,	10,
   215  	"F11",		LFREG,	11,
   216  	"F12",		LFREG,	12,
   217  	"F13",		LFREG,	13,
   218  	"F14",		LFREG,	14,
   219  	"F15",		LFREG,	15,
   220  
   221  	"C",		LC,	0,
   222  
   223  	"C0",		LCREG,	0,
   224  	"C1",		LCREG,	1,
   225  	"C2",		LCREG,	2,
   226  	"C3",		LCREG,	3,
   227  	"C4",		LCREG,	4,
   228  	"C5",		LCREG,	5,
   229  	"C6",		LCREG,	6,
   230  	"C7",		LCREG,	7,
   231  	"C8",		LCREG,	8,
   232  	"C9",		LCREG,	9,
   233  	"C10",		LCREG,	10,
   234  	"C11",		LCREG,	11,
   235  	"C12",		LCREG,	12,
   236  	"C13",		LCREG,	13,
   237  	"C14",		LCREG,	14,
   238  	"C15",		LCREG,	15,
   239  
   240  	"CPSR",		LPSR,	0,
   241  	"SPSR",		LPSR,	1,
   242  
   243  	"FPSR",		LFCR,	0,
   244  	"FPCR",		LFCR,	1,
   245  
   246  	".EQ",		LCOND,	0,
   247  	".NE",		LCOND,	1,
   248  	".CS",		LCOND,	2,
   249  	".HS",		LCOND,	2,
   250  	".CC",		LCOND,	3,
   251  	".LO",		LCOND,	3,
   252  	".MI",		LCOND,	4,
   253  	".PL",		LCOND,	5,
   254  	".VS",		LCOND,	6,
   255  	".VC",		LCOND,	7,
   256  	".HI",		LCOND,	8,
   257  	".LS",		LCOND,	9,
   258  	".GE",		LCOND,	10,
   259  	".LT",		LCOND,	11,
   260  	".GT",		LCOND,	12,
   261  	".LE",		LCOND,	13,
   262  	".AL",		LCOND,	Always,
   263  
   264  	".U",		LS,	C_UBIT,
   265  	".S",		LS,	C_SBIT,
   266  	".W",		LS,	C_WBIT,
   267  	".P",		LS,	C_PBIT,
   268  	".PW",		LS,	C_WBIT|C_PBIT,
   269  	".WP",		LS,	C_WBIT|C_PBIT,
   270  
   271  	".F",		LS,	C_FBIT,
   272  
   273  	".IBW",		LS,	C_WBIT|C_PBIT|C_UBIT,
   274  	".IAW",		LS,	C_WBIT|C_UBIT,
   275  	".DBW",		LS,	C_WBIT|C_PBIT,
   276  	".DAW",		LS,	C_WBIT,
   277  	".IB",		LS,	C_PBIT|C_UBIT,
   278  	".IA",		LS,	C_UBIT,
   279  	".DB",		LS,	C_PBIT,
   280  	".DA",		LS,	0,
   281  
   282  	"@",		LAT,	0,
   283  
   284  	"AND",		LTYPE1,	AAND,
   285  	"EOR",		LTYPE1,	AEOR,
   286  	"SUB",		LTYPE1,	ASUB,
   287  	"RSB",		LTYPE1,	ARSB,
   288  	"ADD",		LTYPE1,	AADD,
   289  	"ADC",		LTYPE1,	AADC,
   290  	"SBC",		LTYPE1,	ASBC,
   291  	"RSC",		LTYPE1,	ARSC,
   292  	"ORR",		LTYPE1,	AORR,
   293  	"BIC",		LTYPE1,	ABIC,
   294  
   295  	"SLL",		LTYPE1,	ASLL,
   296  	"SRL",		LTYPE1,	ASRL,
   297  	"SRA",		LTYPE1,	ASRA,
   298  
   299  	"MUL",		LTYPE1, AMUL,
   300  	"MULA",		LTYPEN, AMULA,
   301  	"DIV",		LTYPE1,	ADIV,
   302  	"MOD",		LTYPE1,	AMOD,
   303  
   304  	"MULL",		LTYPEM, AMULL,
   305  	"MULAL",	LTYPEM, AMULAL,
   306  	"MULLU",	LTYPEM, AMULLU,
   307  	"MULALU",	LTYPEM, AMULALU,
   308  
   309  	"MVN",		LTYPE2, AMVN,	/* op2 ignored */
   310  
   311  	"MOVB",		LTYPE3, AMOVB,
   312  	"MOVBU",	LTYPE3, AMOVBU,
   313  	"MOVH",		LTYPE3, AMOVH,
   314  	"MOVHU",	LTYPE3, AMOVHU,
   315  	"MOVW",		LTYPE3, AMOVW,
   316  
   317  	"MOVD",		LTYPE3, AMOVD,
   318  	"MOVDF",		LTYPE3, AMOVDF,
   319  	"MOVDW",	LTYPE3, AMOVDW,
   320  	"MOVF",		LTYPE3, AMOVF,
   321  	"MOVFD",		LTYPE3, AMOVFD,
   322  	"MOVFW",		LTYPE3, AMOVFW,
   323  	"MOVWD",	LTYPE3, AMOVWD,
   324  	"MOVWF",		LTYPE3, AMOVWF,
   325  
   326  	"LDREX",		LTYPE3, ALDREX,
   327  	"LDREXD",		LTYPE3, ALDREXD,
   328  	"STREX",		LTYPE9, ASTREX,
   329  	"STREXD",		LTYPE9, ASTREXD,
   330  
   331  /*
   332  	"NEGF",		LTYPEI, ANEGF,
   333  	"NEGD",		LTYPEI, ANEGD,
   334  	"SQTF",		LTYPEI,	ASQTF,
   335  	"SQTD",		LTYPEI,	ASQTD,
   336  	"RNDF",		LTYPEI,	ARNDF,
   337  	"RNDD",		LTYPEI,	ARNDD,
   338  	"URDF",		LTYPEI,	AURDF,
   339  	"URDD",		LTYPEI,	AURDD,
   340  	"NRMF",		LTYPEI,	ANRMF,
   341  	"NRMD",		LTYPEI,	ANRMD,
   342  */
   343  
   344  	"ABSF",		LTYPEI, AABSF,
   345  	"ABSD",		LTYPEI, AABSD,
   346  	"SQRTF",	LTYPEI, ASQRTF,
   347  	"SQRTD",	LTYPEI, ASQRTD,
   348  	"CMPF",		LTYPEL, ACMPF,
   349  	"CMPD",		LTYPEL, ACMPD,
   350  	"ADDF",		LTYPEK,	AADDF,
   351  	"ADDD",		LTYPEK,	AADDD,
   352  	"SUBF",		LTYPEK,	ASUBF,
   353  	"SUBD",		LTYPEK,	ASUBD,
   354  	"MULF",		LTYPEK,	AMULF,
   355  	"MULD",		LTYPEK,	AMULD,
   356  	"DIVF",		LTYPEK,	ADIVF,
   357  	"DIVD",		LTYPEK,	ADIVD,
   358  
   359  	"B",		LTYPE4, AB,
   360  	"BL",		LTYPE4, ABL,
   361  	"BX",		LTYPEBX,	ABX,
   362  
   363  	"BEQ",		LTYPE5,	ABEQ,
   364  	"BNE",		LTYPE5,	ABNE,
   365  	"BCS",		LTYPE5,	ABCS,
   366  	"BHS",		LTYPE5,	ABHS,
   367  	"BCC",		LTYPE5,	ABCC,
   368  	"BLO",		LTYPE5,	ABLO,
   369  	"BMI",		LTYPE5,	ABMI,
   370  	"BPL",		LTYPE5,	ABPL,
   371  	"BVS",		LTYPE5,	ABVS,
   372  	"BVC",		LTYPE5,	ABVC,
   373  	"BHI",		LTYPE5,	ABHI,
   374  	"BLS",		LTYPE5,	ABLS,
   375  	"BGE",		LTYPE5,	ABGE,
   376  	"BLT",		LTYPE5,	ABLT,
   377  	"BGT",		LTYPE5,	ABGT,
   378  	"BLE",		LTYPE5,	ABLE,
   379  	"BCASE",	LTYPE5,	ABCASE,
   380  
   381  	"SWI",		LTYPE6, ASWI,
   382  
   383  	"CMP",		LTYPE7,	ACMP,
   384  	"TST",		LTYPE7,	ATST,
   385  	"TEQ",		LTYPE7,	ATEQ,
   386  	"CMN",		LTYPE7,	ACMN,
   387  
   388  	"MOVM",		LTYPE8, AMOVM,
   389  
   390  	"SWPBU",	LTYPE9, ASWPBU,
   391  	"SWPW",		LTYPE9, ASWPW,
   392  
   393  	"RET",		LTYPEA, ARET,
   394  	"RFE",		LTYPEA, ARFE,
   395  
   396  	"TEXT",		LTYPEB, ATEXT,
   397  	"GLOBL",	LTYPEB, AGLOBL,
   398  	"DATA",		LTYPEC, ADATA,
   399  	"CASE",		LTYPED, ACASE,
   400  	"END",		LTYPEE, AEND,
   401  	"WORD",		LTYPEH, AWORD,
   402  	"NOP",		LTYPEI, ANOP,
   403  
   404  	"MCR",		LTYPEJ, 0,
   405  	"MRC",		LTYPEJ, 1,
   406  
   407  	"PLD",		LTYPEPLD, APLD,
   408  	"UNDEF",	LTYPEE,	AUNDEF,
   409  	"CLZ",		LTYPE2, ACLZ,
   410  
   411  	"MULWT",	LTYPE1, AMULWT,
   412  	"MULWB",	LTYPE1, AMULWB,
   413  	"MULAWT",	LTYPEN, AMULAWT,
   414  	"MULAWB",	LTYPEN, AMULAWB,
   415  
   416  	"USEFIELD",	LTYPEN, AUSEFIELD,
   417  
   418  	0
   419  };
   420  
   421  void
   422  cinit(void)
   423  {
   424  	Sym *s;
   425  	int i;
   426  
   427  	nullgen.sym = S;
   428  	nullgen.offset = 0;
   429  	nullgen.type = D_NONE;
   430  	nullgen.name = D_NONE;
   431  	nullgen.reg = NREG;
   432  	if(FPCHIP)
   433  		nullgen.dval = 0;
   434  	for(i=0; i<sizeof(nullgen.sval); i++)
   435  		nullgen.sval[i] = 0;
   436  
   437  	nerrors = 0;
   438  	iostack = I;
   439  	iofree = I;
   440  	peekc = IGN;
   441  	nhunk = 0;
   442  	for(i=0; i<NHASH; i++)
   443  		hash[i] = S;
   444  	for(i=0; itab[i].name; i++) {
   445  		s = slookup(itab[i].name);
   446  		s->type = itab[i].type;
   447  		s->value = itab[i].value;
   448  	}
   449  
   450  	pathname = allocn(pathname, 0, 100);
   451  	if(getwd(pathname, 99) == 0) {
   452  		pathname = allocn(pathname, 100, 900);
   453  		if(getwd(pathname, 999) == 0)
   454  			strcpy(pathname, "/???");
   455  	}
   456  }
   457  
   458  void
   459  syminit(Sym *s)
   460  {
   461  
   462  	s->type = LNAME;
   463  	s->value = 0;
   464  }
   465  
   466  int
   467  isreg(Gen *g)
   468  {
   469  
   470  	USED(g);
   471  	return 1;
   472  }
   473  
   474  void
   475  cclean(void)
   476  {
   477  
   478  	outcode(AEND, Always, &nullgen, NREG, &nullgen);
   479  	Bflush(&obuf);
   480  }
   481  
   482  void
   483  zname(char *n, int t, int s)
   484  {
   485  
   486  	Bputc(&obuf, ANAME);
   487  	Bputc(&obuf, t);	/* type */
   488  	Bputc(&obuf, s);	/* sym */
   489  	while(*n) {
   490  		Bputc(&obuf, *n);
   491  		n++;
   492  	}
   493  	Bputc(&obuf, 0);
   494  }
   495  
   496  void
   497  zaddr(Gen *a, int s)
   498  {
   499  	int32 l;
   500  	int i;
   501  	char *n;
   502  	Ieee e;
   503  
   504  	Bputc(&obuf, a->type);
   505  	Bputc(&obuf, a->reg);
   506  	Bputc(&obuf, s);
   507  	Bputc(&obuf, a->name);
   508  	Bputc(&obuf, 0);
   509  	switch(a->type) {
   510  	default:
   511  		print("unknown type %d\n", a->type);
   512  		exits("arg");
   513  
   514  	case D_NONE:
   515  	case D_REG:
   516  	case D_FREG:
   517  	case D_PSR:
   518  	case D_FPCR:
   519  		break;
   520  
   521  	case D_REGREG:
   522  	case D_REGREG2:
   523  		Bputc(&obuf, a->offset);
   524  		break;
   525  
   526  	case D_OREG:
   527  	case D_CONST:
   528  	case D_BRANCH:
   529  	case D_SHIFT:
   530  		l = a->offset;
   531  		Bputc(&obuf, l);
   532  		Bputc(&obuf, l>>8);
   533  		Bputc(&obuf, l>>16);
   534  		Bputc(&obuf, l>>24);
   535  		break;
   536  
   537  	case D_SCONST:
   538  		n = a->sval;
   539  		for(i=0; i<NSNAME; i++) {
   540  			Bputc(&obuf, *n);
   541  			n++;
   542  		}
   543  		break;
   544  
   545  	case D_FCONST:
   546  		ieeedtod(&e, a->dval);
   547  		Bputc(&obuf, e.l);
   548  		Bputc(&obuf, e.l>>8);
   549  		Bputc(&obuf, e.l>>16);
   550  		Bputc(&obuf, e.l>>24);
   551  		Bputc(&obuf, e.h);
   552  		Bputc(&obuf, e.h>>8);
   553  		Bputc(&obuf, e.h>>16);
   554  		Bputc(&obuf, e.h>>24);
   555  		break;
   556  	}
   557  }
   558  
   559  static int bcode[] =
   560  {
   561  	ABEQ,
   562  	ABNE,
   563  	ABCS,
   564  	ABCC,
   565  	ABMI,
   566  	ABPL,
   567  	ABVS,
   568  	ABVC,
   569  	ABHI,
   570  	ABLS,
   571  	ABGE,
   572  	ABLT,
   573  	ABGT,
   574  	ABLE,
   575  	AB,
   576  	ANOP,
   577  };
   578  
   579  void
   580  outcode(int a, int scond, Gen *g1, int reg, Gen *g2)
   581  {
   582  	int sf, st, t;
   583  	Sym *s;
   584  
   585  	/* hack to make B.NE etc. work: turn it into the corresponding conditional */
   586  	if(a == AB){
   587  		a = bcode[scond&0xf];
   588  		scond = (scond & ~0xf) | Always;
   589  	}
   590  
   591  	if(pass == 1)
   592  		goto out;
   593  jackpot:
   594  	sf = 0;
   595  	s = g1->sym;
   596  	while(s != S) {
   597  		sf = s->sym;
   598  		if(sf < 0 || sf >= NSYM)
   599  			sf = 0;
   600  		t = g1->name;
   601  		if(h[sf].type == t)
   602  		if(h[sf].sym == s)
   603  			break;
   604  		zname(s->name, t, sym);
   605  		s->sym = sym;
   606  		h[sym].sym = s;
   607  		h[sym].type = t;
   608  		sf = sym;
   609  		sym++;
   610  		if(sym >= NSYM)
   611  			sym = 1;
   612  		break;
   613  	}
   614  	st = 0;
   615  	s = g2->sym;
   616  	while(s != S) {
   617  		st = s->sym;
   618  		if(st < 0 || st >= NSYM)
   619  			st = 0;
   620  		t = g2->name;
   621  		if(h[st].type == t)
   622  		if(h[st].sym == s)
   623  			break;
   624  		zname(s->name, t, sym);
   625  		s->sym = sym;
   626  		h[sym].sym = s;
   627  		h[sym].type = t;
   628  		st = sym;
   629  		sym++;
   630  		if(sym >= NSYM)
   631  			sym = 1;
   632  		if(st == sf)
   633  			goto jackpot;
   634  		break;
   635  	}
   636  	Bputc(&obuf, a);
   637  	Bputc(&obuf, scond);
   638  	Bputc(&obuf, reg);
   639  	Bputc(&obuf, stmtline);
   640  	Bputc(&obuf, stmtline>>8);
   641  	Bputc(&obuf, stmtline>>16);
   642  	Bputc(&obuf, stmtline>>24);
   643  	zaddr(g1, sf);
   644  	zaddr(g2, st);
   645  
   646  out:
   647  	if(a != AGLOBL && a != ADATA)
   648  		pc++;
   649  }
   650  
   651  void
   652  outhist(void)
   653  {
   654  	Gen g;
   655  	Hist *h;
   656  	char *p, *q, *op, c;
   657  	int n;
   658   	char *tofree;
   659   	static int first = 1;
   660   	static char *goroot, *goroot_final;
   661   
   662   	if(first) {
   663   		// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
   664   		first = 0;
   665   		goroot = getenv("GOROOT");
   666   		goroot_final = getenv("GOROOT_FINAL");
   667   		if(goroot == nil)
   668   			goroot = "";
   669   		if(goroot_final == nil)
   670   			goroot_final = goroot;
   671   		if(strcmp(goroot, goroot_final) == 0) {
   672   			goroot = nil;
   673   			goroot_final = nil;
   674   		}
   675   	}
   676   
   677   	tofree = nil;
   678  	g = nullgen;
   679  	c = '/';
   680  	for(h = hist; h != H; h = h->link) {
   681  		p = h->name;
   682   		if(p != nil && goroot != nil) {
   683   			n = strlen(goroot);
   684   			if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
   685   				tofree = smprint("%s%s", goroot_final, p+n);
   686   				p = tofree;
   687   			}
   688   		}
   689  		op = 0;
   690  		if(systemtype(Windows) && p && p[1] == ':'){
   691  			c = p[2];
   692  		} else if(p && p[0] != c && h->offset == 0 && pathname){
   693  			if(systemtype(Windows) && pathname[1] == ':') {
   694  				op = p;
   695  				p = pathname;
   696  				c = p[2];
   697  			} else if(pathname[0] == c){
   698  				op = p;
   699  				p = pathname;
   700  			}
   701  		}
   702  		while(p) {
   703  			q = strchr(p, c);
   704  			if(q) {
   705  				n = q-p;
   706  				if(n == 0){
   707  					n = 1;	/* leading "/" */
   708  					*p = '/';	/* don't emit "\" on windows */
   709  				}
   710  				q++;
   711  			} else {
   712  				n = strlen(p);
   713  				q = 0;
   714  			}
   715  			if(n) {
   716  				Bputc(&obuf, ANAME);
   717  				Bputc(&obuf, D_FILE);	/* type */
   718  				Bputc(&obuf, 1);	/* sym */
   719  				Bputc(&obuf, '<');
   720  				Bwrite(&obuf, p, n);
   721  				Bputc(&obuf, 0);
   722  			}
   723  			p = q;
   724  			if(p == 0 && op) {
   725  				p = op;
   726  				op = 0;
   727  			}
   728  		}
   729  		g.offset = h->offset;
   730  
   731  		Bputc(&obuf, AHISTORY);
   732  		Bputc(&obuf, Always);
   733  		Bputc(&obuf, 0);
   734  		Bputc(&obuf, h->line);
   735  		Bputc(&obuf, h->line>>8);
   736  		Bputc(&obuf, h->line>>16);
   737  		Bputc(&obuf, h->line>>24);
   738  		zaddr(&nullgen, 0);
   739  		zaddr(&g, 0);
   740  
   741  		if(tofree) {
   742  			free(tofree);
   743  			tofree = nil;
   744  		}
   745  	}
   746  }
   747  
   748  #include "../cc/lexbody"
   749  #include "../cc/macbody"