#
# general - general style awk script
#	every style script must begin with this general header
#




BEGIN {

#
# used by fixname for parsing name string
#
verbatim="%verbatim[ ]*((\\([^\\)]*\\))|(\\[[^\\]]*\\])|(<[^>]*>)|({[^}]*}))"

	titles["Mr."] = 1;
	titles["Mr"] = 1;
	titles["Mrs."] = 1;
	titles["Mrs"] = 1;
	titles["Ms."] = 1;
	titles["Ms"] = 1;
	titles["Dr."] = 1;
	titles["Dr"] = 1;
	titles["Fr."] = 1;
	titles["Fr"] = 1;
	titles["Rev."] = 1;
	titles["Rev"] = 1;

	postfix["I"] = 1;
	postfix["II"] = 1;
	postfix["III"] = 1;
	postfix["IV"] = 1;
	postfix["Jr."] = 1;
	postfix["Jr"] = 1;
	postfix["M.D."] = 1;
	postfix["MD"] = 1;
	postfix["S.J."] = 1;
	postfix["SJ"] = 1;

	prefix["Mac"] = 1;
	prefix["Mc"] = 1;
	prefix["Van"] = 1;
	prefix["Von"] = 1;
	prefix["mac"] = 1;
	prefix["mc"] = 1;
	prefix["van"] = 1;
	prefix["von"] = 1;
	prefix["di"] = 1;
	prefix["Di"] = 1;
	prefix["de"] = 1;
	prefix["De"] = 1;
	prefix["D'"] = 1;
	prefix["d'"] = 1;
	prefix["Der"] = 1;
	prefix["der"] = 1;
	prefix["Del"] = 1;
	prefix["del"] = 1;
	prefix["La"] = 1;
	prefix["la"] = 1;
	prefix["L'"] = 1;
	prefix["l'"] = 1;



	Monthcode["Foo"] = 00;
	Monthcode["Jan"] = 01;
	Monthcode["Feb"] = 02;
	Monthcode["Mar"] = 03;
	Monthcode["Apr"] = 04;
	Monthcode["May"] = 05;
	Monthcode["Jun"] = 06;
	Monthcode["Jul"] = 07;
	Monthcode["Aug"] = 08;
	Monthcode["Sep"] = 09;
	Monthcode["Oct"] = 10;
	Monthcode["Nov"] = 11;
	Monthcode["Dec"] = 12;
}


##
## Control and reference information from prefer
##

$1 == "%LETS_GO" {
	print PASS;
	if($2 == "nroff") nroff = 1;
	if($3 == "rp") rp = 1;
}

	
$1 == "%BEGIN_CITE"	{
	bibno++;
	cbibno++;
 	assoc = "";
	allauthors[bibno] = "";
}

$1 == "%T" {			# check for refer format
	if(refertitle == 0) {
		print "Warning: reference data is in refer format; use pconvert to change to refer format" | "cat >&2";
	}
	refertitle++;
}

/^%/	{ sub(/[ \t]*$/,""); }

$1 == "%author"	{
	if($2 ~ /^et/ && $3 ~ /^al/) {
		aetal[bibno] = 1;
	}
	else {
		a = ++authors[bibno];
		fixname();
		setauthor(bibno,a);
		if(!aflag)
			assoc = assoc Afull[bibno,a];
		allauthors[bibno] = allauthors[bibno] Afull[bibno,a];
	}
}


$1 == "%booktitle"	{ booktitle[bibno] = getrest();}

$1 == "%address"	{ city[bibno] = getrest(); }

$1 == "%date"	{	# assumes Month Day, Year
	year[bibno] = $NF;
	if(NF > 2) {
		month[bibno] = substr($2,1,3);
		if(NF == 4) {
			day[bibno] = $3;
			sub(",","",day[bibno]);
		}
		date[bibno] = getrest();
	}
	else date[bibno] = $NF;
	if(!aflag)
		assoc = assoc date[bibno];
}

$1 == "%editor"	 {
	if($2 ~ /^et/ && $3 ~ /^al/)
		eetal[bibno] = 1;
	else {
		e = ++editors[bibno];
		fixname();
		seteditor(bibno,e);
	}
}

$1 == "%publisher"	{ issuer[bibno] = getrest(); }

$1 == "%journal"	{ journal[bibno] = getrest(); }

$1 == "%number"	{
	number[bibno] = $2;
	if(NF > 2) numstr[bibno] = getrest();
}

$1 == "%other"		{ other[bibno] = getrest(); }

$1 == "%pages"	{ 
	pages[bibno] = getrest();
	gsub(/- /,"-",pages[bibno]);
	gsub(/ -/,"-",pages[bibno]);
}

$1 == "%part"		{
	part[bibno] =  $2
	if(NF > 2) partstr[bibno] = getrest();
}

$1 == "%report"		{ report[bibno] = getrest(); }

$1 == "%tm"		{ tmno[bibno] = getrest(); }

$1 == "%type" 		{ reftype[bibno] = $2; }

$1 == "%title"	{
	title[bibno] = getrest();
	if(!aflag)
		assoc = assoc title[bibno];
}

$1 == "%volume"	{
	volume[bibno] = $2;
	if(NF > 2) volstr[bibno] = getrest();
}

$1 == "%also_begin"	{
	if(++aflag == 1) {
		savebibno = bibno;
	}
	bibno = savebibno " " ++also[savebibno];
	allauthors[bibno] = "";
	pre_also[bibno] = getrest();
}


$1 == "%also_end"	{
	aflag--;
	if(reftype[bibno] == "not_found" || reftype[savebibno] == "not_found") {
		erasebib(bibno);
		also[savebibno]--;
	}

	else {
		if(title[savebibno] == title[bibno])
			title[bibno] = "";
		if(allauthors[savebibno] == allauthors[bibno])
			authors[bibno] = 0;
		post_also[bibno] = getrest();
	}
	if(aflag)
		bibno = savebibno " " aflag;
	else 
		bibno = savebibno;
}

$1 == "%no_cite"	{ no_cite[cbibno] = 1; }

$1 == "%no_author"	{ no_author[cbibno] = 1; }

$1 == "%no_date"	{ no_date[cbibno] = 1; }

$1 == "%pre_text"	{ pre_text[cbibno] = getrest(); }

$1 == "%post_text"	{ post_text[cbibno] = getrest(); }

$1 == "%END_CITE"	{
	if(reftype[bibno] == "not_found") {
		erasebib(bibno);
		erasecite(cbibno);
		bibno--;
		cbibno--;
	}
	else {
		assoc = assoc reftype[bibno];
		if (biblist[assoc] != 0) {
			erasebib(bibno);
			bibno--;
		}
		else
			biblist[assoc] = bibno;
		uniqno[cbibno] = biblist[assoc];

		if (no_cite[cbibno] != 1) {
			cites++;
			bibptr[cites] = cbibno;
		}
	}
}

$1 == "%END_LIST"	{
	if (cites > 0) {
		citations($2);
		cites = 0;
	}
	else printf $2;
	print $1;
}

$1 == "%BIBLIO"	{
	if(bibno > 0 && $2 != "no_bib") {
		if(sortflag && PASS == "")
			bibsort(SKEY);
		bibliography();
	}
	print "%END_BIB";
}

$1 == "%WHOLEBIB"	{
	if(bibno > 0) {
		if ($2) {
			sortflag = 1;
			if($2 == "sort")
				bibsort(SKEY);
			else
				bibsort($2);
		}
		else sortflag = 0;
		bibliography();
	}
	print "%END_BIB";
}


##
## For two passes
##
$1 == "%END_CITE2" {
	cbibno++
	if (no_cite[cbibno] != 1) {
		cites++;
		bibptr[cites] = cbibno;
		
	}
}

$1 == "%END_LIST1" {
	cites = 0;
	print $2 "%END_LIST";
}


$1 == "%BIBLIO1" {
	if(sortflag)
		bibsort(SKEY);
	cbibno = 0;
}

$1 == "%DBINCLUDE"	{
	cbibno +=$2;
}



##############################################
##
## functions
##
##############################################

##
## Sort the entire bibliography by the stated keys
##
func bibsort(keys)
{
	if (bibno == 0) return;

	"echo $$" | getline pid;
	sortout = "/tmp/sort" pid;
	sort = "sort -f -o " sortout;
	for(k=1; k <=3; k++)
		key[k] = substr(keys,k,1);
	for(i = 1; i <= bibno; i++) {
		for(k=1; k <=3; k++) {
			if(key[k] == "a") {
				if(authors[i] )
					printf "%s\t", Asort[i] | sort;
				else if(editors[i])
					printf "%s\t", Esort[i] | sort;
				else if(issuer[i])
				printf "%s\t", issuer[i] | sort;
				else
					printf "%s\t", title[i] | sort;
			}
			else if(key[k] == "d") {
				printf "%s", year[i] | sort;
				printf "%2s", Monthcode[month[i]] | sort;
				printf "%2s\t", day[i] | sort;
			}
			else if(key[k] == "t")
				printf "%s\t", title[i] | sort;
			else
				printf " \t" | sort;
		}
		print i | sort;
	}
	close(sort);
	FS = "\t";
	for(i = 1; i <= bibno; i++) {
		getline < sortout;
		sortorder[i] = $4;
		inverse[$4] = i;
	}
	FS = " ";
	system("rm " sortout);
}

##
## erase bibliographic entry
##
func erasebib(b)
{
	authors[b] = 0;
	allauthors[b] = "";
	aetal[b] = 0;
	editors[b] = 0;
	eetal[b] = 0;
	title[b] = "";
	booktitle[b] = "";
	issuer[b] = "";
	journal[b] = "";
	number[b] = "";
	other[b] = "";
	pages[b] = "";
	part[b] = "";
	report[b] = "";
	reftype[b] = "";
	volume[b] = "";
	volstr[b] = "";
	date[b] = "";
	year[b] = "";
	month[b] = "Foo";
	day[b] = "00";
	city[b] = "";
	Asort[b] = "";
	Esort[b] = "";
	also[b] = 0;
	pre_also[b] = "";
	post_also[b] = "";
}


##
## erase citation entry
##
func erasecite(b) {
	no_cite[b] = 0;
	no_author[b] = 0;
	no_date[b] = 0;
	pre_text[b] = "";
	post_text[b] = "";
}

##
## sequence - dtermine if c is in a sequence c-1, c, c+1
##
func sequence(c,n) {

# take care of endpoints 1 and n
	if (c == 1) return "no";
	if (c == n) {
		if(seq == "in") return "end";
		else return "no"
	}

# ignore sequence if pretext or posttext exists

	text = 0;
	if (pretext[bibptr[c-1]] || posttext[bibptr[c-1]] || \
	pretext[bibptr[c]] || posttext[bibptr[c]] || \
	pretext[bibptr[c+1]] || posttext[bibptr[c+1]] ) text = 1 ;

# detect a sequence ..1,2,3..

	if((makemark(c-1) == makemark(c)-1) && (makemark(c+1) == makemark(c)+1)) {
		if (text == 1) 
			if(seq == "in") return "end";
			else return "no";
		else return "in";
	}

# detect end ..7,8,22

	if((seq == "in") && (makemark(c+1) != makemark(c)+1)) return "end";
}



##
## format a list of bibliographies
##	used by both reference_placement and reference_list
##
func bibliography()
{
	print ".in .5i";
	for(i = 1; i <= bibno; i++) {
		b = bibindex(i);
		printref(b);
	}
	print ".in -5i"
	print ".nr RF " bibno;
}

##
## format a single reference
##
func printref(b) {
	if (reftype[b] == "book") book(b)
	else if (reftype[b] == "article") article(b)
	else if (reftype[b] == "review") review(b);
	else if (reftype[b] == "incollection") incollection(b)
	else if (reftype[b] == "inproceedings") inproceedings(b)
	else if (reftype[b] == "techreport") techreport(b)
	else if (reftype[b] == "phdthesis") thesis(b)
	else if (reftype[b] == "mastersthesis") thesis(b)
	else if (reftype[b] == "editedbook") editedbook(b)
	else if (reftype[b] == "misc") default(b)
	else if (reftype[b] == "pamphlet") pamphlet(b)
	else if (reftype[b] == "manual") manual(b)
	else if (reftype[b] == "proceedings") proceedings(b)
	else if (reftype[b] == "tm") tm(b)
	else if (reftype[b] == "unpublished") default(b)
	else {
		print "Unknown reference type " reftype[b] " for " Afull[b,1] " ... " title[b] ", " date[b] | "cat >&2";
		default(b);
	}
	if (other[b]) {
		printf ".\n" other[b];
		if(substr(other[b],length(other[b]),1) != ".")
			printf ".";
	}
	else printf ".";
	if(also[b]) {
		aprint++;
		print "";
		for(ia=1; ia <= also[b]; ia++) {
			prea = pre_also[b " " ia]
			if(prea) {
				printf prea;
				if(bracket(prea) == 0)
					printf " ";
			}
			else printf "Also " ;
			printref(b " " ia);
			posta = post_also[b " " ia]
			if(posta) {
				if(bracket(posta) == 0)
					printf " ";
				print posta;
			}
			else print "";
		}
		aprint--;
	}
	else if(aprint == 0) print "";
}

func bracket(string)
{
	brack = substr(string,length(string));
	if(brack ~ /[<>\(\){}\[\]]/)
		return 1;
	return 0;
}

##
## fixverbatim
##	handle strings with %verbatim around them
##
func fixverbatim()
{
	vb = 0;
	while(match($0,verbatim)) {
		vb++;
		beg=substr($0,1,RSTART-1);
		mid=substr($0,RSTART,RLENGTH);
		end=substr($0,RSTART+RLENGTH,length($0)-(RLENGTH+RSTART-1));
		gsub("%verbatim[ ]*","",mid);
		mid=substr(mid,2,length(mid)-2);
		gsub(" ","\\\\&",mid);
		$0 = beg mid end;
	}
	return vb;
}



##
## fixname
## 	parse namestring from %author and %editor into
##	Given Last Title and Post
##	e.g., Given = Fred P., Last = Smith, Title = Mr., Post = Jr.
##	
func fixname() {
	verbflag = fixverbatim()
	Given = "";
	Last = "";
	Title = "";
	Post = "";
	if(postfix[$NF]) {			#....Jr.
		Post = $NF;
		NF--;
		if(substr($NF,length($NF),1) == ",") {
			$NF = substr($NF,1,length($NF)-1);
		}
	}
	for(i=2; i<=NF; i++) {			# look for field ending with ","
		if(substr($i,length($i),1) == ",") {
			$i = substr($i,1,length($i)-1);
			break;
		}
	}
	if (i < NF) {				 # Last, Given...
		for(k=2; k<i; k++) {	
			Last = Last $k " ";
		}
		Last = Last $i;
		j=i+1;
		if(titles[$j]) {
			Title = $j;
			j++;
		}
		for(; j<NF; j++) {
			Given = Given $j " ";
		}
		Given = Given $NF;
	}
	else {					# Given....Last
		if(NF > 1) Last = $NF;
		for(i=NF-1 ;i>1; i--) {
			if(prefix[$i]) Last = $i " " Last;
			else break;
		}
		j = 2;
		if (titles[$j]) {
			Title = $2;
			j++;
		}
		if(j <= i) {
			for(; j<i; j++) {
				Given = Given $j " ";
			}
			Given = Given $i;
		}
	}
	if(verbflag) {
		gsub("\\\\&"," ",Last);
		gsub("\\\\&"," ",Title);
		gsub("\\\\&"," ",Post);
	}
}


##
## initial - return initial of name string
##
func initial(string) {
	return(substr(string,1,1) ".")
}


##
## LastFM - Organize Name: Last, F.M., e.g. Smith, F.P. Jr.
##
func LastFM() {
	Name = "";
	punc = "";
	if(Last) {
		Name = Name Last;
		punc = ", ";
	}
	if(Given) {
		if(Given ~ /\\\&/) {
			gsub("\\\\&"," ",Given);
			Name = Name punc Given;
		}
		else {
			ng = split(Given,G);
			Name = Name punc initial(G[1]);
			for(i = 2; i <= ng; i++) 
				Name = Name initial(G[i]);
		}
	}
	punc = " ";
	if(Post) {
		Name = Name punc Post;
	}
	return(Name);

}


##
## FMLast - Organize Name: F.M. Last, e.g., F.P. Smith Jr.
##
func FMLast() {
	Name = "";
	punc = "";
	if(Given) {
		if(Given ~ /\\\&/) {
			gsub("\\\\&"," ",Given);
			Name = Name punc Given;
		}
		else {
			ng = split(Given,G);
			Name = Name initial(G[1]);
			for(i = 2; i <= ng; i++) 
				Name = Name initial(G[i]);
		}
		punc = " ";
	}
	if(Last) {
		Name = Name punc Last;
		punc = " ";
	}
	if(Post) {
		Name = Name punc Post;
	}
	
	return(Name);
}

##
## F_M_Last - Organize Name: F.M. Last, e.g., F.P. Smith Jr.
##
func F_M_Last() {
	Name = "";
	punc = "";
	if(Given) {
		if(Given ~ /\\\&/) {
			gsub("\\\\&"," ",Given);
			Name = Name punc Given;
		}
		else {
			ng = split(Given,G);
			Name = Name initial(G[1]);
			for(i = 2; i <= ng; i++) {
				Name = punc Name initial(G[i]);
				punc = " ";
			}
		}
		punc = " ";
	}
	if(Last) {
		Name = Name punc Last;
		punc = " ";
	}
	if(Post) {
		Name = Name punc Post;
	}
	
	return(Name);
}

##
## LastF_M - Organize Name: Last, F. M., e.g. Smith F. P. Jr.
##
func LastF_M() {
	Name = "";
	punc = "";
	if(Last) {
		Name = Name Last;
		punc = ", ";
	}
	if(Given) {
		if(Given ~ /\\\&/) {
			gsub("\\\\&"," ",Given);
			Name = Name punc Given;
		}
		else {
			ng = split(Given,G);
			Name = Name punc initial(G[1]);
			for(i = 2; i <= ng; i++) 
				Name = Name " " initial(G[i]);
		}
	}
	punc = " ";
	if(Post) {
		Name = Name punc Post;
	}
	return(Name);
}

##
## FMLast - Organize Name: F. M. Last, e.g., F. P. Smith Jr.
##
func F_MLast() {
	Name = "";
	punc = "";
	if(Given) {
		if(Given ~ /\\\&/) {
			gsub("\\\\&"," ",Given);
			Name = Name punc Given;
		}
		else {
			ng = split(Given,G);
			Name = Name initial(G[1]);
			for(i = 2; i <= ng; i++) 
				Name = Name " " initial(G[i]);
		}
		punc = " ";
	}
	if(Last) {
		Name = Name punc Last;
		punc = " ";
	}
	if(Post) {
		Name = Name punc Post;
	}
	return(Name);
}


##
## FirstMiddleLast - Organize Name: First Middle Last e.g., Fred Peter Smith Jr.
##
func FirstMiddleLast()
{
	Name = "";
	punc = "";
	if(Given) {
		if(Given ~ /\\\&/) {
			gsub("\\\\&"," ",Given);
		}
		Name = Name Given;
		punc = " ";
	}
	if(Last) {
		Name = Name punc Last;
		punc = " ";
	}
	if(Post) {
		Name = Name punc Post;
	}
	return(Name);
}

##
## LastFirstMiddle - Organize Name: Last, First Middle Last e.g., Smith, Fred Peter, Jr.
##
func LastFirstMiddle()
{
	Name = "";
	punc = "";
	if(Last) {
		Name = Name Last;
		punc = ", ";
	}
	if(Given) {
		if(Given ~ /\\\&/) {
			gsub("\\\\&"," ",Given);
		}
		Name = Name punc Given;
		punc = ", ";
	}
	if(Post) {
		Name = Name punc Post;
	}
	return(Name);
}



##
## getrest - get rest of $0 after lopping off $1.
##
func getrest()
{
	rest = substr($0,length($1)+2);
	return(substr(rest,index(rest,$2))); # strip off blanks
}
###
### lsa reference formatting style
###

BEGIN	{
	PASS="";		# only one pass thru document
	sortflag = 1;		# reference_placement bib is sortedone
	STYLE = "lsa";
	SKEY = "adt";
}



#######################################################
#
# Functions required by general awk script
#
#######################################################


##
## Set author and editor fields
##	for reference list
##	for citation
##	for possible sorting
##
func setauthor(b,a) {
	Afull[b,a] = FirstMiddleLast();
	Arfull[b,a] = LastFirstMiddle();
	Alast[b,a] = Last;
	Asort[b] = Asort[b] Arfull[b,a] " ";
}

func seteditor(b,a) {
	Efull[b,a] = FirstMiddleLast();;
	Erfull[b,a] = LastFirstMiddle();
	Elast[b,a] = Last;
	Esort[b] = Esort[b] Erfull[b,a] " ";
}




##
## citations
##	print a citation list
##	(Last year{, year}, Last year...)
##
func citations(lastpunc) {
	sep = "\n(";
	if(lastpunc == "\"" || lastpunc == "'") {
		sep = lastpunc " (";
		lastpunc = "\\ ";
	}
	ptext = 0;
	ctext = 0;
	for(i=1; i<=cites; i++) {
		cn = bibptr[i];
		b = uniqno[cn];
		if (pre_text[cn]) ctext = 1;
		if ((ctext == 1) || (ptext == 1) || new_author(i)) {
			printf sep;
			if (pre_text[cn]) {
				printf "%s", pre_text[cn];
				if((no_author[cn] == 0) || (no_date[cn] == 0))
					printf " ";
			}	
			if (no_author[cn] == 0) {
				if(authors[b])
					printlast(b);
				else if (editors[b])
					printlasted(b);
				else if (issuer[b])
					printf issuer[b];
				else
					printf title[b];
				punc = " ";
			}
			else punc = "";
		}
		else {
			punc = ", ";
		}
		if(no_date[cn] == 0) {
			if(year[b] ~ /^[0-9][0-9][0-9][0-9]$/)
				printf "%s%s", punc, year[b];
			else {
				if (date[b] != 0) printf "%s%s", punc, date[b];
			}
		}
		if (post_text[cn]) {
			if (is_punc(substr(post_text[cn],1,1)) == 0) print "";
			printf "%s", post_text[cn];
		}
		sep = ",\n";
		ptext = ctext;
		ctext = 0;
	}
	printf ")";
	printf lastpunc;
}

func is_punc(p)
{
	if(p == ",") return 1;
	if(p == ".") return 1;
	if(p == ";") return 1;
	return 0;
}

##
## new_author
##	returns 1 if current author is difference from
##	previous author in the citation list
##
func new_author(c) {
	if (c == 1) return 1;
	b1 = uniqno[bibptr[c-1]];
	b = uniqno[bibptr[c]];
	if(authors[b] == 0) return 1;
	if(authors[b1] != authors[b]) return 1;
	for(k = 1; k <= authors[b]; k++) {
		if (Alast[b1,k] != Alast[b,k]) return 1;
	}
	return 0;
}


##
## print author last name for citation
##	First
##	First and Second
##	First, Second,..., & Last
func printlast(c) {			
        a = authors[c]			
	if ( a == 1 ) printf "%s", Alast[c,1];
	else if ( a == 2 ) printf "%s & %s", Alast[c,1], Alast[c,2];
	else if (a > 5) printf "%s et al.", Alast[c,1];
	else {
		for ( j = 1; j < a; j++ ) printf Alast[c,j] ", ";
		printf "& %s", Alast[c,a];
	}
}

##

## print editor last name for citation
##	First
##	First and Second
##	First, Second,..., & Last
func printlasted(c) {			
        a = editors[c]			
	if ( a == 1 ) printf "%s", Elast[c,1];
	else if ( a == 2 ) printf "%s & %s", Elast[c,1], Elast[c,2];
	else if (a > 5) printf "%s et al.", Elast[c,1] ;
	else {
		for ( j = 1; j < a; j++ ) printf "%s, ", Elast[c,j];
		printf "& %s", Elast[c,a];
	}
}


##
## bibindex
##	set up indentation for bibliography;
##	return an index for accessing rest of citation
##	do misc stuff specific to this style
##
func bibindex(i) {
	printf ".sp .3\n.ti -.3i\n";
	if (sortflag)
		return sortorder[i];
	else return i;
}



#############################################
#
# Reference types
#
############################################


func book(b) {
	# authorlist.
			if(authors[b]) {
				if(printfull(b) != ".")
					printf ".";
				printf "\n";
			}
	# date.
			printf "%s", date[b] ;
			punc = ".\n";
	# title
			if(title[b]) {
				printf "%s%s", punc, title[b];
	# Vol #.
				if(volstr[b])
					printf ", %s", volstr[b];
				else if(volume[b])
					printf ", Vol. %s", volume[b];
			}
	# location: publisher.
			if (city[b]) {
				printf "%s%s", punc, city[b] ;
				punc = ": ";
			}
			printf "%s%s", punc, issuer[b] ;
}


func editedbook(b) {
	# authorlist.
			if(authors[b]) {
				if(printfull(b) != ".")
					printf ".";
				printf "\n";
			}
	# date.
			printf "%s", date[b] ;
				if(authors[b] <2)
					printf " (ed.)\n";
				else
					printf " (eds.)\n";
	# italic(title)
			if(title[b]) {
				printf title[b];
				punc = ".\n";
			}
	# (Vol #).
			if(volstr[b])
				printf ", %s", volstr[b];
			else if(volume[b])
				printf ", Vol. %s", volume[b];
	# location: publisher.
			if (city[b]) {
				printf "%s%s", punc, city[b] ;
				punc = ": ";
			}
			printf "%s%s", punc, issuer[b] ;
}


func thesis(b) {

	# authorlist.
			if(authors[b]) {
				if(printfull(b) != ".")
					printf ".";
				printf "\n";
			}
	# date.
			printf "%s.\n", date[b] ;
	# title.
			if(title[b]) {
				printf "%s.\n", title[b];
			}
	# city
			if(address[b]) {
				printf "%s: ", address[b];
			}
	# thesis, school.
			if(reftype[b] == "phdthesis")
				printf "%s dissertation", issuer[b];
			else if(reftype[b] == "mastersthesis")
				printf "%s master's thesis", issuer[b];
}

func review(b) {
	article(b);
}


func article(b) {

	# authorlist.
			if(authors[b]) {
				if(printfull(b) != ".")
					printf ".";
				printf "\n";
			}
	# date.
			printf "%s.\n", date[b] ;
	# title.
			if(title[b]) {
				printf title[b] ".\n";
			}
	# [reviewed title.]
			if(booktitle[b]) {
				printf "[Review of %s", booktitle[b];
				if(editors[b]) {
					printf " by ";
					editorlist(b);
				if (issuer[b]) {
					printf " %s", issuer[b];
				}
				}
				printf "].\n";
			}

	# italics journal,
			printf "%s", journal[b];
			punc = ", ";
	# volume:number.pages
			if (volstr[b]) {
				printf ", %s", volstr[b];
				if (numstr[b]) {
					printf ", %s", numstr[b];
				}
				else if (number[b]) {
					printf ", %s", number[b];
				}
				punc = ".";
			}
			else if (volume[b]) {
				printf " %s", volume[b];
				if (numstr[b]) {
					printf ", %s", numstr[b];
				}
				else if (number[b]) {
					printf ":%s",number[b];
				}
				punc = ".";
			}
			if ( pages[b] ) printf "%s%s", punc, pages[b];
}

func inproceedings(b) {

	# authorlist.
			if(authors[b]) {
				if(printfull(b) != ".")
					printf ".";
				printf "\n";
			}
	# date.
			printf "%s.\n", date[b] ;
	# title.
			if(title[b]) {
				printf title[b] ".\n";
			}

	# italics journal,
			printf "%s", journal[b];
			punc = ",\n";

	# ed. by editorlist,
			if(editors[b]) {
				printf ", ed. by "
				editorlist(b);
			}
			punc = ".\n";
	# pages.
			if(pages[b]) {
				printf ", %s", pages[b];
			}
	# location: publisher,
			if (city[b]) {
				printf "%s%s", punc, city[b] ;
				punc = ": ";
			}
			if (issuer[b])
				printf "%s%s", punc, issuer[b] ;
}

func proceedings(b) {
			punc = "";
	# authorlist.
			if(authors[b] >0) {
				if(printfull(b) != ".")
					printf ".";
				printf "\n";
			}
	# editor
			else if(editors[b]) {
				printedfull(b);
				if (editors[b] == 1) printf " (Ed.)"
				else if (editors[b] > 1) printf " (Eds.)"
				punc = ".\n";
			}

	# publisher
			else if(issuer[b]) {
				printf "%s%s", punc, issuer[b];
				punc = ".\n";
			}
	# date.
			printf "%s%s.\n", punc, date[b] ;
	# title
			if (title[b]) {
				printf "%s", title[b];
				punc = ".\n";
				if(substr(title[b],length(title[b]),1) == ".")
					punc = "\n";
			}
	# volume:number
			if (volstr[b]) {
				printf ", %s", volstr[b];
				if (numstr[b]) {
					printf ", %s", numstr[b];
				}
				else if (number[b]) {
					printf ", %s", number[b];
				}
				punc = ".";
			}
			else if (volume[b]) {
				printf " %s", volume[b];
				if (numstr[b]) {
					printf ", %s", numstr[b];
				}
				else if (number[b]) {
					printf ":%s",number[b];
				}
				punc = ".";
			}
	# location: publisher,
			if (city[b]) {
				printf "%s%s", punc, city[b] ;
				punc = ": ";
			}
			printf "%s%s", punc, issuer[b] ;
}


func incollection(b) {

	# authorlist.
			if(authors[b]) {
				if(printfull(b) != ".")
					printf ".";
				printf "\n";
			}	
	# date.
			printf "%s.\n", date[b] ;
	# title
			if(title[b]) {
				printf "%s.\n", title[b];
			}
	# booktitle,
			printf "%s", booktitle[b];
	# Vol #.
			if(volstr[b])
				printf ", %s", volstr[b];
			else if(volume[b])
				printf ", Vol. %s", volume[b];
	# ed. by editorlist,
			if(editors[b]) {
				printf ", ed. by "
				editorlist(b);
			}
			punc = ".\n";
	# pages.
			if(pages[b]) {
				printf ", %s", pages[b];
			}
	# location: publisher,
			if (city[b]) {
				printf "%s%s", punc, city[b] ;
				punc = ": ";
			}
			printf "%s%s", punc, issuer[b];
}



func techreport(b) {

	# authorlist.
			if(authors[b]) {
				if(printfull(b) != ".")
					printf ".";
				printf "\n";
			}
	# date.
			printf "%s.\n", date[b] ;
	# title.
			if(title[b])
				printf "%s.\n", title[b];
	# (report number).
			printf "(%s).\n", report[b];

	# location: publisher.
			if (city[b]) printf "%s: ", city[b] ;
			printf issuer[b];
}

func tm(b) {

	# authorlist.
			if(authors[b]) {
				if(printfull(b) != ".")
					printf ".";
				printf "\n";
			}
	# date.
			printf "%s.\n", date[b] ;
	# title.
			if(title[b])
				printf "%s.\n", title[b];
	# (tm number).
			if(rp)
				printf "(AT&T Bell Laboratories internal memorandum)";
			else
				printf "(%s)", tmno[b] 
}

func manual(b) {
			punc = "";
	# authorlist.
			if(authors[b] >0) {
				if(printfull(b) != ".")
					printf ".";
				printf "\n";
			}
	# editor.
			else if(editors[b]) {
				if(printedfull(b) != ".")
					printf ".";
				printf "\n";
			}

	# publisher
			else if(issuer[b]) {
				printf "%s%s", punc, issuer[b];
				punc = ".\n";
			}
	# date.
			printf "%s%s", punc, date[b] ;
				if (editors[b] == 1) printf " (ed.)\n";
				else if (editors[b] > 1) printf " (eds.)\n";
				else printf ".\n";
	# title
			if(title[b]) {
				printf "%s", title[b];
				punc = ".\n";
			}
	# location: publisher.
			if (city[b]) {
				printf "%s%s", punc, city[b] ;
				punc = ": ";
			}
			if(issuer[b]) {
				if(editors[b] || authors[b]);
					printf "%s%s", punc, issuer[b];
			}
}

func pamphlet(b)
{

			punc = "";
	# authorlist.
			if(authors[b] >0) {
				if(printfull(b) != ".")
					printf ".";
				printf "\n";
			}
	# publisher.
			else if(issuer[b]) {
				printf issuer[b];
				punc = ".\n";
			}
	# title.
			else if(title[b]) {
				printf title[b];
				punc = ".\n"
			}
	# date.
			if(date[b]) {
				printf "%s%s", punc, date[b] ;
				punc = ".\n";
			}
	# title
			if(editors[b] || authors[b] || issuer[b]) {
				if(title[b]) {
					printf "%s%s", punc, title[b];
					punc = ".\n"
				}
			}

	# Vol #.
			if(volstr[b])
				printf ", %s", volstr[b];
			else if(volume[b])
				printf ", Vol. %s", volume[b];
	# location: publisher.
			if (city[b]) {
				printf "%s%s", punc, city[b] ;
				punc = ": ";
			}
			if(issuer[b]) {
				if(editors[b] || authors[b]);
					printf "%s%s", punc, issuer[b];
			}

}

func default(b) {
			punc = "";
	# authorlist.
			if(authors[b]) {
				if(printfull(b) != ".")
					printf ".";
				printf "\n";
			}
	# publisher.
			else if(issuer[b]) {
				printf  issuer[b];
				punc = ".\n";
			}
	# title.
			else if(title[b]) {
				printf  title[b];
				punc = ".\n"
			}
	# date.
			if(date[b]) {
				printf "%s%s", punc, date[b] ;
				punc = ".\n";
			}
	# title
			if(editors[b] || authors[b] || issuer[b] ) {
				if(title[b]) {
					printf "%s%s", punc, title[b];
					punc = ".\n"
				}
			}
	# Vol #,
			if(volstr[b]) {
				printf ", %s", volstr[b];
				punc = ".\n";
			}
			else if(volume[b]) {
				printf ", Vol. %s", volume[b];
				punc = ".\n";
			}
	# pages.
			if (pages[b]) {
				printf ", %s", pages[b];
				punc = ".\n";
			}

	# location: publisher.
			if (city[b]) {
				printf "%s%s", punc, city[b] ;
				punc = ": ";
			}
			if(issuer[b]) {
				if(editors[b] || authors[b]);
					printf "%s%s", punc, issuer[b];
			}
}

#
# return index of previous item
#

func previous(q)
{
	if (sortflag)
		return sortorder[inverse[q]-1];
	else
		return q-1;
}



# Author, First
# Author, First, and Second Author
# Author, First, Second Author, and Remaining Authors

func printfull(b) {
	longdash = "\\(em\\(em\\(em";
	dash = 0;			
	prev = previous(b);
	if ( authors[b] == 1 ) {
		if(Arfull[b,1] == Arfull[prev,1]) {
			printf longdash;
			return "";
		}
		else printf Arfull[b,1] ;
		if(aetal[b]) {
			printf ", et al.";
			return ".";
		}
		return substr(Arfull[b,1],length(Arfull[b,1]));
	}
	else if ( authors[b] == 2 ) {
		if(Arfull[b,1] == Arfull[prev,1]) {
			printf longdash;
			dash = 1;
		}
		else printf Arfull[b,1];
		printf ", and "
		if(dash && (Afull[b,2] == Afull[prev,2]))
			printf longdash;
		else printf Afull[b,2];
	}	
	else {
		if(Arfull[b,1] == Arfull[prev,1]) {
			printf longdash;
			dash = 1;
		}
		else printf Arfull[b,1];
		printf "; ";
		for ( j = 2 ; j < authors[b]; j++ ) {
			if(dash && (Afull[b,j] == Afull[prev,j]))
				printf longdash;
			else {
				dash = 0;
				printf Afull[b,j];
			}
			printf  "; ";
		}
		printf "and "
		j = authors[b];
		if(dash && (Afull[b,j] == Afull[prev,j]))
			printf longdash;
		else printf Afull[b,j];
	}
	return "";
}

func printedfull(b) {
	longdash = "\\(em\\(em\\(em\\(em";
	dash = 0;
	prev = previous(b);			
 	if ( editors[b] == 0 ) ;
	else if ( editors[b] == 1 ) {
		if(Erfull[b,1] == Erfull[prev,1]) {
			printf longdash;
			return "";
		}
		else printf Erfull[b,1] ;
		if(aetal[b]) {
			printf ", et al.";
			return ".";
		}
		return substr(Erfull[b,1],length(Erfull[b,1]));
	}
	else if ( editors[b] == 2 ) {
		if(Erfull[b,1] == Erfull[prev,1]) {
			printf longdash;
			dash = 1;
		}
		else printf Erfull[b,1];
		printf ", and "
		if(dash && (Efull[b,2] == Efull[prev,2]))
			printf longdash;
		else printf Efull[b,2];
	}	
	else {
		if(Erfull[b,1] == Erfull[prev,1]) {
			printf longdash;
			dash = 1;
		}
		else printf Erfull[b,1];
		printf "; ";
		for ( j = 2 ; j < editors[b]; j++ ) {
			if(dash && (Efull[b,j] == Efull[prev,j]))
				printf longdash;
			else {
				dash = 0;
				printf Efull[b,j];
			}
			printf  "; ";
		}
		printf "and "
		j = editors[b];
		if(dash && (Efull[b,j] == Efull[prev,j]))
			printf longdash;
		else printf Efull[b,j];
	}
	return "";
}



func editorlist(b) {			
 	if ( editors[b] == 0 ) ;
	else if ( editors[b] == 1 ) printf "%s", Efull[b,1] ;
	else if ( editors[b] == 2 ) printf "%s & %s", Efull[b,1], Efull[b,2];
	else {
		printf  "%s et al.", Efull[b,1];
	}
}
