aboutsummaryrefslogtreecommitdiff
path: root/unix/boot/mkpkg/main.c
blob: eb2cb5c34fbd15485729b19752ec4090bc1a8729 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
 */

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define	import_spp
#define	import_knames
#define	import_error

#include <iraf.h>

#include "mkpkg.h"
#include "../bootProto.h"

/*
 * MKPKG -- Make a package or library, following the instructions given in
 * the mkpkg file in the current directory.
 *
 *	mkpkg [-flags] [module] [sym=val ...]
 *
 *		-dddd		output debug info; up to 4 levels
 *		-i		ignore errors (cannot ignore interrupt)
 *		-f fname	set mkpkg filename; default "mkpkg"
 *		-n		no execute, just go through the motions
 *		-p pkg		load environment for the named package
 *		-u		forcibly update library module dates
 *		-v		verbose: show actions (implied by -n)
 *
 * The switch "-f stdin" causes MKPKG to read its commands from the standard
 * input, e.g., the terminal.  If a module name is given execution will start
 * at the mkpkg entry for the module, else execution starts at the beginning
 * of file.  See the manual page, etc. for additional documentation.
 */

char	sbuf[SZ_SBUF];			/* string buffer		*/
struct	symbol symtab[MAX_SYMBOLS];	/* symbol table (macros)	*/
struct	context *topcx;			/* currently active context	*/
char	*cp = sbuf;			/* pointer into sbuf		*/
char	*ctop = &sbuf[SZ_SBUF];		/* top of sbuf			*/
int	npkg = 0;			/* number of packages		*/
char	*pkgenv[MAX_PKGENV];		/* package environments		*/
char	v_pkgenv[SZ_PKGENV+1];		/* buffer for pkgenv names	*/
char	irafdir[SZ_PATHNAME+1];		/* iraf root directory		*/
int	nsymbols = 0;			/* number of defined symbols	*/
int	ifstate[SZ_IFSTACK];		/* $IF stack			*/
int	iflev;				/* $IF stack pointer		*/
int	debug = 0;			/* print debug messages		*/
int	dbgout = 0;			/* compile for debugging	*/
int	verbose = NO;			/* print informative messages	*/
int	ignore = YES;			/* ignore warns			*/
int	execute = YES;			/* think but don't act?		*/
int	exit_status;			/* exit status of last syscall	*/
int	forceupdate = NO;		/* forcibly update libmod dates	*/
extern	char *os_getenv();


void warns (char *fmt, char *arg);
void fatals (char *fmt, char *arg);

extern  int  ZZSTRT (void);
extern  int  ZZSTOP (void);

extern  int  do_mkpkg (struct context *cx, int islib);



void zzpause () { printf ("ready ...."); (void) getc(stdin); }


/* MAIN -- Entry point of mkpkg.e
 */
int
main (int argc, char *argv[])
{
	struct	context *cx;
	char	flags[SZ_LINE+1];
	char	*symargs[MAX_ARGS], *modules[MAX_ARGS];
	int	islib, nsymargs=0, nmodules=0, i;
	char	**argp, *ip, *op;

	ZZSTRT();

	/* Initialize the MKPKG context.
	 */
	irafdir[0] = EOS;
	topcx = cx = (struct context *) calloc (1, sizeof (struct context));
	if (cx == NULL)
	    fatals ("out of memory (%s)", "mkpkg.e");

	strcpy (cx->mkpkgfile, MKPKGFILE);
	os_fpathname ("", cx->dirpath, SZ_PATHNAME);
	m_fninit (0);
	m_fdinit (0);

	exit_status = OK;
	ifstate[0]  = PASS;
	iflev       = 0;
	flags[0]    = EOS;
	islib       = YES;
	npkg	    = 0;

	/* Process the command line.
	 */
	for (argp = &argv[1];  *argp;  ) {
	    if (**argp == '-') {
		/* A Mkpkg switch, or a flag to be passed on to XC.
		 */
		for (ip = *argp++ + 1;  *ip;  ip++) {
		    switch (*ip) {
		    case 'f':
			if (*argp == NULL)
			    warns ("missing argument to switch `-f'", NULL);
			else
			    strcpy (cx->mkpkgfile, *argp++);
			break;
		    case 'i':
			ignore = YES;
			break;
		    case 'd':
			/* There are multiple levels of "debug"; each
			 * -d in the arg list adds a level.
			 */
			debug++;
			verbose = YES;
			break;
		    case 'x':
		    case 'g':
			dbgout++;
			goto addflag;
		    case 'n':
			execute = NO;
			verbose = YES;
			break;
		    case 'p':
			if (*argp == NULL)
			    warns ("missing argument to switch `-p'", NULL);
			else {
			    pkgenv[npkg] = *argp++;
			    loadpkgenv (pkgenv[npkg]);
			    if (npkg++ >= MAX_PKGENV)
				fatals ("too many -p package arguments", NULL);
			}
			break;
		    case 'u':
			forceupdate = YES;
			break;
		    case 'v':
			verbose = YES;
			break;
		    case 'w':
			zzpause();
			break;
		    case 'r':
			if (*argp == NULL)
			    warns ("missing argument to switch `-r'", NULL);
			else
			    strcpy (irafdir, *argp++);
			break;
		    default:
addflag:		for (op=flags;  *op;  op++)
			    ;
			*op++ = ' ';
			*op++ = '-';
			*op++ = *ip;
			*op++ = EOS;
			break;
		    }
		}

	    } else if (index (*argp, '=') != NULL) {
		/* Mark the position of a symbol definition argument.  Wait
		 * to enter this into the symbol table until after the command
		 * line has been processed and the mkpkg global include file
		 * has been read in, but go ahead and update the environment
		 * in case a logical name is affected which is referenced while
		 * processing the rest of the argument list.
		 */
		char    symbol[SZ_FNAME+1];
		char    *ip, *op;

		ip = symargs[nsymargs++] = *argp++;
		for (op=symbol;  (*op = *ip++) != '=';  op++)
		    ;
		*op = EOS;
		os_putenv (symbol, ip);

	    } else {
		/* The name of a module to be processed.
		 */
		modules[nmodules++] = *argp++;
	    }
	}

	if (debug) {
	    printf ("mkpkg");
	    for (argp = &argv[1];  *argp;  argp++)
		printf (" %s", *argp);
	    printf ("\n");
	    fflush (stdout);
	}

	/* Initialize the package environment.  This has already been done
	 * if any -p pkgname arguments were given on the command line,
	 * otherwise look for the name PKGENV in the user's environment.
	 */
	if (npkg <= 0)
	    if ((pkgenv[0] = os_getenv (PKGENV))) {
		char    *ip;

		strcpy (v_pkgenv, pkgenv[0]);
		for (ip=v_pkgenv;  *ip;  ) {
		    while (isspace (*ip))
			ip++;
		    pkgenv[npkg] = ip;
		    while (*ip && !isspace (*ip))
			ip++;
		    *ip++ = EOS;
		    loadpkgenv (pkgenv[npkg]);
		    if (npkg++ >= MAX_PKGENV)
			fatals ("too many -p package arguments", NULL);
		}
	    }

	/* Initialize the symbol table from the system dependent global
	 * MKPKG include file.
	 */
	do_include (cx, MKPKGINC);

	/* Likewise load the package global mkpkg.inc files for each
	 * reference package.
	 */
	if (npkg > 0) {
	    char   fname[SZ_PATHNAME+1];
	    int    i;

	    for (i=0;  i < npkg;  i++) {
		sprintf (fname, "%s$lib/mkpkg.inc", pkgenv[i]);
		do_include (cx, fname);
	    }
	}

	/* Append any flags given on the command line to XFLAGS.
	 */
	if (flags[0]) {
	    char   new_xflags[SZ_LINE+1];
	    sprintf (new_xflags, "%s %s", getsym(XFLAGS), flags);
	    putsym (XFLAGS, new_xflags);
	}

	/* Append any flags given on the command line to XVFLAGS.
	 */
	if (flags[0]) {
	    char   new_xvflags[SZ_LINE+1];
	    sprintf (new_xvflags, "%s %s", getsym(XVFLAGS), flags);
	    putsym (XVFLAGS, new_xvflags);
	}

	/* Append any flags given on the command line to LFLAGS.
	 */
	if (flags[0]) {
	    char   new_lflags[SZ_LINE+1];
	    sprintf (new_lflags, "%s %s", getsym(LFLAGS), flags);
	    putsym (LFLAGS, new_lflags);
	}

	/* Define the symbol "DEBUG" if building for debugging (-x).
	 */
	if (dbgout)
	    putsym (DEBUGSYM, "1");

	/* Enter any symbols or macros defined on the command line into the
	 * symbol table and environment.  Must be given without embedded
	 * whitespace, e.g., "symbol=value".
	 */
	for (i=0;  i < nsymargs;  i++) {
	    char    symbol[SZ_FNAME+1];
	    char    *ip, *op, *value;

	    for (ip = symargs[i], op=symbol;  (*op = *ip++) != '=';  op++)
		;
	    *op = EOS;
	    value = ip;
	    putsym (symbol, value);
	    os_putenv (symbol, value);
	}

	/* Process the named modules (or the first module in the mkpkg file
	 * if no modules were named.
	 */
	if (nmodules == 0) {
	    cx->library[0] = EOS;
	    exit_status = do_mkpkg (cx, islib = 0);
	} else {
	    for (i=0;  i < nmodules;  i++) {
		/* If the module is a library specification, the module name,
		 * which is the filename of the library, must end in ".a".
		 */
		char    *ip, *op;
		for (ip = modules[i], op=cx->library;  (*op = *ip++);  op++)
		    ;
		islib = (strcmp (op - 2, ".a") == 0);
		exit_status += do_mkpkg (cx, islib);
	    }
	}

	free (cx);
	m_fninit (debug);
	m_fdinit (debug);

	ZZSTOP();
	exit (exit_status == OK ? OSOK : exit_status);
}


/* WARNS -- Print error message with one string argument but do not terminate
 * program execution.
 */
void
warns (char *fmt, char *arg)
{
	char	errmsg[SZ_LINE+1];

	sprintf (errmsg, fmt, arg);
	printf ("Warning, %s line %d: %s\n", topcx->mkpkgfile, topcx->lineno,
	    errmsg);
	fflush (stdout);
}


/* FATALS -- Print error message with one string argument and terminate
 * program execution.
 */
void
fatals (char *fmt, char	*arg)
{
	char	errmsg[SZ_LINE+1];

	sprintf (errmsg, fmt, arg);
	printf ("Fatal error, %s line %d: %s\n", topcx->mkpkgfile,
	    topcx->lineno, errmsg);
	fflush (stdout);
	exit (OSOK+1);
}