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