xref: /original-bsd/old/refer/addbib/addbib.c (revision 698bcc85)
1 /*-
2  * %sccs.include.proprietary.c%
3  */
4 
5 #ifndef lint
6 static char sccsid[] = "@(#)addbib.c	4.3 (Berkeley) 04/18/91";
7 #endif /* not lint */
8 
9 #include <stdio.h>
10 #include <ctype.h>
11 #include <signal.h>
12 #define MAXENT 50
13 
14 struct skeleton {
15 	char prompt[20];	/* prompt user for entry */
16 	char keylet[5]; 	/* key letter for database */
17 } bibskel[MAXENT] = {
18 	"   Author:",	"%A",
19 	"    Title:",	"%T",
20 	"  Journal:",	"%J",
21 	"   Volume:", 	"%V",
22 	"    Pages:",	"%P",
23 	"Publisher:",	"%I",
24 	"     City:", 	"%C",
25 	"     Date:", 	"%D",
26 	"    Other:",	"%O",
27 	" Keywords:",	"%K",	};
28 
29 int entries = 10;	/* total number of entries in bibskel */
30 int abstract = 1;	/* asking for abstracts is the default */
31 
32 usage()			/* print proper usage and exit */
33 {
34 	puts("Usage:  addbib [-p promptfile] [-a] database");
35 	puts("\t-p: the promptfile defines alternate fields");
36 	puts("\t-a: don't include prompting for the abstract");
37 	exit(1);
38 }
39 
40 main(argc, argv)	/* addbib: bibliography entry program */
41 int argc;
42 char *argv[];
43 {
44 	FILE *fp, *fopen();
45 	int i;
46 
47 	if (argc == 1)
48 	{
49 		puts("You must specify a bibliography file (database).");
50 		usage();
51 	}
52 	for (i = 1; argv[i][0] == '-'; i++)
53 	{
54 		if (argv[i][1] == 'p')
55 		{
56 			if (i >= argc - 2)
57 			{
58 				puts("Not enough arguments for -p option.");
59 				usage();
60 			}
61 			rd_skel(argv[++i]);
62 		}
63 		else if (argv[i][1] == 'a')
64 		{
65 			if (i >= argc - 1)
66 			{
67 				puts("No bibliofile specified after -a.");
68 				usage();
69 			}
70 			abstract = 0;
71 		}
72 		else  /* neither -p nor -a */
73 		{
74 			printf("Invalid command line flag: %s\n", argv[i]);
75 			usage();
76 		}
77 	}
78 	if (i < argc - 1)
79 	{
80 		puts("Too many arguments with no options.");
81 		usage();
82 	}
83 	if ((fp = fopen(argv[i], "a")) == NULL)
84 	{
85 		perror(argv[i]);
86 		exit(1);
87 	}
88 	addbib(fp, argv[i]);	/* loop for input */
89 	exit(0);
90 }
91 
92 addbib(fp, argv)	/* add entries to a bibliographic database */
93 FILE *fp;
94 char *argv;
95 {
96 	char line[BUFSIZ];
97 	int i = 0, firstln, repeat = 0, escape = 0;
98 
99 	printf("Instructions? ");
100 	fgets(line, BUFSIZ, stdin);
101 	if (line[0] == 'y' || line[0] == 'Y')
102 		instruct();
103 	while (1)
104 	{
105 		putchar('\n');
106 		putc('\n', fp);
107 		for (i = 0; i < entries; i++)
108 		{
109 			printf("%s\t", bibskel[i].prompt);
110 			if (fgets(line, BUFSIZ, stdin) == NULL)
111 			{
112 				clearerr(stdin);
113 				break;
114 			}
115 			if (line[0] == '-' && line[1] == '\n')
116 			{
117 				i -= 2;
118 				if (i < -1)
119 				{
120 					printf("Too far back.\n");
121 					i++;
122 				}
123 				continue;
124 			}
125 			else if (line[strlen(line)-2] == '\\')
126 			{
127 				if (line[0] != '\\')
128 				{
129 					line[strlen(line)-2] = '\n';
130 					line[strlen(line)-1] = NULL;
131 					trim(line);
132 					fprintf(fp, "%s %s",
133 						bibskel[i].keylet, line);
134 				}
135 				printf("> ");
136 				again:
137 				fgets(line, BUFSIZ, stdin);
138 				if (line[strlen(line)-2] == '\\')
139 				{
140 					line[strlen(line)-2] = '\n';
141 					line[strlen(line)-1] = NULL;
142 					trim(line);
143 					fputs(line, fp);
144 					printf("> ");
145 					goto again;
146 				}
147 				trim(line);
148 				fputs(line, fp);
149 			}
150 			else if (line[0] != '\n')
151 			{
152 				trim(line);
153 				fprintf(fp, "%s %s", bibskel[i].keylet, line);
154 			}
155 		}
156 		if (abstract)
157 		{
158 			puts(" Abstract: (ctrl-d to end)");
159 			firstln = 1;
160 			while (fgets(line, BUFSIZ, stdin))
161 			{
162 				if (firstln && line[0] != '%')
163 				{
164 					fprintf(fp, "%%X ");
165 					firstln = 0;
166 				}
167 				fputs(line, fp);
168 			}
169 			clearerr(stdin);
170 		}
171 		fflush(fp);	/* write to file at end of each cycle */
172 		if (ferror(fp))
173 		{
174 			perror(argv);
175 			exit(1);
176 		}
177 		editloop:
178 		printf("\nContinue? ");
179 			fgets(line, BUFSIZ, stdin);
180 		if (line[0] == 'e' || line[0] == 'v')
181 		{
182 			bibedit(fp, line, argv);
183 			goto editloop;
184 		}
185 		if (line[0] == 'q' || line[0] == 'n')
186 			return;
187 	}
188 }
189 
190 trim(line)		/* trim line of trailing white space */
191 char line[];
192 {
193 	int n;
194 
195 	n = strlen(line);
196 	while (--n >= 0)
197 	{
198 		if (!isspace(line[n]))
199 			break;
200 	}
201 	line[++n] = '\n';
202 	line[++n] = NULL;
203 }
204 
205 bibedit(fp, cmd, arg)	/* edit database with edit, ex, or vi */
206 FILE *fp;
207 char *cmd, *arg;
208 {
209 	int i = 0, status;
210 
211 	fclose(fp);
212 	while (!isspace(cmd[i]))
213 		i++;
214 	cmd[i] = NULL;
215 	if (fork() == 0)
216 	{
217 		if (cmd[0] == 'v' && cmd[1] == 'i')
218 			execlp(cmd, cmd, "+$", arg, NULL);
219 		else /* either ed, ex, or edit */
220 			execlp(cmd, cmd, arg, NULL);
221 	}
222 	signal(SIGINT, SIG_IGN);
223 	signal(SIGQUIT, SIG_IGN);
224 	wait(&status);
225 	signal(SIGINT, SIG_DFL);
226 	signal(SIGQUIT, SIG_DFL);
227 	if ((fp = fopen(arg, "a")) == NULL)
228 	{
229 		perror(arg);
230 		exit(1);
231 	}
232 }
233 
234 instruct()		/* give user elementary directions */
235 {
236 	putchar('\n');
237 	puts("Addbib will prompt you for various bibliographic fields.");
238 	puts("If you don't need a particular field, just hit RETURN,");
239 	puts("\tand that field will not appear in the output file.");
240 	puts("If you want to return to previous fields in the skeleton,");
241 	puts("\ta single minus sign will go back a field at a time.");
242 	puts("\t(This is the best way to input multiple authors.)");
243 	puts("If you have to continue a field or add an unusual field,");
244 	puts("\ta trailing backslash will allow a temporary escape.");
245 	puts("Finally, (without -a) you will be prompted for an abstract.");
246 	puts("Type in as many lines as you need, and end with a ctrl-d.");
247 	puts("To quit, type `q' or `n' when asked if you want to continue.");
248 	puts("To edit the database, type `edit', `vi', or `ex' instead.");
249 }
250 
251 rd_skel(arg)		/* redo bibskel from user-supplied file */
252 char *arg;
253 {
254 	FILE *pfp, *fopen();
255 	char str[BUFSIZ];
256 	int entry, i, j;
257 
258 	if ((pfp = fopen(arg, "r")) == NULL)
259 	{
260 		fprintf(stderr, "Promptfile ");
261 		perror(arg);
262 		exit(1);
263 	}
264 	for (entry = 0; fgets(str, BUFSIZ, pfp); entry++)
265 	{
266 		for (i = 0; str[i] != '\t' && str[i] != '\n'; i++)
267 			bibskel[entry].prompt[i] = str[i];
268 		bibskel[entry].prompt[i] = NULL;
269 		if (str[i] == '\n')
270 		{
271 			fprintf(stderr, "No tabs between promptfile fields.\n");
272 			fprintf(stderr, "Format: prompt-string <TAB> %%key\n");
273 			exit(1);
274 		}
275 		for (i++, j = 0; str[i] != '\n'; i++, j++)
276 			bibskel[entry].keylet[j] = str[i];
277 		bibskel[entry].keylet[j] = NULL;
278 
279 		if (entry >= MAXENT)
280 		{
281 			fprintf(stderr, "Too many entries in promptfile.\n");
282 			exit(1);
283 		}
284 	}
285 	entries = entry;
286 	fclose(pfp);
287 }
288