[comp.os.minix] fixs for ar, lorder, & tsort

walls@killer.UUCP (Monty Walls) (02/24/88)

In response to bug reports I've received I am posting these
patches to ar, lorder, and tsort.  All these diff's are 
relative to my original versions, and lorder.c is a complete 
reposting.  Also the original LEX scanner for lorder has been
replaced with a hand written scanner(this one will happily think
the asm directives are global symbols the code is referencing
but since no module ever actually defines them it doesn't 
hurt any thing).  So sorry about missing this stuff the 
first time.
-------------------------CUT HERE-------------------------------
echo x - ar.c.diff
gres '^X' '' > ar.c.diff << '/'
X32a33
X>  *	fixed up error messages to give more info (mrw).
X35a37,41
X>  *
X>  * change log:
X>  *	forgot that ar_size is a long for printing - 2/14/88 - mrw
X>  *	got the mode bit maps mirrored - 2/19/88 - mrw
X>  *	print & extract member logic fixed - 2/19/88 - mrw
X72c78
X< #define EXEC_OWNER	00001
X---
X> #define EXEC_OWNER	00100
X74,75c80,81
X< #define EXEC_ALL	00100
X< #define READ_OWNER	00004
X---
X> #define EXEC_ALL	00001
X> #define READ_OWNER	00400
X77,78c83,84
X< #define READ_ALL	00400
X< #define WRITE_OWNER	00002
X---
X> #define READ_ALL	00004
X> #define WRITE_OWNER	00200
X80c86
X< #define WRITE_ALL	00200
X---
X> #define WRITE_ALL	00002
X247c253
X< 			fprintf(stderr,"Error %s: %s not found in ar\n", progname, argv[ac]);
X---
X> 			fprintf(stderr,"Error %s: %s not found in %s\n", progname, argv[ac], afile);
X324c330
X< 		fprintf(stderr,"Error: ar corrupted archive ar\n");
X---
X> 		fprintf(stderr,"Error: ar corrupted archive %s\n",afile);
X440c446
X< 		fprintf(stdout,"%5.5d",member->ar_size);
X---
X> 		fprintf(stdout,"%5.5D",member->ar_size);	/* oops is long - mrw */
X450a457
X> 	long size;
X469,471c476,479
X< 	
X< 	for (cnt = member->ar_size; cnt > 0; cnt -= ret) {
X< 		ret = read(fd, buffer, (cnt < BUFFERSIZE ? cnt : BUFFERSIZE));
X---
X> 	/* changed loop to use long size for correct extracts */	
X> 	for (size = member->ar_size; size > 0; size -= ret) {
X> 		cnt = (size < BUFFERSIZE ? size : BUFFERSIZE);
X> 		ret = read(fd, buffer, cnt);
X661c669
X< 	int a, fd;
X---
X> 	int a, fd, did_print;
X665a674
X> 		did_print = 0;
X671c680
X< 					else if (major & (PRINT | EXTRACT))
X---
X> 					else if (major & (PRINT | EXTRACT)) {
X672a682,683
X> 						did_print = 1;
X> 					}
X676,677d686
X< 				else if (major & (PRINT | EXTRACT))
X< 					lseek(fd, (long)even(member->ar_size), 1);
X683c692
X< 			else if (major & (PRINT | EXTRACT))
X---
X> 			else if (major & (PRINT | EXTRACT)) {
X684a694,695
X> 				did_print = 1;
X> 			}
X686c697,700
X< 		if (major & TABLE)
X---
X> 		/* if we didn't print the member or didn't use it we will
X> 		 * have to seek over its contents
X> 		 */
X> 		if (!did_print)
/
echo x - tsort.c.diff
gres '^X' '' > tsort.c.diff << '/'
X24a25
X>  *	possible bug in ungetc(), fixed readone() to avoid - 2/19/88 - mrw
X26d26
X<  *
X156,161c156,163
X< 	if (c != EOF && !isspace(c))
X< 		ungetc(c,stdin);
X< 
X< 	while ((c = getchar()) != EOF && !isspace(c)) {
X< 		if (n < MAXNAMELEN)
X< 			name[n++] = c;
X---
X> 	if (c != EOF) {
X> 		name[n++] = c;	/* save into name first non blank */
X> 		while ((c = getchar()) != EOF && !isspace(c)) {
X> 			if (n < MAXNAMELEN)
X> 				name[n++] = c;
X> 		}
X> 		name[n] = '\0';
X> 		return (name);
X163,164c165
X< 
X< 	if (c == EOF) 
X---
X> 	else
X167,168d167
X< 	name[n] = '\0';
X< 	return (name);
/
echo x - lorder.c
gres '^X' '' > lorder.c << '/'
X/*
X * lorder: find ordering relations for object library
X *
X * author:	Monty Walls
X * written:	1/29/88
X * Copyright:	Copyright (c) 1988 by Monty Walls.
X *		Not derived from licensed software.
X *
X *		Permission to copy and/or distribute granted under the
X *		following conditions:
X *	
X *		1). This notice must remain intact.
X *		2). The author is not responsible for the consequences of use
X *			this software, no matter how awful, even if they
X *			arise from defects in it.
X *		3). Altered version must not be represented as being the 
X *			original software.
X *
X * change log:
X *		corrected & rewrote scanner to avoid lex. - 2/22/88 - mrw
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <signal.h>
X#include <ar.h>
X
X#define MAXLINE		256
X
XFILE *lexin;
Xchar *yyfile;
Xchar *tmpfile;
Xchar *progname;
Xchar template[] = "lorder.XXXXXX";
X
Xstruct filelist {
X	char *name;
X	struct filelist *next;
X};
X
Xstruct node {
X	char *name;
X	char *file;
X	struct filelist *list;
X	struct node *left, *right;
X};
X
Xstruct filelist *list;
Xstruct node *tree, *lastnode;
Xextern char *malloc(), *mktemp();
Xextern FILE *popen(), *fopen();
Xextern char *addfile();
Xextern void user_abort();
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	int i;
X	char cmdstr[MAXLINE];
X
X	if (argc > 1) {
X		progname = argv[0];
X		signal(SIGINT, user_abort);
X		for (i = 1; argv[i] && *argv[i]; ++i ) {
X			/* the following code is caused by 
X			 * not enough memory on floppy systems.
X			 *
X			 * so instead of ar | libupack ->to us. we use
X			 * ar >tmpfle; libupack <tmpfile ->to us
X			 */
X			if (is_liba(argv[i])) {
X				tmpfile = mktemp(template);
X				sprintf(cmdstr,"ar pv %s >%s",argv[i],tmpfile);
X				system(cmdstr);
X				sprintf(cmdstr,"libupack <%s",tmpfile);
X			}
X			else {
X				yyfile = addfile(argv[i]);
X				sprintf(cmdstr, "libupack <%s", argv[i]);
X			}
X			if ((lexin = popen(cmdstr, "r")) != (FILE *)NULL) {
X				while (yylex() != EOF) ;
X				pclose(lexin);
X				if (tmpfile)
X					unlink(tmpfile);
X			}
X			else {
X				fprintf(stderr,"Error: %s could not open %s\n",progname, argv[i]);
X				exit(1);
X			}
X		}
X		printtree(tree);
X		/* then print list of files for ar also */
X		for (; list; list = list->next) 
X			fprintf(stdout,"%s %s\n",list->name, list->name);
X	}
X	else {
X		fprintf(stderr,"Usage: %s file ....\n",progname);
X		exit(1);
X	}
X}
X
Xvoid
Xuser_abort()
X{
X	unlink(tmpfile);
X	exit(1);
X}
X
Xchar *
Xxalloc(n)
Xint n; 
X{
X	char *p;
X
X	if ((p = malloc(n)) == (char *)NULL) {
X		fprintf(stderr, "Error %s - out of memory\n", progname);
X		exit(1);
X	}
X	return (p);
X}
X
Xint
Xis_liba(s)	/* error handling done later */
Xchar *s;
X{
X	unsigned short key;
X	FILE *fp;
X	int ret = 0;
X
X	if ((fp = fopen(s,"r")) != (FILE *)NULL) {
X		fread(&key, sizeof(key), 1, fp);
X		if (key == ARMAG) ret = 1;
X		fclose(fp);
X	}
X	return (ret);
X}
X
Xchar *
Xstrsave(s)
Xchar *s;
X{
X	char *p;
X
X	p = xalloc(strlen(s) + 1);
X	strcpy(p,s);
X	return (p);
X}
X
Xchar *
Xaddfile(s)
Xchar *s;
X{
X	struct filelist *p;
X
X	p = (struct filelist *)xalloc(sizeof(struct filelist));
X	p->name = strsave(s);
X	if (list)
X		p->next = list;
X	else
X		p->next = NULL;
X	list = p;
X	return (p->name);
X}
X
Xprinttree(t)
Xstruct node *t;
X{
X	struct filelist *fp;
X
X	if (t) {
X		if (t->file) {
X			for (fp = t->list; fp && fp->name; fp = fp->next)
X				if (t->file != fp->name)
X					fprintf(stdout,"%s %s\n",t->file, fp->name);
X		}
X		printtree(t->right);
X		printtree(t->left);
X	}
X}
X
X
Xstruct node *
Xfinddef(s)
Xchar *s;
X{
X	struct node *n;
X	int cmp;
X
X	if (tree) {
X		lastnode = n = tree;
X		while (n && n->name) {
X			lastnode = n;
X			if (!(cmp=strcmp(s,n->name)))
X				return (n);
X			else if (cmp > 0)
X				n = n->left;
X			else 
X				n = n->right;
X		}			
X	}
X	return ((struct node *)NULL);
X}
X
Xstruct node *
Xmakedef(s)
Xchar *s;
X{
X	struct node *n;
X	int cmp;
X
X	n = (struct node *)xalloc(sizeof(struct node));
X	n->name = strsave(s);
X	n->left = (struct node *)NULL;
X	n->right = (struct node *)NULL;
X	if (tree) {
X		cmp = strcmp(s, lastnode->name);
X		if (cmp > 0)
X			lastnode->left = n;
X		else
X			lastnode->right = n;
X	}
X	else
X		tree = n;
X
X	return (n);
X}
X
Xvoid
Xdodef(s) 
Xchar *s;
X{
X	struct node *n;
X
X	if (n = finddef(s)) {
X		if (n->file != NULL) 
X			fprintf(stderr,"Error %s - %s defined twice in %s and %s", progname, s, n->file, yyfile);
X		else
X			n->file = yyfile;
X	}
X	else {
X		n = makedef(s);
X		n->file = yyfile;
X		n->list = (struct filelist *)NULL;
X	}
X}
X
Xvoid
Xusedef(s) 
Xchar *s;
X{
X	struct node *n;
X	struct filelist *fp, *lastfp;
X
X	if (n = finddef(s)) {
X		/* scan file list for match */
X		if (n->list) {
X			for (fp = n->list; fp ; fp = fp->next) {
X				if (fp->name == yyfile) {
X					return;
X				}
X				lastfp = fp;
X			}
X			/* reached here with no match */
X			lastfp->next = (struct filelist *)xalloc(sizeof(struct filelist));
X			lastfp->next->name = yyfile;
X			lastfp->next->next  = (struct filelist *)NULL;
X		}
X		else {
X			/* empty list so far */
X			n->list = (struct filelist *)xalloc(sizeof(struct filelist));
X			n->list->name = yyfile;
X			n->list->next = (struct filelist *)NULL;
X		}
X	}
X	else {
X		n = makedef(s);
X		n->file = (char *)NULL;
X		n->list = (struct filelist *) xalloc(sizeof(struct filelist));
X		n->list->name = yyfile;
X		n->list->next = (struct filelist *)NULL;
X	}
X}
X
X/*
X * yylex - scanner for lorder
X *
X */
X#define MAXNAME 33
X#define is_first_char(c)	((c) == '.' || (c) == '_')
X#define is_second_char(c)	((c) == '_' || isalpha((c)))
X#define is_other_char(c)	((c) == '_' || isalnum((c)))
X
Xint yylex()
X{
X	int col = 0;
X	int i = 0;
X	int is_member = 0;
X	int in_define = 0;
X	int lastch = 0;
X	char s[MAXNAME];
X
X
X	while ((lastch = fgetc(lexin)) != EOF) {
X		col++;				/* increment col */
X		if (isspace(lastch)) {
X			EOS:			/* eos comes here */
X			if (i) {		/* we have a string */
X				s[i] = '\0';	/* set eos */
X				i = 0;
X				/*
X				 * if we are in a define use dodef to add location
X				 *   of defining member and global to symbol table.
X				 */
X				if (in_define)
X					dodef(s);
X				/*
X				 * if we are on a 'p -' line for an ar lib define
X				 *   this member as the file we are using.
X				 */
X				else if (is_member > 0) {
X					is_member = 0;
X					yyfile = addfile(s);
X				}
X				/*
X				 * if we have a '.define' mark this line as in_define.
X				 */
X				else if (strcmp(s,".define") == 0)
X					in_define = 1;
X				/*
X				 * just a reference in the code to a var, so add this
X				 *   reference to our symbol table.
X				 */
X				else
X					usedef(s);
X			}
X			/*
X			 * we are at the eol: reset our counters and switches
X			 */
X			if (lastch == '\n') {
X				col = 0;
X				is_member = 0;
X				in_define = 0;
X			}
X			/*
X			 * lets do another character
X			 */
X			continue;
X		}
X		/*
X		 *  not a space and i == 0
X		 */
X		if (i == 0) {
X			/*
X			 *  are we seeing 'p' in col 1
X			 */
X			if (lastch == 'p' && col == 1) {
X				is_member = -1;
X				continue;
X			}
X			/*
X			 *  are we seeing '-' that follows 'p' in col 1
X		 	 */
X			else if (lastch == '-' && is_member < 0 && col == 3) {
X				is_member = 1;
X				continue;
X			}
X			/*
X			 *  if we have seen 'p -' now we are reading the name or
X			 *    the first character of a global symbol
X			 */
X			if (is_member > 0 || is_first_char(lastch)) {
X				s[i++] = lastch;
X				if (is_member < 0) 
X					is_member = 0;
X			}
X			continue;
X		}
X		/*
X		 *  do the second char of a name 
X		 */
X		else if (i == 1) {
X			if (is_member > 0 || is_second_char(lastch)) {
X				s[i++] = lastch;
X			}
X			else
X				is_member = 0;
X		}
X		/*
X		 *  do the rest of a symbol or member name
X		 */
X		else if (is_member > 0 || is_other_char(lastch)) {
X			s[i++] = lastch;
X			continue;
X		}
X		else
X	            goto EOS;
X	}
X	/*
X	 *  returns EOF on end of file
X	 */
X	return (lastch);
X}
/
-------------------------END HERE-------------------------------

Monty Walls
MIS Division, Tech. Support
Oklahoma Tax Commission
2501 N. Lincoln
OKC, OK, 73194