The Go Programming Language

Text file src/cmd/5l/list.c

     1	// Inferno utils/5l/list.h
     2	// http://code.google.com/p/inferno-os/source/browse/utils/5l/list.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	// Printing.
    32	
    33	#include "l.h"
    34	#include "../ld/lib.h"
    35	
    36	void
    37	listinit(void)
    38	{
    39	
    40		fmtinstall('A', Aconv);
    41		fmtinstall('C', Cconv);
    42		fmtinstall('D', Dconv);
    43		fmtinstall('P', Pconv);
    44		fmtinstall('S', Sconv);
    45		fmtinstall('N', Nconv);
    46		fmtinstall('O', Oconv);		// C_type constants
    47		fmtinstall('I', Iconv);
    48	}
    49	
    50	void
    51	prasm(Prog *p)
    52	{
    53		print("%P\n", p);
    54	}
    55	
    56	int
    57	Pconv(Fmt *fp)
    58	{
    59		Prog *p;
    60		int a;
    61	
    62		p = va_arg(fp->args, Prog*);
    63		curp = p;
    64		a = p->as;
    65		switch(a) {
    66		default:
    67			fmtprint(fp, "(%d)", p->line);
    68			if(p->reg == NREG)
    69				fmtprint(fp, "	%A%C	%D,%D",
    70					a, p->scond, &p->from, &p->to);
    71			else
    72			if(p->from.type != D_FREG)
    73				fmtprint(fp, "	%A%C	%D,R%d,%D",
    74					a, p->scond, &p->from, p->reg, &p->to);
    75			else
    76				fmtprint(fp, "	%A%C	%D,F%d,%D",
    77					a, p->scond, &p->from, p->reg, &p->to);
    78			break;
    79	
    80		case ASWPW:
    81		case ASWPBU:
    82			fmtprint(fp, "(%d)	%A%C	R%d,%D,%D",
    83				p->line, a, p->scond, p->reg, &p->from, &p->to);
    84			break;
    85	
    86		case ADATA:
    87		case AINIT_:
    88		case ADYNT_:
    89			fmtprint(fp, "(%d)	%A%C	%D/%d,%D",
    90				p->line, a, p->scond, &p->from, p->reg, &p->to);
    91			break;
    92	
    93		case AWORD:
    94			fmtprint(fp, "(%d)	WORD	%D", p->line, &p->to);
    95			break;
    96	
    97		case ADWORD:
    98			fmtprint(fp, "(%d)	DWORD	%D %D", p->line, &p->from, &p->to);
    99			break;
   100		}
   101		
   102		if(p->spadj)
   103			fmtprint(fp, "  (spadj%+d)", p->spadj);
   104	
   105		return 0;
   106	}
   107	
   108	int
   109	Aconv(Fmt *fp)
   110	{
   111		char *s;
   112		int a;
   113	
   114		a = va_arg(fp->args, int);
   115		s = "???";
   116		if(a >= AXXX && a < ALAST)
   117			s = anames[a];
   118		return fmtstrcpy(fp, s);
   119	}
   120	
   121	char*	strcond[16] =
   122	{
   123		".EQ",
   124		".NE",
   125		".HS",
   126		".LO",
   127		".MI",
   128		".PL",
   129		".VS",
   130		".VC",
   131		".HI",
   132		".LS",
   133		".GE",
   134		".LT",
   135		".GT",
   136		".LE",
   137		"",
   138		".NV"
   139	};
   140	
   141	int
   142	Cconv(Fmt *fp)
   143	{
   144		char s[20];
   145		int c;
   146	
   147		c = va_arg(fp->args, int);
   148		strcpy(s, strcond[c & C_SCOND]);
   149		if(c & C_SBIT)
   150			strcat(s, ".S");
   151		if(c & C_PBIT)
   152			strcat(s, ".P");
   153		if(c & C_WBIT)
   154			strcat(s, ".W");
   155		if(c & C_UBIT)		/* ambiguous with FBIT */
   156			strcat(s, ".U");
   157		return fmtstrcpy(fp, s);
   158	}
   159	
   160	int
   161	Dconv(Fmt *fp)
   162	{
   163		char str[STRINGSZ];
   164		char *op;
   165		Adr *a;
   166		int32 v;
   167	
   168		a = va_arg(fp->args, Adr*);
   169		switch(a->type) {
   170	
   171		default:
   172			snprint(str, sizeof str, "GOK-type(%d)", a->type);
   173			break;
   174	
   175		case D_NONE:
   176			str[0] = 0;
   177			if(a->name != D_NONE || a->reg != NREG || a->sym != S)
   178				snprint(str, sizeof str, "%N(R%d)(NONE)", a, a->reg);
   179			break;
   180	
   181		case D_CONST:
   182			if(a->reg == NREG)
   183				snprint(str, sizeof str, "$%N", a);
   184			else
   185				snprint(str, sizeof str, "$%N(R%d)", a, a->reg);
   186			break;
   187	
   188		case D_CONST2:
   189			snprint(str, sizeof str, "$%d-%d", a->offset, a->offset2);
   190			break;
   191	
   192		case D_SHIFT:
   193			v = a->offset;
   194			op = "<<>>->@>" + (((v>>5) & 3) << 1);
   195			if(v & (1<<4))
   196				snprint(str, sizeof str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15);
   197			else
   198				snprint(str, sizeof str, "R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31);
   199			if(a->reg != NREG)
   200				seprint(str+strlen(str), str+sizeof str, "(R%d)", a->reg);
   201			break;
   202	
   203		case D_OCONST:
   204			snprint(str, sizeof str, "$*$%N", a);
   205			if(a->reg != NREG)
   206				snprint(str, sizeof str, "%N(R%d)(CONST)", a, a->reg);
   207			break;
   208	
   209		case D_OREG:
   210			if(a->reg != NREG)
   211				snprint(str, sizeof str, "%N(R%d)", a, a->reg);
   212			else
   213				snprint(str, sizeof str, "%N", a);
   214			break;
   215	
   216		case D_REG:
   217			snprint(str, sizeof str, "R%d", a->reg);
   218			if(a->name != D_NONE || a->sym != S)
   219				snprint(str, sizeof str, "%N(R%d)(REG)", a, a->reg);
   220			break;
   221	
   222		case D_REGREG:
   223			snprint(str, sizeof str, "(R%d,R%d)", a->reg, (int)a->offset);
   224			if(a->name != D_NONE || a->sym != S)
   225				snprint(str, sizeof str, "%N(R%d)(REG)", a, a->reg);
   226			break;
   227	
   228		case D_FREG:
   229			snprint(str, sizeof str, "F%d", a->reg);
   230			if(a->name != D_NONE || a->sym != S)
   231				snprint(str, sizeof str, "%N(R%d)(REG)", a, a->reg);
   232			break;
   233	
   234		case D_PSR:
   235			switch(a->reg) {
   236			case 0:
   237				snprint(str, sizeof str, "CPSR");
   238				break;
   239			case 1:
   240				snprint(str, sizeof str, "SPSR");
   241				break;
   242			default:
   243				snprint(str, sizeof str, "PSR%d", a->reg);
   244				break;
   245			}
   246			if(a->name != D_NONE || a->sym != S)
   247				snprint(str, sizeof str, "%N(PSR%d)(REG)", a, a->reg);
   248			break;
   249	
   250		case D_FPCR:
   251			switch(a->reg){
   252			case 0:
   253				snprint(str, sizeof str, "FPSR");
   254				break;
   255			case 1:
   256				snprint(str, sizeof str, "FPCR");
   257				break;
   258			default:
   259				snprint(str, sizeof str, "FCR%d", a->reg);
   260				break;
   261			}
   262			if(a->name != D_NONE || a->sym != S)
   263				snprint(str, sizeof str, "%N(FCR%d)(REG)", a, a->reg);
   264	
   265			break;
   266	
   267		case D_BRANCH:	/* botch */
   268			if(curp->cond != P) {
   269				v = curp->cond->pc;
   270				if(a->sym != S)
   271					snprint(str, sizeof str, "%s+%.5ux(BRANCH)", a->sym->name, v);
   272				else
   273					snprint(str, sizeof str, "%.5ux(BRANCH)", v);
   274			} else
   275				if(a->sym != S)
   276					snprint(str, sizeof str, "%s+%d(APC)", a->sym->name, a->offset);
   277				else
   278					snprint(str, sizeof str, "%d(APC)", a->offset);
   279			break;
   280	
   281		case D_FCONST:
   282			snprint(str, sizeof str, "$%e", ieeedtod(&a->ieee));
   283			break;
   284	
   285		case D_SCONST:
   286			snprint(str, sizeof str, "$\"%S\"", a->sval);
   287			break;
   288		}
   289		return fmtstrcpy(fp, str);
   290	}
   291	
   292	int
   293	Nconv(Fmt *fp)
   294	{
   295		char str[STRINGSZ];
   296		Adr *a;
   297		Sym *s;
   298	
   299		a = va_arg(fp->args, Adr*);
   300		s = a->sym;
   301		switch(a->name) {
   302		default:
   303			sprint(str, "GOK-name(%d)", a->name);
   304			break;
   305	
   306		case D_NONE:
   307			sprint(str, "%d", a->offset);
   308			break;
   309	
   310		case D_EXTERN:
   311			if(s == S)
   312				sprint(str, "%d(SB)", a->offset);
   313			else
   314				sprint(str, "%s+%d(SB)", s->name, a->offset);
   315			break;
   316	
   317		case D_STATIC:
   318			if(s == S)
   319				sprint(str, "<>+%d(SB)", a->offset);
   320			else
   321				sprint(str, "%s<>+%d(SB)", s->name, a->offset);
   322			break;
   323	
   324		case D_AUTO:
   325			if(s == S)
   326				sprint(str, "%d(SP)", a->offset);
   327			else
   328				sprint(str, "%s-%d(SP)", s->name, -a->offset);
   329			break;
   330	
   331		case D_PARAM:
   332			if(s == S)
   333				sprint(str, "%d(FP)", a->offset);
   334			else
   335				sprint(str, "%s+%d(FP)", s->name, a->offset);
   336			break;
   337		}
   338		return fmtstrcpy(fp, str);
   339	}
   340	
   341	int
   342	Sconv(Fmt *fp)
   343	{
   344		int i, c;
   345		char str[STRINGSZ], *p, *a;
   346	
   347		a = va_arg(fp->args, char*);
   348		p = str;
   349		for(i=0; i<sizeof(int32); i++) {
   350			c = a[i] & 0xff;
   351			if(c >= 'a' && c <= 'z' ||
   352			   c >= 'A' && c <= 'Z' ||
   353			   c >= '0' && c <= '9' ||
   354			   c == ' ' || c == '%') {
   355				*p++ = c;
   356				continue;
   357			}
   358			*p++ = '\\';
   359			switch(c) {
   360			case 0:
   361				*p++ = 'z';
   362				continue;
   363			case '\\':
   364			case '"':
   365				*p++ = c;
   366				continue;
   367			case '\n':
   368				*p++ = 'n';
   369				continue;
   370			case '\t':
   371				*p++ = 't';
   372				continue;
   373			}
   374			*p++ = (c>>6) + '0';
   375			*p++ = ((c>>3) & 7) + '0';
   376			*p++ = (c & 7) + '0';
   377		}
   378		*p = 0;
   379		return fmtstrcpy(fp, str);
   380	}
   381	
   382	int
   383	Iconv(Fmt *fp)
   384	{
   385		int i, n;
   386		uint32 *p;
   387		char *s;
   388		Fmt fmt;
   389		
   390		n = fp->prec;
   391		fp->prec = 0;
   392		if(!(fp->flags&FmtPrec) || n < 0)
   393			return fmtstrcpy(fp, "%I");
   394		fp->flags &= ~FmtPrec;
   395		p = va_arg(fp->args, uint32*);
   396	
   397		// format into temporary buffer and
   398		// call fmtstrcpy to handle padding.
   399		fmtstrinit(&fmt);
   400		for(i=0; i<n/4; i++) {
   401			if(i > 0)
   402				fmtprint(&fmt, " ");
   403			fmtprint(&fmt, "%.8ux", *p++);
   404		}
   405		s = fmtstrflush(&fmt);
   406		fmtstrcpy(fp, s);
   407		free(s);
   408		return 0;
   409	}
   410	
   411	static char*
   412	cnames[] =
   413	{
   414		[C_ADDR]	= "C_ADDR",
   415		[C_FAUTO]	= "C_FAUTO",
   416		[C_ZFCON]	= "C_SFCON",
   417		[C_SFCON]	= "C_SFCON",
   418		[C_LFCON]	= "C_LFCON",
   419		[C_FCR]		= "C_FCR",
   420		[C_FOREG]	= "C_FOREG",
   421		[C_FREG]	= "C_FREG",
   422		[C_GOK]		= "C_GOK",
   423		[C_HAUTO]	= "C_HAUTO",
   424		[C_HFAUTO]	= "C_HFAUTO",
   425		[C_HFOREG]	= "C_HFOREG",
   426		[C_HOREG]	= "C_HOREG",
   427		[C_HREG]	= "C_HREG",
   428		[C_LACON]	= "C_LACON",
   429		[C_LAUTO]	= "C_LAUTO",
   430		[C_LBRA]	= "C_LBRA",
   431		[C_LCON]	= "C_LCON",
   432		[C_LOREG]	= "C_LOREG",
   433		[C_NCON]	= "C_NCON",
   434		[C_NONE]	= "C_NONE",
   435		[C_PC]		= "C_PC",
   436		[C_PSR]		= "C_PSR",
   437		[C_RACON]	= "C_RACON",
   438		[C_RCON]	= "C_RCON",
   439		[C_REG]		= "C_REG",
   440		[C_REGREG]	= "C_REGREG",
   441		[C_ROREG]	= "C_ROREG",
   442		[C_SAUTO]	= "C_SAUTO",
   443		[C_SBRA]	= "C_SBRA",
   444		[C_SCON]	= "C_SCON",
   445		[C_SHIFT]	= "C_SHIFT",
   446		[C_SOREG]	= "C_SOREG",
   447		[C_SP]		= "C_SP",
   448		[C_SROREG]	= "C_SROREG"
   449	};
   450	
   451	int
   452	Oconv(Fmt *fp)
   453	{
   454		char buf[500];
   455		int o;
   456	
   457		o = va_arg(fp->args, int);
   458		if(o < 0 || o >= nelem(cnames) || cnames[o] == nil) {
   459			snprint(buf, sizeof(buf), "C_%d", o);
   460			return fmtstrcpy(fp, buf);
   461		}
   462		return fmtstrcpy(fp, cnames[o]);
   463	}
   464	
   465	void
   466	diag(char *fmt, ...)
   467	{
   468		char buf[STRINGSZ], *tn, *sep;
   469		va_list arg;
   470	
   471		tn = "";
   472		sep = "";
   473		if(cursym != S) {
   474			tn = cursym->name;
   475			sep = ": ";
   476		}
   477		va_start(arg, fmt);
   478		vseprint(buf, buf+sizeof(buf), fmt, arg);
   479		va_end(arg);
   480		print("%s%s%s\n", tn, sep, buf);
   481	
   482		nerrors++;
   483		if(nerrors > 20) {
   484			print("too many errors\n");
   485			errorexit();
   486		}
   487	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.