#define about "tibtobib 0.3, 1989 by uf"

#include <stdio.h>
#include <ctype.h>

#define maxlines 50
#define linelen 256
#define ntypes 8
#define ntags 18

#define article 0
#define conference 1
#define inbook 2
#define mastersthesis 3
#define phdthesis 4
#define techreport 5
#define book 6
#define misc 7

#define HELP 0
#define NOREF 10
#define NOBIB 11
#define BIGITEM 12
#define NOCONT1 13
#define NOCONT2 14
#define BIGLINE 15
#define BADTAG 16
#define MEMFULL 17

char RCSHeader[]="$Header: /home/tex/local/ttb.c,v 1.3 90/02/15 14:55:30 sk Rel $";

static char *inputtype[]={"ARTICLE","CONFERENCE","INBOOK","MASTERSTHESIS",
			     "PHDTHESIS","TECHREPORT","BOOK","MISC"},
  *recordtype[]={"AUTHOR","BOOKTITLE","ADDRESS","YEAR","EDITOR",
		   "PUBLISHER","JOURNAL","KEY","NUMBER","NOTE","PAGES",
		   "TYPE","SERIES","TITLE","VOLUME","COMMENT","ANNOTE",
		   "ABSTRACT"},
  allowedtag[]={'A','B','C','D','E','I','J','K','N','O','P','R','S','T','V',
		  '%','x','X'},
  organization[]="ORGANIZATION";


char *item[maxlines],buffer[maxlines*linelen],
  reffile[linelen],bibfile[linelen];
int curline=0,type,ilines;

FILE *ref,*bib,*fopen();

main(argc,argv)
int argc;
char **argv;
{ int notready;

  if (argc != 2) {
    fprintf(stderr,"%s, usage: ttb <filename>\n",about);
    exit(HELP);
  }

  strcpy(reffile,argv[1]);
  if ((ref=fopen(reffile,"r")) == NULL) {
    sprintf(reffile,"%s.ref",argv[1]);
    if ((ref=fopen(reffile,"r")) == NULL) {
      fprintf(stderr,"ttb: can open neither %s nor %s\n",argv[1],reffile);
      exit(NOREF);
    }
  }

  if (!strcmp(argv[1]+strlen(argv[1])-4,".ref"))
      argv[1][strlen(argv[1])-4]='\0';
  sprintf(bibfile,"%s.bib",argv[1]);
  if ((bib=fopen(bibfile,"w")) == NULL) {
    fprintf(stderr,"ttb: can't open %s\n",bibfile);
    exit(NOBIB);
  }

  /* main loop */

  do {
    notready=getitem();
    type=classifyitem();
    /* printitem(); */
    putitem();
  }
  while(notready);

  /* exit */

  fclose(ref);
  fclose(bib);
}


getitem()
{ char firstchar,secondchar;
  int i,j,k,ok,ilm1,space,used,ignored=0;

  ilines = 0;
  space = maxlines*linelen-1;
  *item = buffer;

  while(!feof(ref)) {

    if (space<=0) {
      fprintf(stderr,"ttb: %s, %d: buffer space exhausted\n",reffile,curline);
      exit(MEMFULL);
    }

    fgets(item[ilines++],space,ref);
    ilm1 = ilines-1;
    for (k=strlen(item[ilm1])-1; k>-1 && isspace(item[ilm1][k]); item[ilm1][k--]=0)
      ;
    /* printf("%s\n",item[ilm1]); */
    curline++;

    if (ilines>maxlines) {
      fprintf(stderr,"ttb: %s, line %d: too many lines for this item, line ignored\n",reffile,curline);
      ilines--;
      continue;
    }

    if (strlen(item[ilm1]) == 0) {  /* blank line */
      ilines--;
      ignored=0;
      break;
    }

    if ((firstchar=item[ilm1][0]) != '%') {  /* continuation line */
      if (ilines == 1) {
	fprintf(stderr,"ttb: %s, line %d: leading continuation line ignored\n",reffile,curline);
	ilines--;
	continue;
      }
      if (ignored) {
	fprintf(stderr,"ttb: %s, line %d: continuation line ignored\n",reffile,curline);
	ilines--;
	continue;
      }

      ilines--;
      *(item[ilines]-1) = '\n';
      used = strlen(item[ilines])+1;
      item[ilines] += used;
      continue;
    }

    secondchar = item[ilm1][1];
    ok = 0;
    for (i=0; i<ntags; i++)
      if (secondchar == allowedtag[i]) {
	ok = -1;
	break;
      }

    if (!ok) {
      fprintf(stderr,"ttb: %s, line %d: field tag %c not allowed, line ignored\n",reffile,curline,secondchar);
      ignored = -1;
      ilines--;
      continue;
    }

    ignored = 0;
    space -= (used = strlen(item[ilm1])+1);
    item[ilines] = item[ilm1]+used;
  }

  return(!feof(ref));
}


int classifyitem()
{ int p,type;

  if (test('J') && test('V'))
      type = article;
  else
    if (test('B'))
      type = inbook;
    else
      if (p=test('R'))
	if (index(item[p-1],"thesis"))
	  if (index(item[p-1],"master"))
	    type = mastersthesis;
	  else
	    type = phdthesis;
	else
	  type = techreport;
      else
	if (test('I'))
	  type = book;
	else
	  type = conference;
  
  return(type);
}


index(s,t)
char s[],t[];
{ int i,j,k;

  for (i=0; s[i]; i++) {
    for (j=i,k=0; t[k] && tolower(s[j])==tolower(t[k]); j++,k++)
      ;
    if (t[k] == 0)
      return(i+1);
  }

  return(0);
}


int test(c)
char c;
{ int i;

  for (i=0; i<ilines; i++)
    if (item[i][1] == c)
      return(i+1);

  return(0);
}


putitem()
{ char author[linelen],year[linelen],page[linelen],record[linelen],
    editor[linelen],secondchar;
  int i,j,k,p,first;

  if (p=test('A')) {
    if ((i = index(item[p-1],",")) > 4) {
      strcpy(author,item[p-1]+3);
      author[i-4]=0;
    }
    else {
      for (k=strlen(item[p-1]); k>2 && item[p-1][k] != ' ' && item[p-1][k] != '.'; k--)
	;
      strcpy(author,item[p-1]+k+1);
    }
  }
  else
    strcpy(author,"Mr.X");

  if (p=test('D'))
    strcpy(year,item[p-1]+strlen(item[p-1])-2);
  else
    strcpy(year,"??");

  if (p=test('P')) {
    for (i=3; i<strlen(item[p-1]) && (isalpha(item[p-1][i]) && i==3 || isdigit(item[p-1][i])); page[i-3]=item[p-1][i], i++)
      ;
    page[i-3]=0;
  }
  else
    strcpy(page,"0");

  if (p=test('K'))     /* user provides keyword */
    fprintf(bib,"@%s{%s%c\n",inputtype[type],item[p-1]+3,ilines>0 ? ',' : ' ');
  else
    fprintf(bib,"@%s{%s%s:%s%c\n",inputtype[type],author,year,page,ilines>0 ? ',' : ' ');

  /* special cases: several authors, editors */

  first = !0;
  strcpy(author,"");
  if (test('A')) {
    for (i=0; i<ilines; i++) {
      if (item[i][1] == 'A') {
	if (first)
	  first = 0;
	else
	  strcat(author," and ");
	strcat(author,item[i]+3);
      }
    }
    fprintf(bib,"  %s = {%s}%c\n",recordtype[0],author,item[ilines-1][1] != 'A' ? ',' : ' ');
  }
  
  first = !0;
  strcpy(editor,"");
  if (test('E')) {
    for (i=0; i<ilines; i++) {
      if (item[i][1] == 'E') {
	if (first)
	  first = 0;
	else
	  strcat(editor," and ");
	strcat(editor,item[i]+3);
      }
    }
    fprintf(bib,"  %s = {%s}%c\n",recordtype[4],editor,item[ilines-1][1] != 'E' ? ',' : ' ');
  }

  /* all other fields */
  
  for (i=0; i<ilines; i++) {
    secondchar = item[i][1];
    if (secondchar == 'A' || secondchar == 'E')
      continue;
    
    /* special case: %J in a conference */
    
    if (secondchar == 'J' && type == conference)
      strcpy(record,organization);
    
    /* all other cases */
    
    else
      for (j=0; j<ntags; j++)
	if (secondchar == allowedtag[j]) {
	  strcpy(record,recordtype[j]);
	  break;
	}
    
    fprintf(bib,"  %s = {%s}%c\n",record,item[i]+3,i<ilines-1 ? ',' : ' ');
  }
  
  fprintf(bib,"}\n\n");
}

option(argc,argv,c)
char **argv,c;
int argc;
{ int i,j;

  for (i=1; i<argc; i++)
    if (argv[i][0] == '-')
      for (j=1; j<strlen(argv[i]); j++)
	if (argv[i][j] == c)
	  return(i);
  return(0);
}

printitem()
{ int i;

  for (i=0; i<ilines; i++)
    printf("%s\n",item[i]);
  printf("\nitem consisting of %d lines, type = %d\n\n",ilines,type);
}