home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume2 / refer2tex / r2bib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-07  |  7.6 KB  |  377 lines

  1. /* r2bib - convert refer input files to bibtex .bib files
  2.    Author - Rusty Wright, Center for Music Experiment, UCSD
  3.    Modified by - Rod Oldehoeft, LLNL & Colorado State University:
  4. From: Rod Oldehoeft <rro@lll-crg.ARPA>
  5.       1.  Accept a lower-case refer letter code as well as upper case
  6.       2.  Map "%X" refer entry to "note=" bibtex entry
  7.       3.  A "%B" entry results in "@inbook" result
  8.       4.  Use {} instead of "" to bracket output fields
  9.      5.  Map "%M" to "month=" bibtex entry
  10.      6.  Map "%Y" to "year=" bibtex entry
  11.       7.  Try to make bibtex entry key from author initials and year
  12.    Modified by David Kotz, Duke University Computer Science (dfk@cs.duke.edu):
  13.    1. Fixed a bug (indirect through NULL) found when run on Suns.
  14.    2. Make the keyword generator smarter about dates and repeated entries.
  15.       To use this effectively do a 'sortbib -sA+D' on the file before sending
  16.      it through here.
  17.    3. map %K to keywords and %X to abstract instead of note. %O maps to note.
  18. */
  19. # include <ctype.h>
  20. # include <stdio.h>
  21.  
  22. struct rb {
  23.     char    rb_kl;        /* refer key letter        */
  24.     char *    rb_kw;        /* bibtex string        */
  25.     char    rb_emit;    /* don't print data if 0    */
  26.     char *    rb_data;    /* refer data            */
  27. };
  28.  
  29. struct rb rb[] = {
  30.     { 'A',    "author",        1,    NULL    },
  31.     { 'B',    "booktitle",    1,    NULL    },
  32.     { 'C',    "address",    1,    NULL    },
  33.     { 'D',    "year",        1,    NULL    },
  34.     { 'E',    "editor",        1,    NULL    },
  35. /*    { 'H',    "commentary1",    1,    NULL    },*/
  36.     { 'I',    "publisher",    1,    NULL    },
  37.     { 'J',    "journal",    1,    NULL    },
  38.     { 'K',    "keywords",    1,    NULL    },
  39.     { 'L',    "label",        0,    NULL    },    /* use as bibtex key */
  40.      { 'M',    "month",        1,    NULL },
  41.     { 'N',    "number",        1,    NULL    },
  42.     { 'O',    "note",        1,    NULL    },
  43.     { 'P',    "pages",        1,    NULL    },
  44.     { 'Q',    "institution",    1,    NULL    },
  45.     { 'R',    "report",        0,    NULL    },
  46.     { 'S',    "series",        1,    NULL    },
  47.     { 'T',    "title",        1,    NULL    },
  48.     { 'V',    "volume",        1,    NULL    },
  49.     { 'X',    "abstract",    1,    NULL    },
  50.     { 'Y',    "year",        1,    NULL },
  51.     { 0,    0,        0,    0    }
  52. };
  53.  
  54. struct bmap {
  55.     char    bm_kl;
  56.     char    *bm_entry;
  57. };
  58.  
  59. /*
  60.  * entries are in order of precedence.
  61.  * any entry with a 'J' field must be
  62.  * an article, but anthing with an 'I'
  63.  * field doesn't have to be a book (if
  64.  * an entry has both 'J' and 'I' it is
  65.  * considered to be an article).
  66.  */
  67. struct bmap    bmap[] = {
  68.     { 'J',    "article"    },
  69.     { 'R',    "techreport"    },
  70.     { 'I',    "book"    },
  71.     { 'B',    "inbook"    },
  72.     { 0,    0        }
  73. };
  74.  
  75. main(argc, argv)
  76.     char        **argv;
  77. {
  78.     register FILE    *fid;
  79.     register int    i;
  80.     int        err;
  81.  
  82.     err = 0;
  83.  
  84.     if (argc > 1) {
  85.         for (i = 1; i < argc; i++) {
  86.             if ((fid = fopen(argv[i], "r")) == NULL) {
  87.                 fprintf(stderr, "fopen: ");
  88.                 perror(argv[i]);
  89.                 continue;
  90.             }
  91.             err += r2bib(argv[i], fid);
  92.         }
  93.     }
  94.     else
  95.         err += r2bib("stdin", stdin);
  96.  
  97.     if (err)
  98.         exit(1);
  99.  
  100.     exit(0);
  101. }
  102.  
  103. r2bib(file, fid)
  104.     char        *file;
  105.     FILE        *fid;
  106. {
  107.     extern char    *sanz();
  108.     register char    *cp;
  109.     struct rb    *lrb;        /* last rb stored into */
  110.     int        line;
  111.     char        buf[BUFSIZ];
  112.     int        err;
  113.  
  114.     lrb = NULL;
  115.     err = 0;
  116.     line = 0;
  117.  
  118.     while (fgets(buf, sizeof(buf), fid) != NULL) {
  119.         line++;
  120.  
  121.         if ((cp = sanz(buf)) == NULL) {
  122.             if (lrb != NULL) {
  123.                 dumprb();
  124.                 lrb = NULL;
  125.             }
  126.             continue;
  127.         }
  128.  
  129.         /*
  130.          * if the first letter is a % then it's the
  131.          * a new record, otherwise it's a continuation
  132.          * of the previous one.
  133.          */
  134.         if (cp[0] == '%') {
  135.             for (lrb = &rb[0]; lrb->rb_kl != 0; lrb++) {
  136.                 if(lrb->rb_kl == (islower(cp[1]) ? toupper(cp[1]) : cp[1])){
  137.                     stuffrb(lrb, &cp[2]);
  138.                     break;
  139.                 }
  140.             }
  141.             if (lrb->rb_kl == 0) {
  142.                 fprintf(stderr, "r2b: %s: line %d: unknown key letter %c, ignoring\n", file, line, cp[1]);
  143.                 err = 1;
  144.             }
  145.         }
  146.         else {
  147.             if (lrb == NULL) {
  148.                 fprintf(stderr, "r2b: %s: line %d: bad format, ignoring\n", file, line);
  149.                 err = 1;
  150.                 continue;
  151.             }
  152.  
  153.             stuffrb(lrb, &cp[0]);
  154.         }
  155.     }
  156.  
  157.     if (lrb != NULL)
  158.         dumprb();
  159.  
  160.     return(err);
  161. }
  162.  
  163. #define KEYSIZ 100            /* hopefully long enough */
  164.  
  165. dumprb() {
  166.     register struct rb    *trb;
  167.     register struct bmap    *bm;
  168.     static int        key;
  169.     char            *bibkey;
  170.     char            *cp;
  171.     int            first;
  172.     static char lastkey[KEYSIZ];    /* the previous key we output */
  173.     char thiskey[KEYSIZ];    /* key we are now building */
  174.     static int repeat = 0;
  175.  
  176.     /*
  177.      * first, figure out what type of entry this
  178.      * is.
  179.      */
  180.     for (bm = &bmap[0]; bm->bm_kl != 0; bm++) {
  181.         for (trb = &rb[0]; trb->rb_kl != 0; trb++) {
  182.             if ((trb->rb_kl == bm->bm_kl) && (trb->rb_data != NULL)) {
  183.                 printf("@%s{", bm->bm_entry);
  184.                 goto out;
  185.             }
  186.         }
  187.     }
  188. out:
  189.     if (bm->bm_kl == 0)
  190.         printf("@misc{");
  191.  
  192.     /*
  193.      * in order of precedence; how to determine the
  194.      * bibtex key:
  195.      *    1. use capital letters from %A, followed if possible
  196.       *      by the two chars after "19" in %D or %Y field.
  197.      *    2. otherwise just use the string "keyN" where N
  198.      *       is the count of this bibliographic entry in
  199.      *       the refer file.
  200.      */
  201.  
  202.     key++;
  203.     bibkey = thiskey;
  204.  
  205.     for (trb = &rb[0]; trb->rb_kl != 0; trb++) {
  206.         if( trb->rb_kl == 'A'){
  207.             if( trb->rb_data == NULL ) {
  208.                 sprintf(thiskey, "key%d,\n",key); 
  209.                 printf("key%d",key);
  210.                 break;
  211.             }else{
  212.                 for( cp = trb->rb_data; *cp != NULL; cp++ ) {
  213.                     if( isupper(*cp)) {
  214.                         printf("%c", *cp);
  215.                         *bibkey++ = *cp;
  216.                     }
  217.                 };
  218.                 *bibkey = '\0';
  219.             };
  220.         }else{ if((trb->rb_kl == 'D') || (trb->rb_kl == 'Y')) {
  221.                 for( cp = trb->rb_data; cp != NULL && *cp != NULL; cp++ ) {
  222.                     if(isdigit(cp[0]) && isdigit(cp[1]) &&
  223.                        isdigit(cp[2]) && isdigit(cp[3])) {
  224.                          *bibkey++ = cp[2];
  225.                          *bibkey++ = cp[3];
  226.                         printf("%c%c", cp[2], cp[3]);
  227.                         break;
  228.                     };
  229.                 };
  230.                 *bibkey = '\0';
  231.                 break;
  232.               };
  233.         };
  234.     };
  235.  
  236.     if (strcmp(thiskey, lastkey) == 0) {
  237.         /* key was the same as previous; add a letter */
  238.         printf("%c", 'a' + repeat++);
  239.     } else {
  240.         /* key differed from previous, but remember it */
  241.         strcpy(lastkey, thiskey);
  242.         repeat = 0;
  243.     }
  244.  
  245.     printf(",\n");
  246.  
  247.     first = 1;
  248.  
  249.     for (trb = &rb[0]; trb->rb_kl != 0; trb++) {
  250.         if (trb->rb_data == NULL)
  251.             continue;
  252.  
  253.         if (trb->rb_emit != 0) {
  254.             /*
  255.              * clank,
  256.              * this is so that things will line up.
  257.              */
  258.             if (strlen(trb->rb_kw) < 6)
  259.                 cp = "\t\t";
  260.             else
  261.                 cp = "\t";
  262.  
  263.             if (! first)
  264.                 printf(",\n");
  265.  
  266.             printf("\t%s =%s{%s}", trb->rb_kw, cp, trb->rb_data);
  267.             first = 0;
  268.         }
  269.  
  270.         (void) free(trb->rb_data);
  271.         trb->rb_data = NULL;
  272.     }
  273.  
  274.     printf("\n}\n\n");
  275. }
  276.  
  277. stuffrb(lrb, cp)
  278.     struct rb    *lrb;
  279.     char        *cp;
  280. {
  281.     extern char    *andfix();
  282.     extern char    *malloc();
  283.     extern char    *realloc();
  284.  
  285.     /* empty data field */
  286.     if ((cp = sanz(cp)) == NULL)
  287.         return;
  288.  
  289.     if (lrb->rb_kl == 'A')
  290.         cp = andfix(cp);
  291.  
  292.     if (lrb->rb_data == NULL) {
  293.         if ((lrb->rb_data = malloc(strlen(cp) + 1)) == NULL) {
  294.             perror("malloc");
  295.             exit(1);
  296.         }
  297.  
  298.         strcpy(lrb->rb_data, cp);
  299.     }
  300.     else {
  301.         char    *conj;
  302.  
  303.         if (lrb->rb_kl == 'A')
  304.             conj = " and ";
  305.         else
  306.             conj = " ";
  307.  
  308.         if ((lrb->rb_data = realloc(lrb->rb_data, strlen(lrb->rb_data) + strlen(cp) + strlen(conj) + 1)) == NULL) {
  309.             perror("realloc");
  310.             exit(1);
  311.         }
  312.  
  313.         strcat(lrb->rb_data, conj);
  314.         strcat(lrb->rb_data, cp);
  315.     }
  316. }
  317.  
  318. /*
  319.  */
  320. char *
  321. andfix(string)
  322.     register char    *string;
  323. {
  324.     register char    *tmp;
  325.     register char    *cp;
  326.  
  327.     tmp = string;
  328.  
  329.     for (cp = string; *cp != NULL; cp++) {
  330.         if (strncmp(cp, " and ", 5) == 0) {
  331.             /*
  332.              * +2 for the curly braces around "{and}",
  333.              * +1 for the null at the end.
  334.              */
  335.             if ((tmp = malloc(strlen(string) + 2 + 1)) == NULL) {
  336.                 perror("malloc");
  337.                 exit(1);
  338.             }
  339.  
  340.             strncpy(tmp, string, cp - string);
  341.             tmp[cp - string] = NULL; /* strncpy doesn't */
  342.             strcat(tmp, " {and} ");
  343.             strcat(tmp, cp + 5);
  344.         }
  345.     }
  346.  
  347.     return(tmp);
  348. }
  349.  
  350. char *
  351. sanz(bp)
  352.     char        *bp;
  353. {
  354.     register char    *cp;
  355.  
  356.     cp = &bp[strlen(bp) - 1];
  357.  
  358.     /*
  359.      * back up over any spaces chars
  360.      */
  361.     while (isspace(*cp) && (cp >= bp))
  362.         cp--;
  363.  
  364.     if (cp < bp)
  365.         return(NULL);    /* empty line */
  366.  
  367.     *++cp = NULL;
  368.  
  369.     while (isspace(*bp) && (bp < cp))
  370.         bp++;
  371.  
  372.     if (cp == bp)
  373.         return(NULL);    /* empty line */
  374.  
  375.     return(bp);
  376. }
  377.