github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/8l/list.c (about)

     1  // Inferno utils/8l/list.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/8l/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('R', Rconv);
    41  	fmtinstall('A', Aconv);
    42  	fmtinstall('D', Dconv);
    43  	fmtinstall('S', Sconv);
    44  	fmtinstall('P', Pconv);
    45  	fmtinstall('I', Iconv);
    46  }
    47  
    48  static	Prog	*bigP;
    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,%D",
    61  				p->line, p->as, &p->from, p->from.scale, &p->to);
    62  			break;
    63  		}
    64  	default:
    65  		fmtprint(fp, "(%d)	%A	%D,%D",
    66  			p->line, p->as, &p->from, &p->to);
    67  		break;
    68  	case ADATA:
    69  	case AINIT_:
    70  	case ADYNT_:
    71  		fmtprint(fp, "(%d)	%A	%D/%d,%D",
    72  			p->line, p->as, &p->from, p->from.scale, &p->to);
    73  		break;
    74  	}
    75  	bigP = P;
    76  	return 0;
    77  }
    78  
    79  int
    80  Aconv(Fmt *fp)
    81  {
    82  	int i;
    83  
    84  	i = va_arg(fp->args, int);
    85  	return fmtstrcpy(fp, anames[i]);
    86  }
    87  
    88  char*
    89  xsymname(Sym *s)
    90  {
    91  	if(s == nil)
    92  		return "!!noname!!";
    93  	return s->name;
    94  }
    95  
    96  int
    97  Dconv(Fmt *fp)
    98  {
    99  	char str[STRINGSZ], s[STRINGSZ];
   100  	Adr *a;
   101  	int i;
   102  
   103  	a = va_arg(fp->args, Adr*);
   104  	i = a->type;
   105  	if(i >= D_INDIR && i < 2*D_INDIR) {
   106  		if(a->offset)
   107  			snprint(str, sizeof str, "%d(%R)", a->offset, i-D_INDIR);
   108  		else
   109  			snprint(str, sizeof str, "(%R)", i-D_INDIR);
   110  		goto brk;
   111  	}
   112  	switch(i) {
   113  
   114  	default:
   115  		snprint(str, sizeof str, "%R", i);
   116  		break;
   117  
   118  	case D_NONE:
   119  		str[0] = 0;
   120  		break;
   121  
   122  	case D_BRANCH:
   123  		if(bigP != P && bigP->pcond != P)
   124  			if(a->sym != S)
   125  				snprint(str, sizeof str, "%ux+%s", bigP->pcond->pc,
   126  					a->sym->name);
   127  			else
   128  				snprint(str, sizeof str, "%ux", bigP->pcond->pc);
   129  		else
   130  			snprint(str, sizeof str, "%d(PC)", a->offset);
   131  		break;
   132  
   133  	case D_EXTERN:
   134  		snprint(str, sizeof str, "%s+%d(SB)", xsymname(a->sym), a->offset);
   135  		break;
   136  
   137  	case D_STATIC:
   138  		snprint(str, sizeof str, "%s<%d>+%d(SB)", xsymname(a->sym),
   139  			a->sym->version, a->offset);
   140  		break;
   141  
   142  	case D_AUTO:
   143  		snprint(str, sizeof str, "%s+%d(SP)", xsymname(a->sym), a->offset);
   144  		break;
   145  
   146  	case D_PARAM:
   147  		if(a->sym)
   148  			snprint(str, sizeof str, "%s+%d(FP)", a->sym->name, a->offset);
   149  		else
   150  			snprint(str, sizeof str, "%d(FP)", a->offset);
   151  		break;
   152  
   153  	case D_CONST:
   154  		snprint(str, sizeof str, "$%d", a->offset);
   155  		break;
   156  
   157  	case D_CONST2:
   158  		snprint(str, sizeof str, "$%d-%d", a->offset, a->offset2);
   159  		break;
   160  
   161  	case D_FCONST:
   162  		snprint(str, sizeof str, "$(%.8ux,%.8ux)", a->ieee.h, a->ieee.l);
   163  		break;
   164  
   165  	case D_SCONST:
   166  		snprint(str, sizeof str, "$\"%S\"", a->scon);
   167  		break;
   168  
   169  	case D_ADDR:
   170  		a->type = a->index;
   171  		a->index = D_NONE;
   172  		snprint(str, sizeof str, "$%D", a);
   173  		a->index = a->type;
   174  		a->type = D_ADDR;
   175  		goto conv;
   176  	}
   177  brk:
   178  	if(a->index != D_NONE) {
   179  		sprint(s, "(%R*%d)", (int)a->index, a->scale);
   180  		strcat(str, s);
   181  	}
   182  conv:
   183  	fmtstrcpy(fp, str);
   184  //	if(a->gotype)
   185  //		fmtprint(fp, "«%s»", a->gotype->name);
   186  	return 0;
   187  }
   188  
   189  char*	regstr[] =
   190  {
   191  	"AL",		/* [D_AL] */
   192  	"CL",
   193  	"DL",
   194  	"BL",
   195  	"AH",
   196  	"CH",
   197  	"DH",
   198  	"BH",
   199  
   200  	"AX",		/* [D_AX] */
   201  	"CX",
   202  	"DX",
   203  	"BX",
   204  	"SP",
   205  	"BP",
   206  	"SI",
   207  	"DI",
   208  
   209  	"F0",		/* [D_F0] */
   210  	"F1",
   211  	"F2",
   212  	"F3",
   213  	"F4",
   214  	"F5",
   215  	"F6",
   216  	"F7",
   217  
   218  	"CS",		/* [D_CS] */
   219  	"SS",
   220  	"DS",
   221  	"ES",
   222  	"FS",
   223  	"GS",
   224  
   225  	"GDTR",		/* [D_GDTR] */
   226  	"IDTR",		/* [D_IDTR] */
   227  	"LDTR",		/* [D_LDTR] */
   228  	"MSW",		/* [D_MSW] */
   229  	"TASK",		/* [D_TASK] */
   230  
   231  	"CR0",		/* [D_CR] */
   232  	"CR1",
   233  	"CR2",
   234  	"CR3",
   235  	"CR4",
   236  	"CR5",
   237  	"CR6",
   238  	"CR7",
   239  
   240  	"DR0",		/* [D_DR] */
   241  	"DR1",
   242  	"DR2",
   243  	"DR3",
   244  	"DR4",
   245  	"DR5",
   246  	"DR6",
   247  	"DR7",
   248  
   249  	"TR0",		/* [D_TR] */
   250  	"TR1",
   251  	"TR2",
   252  	"TR3",
   253  	"TR4",
   254  	"TR5",
   255  	"TR6",
   256  	"TR7",
   257  	
   258  	"X0",
   259  	"X1",
   260  	"X2",
   261  	"X3",
   262  	"X4",
   263  	"X5",
   264  	"X6",
   265  	"X7",
   266  
   267  	"NONE",		/* [D_NONE] */
   268  };
   269  
   270  int
   271  Rconv(Fmt *fp)
   272  {
   273  	char str[STRINGSZ];
   274  	int r;
   275  
   276  	r = va_arg(fp->args, int);
   277  	if(r >= D_AL && r <= D_NONE)
   278  		sprint(str, "%s", regstr[r-D_AL]);
   279  	else
   280  		sprint(str, "gok(%d)", r);
   281  
   282  	return fmtstrcpy(fp, str);
   283  }
   284  
   285  int
   286  Sconv(Fmt *fp)
   287  {
   288  	int i, c;
   289  	char str[STRINGSZ], *p, *a;
   290  
   291  	a = va_arg(fp->args, char*);
   292  	p = str;
   293  	for(i=0; i<sizeof(double); i++) {
   294  		c = a[i] & 0xff;
   295  		if(c >= 'a' && c <= 'z' ||
   296  		   c >= 'A' && c <= 'Z' ||
   297  		   c >= '0' && c <= '9') {
   298  			*p++ = c;
   299  			continue;
   300  		}
   301  		*p++ = '\\';
   302  		switch(c) {
   303  		default:
   304  			if(c < 040 || c >= 0177)
   305  				break;	/* not portable */
   306  			p[-1] = c;
   307  			continue;
   308  		case 0:
   309  			*p++ = 'z';
   310  			continue;
   311  		case '\\':
   312  		case '"':
   313  			*p++ = c;
   314  			continue;
   315  		case '\n':
   316  			*p++ = 'n';
   317  			continue;
   318  		case '\t':
   319  			*p++ = 't';
   320  			continue;
   321  		}
   322  		*p++ = (c>>6) + '0';
   323  		*p++ = ((c>>3) & 7) + '0';
   324  		*p++ = (c & 7) + '0';
   325  	}
   326  	*p = 0;
   327  	return fmtstrcpy(fp, str);
   328  }
   329  
   330  int
   331  Iconv(Fmt *fp)
   332  {
   333  	int i, n;
   334  	uchar *p;
   335  	char *s;
   336  	Fmt fmt;
   337  	
   338  	n = fp->prec;
   339  	fp->prec = 0;
   340  	if(!(fp->flags&FmtPrec) || n < 0)
   341  		return fmtstrcpy(fp, "%I");
   342  	fp->flags &= ~FmtPrec;
   343  	p = va_arg(fp->args, uchar*);
   344  
   345  	// format into temporary buffer and
   346  	// call fmtstrcpy to handle padding.
   347  	fmtstrinit(&fmt);
   348  	for(i=0; i<n; i++)
   349  		fmtprint(&fmt, "%.2ux", *p++);
   350  	s = fmtstrflush(&fmt);
   351  	fmtstrcpy(fp, s);
   352  	free(s);
   353  	return 0;
   354  }
   355  
   356  void
   357  diag(char *fmt, ...)
   358  {
   359  	char buf[STRINGSZ], *tn, *sep;
   360  	va_list arg;
   361  
   362  	tn = "";
   363  	sep = "";
   364  	if(cursym != S) {
   365  		tn = cursym->name;
   366  		sep = ": ";
   367  	}
   368  	va_start(arg, fmt);
   369  	vseprint(buf, buf+sizeof(buf), fmt, arg);
   370  	va_end(arg);
   371  	print("%s%s%s\n", tn, sep, buf);
   372  
   373  	nerrors++;
   374  	if(nerrors > 20) {
   375  		print("too many errors\n");
   376  		errorexit();
   377  	}
   378  }