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