// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include <u.h>
#include <libc.h>
#include <bio.h>
#include <link.h>

enum
{
	HISTSZ = 10,
	NSYM = 50,
};

int
linklinefmt(Link *ctxt, Fmt *fp)
{
	struct
	{
		Hist*	incl;	/* start of this include file */
		int32	idel;	/* delta line number to apply to include */
		Hist*	line;	/* start of this #line directive */
		int32	ldel;	/* delta line number to apply to #line */
	} a[HISTSZ];
	int32 lno, d;
	int i, n;
	Hist *h;

	lno = va_arg(fp->args, int32);

	n = 0;
	for(h=ctxt->hist; h!=nil; h=h->link) {
		if(h->offset < 0)
			continue;
		if(lno < h->line)
			break;
		if(h->name) {
			if(h->offset > 0) {
				// #line directive
				if(n > 0 && n < HISTSZ) {
					a[n-1].line = h;
					a[n-1].ldel = h->line - h->offset + 1;
				}
			} else {
				// beginning of file
				if(n < HISTSZ) {
					a[n].incl = h;
					a[n].idel = h->line;
					a[n].line = 0;
				}
				n++;
			}
			continue;
		}
		n--;
		if(n > 0 && n < HISTSZ) {
			d = h->line - a[n].incl->line;
			a[n-1].ldel += d;
			a[n-1].idel += d;
		}
	}

	if(n > HISTSZ)
		n = HISTSZ;

	for(i=n-1; i>=0; i--) {
		if(i != n-1) {
			if(fp->flags & ~(FmtWidth|FmtPrec))
				break;
			fmtprint(fp, " ");
		}
		if(ctxt->debugline || (fp->flags&FmtLong))
			fmtprint(fp, "%s/", ctxt->pathname);
		if(a[i].line)
			fmtprint(fp, "%s:%d[%s:%d]",
				a[i].line->name, lno-a[i].ldel+1,
				a[i].incl->name, lno-a[i].idel+1);
		else
			fmtprint(fp, "%s:%d",
				a[i].incl->name, lno-a[i].idel+1);
		lno = a[i].incl->line - 1;	// now print out start of this file
	}
	if(n == 0)
		fmtprint(fp, "<unknown line number>");

	return 0;
}

// This is a simplified copy of linklinefmt above.
// It doesn't allow printing the full stack, and it returns the file name and line number separately.
// TODO: Unify with linklinefmt somehow.
void
linkgetline(Link *ctxt, int32 line, LSym **f, int32 *l)
{
	struct
	{
		Hist*	incl;	/* start of this include file */
		int32	idel;	/* delta line number to apply to include */
		Hist*	line;	/* start of this #line directive */
		int32	ldel;	/* delta line number to apply to #line */
	} a[HISTSZ];
	int32 lno, d, dlno;
	int n;
	Hist *h;
	char buf[1024], *file;

	lno = line;
	n = 0;
	for(h=ctxt->hist; h!=nil; h=h->link) {
		if(h->offset < 0)
			continue;
		if(lno < h->line)
			break;
		if(h->name) {
			if(h->offset > 0) {
				// #line directive
				if(n > 0 && n < HISTSZ) {
					a[n-1].line = h;
					a[n-1].ldel = h->line - h->offset + 1;
				}
			} else {
				// beginning of file
				if(n < HISTSZ) {
					a[n].incl = h;
					a[n].idel = h->line;
					a[n].line = 0;
				}
				n++;
			}
			continue;
		}
		n--;
		if(n > 0 && n < HISTSZ) {
			d = h->line - a[n].incl->line;
			a[n-1].ldel += d;
			a[n-1].idel += d;
		}
	}

	if(n > HISTSZ)
		n = HISTSZ;

	if(n <= 0) {
		*f = linklookup(ctxt, "??", HistVersion);
		*l = 0;
		return;
	}
	
	n--;
	if(a[n].line) {
		file = a[n].line->name;
		dlno = a[n].ldel-1;
	} else {
		file = a[n].incl->name;
		dlno = a[n].idel-1;
	}
	if((!ctxt->windows && file[0] == '/') || (ctxt->windows && file[1] == ':'))
		snprint(buf, sizeof buf, "%s", file);
	else
		snprint(buf, sizeof buf, "%s/%s", ctxt->pathname, file);
	lno -= dlno;
	*f = linklookup(ctxt, buf, HistVersion);
	*l = lno;
}

void
linklinehist(Link *ctxt, int lineno, char *f, int offset)
{
	Hist *h;

	if(0) // debug['f']
		if(f) {
			if(offset)
				print("%4d: %s (#line %d)\n", lineno, f, offset);
			else
				print("%4d: %s\n", lineno, f);
		} else
			print("%4d: <pop>\n", lineno);

	h = malloc(sizeof(Hist));
	memset(h, 0, sizeof *h);
	h->name = f;
	h->line = lineno;
	h->offset = offset;
	h->link = nil;
	if(ctxt->ehist == nil) {
		ctxt->hist = h;
		ctxt->ehist = h;
		return;
	}
	ctxt->ehist->link = h;
	ctxt->ehist = h;
}

void
linkprfile(Link *ctxt, int32 l)
{
	int i, n;
	Hist a[HISTSZ], *h;
	int32 d;

	n = 0;
	for(h = ctxt->hist; h != nil; h = h->link) {
		if(l < h->line)
			break;
		if(h->name) {
			if(h->offset == 0) {
				if(n >= 0 && n < HISTSZ)
					a[n] = *h;
				n++;
				continue;
			}
			if(n > 0 && n < HISTSZ)
				if(a[n-1].offset == 0) {
					a[n] = *h;
					n++;
				} else
					a[n-1] = *h;
			continue;
		}
		n--;
		if(n >= 0 && n < HISTSZ) {
			d = h->line - a[n].line;
			for(i=0; i<n; i++)
				a[i].line += d;
		}
	}
	if(n > HISTSZ)
		n = HISTSZ;
	for(i=0; i<n; i++)
		print("%s:%ld ", a[i].name, (long)(l-a[i].line+a[i].offset+1));
}

/*
 * start a new Prog list.
 */
Plist*
linknewplist(Link *ctxt)
{
	Plist *pl;

	pl = malloc(sizeof(*pl));
	memset(pl, 0, sizeof *pl);
	if(ctxt->plist == nil)
		ctxt->plist = pl;
	else
		ctxt->plast->link = pl;
	ctxt->plast = pl;

	return pl;
}
