#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);
}