|
|
1.1 ! root 1: /* ! 2: * Facilitate entry of references ! 3: */ ! 4: ! 5: #include <stdio.h> ! 6: #include <signal.h> ! 7: #include <sys/types.h> ! 8: #include <sys/stat.h> ! 9: ! 10: #define TEMPLATE "/usr/frodo/lib/refer/template" ! 11: #define REFER "refer.out" ! 12: #define TMPREF "/tmp/referXXXXXX" ! 13: ! 14: #ifdef PREFER ! 15: #define TYPE "%type" ! 16: #endif /* PREFER */ ! 17: ! 18: #define TRUE (1) ! 19: #define FALSE (0) ! 20: ! 21: #define EDITOR "EDITOR" ! 22: #define VISUAL "VISUAL" ! 23: ! 24: struct ref { ! 25: struct ref *r_next; /* next reference node */ ! 26: char *r_prompt; /* prompt for reference */ ! 27: struct att *r_att; /* attributes */ ! 28: }; ! 29: ! 30: struct att { ! 31: struct att *a_next; /* next attribute node */ ! 32: char a_flag; /* prompt flag */ ! 33: char *a_prompt; /* prompt for attribute */ ! 34: char *a_def; /* default value for attribute */ ! 35: char *a_refer; /* refer string to output */ ! 36: char *a_mcont; /* middle continue string to output */ ! 37: char *a_econt; /* end continue string to output */ ! 38: }; ! 39: ! 40: char ! 41: *getenv(), ! 42: *malloc(), ! 43: *mktemp(), ! 44: *strchr(), ! 45: *strtok(), ! 46: *tmpref ! 47: ; ! 48: ! 49: int cleanup(); ! 50: ! 51: FILE ! 52: *tmpopen(), ! 53: *tmp, ! 54: *refer ! 55: ; ! 56: ! 57: void ! 58: fixrefer(), ! 59: edit() ! 60: ; ! 61: ! 62: struct ref ! 63: *ref, ! 64: *sr ! 65: ; ! 66: ! 67: main(argc, argv) ! 68: int argc; ! 69: char *argv[]; ! 70: { ! 71: register char ! 72: *tempname, ! 73: *refname ! 74: ; ! 75: ! 76: signal(SIGINT, cleanup); ! 77: signal(SIGQUIT, cleanup); ! 78: ! 79: tempname = refname = NULL; ! 80: while (--argc) { ! 81: if (!strcmp("-o", *++argv)) { ! 82: refname = *++argv; ! 83: --argc; ! 84: } else ! 85: tempname = *argv; ! 86: } ! 87: readtemplate(tempname ? tempname : TEMPLATE); ! 88: ! 89: if ((refer = fopen(refname ? refname : REFER, "a")) == NULL) ! 90: errexit(1, "Can't open reference file, %s\n", REFER); ! 91: ! 92: doreferences(); ! 93: } ! 94: ! 95: /* ! 96: * Process all user input. ! 97: */ ! 98: doreferences() ! 99: { ! 100: int cont; ! 101: struct ref ! 102: *rr, ! 103: *r ! 104: ; ! 105: struct att *a; ! 106: char buf[BUFSIZ]; ! 107: register char ! 108: *p, ! 109: *bufp ! 110: ; ! 111: char comm[80]; ! 112: ! 113: tmpref = mktemp(TMPREF); ! 114: sr = NULL; ! 115: for (;;) { ! 116: sprintf(comm, "Reference type [%s] ", ref->r_prompt); ! 117: if (getln(comm, buf, sizeof(buf)) == NULL) ! 118: cleanup(); ! 119: ! 120: if ((p = strchr(&buf[0], '\n')) != NULL) ! 121: *p = '\0'; ! 122: ! 123: if (!strlen(&buf[0])) ! 124: strcpy(&buf[0], ref->r_prompt); ! 125: ! 126: switch (match(&rr, buf)) { ! 127: case 0: ! 128: printf("Legal reference types are:\n"); ! 129: for (r = ref; r; r = r->r_next) ! 130: printf("%s\n", r->r_prompt); ! 131: continue; ! 132: ! 133: case 1: ! 134: r = rr; ! 135: break; ! 136: ! 137: default: /* handled in match() */ ! 138: continue; ! 139: } ! 140: ! 141: if (!strcmp(r->r_prompt, "quit")) ! 142: cleanup(); ! 143: ! 144: fixrefer(); ! 145: ! 146: if (!strcmp(r->r_prompt, "help")) { ! 147: help(); ! 148: continue; ! 149: } ! 150: ! 151: printf("referencing a %s\n", r->r_prompt); ! 152: sr = r; ! 153: if ((tmp = fopen(tmpref, "w")) == NULL) ! 154: errexit(1, "Can't open %s\n", tmpref); ! 155: ! 156: for (a = r->r_att; a; a = a->a_next) { ! 157: if (a->a_flag == '!') ! 158: continue; ! 159: do { ! 160: do { ! 161: if (a->a_def[0]) ! 162: sprintf(comm, "%s [%s]: ", ! 163: a->a_prompt, a->a_def); ! 164: else ! 165: sprintf(comm, "%s: ", a->a_prompt); ! 166: if (getln(comm, buf, sizeof(buf)) == NULL) ! 167: cleanup(); ! 168: ! 169: p = strchr(buf, '\n'); ! 170: *p = '\0'; ! 171: ! 172: if (a->a_flag == '\0' && !strlen(buf) ! 173: && !a->a_def[0]) ! 174: printf("The %s field is not optional\n", ! 175: a->a_prompt); ! 176: else if (a->a_def[0]) ! 177: break; ! 178: } while (a->a_flag == '\0' && !strlen(buf)); ! 179: ! 180: if ((cont = strlen(buf)) != 0 && buf[strlen(buf) - 1] == '&') ! 181: buf[strlen(buf) - 1] = '\0'; ! 182: else ! 183: cont = 0; ! 184: ! 185: bufp = buf; ! 186: while (*bufp == ' ' || *bufp == '\t') ! 187: ++bufp; ! 188: if (strlen(buf)) ! 189: fprintf(tmp, "%s: %s\n", a->a_prompt, bufp); ! 190: else ! 191: fprintf(tmp, "%s: %s\n", a->a_prompt, a->a_def); ! 192: fflush(tmp); ! 193: } while (cont != 0); ! 194: fflush(tmp); ! 195: } ! 196: fprintf(tmp, "\n"); ! 197: fclose(tmp); ! 198: } ! 199: } ! 200: ! 201: /* ! 202: * Print out all attributes for a given reference; ``?'' for all. ! 203: */ ! 204: help() ! 205: { ! 206: register struct att *a; ! 207: char helpref[BUFSIZ]; ! 208: struct ref *r; ! 209: ! 210: printf("which reference type: "); ! 211: fgets(helpref, sizeof(helpref), stdin); ! 212: helpref[strlen(&helpref[0]) - 1] = '\0'; ! 213: switch (match(&r, helpref)) { ! 214: case 0: ! 215: if (!strcmp(helpref, "?")) { ! 216: for (r = ref; r; r = r->r_next) { ! 217: printf("%s:\n", r->r_prompt); ! 218: for (a = r->r_att; a; a = a->a_next) ! 219: printf("\t%s\n", a->a_prompt); ! 220: } ! 221: } else ! 222: printf("No matches for %s\n", helpref); ! 223: break; ! 224: ! 225: case 1: ! 226: printf("Attributes for `%s':\n", r->r_prompt); ! 227: for (a = r->r_att; a; a = a->a_next) ! 228: printf("\t%s\n", a->a_prompt); ! 229: break; ! 230: } ! 231: } ! 232: ! 233: /* ! 234: * Read in references from template file ! 235: */ ! 236: readtemplate(file) ! 237: char *file; ! 238: { ! 239: FILE *template; ! 240: register char ! 241: *p, ! 242: *pp ! 243: ; ! 244: register struct att *a = NULL; ! 245: char buf[BUFSIZ]; ! 246: struct ref *r = NULL; ! 247: ! 248: template = tmpopen(file); ! 249: while (fgets(&buf[0], sizeof(buf), template) != NULL) { ! 250: if ((p = strchr(&buf[0], '\n')) != NULL) ! 251: *p = '\0'; ! 252: ! 253: switch (buf[0]) { ! 254: case ':': ! 255: continue; ! 256: ! 257: case '\t': ! 258: if (r == NULL) ! 259: errexit(1, "Attribute without reference active\n"); ! 260: ! 261: if (a == NULL) { ! 262: if ((a = r->r_att = ! 263: (struct att *)malloc((unsigned)sizeof(struct att))) ! 264: == NULL) ! 265: errexit(1, "Out of memory for attributes\n"); ! 266: } else if ((a = a->a_next = ! 267: (struct att *)malloc((unsigned)sizeof(struct att))) == NULL) ! 268: errexit(1, "Out of memory for attributes\n"); ! 269: p = &buf[1]; ! 270: ! 271: switch (*p) { ! 272: case '?': ! 273: case '-': ! 274: case '!': ! 275: a->a_flag = *p++; ! 276: break; ! 277: ! 278: default: ! 279: a->a_flag = '\0'; ! 280: } ! 281: ! 282: if ((p = strtok(p, "\n\t")) == NULL) ! 283: errexit(1, "Attribute without prompt\n"); ! 284: ! 285: if ((a->a_prompt = malloc((unsigned)strlen(p) + 1)) == NULL) ! 286: errexit(1, "Out of memory for attribute prompt\n"); ! 287: strcpy(a->a_prompt, p); ! 288: if ((pp = strchr(a->a_prompt, '[')) != NULL) { ! 289: *pp = '\0'; ! 290: while (a->a_prompt[strlen(a->a_prompt) - 1] == ' ') ! 291: a->a_prompt[strlen(a->a_prompt) - 1] = '\0'; ! 292: if ((a->a_def = malloc((unsigned)strlen(pp + 1) + 1)) ! 293: == NULL) ! 294: errexit(1, "Out of memory for attribute default\n"); ! 295: strcpy(a->a_def, pp + 1); ! 296: if ((pp = strchr(a->a_def, ']')) == NULL) ! 297: errexit(1, "Unmatched []\n"); ! 298: *pp = '\0'; ! 299: } else ! 300: a->a_def = ""; ! 301: ! 302: if ((p = strtok(NULL, "\t\n")) == NULL) ! 303: errexit(1, "Attribute without refer\n"); ! 304: ! 305: if ((a->a_refer = malloc((unsigned)strlen(p) + 1)) == NULL) ! 306: errexit(1, "Out of memory for attribute refer\n"); ! 307: ! 308: strcpy(a->a_refer, p); ! 309: ! 310: a->a_next = NULL; ! 311: ! 312: if ((p = strtok(NULL, "\n\t")) == NULL || !strcmp(p, "NULL")) ! 313: a->a_mcont = ""; ! 314: else { ! 315: if ((a->a_mcont = malloc((unsigned)strlen(p) + 1)) ! 316: == NULL) ! 317: errexit(1, "Out of memory for attribute continue\n"); ! 318: strcpy(a->a_mcont, p); ! 319: } ! 320: ! 321: if ((p = strtok(NULL, "\n\t")) == NULL || !strcmp(p, "NULL")) ! 322: a->a_econt = ""; ! 323: else { ! 324: if ((a->a_econt = malloc((unsigned)strlen(p) + 1)) ! 325: == NULL) ! 326: errexit(1, "Out of memory for attribute continue\n"); ! 327: strcpy(a->a_econt, p); ! 328: } ! 329: ! 330: break; ! 331: ! 332: default: ! 333: addref(&r, buf); ! 334: a = NULL; ! 335: } ! 336: } ! 337: fclose(template); ! 338: ! 339: addref(&r, "help"); ! 340: addref(&r, "quit"); ! 341: r->r_next = NULL; ! 342: } ! 343: ! 344: /* ! 345: * Add a reference with prompt. ! 346: */ ! 347: addref(r, prompt) ! 348: register struct ref **r; ! 349: char *prompt; ! 350: { ! 351: if (ref == NULL) { ! 352: if ((*r = ref = (struct ref *)malloc((unsigned)sizeof(struct ref))) ! 353: == NULL) ! 354: errexit(1, "Out of memory for reference.\n"); ! 355: } else if ((*r = (*r)->r_next = (struct ref *)malloc((unsigned)sizeof(struct ref))) ! 356: == NULL) ! 357: errexit(1, "Out of memory for references\n"); ! 358: ! 359: if (((*r)->r_prompt = malloc((unsigned)strlen(prompt) + 1)) == NULL) ! 360: errexit(1, "Out of memory for reference prompt\n"); ! 361: strcpy((*r)->r_prompt, prompt); ! 362: (*r)->r_next = NULL; ! 363: (*r)->r_att = NULL; ! 364: } ! 365: ! 366: /* ! 367: * Get a line to process; if ~e or ~v call editors. ! 368: */ ! 369: getln(msg, str, sz) ! 370: register char *msg, *str; ! 371: int sz; ! 372: { ! 373: for (;;) { ! 374: printf(msg); ! 375: if (fgets(str, sz, stdin) == NULL) ! 376: return(NULL); ! 377: ! 378: if (!strcmp(str, "~e\n")) ! 379: edit(EDITOR); ! 380: else if (!strcmp(str, "~v\n")) ! 381: edit(VISUAL); ! 382: else ! 383: return(1); ! 384: } ! 385: } ! 386: ! 387: char ! 388: editor[80], ! 389: veditor[80] ! 390: ; ! 391: ! 392: /* ! 393: * Call one of the editors on the text entered so far. ! 394: */ ! 395: void ! 396: edit(which) ! 397: char *which; ! 398: { ! 399: char command[100]; ! 400: ! 401: if (!editor[0]) ! 402: open_ed(editor, EDITOR); ! 403: if (!veditor[0]) ! 404: open_ed(veditor, VISUAL); ! 405: ! 406: if (tmp) ! 407: fclose(tmp); ! 408: else { ! 409: printf("There is no file yet.\n"); ! 410: return; ! 411: } ! 412: ! 413: sprintf(command, "%s %s", (!strcmp(which, EDITOR) ? editor : veditor), ! 414: tmpref); ! 415: system(command); ! 416: tmp = fopen(tmpref, "a+"); ! 417: } ! 418: ! 419: /* ! 420: * Get user's editors as set in environment or else use ed or vi. ! 421: */ ! 422: open_ed(ed, which) ! 423: register char *ed, *which; ! 424: { ! 425: char *p; ! 426: struct stat e_stat; ! 427: ! 428: if (p = getenv(which)) ! 429: strcpy(ed, p); ! 430: if (!ed[0] || stat(ed, &e_stat) == -1) ! 431: strcpy(ed, (!strcmp(which, EDITOR) ? "/bin/ed" : "/usr/bin/vi")); ! 432: } ! 433: ! 434: /* ! 435: * Write out to file. ! 436: */ ! 437: void ! 438: fixrefer() ! 439: { ! 440: char ! 441: buf[BUFSIZ], ! 442: savestr[BUFSIZ] ! 443: ; ! 444: register char ! 445: *bufp, ! 446: *p ! 447: ; ! 448: register struct ref *r; ! 449: register struct att ! 450: *a, ! 451: *t ! 452: ; ! 453: int ! 454: first = 1, ! 455: printed ! 456: ; ! 457: ! 458: if ((tmp = fopen(tmpref, "r")) == NULL) ! 459: return; ! 460: ! 461: if ((r = sr) == NULL) ! 462: return; ! 463: ! 464: a = r->r_att; ! 465: if (fgets(buf, sizeof buf, tmp) == NULL) ! 466: return; ! 467: #ifdef PREFER ! 468: putrefer(refer, "%s %s\n", TYPE, r->r_prompt); ! 469: #endif /* PREFER */ ! 470: ! 471: if ((p = strchr(buf, '\n')) != NULL) ! 472: *p = '\0'; ! 473: ! 474: for (t = a; t; t = t->a_next) ! 475: if (!strncmp(t->a_prompt, buf, strlen(t->a_prompt))) ! 476: break; ! 477: ! 478: if (t) { ! 479: bufp = buf + strlen(t->a_prompt); ! 480: if (*bufp == ':') ! 481: bufp += 2; ! 482: } else ! 483: return; ! 484: a = t; ! 485: if (a->a_flag != '!') ! 486: strcpy(savestr, bufp); ! 487: while (fgets(&buf[0], sizeof(buf), tmp) != NULL) { ! 488: if ((p = strchr(buf, '\n')) != NULL) ! 489: *p = '\0'; ! 490: ! 491: for (t = a; t; t = t->a_next) { ! 492: if (!strncmp(t->a_prompt, buf, strlen(t->a_prompt))) ! 493: break; ! 494: } ! 495: ! 496: if (t && t != a) { ! 497: if (first && a->a_flag != '!') /* first line */ ! 498: putrefer(refer, "%s %s\n", a->a_refer, savestr); ! 499: else if (a->a_flag != '!') /* last line */ ! 500: putrefer(refer, "%s %s\n", a->a_econt, savestr); ! 501: first = TRUE; ! 502: a = t; ! 503: bufp = buf + strlen(t->a_prompt); ! 504: if (*bufp == ':') ! 505: bufp += 2; ! 506: } else { ! 507: printed = FALSE; ! 508: if (first && a->a_flag != '!') /* first line */ ! 509: printed = putrefer(refer, "%s %s\n", a->a_refer, ! 510: savestr); ! 511: else if (a->a_flag != '!') /* middle line */ ! 512: putrefer(refer, "%s %s\n", a->a_mcont, savestr); ! 513: if (printed) ! 514: first = FALSE; ! 515: bufp = (t ? buf + strlen(t->a_prompt) : buf); ! 516: if (*bufp == ':') ! 517: bufp += 2; ! 518: } ! 519: strcpy(savestr, bufp); ! 520: } ! 521: if (first) ! 522: putrefer(refer, "%s %s\n", a->a_refer, savestr); ! 523: else ! 524: putrefer(refer, "%s %s\n", a->a_econt, savestr); ! 525: fprintf(refer, "\n"); ! 526: } ! 527: ! 528: /* ! 529: * Print string onto fp, or nothing if arg2 is NULL. ! 530: */ ! 531: putrefer(fp, str, arg1, arg2) ! 532: FILE *fp; ! 533: char *str, *arg1, *arg2; ! 534: { ! 535: if (strlen(arg2)) { ! 536: fprintf(fp, str, arg1, arg2); ! 537: return(1); ! 538: } ! 539: return(0); ! 540: } ! 541: ! 542: /* ! 543: * End of program. ! 544: */ ! 545: cleanup() ! 546: { ! 547: signal(SIGINT, SIG_IGN); ! 548: signal(SIGQUIT, SIG_IGN); ! 549: if (tmp) { ! 550: fflush(tmp); ! 551: fclose(tmp); ! 552: } ! 553: fixrefer(); ! 554: unlink(tmpref); ! 555: printf("\n"); ! 556: exit(0); ! 557: } ! 558: ! 559: /* ! 560: * Open template file. ! 561: */ ! 562: FILE * ! 563: tmpopen(file) ! 564: char *file; ! 565: { ! 566: FILE *fp; ! 567: ! 568: if ((fp = fopen(file, "r")) == NULL) ! 569: errexit(1, "Can't open template file, %s\n", file); ! 570: return(fp); ! 571: } ! 572: ! 573: /* ! 574: * Find matches for buf in ref; set rr to last match. ! 575: */ ! 576: match(rr, buf) ! 577: register struct ref **rr; ! 578: char *buf; ! 579: { ! 580: register struct ref *r; ! 581: register matches; ! 582: ! 583: for (r = ref, matches = 0; r; r = r->r_next) ! 584: if (!strncmp(buf, r->r_prompt, strlen(buf))) { ! 585: ++matches; ! 586: *rr = r; ! 587: } ! 588: ! 589: if (matches >= 2) { ! 590: printf("`%s' is not unique: ", &buf[0]); ! 591: for (r = ref; r; r = r->r_next) ! 592: if (!strncmp(buf, r->r_prompt, strlen(buf))) ! 593: printf("`%s' ", r->r_prompt); ! 594: printf("all match\n"); ! 595: } ! 596: return(matches); ! 597: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.