/* http://www.ctan.org/tex-archive/biblio/bibtex/utils/r2bib/ */ # include # include # include # include struct rb { char rb_kl; /* refer key letter */ char * rb_kw; /* bibtex string */ char rb_emit; /* don't print data if 0 */ char * rb_data; /* refer data */ }; struct rb rb[] = { { 'A', "author", 1, NULL }, { 'B', "booktitle", 1, NULL }, { 'C', "address", 1, NULL }, { 'D', "year", 1, NULL }, /* mismatch */ { 'E', "editor", 1, NULL }, /* { 'H', "commentary1", 1, NULL },*/ { 'I', "publisher", 1, NULL }, { 'J', "journal", 1, NULL }, { 'K', "note", 1, NULL }, /* mismatch */ { 'L', "label", 0, NULL }, /* use as bibtex key */ { 'N', "number", 1, NULL }, /* { 'O', "commentary2", 1, NULL },*/ { 'P', "pages", 1, NULL }, { 'Q', "institution", 1, NULL }, { 'R', "report", 0, NULL }, { 'S', "series", 1, NULL }, { 'T', "title", 1, NULL }, { 'V', "volume", 1, NULL }, /* { 'X', "abstract", 1, NULL },*/ { 0, 0, 0, 0 } }; struct bmap { char bm_kl; char *bm_entry; }; /* * entries are in order of precedence. * any entry with a 'J' field must be * an article, but anthing with an 'I' * field doesn't have to be a book (if * an entry has both 'J' and 'I' it is * considered to be an article). */ struct bmap bmap[] = { { 'J', "article" }, { 'R', "techreport" }, { 'I', "book" }, { 0, 0 } }; void dumprb() { register struct rb *trb; register struct bmap *bm; static int key; char *bibkey; char *cp; int first; /* * first, figure out what type of entry this * is. */ for (bm = &bmap[0]; bm->bm_kl != 0; bm++) { for (trb = &rb[0]; trb->rb_kl != 0; trb++) { if ((trb->rb_kl == bm->bm_kl) && (trb->rb_data != NULL)) { printf("@%s{", bm->bm_entry); goto out; } } } out: if (bm->bm_kl == 0) printf("@misc{"); /* * in order of precedence; how to determine the * bibtex key: * 1. use keyword (%K) if only one word. * 2. use refer label (%L). * 3. otherwise just use the string "keyN" where N * is the count of this bibliographic entry in * the refer file. */ key++; for (trb = &rb[0]; trb->rb_kl != 0; trb++) { if ((trb->rb_kl == 'K') && (trb->rb_data != NULL)) { for (cp = trb->rb_data; *cp ; cp++) { if (isspace(*cp)) break; } /* ran to end of string? */ if (*cp == 0) { printf("%s,\n", trb->rb_data); /* if used here then free & zero it */ (void) free(trb->rb_data); trb->rb_data = NULL; break; } } if ((trb->rb_kl == 'L') && (trb->rb_data != NULL)) { for (cp = trb->rb_data; *cp ; cp++) { if (isspace(*cp)) break; } /* ran to end of string? */ if (*cp == 0) { printf("%s,\n", trb->rb_data); break; } } } /* nothing reasonable to use, punt */ if (trb->rb_kl == 0) printf("key%d,\n", key); first = 1; for (trb = &rb[0]; trb->rb_kl != 0; trb++) { if (trb->rb_data == NULL) continue; if (trb->rb_emit != 0) { /* * clank, * this is so that things will line up. */ if (strlen(trb->rb_kw) < 6) cp = "\t\t"; else cp = "\t"; if (! first) printf(",\n"); printf("\t%s =%s\"%s\"", trb->rb_kw, cp, trb->rb_data); first = 0; } (void) free(trb->rb_data); trb->rb_data = NULL; } printf("\n}\n\n"); } void stuffrb(struct rb *lrb, char *cp) { extern char *andfix(); extern char *sanz(); /* empty data field */ if ((cp = sanz(cp)) == NULL) return; if (lrb->rb_kl == 'A') cp = andfix(cp); if (lrb->rb_data == NULL) { if ((lrb->rb_data = malloc(strlen(cp) + 1)) == NULL) { perror("malloc"); exit(1); } strcpy(lrb->rb_data, cp); } else { char *conj; if (lrb->rb_kl == 'A') conj = " and "; else conj = " "; if ((lrb->rb_data = realloc(lrb->rb_data, strlen(lrb->rb_data) + strlen(cp) + strlen(conj) + 1)) == NULL) { perror("realloc"); exit(1); } strcat(lrb->rb_data, conj); strcat(lrb->rb_data, cp); } } int r2bib(char * file, FILE * fid) { extern char *sanz(); register char *cp; struct rb *lrb; /* last rb stored into */ int line; char buf[BUFSIZ]; int err; lrb = NULL; err = 0; line = 0; while (fgets(buf, sizeof(buf), fid) != NULL) { line++; if ((cp = sanz(buf)) == NULL) { if (lrb != NULL) { dumprb(); lrb = NULL; } continue; } /* * if the first letter is a % then it's the * a new record, otherwise it's a continuation * of the previous one. */ if (cp[0] == '%') { for (lrb = &rb[0]; lrb->rb_kl != 0; lrb++) { if (lrb->rb_kl == cp[1]) { stuffrb(lrb, &cp[2]); break; } } if (lrb->rb_kl == 0) { fprintf(stderr, "r2b: %s: line %d: unknown key letter %c, ignoring\n", file, line, cp[1]); err = 1; } } else { if (lrb == NULL) { fprintf(stderr, "r2b: %s: line %d: bad format, ignoring\n", file, line); err = 1; continue; } stuffrb(lrb, &cp[0]); } } if (lrb != NULL) dumprb(); return(err); } int main(int argc, char *argv[]) { register FILE *fid; register int i; int err; err = 0; if (argc > 1) { for (i = 1; i < argc; i++) { if ((fid = fopen(argv[i], "r")) == NULL) { fprintf(stderr, "fopen: "); perror(argv[i]); continue; } err += r2bib(argv[i], fid); } } else err += r2bib("stdin", stdin); if (err) exit(1); exit(0); } /* */ char * andfix(char *string) { register char *tmp; register char *cp; tmp = string; for (cp = string; *cp ; cp++) { if (strncmp(cp, " and ", 5) == 0) { /* * +2 for the curly braces around "{and}", * +1 for the null at the end. */ if ((tmp = malloc(strlen(string) + 2 + 1)) == NULL) { perror("malloc"); exit(1); } strncpy(tmp, string, cp - string); tmp[cp - string] = 0; /* strncpy doesn't */ strcat(tmp, " {and} "); strcat(tmp, cp + 5); } } return(tmp); } char * sanz(char *bp) { register char *cp; cp = &bp[strlen(bp) - 1]; /* * back up over any spaces chars */ while (isspace(*cp) && (cp >= bp)) cp--; if (cp < bp) return(NULL); /* empty line */ *++cp = 0; while (isspace(*bp) && (bp < cp)) bp++; if (cp == bp) return(NULL); /* empty line */ return(bp); }