github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/liblink/obj.c (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include <u.h>
     6  #include <libc.h>
     7  #include <bio.h>
     8  #include <link.h>
     9  
    10  enum
    11  {
    12  	HISTSZ = 10,
    13  	NSYM = 50,
    14  };
    15  
    16  int
    17  linklinefmt(Link *ctxt, Fmt *fp)
    18  {
    19  	struct
    20  	{
    21  		Hist*	incl;	/* start of this include file */
    22  		int32	idel;	/* delta line number to apply to include */
    23  		Hist*	line;	/* start of this #line directive */
    24  		int32	ldel;	/* delta line number to apply to #line */
    25  	} a[HISTSZ];
    26  	int32 lno, d;
    27  	int i, n;
    28  	Hist *h;
    29  
    30  	lno = va_arg(fp->args, int32);
    31  
    32  	n = 0;
    33  	for(h=ctxt->hist; h!=nil; h=h->link) {
    34  		if(h->offset < 0)
    35  			continue;
    36  		if(lno < h->line)
    37  			break;
    38  		if(h->name) {
    39  			if(h->offset > 0) {
    40  				// #line directive
    41  				if(n > 0 && n < HISTSZ) {
    42  					a[n-1].line = h;
    43  					a[n-1].ldel = h->line - h->offset + 1;
    44  				}
    45  			} else {
    46  				// beginning of file
    47  				if(n < HISTSZ) {
    48  					a[n].incl = h;
    49  					a[n].idel = h->line;
    50  					a[n].line = 0;
    51  				}
    52  				n++;
    53  			}
    54  			continue;
    55  		}
    56  		n--;
    57  		if(n > 0 && n < HISTSZ) {
    58  			d = h->line - a[n].incl->line;
    59  			a[n-1].ldel += d;
    60  			a[n-1].idel += d;
    61  		}
    62  	}
    63  
    64  	if(n > HISTSZ)
    65  		n = HISTSZ;
    66  
    67  	for(i=n-1; i>=0; i--) {
    68  		if(i != n-1) {
    69  			if(fp->flags & ~(FmtWidth|FmtPrec))
    70  				break;
    71  			fmtprint(fp, " ");
    72  		}
    73  		if(ctxt->debugline || (fp->flags&FmtLong))
    74  			fmtprint(fp, "%s/", ctxt->pathname);
    75  		if(a[i].line)
    76  			fmtprint(fp, "%s:%d[%s:%d]",
    77  				a[i].line->name, lno-a[i].ldel+1,
    78  				a[i].incl->name, lno-a[i].idel+1);
    79  		else
    80  			fmtprint(fp, "%s:%d",
    81  				a[i].incl->name, lno-a[i].idel+1);
    82  		lno = a[i].incl->line - 1;	// now print out start of this file
    83  	}
    84  	if(n == 0)
    85  		fmtprint(fp, "<unknown line number>");
    86  
    87  	return 0;
    88  }
    89  
    90  // Does s have t as a path prefix?
    91  // That is, does s == t or does s begin with t followed by a slash?
    92  // For portability, we allow ASCII case folding, so that haspathprefix("a/b/c", "A/B") is true.
    93  // Similarly, we allow slash folding, so that haspathprefix("a/b/c", "a\\b") is true.
    94  static int
    95  haspathprefix(char *s, char *t)
    96  {
    97  	int i, cs, ct;
    98  
    99  	if(t == nil)
   100  		return 0;
   101  	for(i=0; t[i]; i++) {
   102  		cs = s[i];
   103  		ct = t[i];
   104  		if('A' <= cs && cs <= 'Z')
   105  			cs += 'a' - 'A';
   106  		if('A' <= ct && ct <= 'Z')
   107  			ct += 'a' - 'A';
   108  		if(cs == '\\')
   109  			cs = '/';
   110  		if(ct == '\\')
   111  			ct = '/';
   112  		if(cs != ct)
   113  			return 0;
   114  	}
   115  	return s[i] == '\0' || s[i] == '/' || s[i] == '\\';
   116  }
   117  
   118  // This is a simplified copy of linklinefmt above.
   119  // It doesn't allow printing the full stack, and it returns the file name and line number separately.
   120  // TODO: Unify with linklinefmt somehow.
   121  void
   122  linkgetline(Link *ctxt, int32 line, LSym **f, int32 *l)
   123  {
   124  	struct
   125  	{
   126  		Hist*	incl;	/* start of this include file */
   127  		int32	idel;	/* delta line number to apply to include */
   128  		Hist*	line;	/* start of this #line directive */
   129  		int32	ldel;	/* delta line number to apply to #line */
   130  	} a[HISTSZ];
   131  	int32 lno, d, dlno;
   132  	int n;
   133  	Hist *h;
   134  	char buf[1024], buf1[1024], *file;
   135  
   136  	lno = line;
   137  	n = 0;
   138  	for(h=ctxt->hist; h!=nil; h=h->link) {
   139  		if(h->offset < 0)
   140  			continue;
   141  		if(lno < h->line)
   142  			break;
   143  		if(h->name) {
   144  			if(h->offset > 0) {
   145  				// #line directive
   146  				if(n > 0 && n < HISTSZ) {
   147  					a[n-1].line = h;
   148  					a[n-1].ldel = h->line - h->offset + 1;
   149  				}
   150  			} else {
   151  				// beginning of file
   152  				if(n < HISTSZ) {
   153  					a[n].incl = h;
   154  					a[n].idel = h->line;
   155  					a[n].line = 0;
   156  				}
   157  				n++;
   158  			}
   159  			continue;
   160  		}
   161  		n--;
   162  		if(n > 0 && n < HISTSZ) {
   163  			d = h->line - a[n].incl->line;
   164  			a[n-1].ldel += d;
   165  			a[n-1].idel += d;
   166  		}
   167  	}
   168  
   169  	if(n > HISTSZ)
   170  		n = HISTSZ;
   171  
   172  	if(n <= 0) {
   173  		*f = linklookup(ctxt, "??", HistVersion);
   174  		*l = 0;
   175  		return;
   176  	}
   177  	
   178  	n--;
   179  	if(a[n].line) {
   180  		file = a[n].line->name;
   181  		dlno = a[n].ldel-1;
   182  	} else {
   183  		file = a[n].incl->name;
   184  		dlno = a[n].idel-1;
   185  	}
   186  	if((!ctxt->windows && file[0] == '/') || (ctxt->windows && file[1] == ':') || file[0] == '<')
   187  		snprint(buf, sizeof buf, "%s", file);
   188  	else
   189  		snprint(buf, sizeof buf, "%s/%s", ctxt->pathname, file);
   190  
   191  	// Remove leading ctxt->trimpath, or else rewrite $GOROOT to $GOROOT_FINAL.
   192  	if(haspathprefix(buf, ctxt->trimpath)) {
   193  		if(strlen(buf) == strlen(ctxt->trimpath))
   194  			strcpy(buf, "??");
   195  		else {
   196  			snprint(buf1, sizeof buf1, "%s", buf+strlen(ctxt->trimpath)+1);
   197  			if(buf1[0] == '\0')
   198  				strcpy(buf1, "??");
   199  			strcpy(buf, buf1);
   200  		}
   201  	} else if(ctxt->goroot_final != nil && haspathprefix(buf, ctxt->goroot)) {
   202  		snprint(buf1, sizeof buf1, "%s%s", ctxt->goroot_final, buf+strlen(ctxt->goroot));
   203  		strcpy(buf, buf1);
   204  	}
   205  
   206  	lno -= dlno;
   207  	*f = linklookup(ctxt, buf, HistVersion);
   208  	*l = lno;
   209  }
   210  
   211  void
   212  linklinehist(Link *ctxt, int lineno, char *f, int offset)
   213  {
   214  	Hist *h;
   215  
   216  	if(0) // debug['f']
   217  		if(f) {
   218  			if(offset)
   219  				print("%4d: %s (#line %d)\n", lineno, f, offset);
   220  			else
   221  				print("%4d: %s\n", lineno, f);
   222  		} else
   223  			print("%4d: <pop>\n", lineno);
   224  
   225  	h = malloc(sizeof(Hist));
   226  	memset(h, 0, sizeof *h);
   227  	h->name = f;
   228  	h->line = lineno;
   229  	h->offset = offset;
   230  	h->link = nil;
   231  	if(ctxt->ehist == nil) {
   232  		ctxt->hist = h;
   233  		ctxt->ehist = h;
   234  		return;
   235  	}
   236  	ctxt->ehist->link = h;
   237  	ctxt->ehist = h;
   238  }
   239  
   240  void
   241  linkprfile(Link *ctxt, int32 l)
   242  {
   243  	int i, n;
   244  	Hist a[HISTSZ], *h;
   245  	int32 d;
   246  
   247  	n = 0;
   248  	for(h = ctxt->hist; h != nil; h = h->link) {
   249  		if(l < h->line)
   250  			break;
   251  		if(h->name) {
   252  			if(h->offset == 0) {
   253  				if(n >= 0 && n < HISTSZ)
   254  					a[n] = *h;
   255  				n++;
   256  				continue;
   257  			}
   258  			if(n > 0 && n < HISTSZ)
   259  				if(a[n-1].offset == 0) {
   260  					a[n] = *h;
   261  					n++;
   262  				} else
   263  					a[n-1] = *h;
   264  			continue;
   265  		}
   266  		n--;
   267  		if(n >= 0 && n < HISTSZ) {
   268  			d = h->line - a[n].line;
   269  			for(i=0; i<n; i++)
   270  				a[i].line += d;
   271  		}
   272  	}
   273  	if(n > HISTSZ)
   274  		n = HISTSZ;
   275  	for(i=0; i<n; i++)
   276  		print("%s:%ld ", a[i].name, (long)(l-a[i].line+a[i].offset+1));
   277  }
   278  
   279  /*
   280   * start a new Prog list.
   281   */
   282  Plist*
   283  linknewplist(Link *ctxt)
   284  {
   285  	Plist *pl;
   286  
   287  	pl = malloc(sizeof(*pl));
   288  	memset(pl, 0, sizeof *pl);
   289  	if(ctxt->plist == nil)
   290  		ctxt->plist = pl;
   291  	else
   292  		ctxt->plast->link = pl;
   293  	ctxt->plast = pl;
   294  
   295  	return pl;
   296  }