Minix1.5/commands/ibm/lorder.c
/* lorder - order a library Author: Monty Walls */
/* lorder: find ordering relations for object library
*
* author: Monty Walls
* written: 1/29/88
* Copyright: Copyright (c) 1988 by Monty Walls.
* Not derived from licensed software.
*
* Permission to copy and/or distribute granted under the
* following conditions:
*
* 1). This notice must remain intact.
* 2). The author is not responsible for the consequences of use
* this software, no matter how awful, even if they
* arise from defects in it.
* 3). Altered version must not be represented as being the
* original software.
*
* change log:
* corrected & rewrote scanner to avoid lex. - 2/22/88 - mrw
* oops reversed output filename order. 3/14/88 - mrw
* progname = argv[0] - should be first. 5/25/88 - mbeck
*/
#include <ctype.h>
#include <signal.h>
#include <ar.h>
#include <stdio.h>
#define MAXLINE 256
FILE *lexin;
char *yyfile;
char *tempfile;
char *progname;
char template[] = "lorder.XXXXXX";
struct filelist {
char *name;
struct filelist *next;
};
struct node {
char *name;
char *file;
struct filelist *list;
struct node *left, *right;
};
struct filelist *list;
struct node *tree, *lastnode;
extern char *malloc(), *mktemp();
extern FILE *popen(), *fopen();
extern char *addfile();
extern void user_abort();
main(argc, argv)
int argc;
char **argv;
{
int i;
char cmdstr[MAXLINE];
progname = argv[0];
if (argc > 1) {
signal(SIGINT, user_abort);
for (i = 1; argv[i] && *argv[i]; ++i) {
/* The following code is caused by not enough memory
* on floppy systems.
*
* so instead of ar | libupack ->to us. we use ar
* >tmpfle; libupack <tempfile ->to us */
if (is_liba(argv[i])) {
tempfile = mktemp(template);
sprintf(cmdstr, "ar pv %s >%s", argv[i], tempfile);
system(cmdstr);
sprintf(cmdstr, "libupack <%s", tempfile);
} else {
yyfile = addfile(argv[i]);
sprintf(cmdstr, "libupack <%s", argv[i]);
}
if ((lexin = popen(cmdstr, "r")) != (FILE *) NULL) {
while (yylex() != EOF);
pclose(lexin);
if (tempfile) unlink(tempfile);
} else {
fprintf(stderr, "Error: %s could not open %s\n", progname, argv[i]);
exit(1);
}
}
printtree(tree);
/* Then print list of files for ar also */
for (; list; list = list->next)
fprintf(stdout, "%s %s\n", list->name, list->name);
} else {
fprintf(stderr, "Usage: %s file ....\n", progname);
exit(1);
}
}
void user_abort()
{
unlink(tempfile);
exit(1);
}
char *xalloc(n)
int n;
{
char *p;
if ((p = malloc(n)) == (char *) NULL) {
fprintf(stderr, "Error %s - out of memory\n", progname);
exit(1);
}
return(p);
}
int is_liba(s) /* error handling done later */
char *s;
{
unsigned short key;
FILE *fp;
int ret = 0;
if ((fp = fopen(s, "r")) != (FILE *) NULL) {
fread(&key, sizeof(key), 1, fp);
if (key == ARMAG) ret = 1;
fclose(fp);
}
return(ret);
}
char *strsave(s)
char *s;
{
char *p;
p = xalloc(strlen(s) + 1);
strcpy(p, s);
return(p);
}
char *addfile(s)
char *s;
{
struct filelist *p;
p = (struct filelist *) xalloc(sizeof(struct filelist));
p->name = strsave(s);
if (list)
p->next = list;
else
p->next = NULL;
list = p;
return(p->name);
}
printtree(t)
struct node *t;
{
struct filelist *fp;
if (t) {
if (t->file) {
for (fp = t->list; fp && fp->name; fp = fp->next)
if (t->file != fp->name)
fprintf(stdout, "%s %s\n", fp->name, t->file);
}
printtree(t->right);
printtree(t->left);
}
}
struct node *finddef(s)
char *s;
{
struct node *n;
int cmp;
if (tree) {
lastnode = n = tree;
while (n && n->name) {
lastnode = n;
if (!(cmp = strcmp(s, n->name)))
return(n);
else if (cmp > 0)
n = n->left;
else
n = n->right;
}
}
return((struct node *) NULL);
}
struct node *makedef(s)
char *s;
{
struct node *n;
int cmp;
n = (struct node *) xalloc(sizeof(struct node));
n->name = strsave(s);
n->left = (struct node *) NULL;
n->right = (struct node *) NULL;
if (tree) {
cmp = strcmp(s, lastnode->name);
if (cmp > 0)
lastnode->left = n;
else
lastnode->right = n;
} else
tree = n;
return(n);
}
void dodef(s)
char *s;
{
struct node *n;
if (n = finddef(s)) {
if (n->file != NULL) fprintf(stderr,
"Error %s - %s defined twice in %s and %s\n",
progname, s, n->file, yyfile);
else
n->file = yyfile;
} else {
n = makedef(s);
n->file = yyfile;
n->list = (struct filelist *) NULL;
}
}
void usedef(s)
char *s;
{
struct node *n;
struct filelist *fp, *lastfp;
if (n = finddef(s)) {
/* Scan file list for match */
if (n->list) {
for (fp = n->list; fp; fp = fp->next) {
if (fp->name == yyfile) {
return;
}
lastfp = fp;
}
/* Reached here with no match */
lastfp->next = (struct filelist *) xalloc(sizeof(struct filelist));
lastfp->next->name = yyfile;
lastfp->next->next = (struct filelist *) NULL;
} else {
/* Empty list so far */
n->list = (struct filelist *) xalloc(sizeof(struct filelist));
n->list->name = yyfile;
n->list->next = (struct filelist *) NULL;
}
} else {
n = makedef(s);
n->file = (char *) NULL;
n->list = (struct filelist *) xalloc(sizeof(struct filelist));
n->list->name = yyfile;
n->list->next = (struct filelist *) NULL;
}
}
/* Yylex - scanner for lorder
*
*/
#define MAXNAME 33
#define is_first_char(c) ((c) == '.' || (c) == '_')
#define is_second_char(c) ((c) == '_' || isalpha((c)))
#define is_other_char(c) ((c) == '_' || isalnum((c)))
#define alt_space(c) ((c) == ',' || (c) == '#')
int yylex()
{
int col = 0;
int i = 0;
int is_member = 0;
int in_define = 0;
int lastch = 0;
int was_space = 1;
char s[MAXNAME];
while ((lastch = fgetc(lexin)) != EOF) {
col++; /* increment col */
if (isspace(lastch)) {
EOS: /* eos comes here */
if (i) { /* we have a string */
s[i] = '\0'; /* set eos */
i = 0;
/* If we are in a define use dodef to add
* location of defining member and global to
* symbol table. */
if (in_define) dodef(s);
/* If we are on a 'p -' line for an ar lib
* define this member as the file we are
* using. */
else if (is_member > 0) {
is_member = 0;
yyfile = addfile(s);
}
/* If we have a '.define' mark this line as
* in_define. */
else if (strcmp(s, ".define") == 0)
in_define = 1;
/* Just a reference in the code to a var, so
* add this reference to our symbol table. */
else
usedef(s);
}
/* We are at the eol: reset our counters and switches */
if (lastch == '\n') {
col = 0;
is_member = 0;
in_define = 0;
}
/* Lets do another character */
was_space = 1;
continue;
}
/* Not a space and i == 0 */
if (i == 0) {
/* Are we seeing 'p' in col 1 */
if (lastch == 'p' && col == 1) {
is_member = -1;
}
/* Are we seeing '-' that follows 'p' in col 1 */
else if (lastch == '-' && is_member < 0 && col == 3) {
is_member = 1;
}
/* If we have seen 'p -' now we are reading the name
* or the first character of a global symbol */
else if (is_member > 0 || (is_first_char(lastch) && was_space)) {
s[i++] = lastch;
if (is_member < 0) is_member = 0;
}
was_space = alt_space(lastch);
}
/* Do the second char of a name */
else if (i == 1) {
if (is_member > 0 || is_second_char(lastch)) {
s[i++] = lastch;
} else
is_member = 0;
was_space = alt_space(lastch);
}
/* Do the rest of a symbol or member name */
else if (is_member > 0 || is_other_char(lastch)) {
s[i++] = lastch;
was_space = alt_space(lastch);
} else {
was_space = alt_space(lastch);
goto EOS;
}
}
/* Returns EOF on end of file */
return(lastch);
}