github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/cmd/6l/list.c (about)

     1  // Inferno utils/6l/list.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6l/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  static	Prog*	bigP;
    37  
    38  void
    39  listinit(void)
    40  {
    41  
    42  	fmtinstall('R', Rconv);
    43  	fmtinstall('A', Aconv);
    44  	fmtinstall('D', Dconv);
    45  	fmtinstall('S', Sconv);
    46  	fmtinstall('P', Pconv);
    47  	fmtinstall('I', Iconv);
    48  }
    49  
    50  int
    51  Pconv(Fmt *fp)
    52  {
    53  	Prog *p;
    54  
    55  	p = va_arg(fp->args, Prog*);
    56  	bigP = p;
    57  	switch(p->as) {
    58  	case ATEXT:
    59  		if(p->from.scale) {
    60  			fmtprint(fp, "(%d)	%A	%D,%d,%lD",
    61  				p->line, p->as, &p->from, p->from.scale, &p->to);
    62  			break;
    63  		}
    64  		fmtprint(fp, "(%d)	%A	%D,%lD",
    65  			p->line, p->as, &p->from, &p->to);
    66  		break;
    67  	default:
    68  		fmtprint(fp, "(%d)	%A	%D,%D",
    69  			p->line, p->as, &p->from, &p->to);
    70  		break;
    71  	case ADATA:
    72  	case AINIT_:
    73  	case ADYNT_:
    74  		fmtprint(fp, "(%d)	%A	%D/%d,%D",
    75  			p->line, p->as, &p->from, p->from.scale, &p->to);
    76  		break;
    77  	}
    78  	bigP = P;
    79  	return 0;
    80  }
    81  
    82  int
    83  Aconv(Fmt *fp)
    84  {
    85  	int i;
    86  
    87  	i = va_arg(fp->args, int);
    88  	return fmtstrcpy(fp, anames[i]);
    89  }
    90  
    91  int
    92  Dconv(Fmt *fp)
    93  {
    94  	char str[STRINGSZ], s[STRINGSZ];
    95  	Adr *a;
    96  	int i;
    97  
    98  	a = va_arg(fp->args, Adr*);
    99  	i = a->type;
   100  
   101  	if(fp->flags & FmtLong) {
   102  		if(i != D_CONST) {
   103  			// ATEXT dst is not constant
   104  			snprint(str, sizeof(str), "!!%D", a);
   105  			goto brk;
   106  		}
   107  		parsetextconst(a->offset);
   108  		if(textarg == 0) {
   109  			snprint(str, sizeof(str), "$%lld", textstksiz);
   110  			goto brk;
   111  		}
   112  		snprint(str, sizeof(str), "$%lld-%lld", textstksiz, textarg);
   113  		goto brk;
   114  	}
   115  
   116  	if(i >= D_INDIR) {
   117  		if(a->offset)
   118  			snprint(str, sizeof(str), "%lld(%R)", a->offset, i-D_INDIR);
   119  		else
   120  			snprint(str, sizeof(str), "(%R)", i-D_INDIR);
   121  		goto brk;
   122  	}
   123  	switch(i) {
   124  
   125  	default:
   126  		if(a->offset)
   127  			snprint(str, sizeof(str), "$%lld,%R", a->offset, i);
   128  		else
   129  			snprint(str, sizeof(str), "%R", i);
   130  		break;
   131  
   132  	case D_NONE:
   133  		str[0] = 0;
   134  		break;
   135  
   136  	case D_BRANCH:
   137  		if(bigP != P && bigP->pcond != P)
   138  			if(a->sym != S)
   139  				snprint(str, sizeof(str), "%llux+%s", bigP->pcond->pc,
   140  					a->sym->name);
   141  			else
   142  				snprint(str, sizeof(str), "%llux", bigP->pcond->pc);
   143  		else
   144  			snprint(str, sizeof(str), "%lld(PC)", a->offset);
   145  		break;
   146  
   147  	case D_EXTERN:
   148  		if(a->sym) {
   149  			snprint(str, sizeof(str), "%s+%lld(SB)", a->sym->name, a->offset);
   150  			break;
   151  		}
   152  		snprint(str, sizeof(str), "!!noname!!+%lld(SB)", a->offset);
   153  		break;
   154  
   155  	case D_STATIC:
   156  		if(a->sym) {
   157  			snprint(str, sizeof(str), "%s<%d>+%lld(SB)", a->sym->name,
   158  				a->sym->version, a->offset);
   159  			break;
   160  		}
   161  		snprint(str, sizeof(str), "!!noname!!<999>+%lld(SB)", a->offset);
   162  		break;
   163  
   164  	case D_AUTO:
   165  		if(a->sym) {
   166  			snprint(str, sizeof(str), "%s+%lld(SP)", a->sym->name, a->offset);
   167  			break;
   168  		}
   169  		snprint(str, sizeof(str), "!!noname!!+%lld(SP)", a->offset);
   170  		break;
   171  
   172  	case D_PARAM:
   173  		if(a->sym) {
   174  			snprint(str, sizeof(str), "%s+%lld(%s)", a->sym->name, a->offset, paramspace);
   175  			break;
   176  		}
   177  		snprint(str, sizeof(str), "!!noname!!+%lld(%s)", a->offset, paramspace);
   178  		break;
   179  
   180  	case D_CONST:
   181  		snprint(str, sizeof(str), "$%lld", a->offset);
   182  		break;
   183  
   184  	case D_FCONST:
   185  		snprint(str, sizeof(str), "$(%.8ux,%.8ux)", a->ieee.h, a->ieee.l);
   186  		break;
   187  
   188  	case D_SCONST:
   189  		snprint(str, sizeof(str), "$\"%S\"", a->scon);
   190  		break;
   191  
   192  	case D_ADDR:
   193  		a->type = a->index;
   194  		a->index = D_NONE;
   195  		snprint(str, sizeof(str), "$%D", a);
   196  		a->index = a->type;
   197  		a->type = D_ADDR;
   198  		goto conv;
   199  	}
   200  brk:
   201  	if(a->index != D_NONE) {
   202  		snprint(s, sizeof(s), "(%R*%d)", a->index, a->scale);
   203  		strcat(str, s);
   204  	}
   205  conv:
   206  	fmtstrcpy(fp, str);
   207  //	if(a->gotype)
   208  //		fmtprint(fp, "«%s»", a->gotype->name);
   209  	return 0;
   210  
   211  }
   212  
   213  char*	regstr[] =
   214  {
   215  	"AL",		/* [D_AL] */
   216  	"CL",
   217  	"DL",
   218  	"BL",
   219  	"SPB",
   220  	"BPB",
   221  	"SIB",
   222  	"DIB",
   223  	"R8B",
   224  	"R9B",
   225  	"R10B",
   226  	"R11B",
   227  	"R12B",
   228  	"R13B",
   229  	"R14B",
   230  	"R15B",
   231  
   232  	"AX",		/* [D_AX] */
   233  	"CX",
   234  	"DX",
   235  	"BX",
   236  	"SP",
   237  	"BP",
   238  	"SI",
   239  	"DI",
   240  	"R8",
   241  	"R9",
   242  	"R10",
   243  	"R11",
   244  	"R12",
   245  	"R13",
   246  	"R14",
   247  	"R15",
   248  
   249  	"AH",
   250  	"CH",
   251  	"DH",
   252  	"BH",
   253  
   254  	"F0",		/* [D_F0] */
   255  	"F1",
   256  	"F2",
   257  	"F3",
   258  	"F4",
   259  	"F5",
   260  	"F6",
   261  	"F7",
   262  
   263  	"M0",
   264  	"M1",
   265  	"M2",
   266  	"M3",
   267  	"M4",
   268  	"M5",
   269  	"M6",
   270  	"M7",
   271  
   272  	"X0",
   273  	"X1",
   274  	"X2",
   275  	"X3",
   276  	"X4",
   277  	"X5",
   278  	"X6",
   279  	"X7",
   280  	"X8",
   281  	"X9",
   282  	"X10",
   283  	"X11",
   284  	"X12",
   285  	"X13",
   286  	"X14",
   287  	"X15",
   288  
   289  	"CS",		/* [D_CS] */
   290  	"SS",
   291  	"DS",
   292  	"ES",
   293  	"FS",
   294  	"GS",
   295  
   296  	"GDTR",		/* [D_GDTR] */
   297  	"IDTR",		/* [D_IDTR] */
   298  	"LDTR",		/* [D_LDTR] */
   299  	"MSW",		/* [D_MSW] */
   300  	"TASK",		/* [D_TASK] */
   301  
   302  	"CR0",		/* [D_CR] */
   303  	"CR1",
   304  	"CR2",
   305  	"CR3",
   306  	"CR4",
   307  	"CR5",
   308  	"CR6",
   309  	"CR7",
   310  	"CR8",
   311  	"CR9",
   312  	"CR10",
   313  	"CR11",
   314  	"CR12",
   315  	"CR13",
   316  	"CR14",
   317  	"CR15",
   318  
   319  	"DR0",		/* [D_DR] */
   320  	"DR1",
   321  	"DR2",
   322  	"DR3",
   323  	"DR4",
   324  	"DR5",
   325  	"DR6",
   326  	"DR7",
   327  
   328  	"TR0",		/* [D_TR] */
   329  	"TR1",
   330  	"TR2",
   331  	"TR3",
   332  	"TR4",
   333  	"TR5",
   334  	"TR6",
   335  	"TR7",
   336  
   337  	"NONE",		/* [D_NONE] */
   338  };
   339  
   340  int
   341  Rconv(Fmt *fp)
   342  {
   343  	char str[STRINGSZ];
   344  	int r;
   345  
   346  	r = va_arg(fp->args, int);
   347  	if(r >= D_AL && r <= D_NONE)
   348  		snprint(str, sizeof(str), "%s", regstr[r-D_AL]);
   349  	else
   350  		snprint(str, sizeof(str), "gok(%d)", r);
   351  
   352  	return fmtstrcpy(fp, str);
   353  }
   354  
   355  int
   356  Sconv(Fmt *fp)
   357  {
   358  	int i, c;
   359  	char str[STRINGSZ], *p, *a;
   360  
   361  	a = va_arg(fp->args, char*);
   362  	p = str;
   363  	for(i=0; i<sizeof(double); i++) {
   364  		c = a[i] & 0xff;
   365  		if(c >= 'a' && c <= 'z' ||
   366  		   c >= 'A' && c <= 'Z' ||
   367  		   c >= '0' && c <= '9') {
   368  			*p++ = c;
   369  			continue;
   370  		}
   371  		*p++ = '\\';
   372  		switch(c) {
   373  		default:
   374  			if(c < 040 || c >= 0177)
   375  				break;	/* not portable */
   376  			p[-1] = c;
   377  			continue;
   378  		case 0:
   379  			*p++ = 'z';
   380  			continue;
   381  		case '\\':
   382  		case '"':
   383  			*p++ = c;
   384  			continue;
   385  		case '\n':
   386  			*p++ = 'n';
   387  			continue;
   388  		case '\t':
   389  			*p++ = 't';
   390  			continue;
   391  		}
   392  		*p++ = (c>>6) + '0';
   393  		*p++ = ((c>>3) & 7) + '0';
   394  		*p++ = (c & 7) + '0';
   395  	}
   396  	*p = 0;
   397  	return fmtstrcpy(fp, str);
   398  }
   399  
   400  int
   401  Iconv(Fmt *fp)
   402  {
   403  	int i, n;
   404  	uchar *p;
   405  	char *s;
   406  	Fmt fmt;
   407  	
   408  	n = fp->prec;
   409  	fp->prec = 0;
   410  	if(!(fp->flags&FmtPrec) || n < 0)
   411  		return fmtstrcpy(fp, "%I");
   412  	fp->flags &= ~FmtPrec;
   413  	p = va_arg(fp->args, uchar*);
   414  
   415  	// format into temporary buffer and
   416  	// call fmtstrcpy to handle padding.
   417  	fmtstrinit(&fmt);
   418  	for(i=0; i<n; i++)
   419  		fmtprint(&fmt, "%.2ux", *p++);
   420  	s = fmtstrflush(&fmt);
   421  	fmtstrcpy(fp, s);
   422  	free(s);
   423  	return 0;
   424  }
   425  
   426  void
   427  diag(char *fmt, ...)
   428  {
   429  	char buf[1024], *tn, *sep;
   430  	va_list arg;
   431  
   432  	tn = "";
   433  	sep = "";
   434  	if(cursym != S) {
   435  		tn = cursym->name;
   436  		sep = ": ";
   437  	}
   438  	va_start(arg, fmt);
   439  	vseprint(buf, buf+sizeof(buf), fmt, arg);
   440  	va_end(arg);
   441  	print("%s%s%s\n", tn, sep, buf);
   442  
   443  	nerrors++;
   444  	if(nerrors > 20) {
   445  		print("too many errors\n");
   446  		errorexit();
   447  	}
   448  }
   449  
   450  void
   451  parsetextconst(vlong arg)
   452  {
   453  	textstksiz = arg & 0xffffffffLL;
   454  	if(textstksiz & 0x80000000LL)
   455  		textstksiz = -(-textstksiz & 0xffffffffLL);
   456  
   457  	textarg = (arg >> 32) & 0xffffffffLL;
   458  	if(textarg & 0x80000000LL)
   459  		textarg = 0;
   460  	textarg = (textarg+7) & ~7LL;
   461  }