mamnew.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1989-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Bell Laboratories
*
* convert a make abstract machine stream on stdin
* to an nmake makefile on stdout
*/
static const char usage[] =
"[-?\n@(#)$Id: mamnew (AT&T Research) 1990-06-11 $\n]"
"[+NAME?mamnew - make abstract machine to nmake makefile conversion filter]"
"[+DESCRIPTION?\bmamnew\b reads MAM (Make Abstract Machine) target and"
" prerequisite file descriptions from the standard input and writes"
" an equivalent \bnmake\b(1) makefile on the standard output. Mamfiles"
" are generated by the \b--mam\b option of \bnmake\b(1) and"
" \bgmake\b(1).]"
"[+?Symbolic information is preserved where possible in the output makefile."
" Comments, however, are lost in the conversion. Header file"
" dependencies are omitted since these are implicitly determined by"
" \bnmake\b(1). Recursive makefiles are not converted; each makefile"
" level must be converted separately. Some targets are omitted; most"
" of these are provided as predefined \bnmake\b(1) targets.]"
"[+?\bmamnew\b is only an \aaid\a in the makefile conversion process. It is"
" a rare old-make makefile that requires no manual intervention after"
" \bmamnew\b conversion.]"
"[d:debug?]#[level]"
"[x:omit?Omit pathnames with directory \aprefix\a.]#[prefix]"
"[+SEE ALSO?\bmamold\b(1), \bgmake\b(1), \bnmake\b(1)]"
"[+REFERENCES]{"
" [+A Make abstract machine, Glenn Fowler, 1994.?"
"}"
;
#include <ast.h>
#include <mam.h>
#include <ctype.h>
#include <error.h>
struct local /* local rule info */
{
char* base; /* base name */
char* suffix; /* suffix */
char* target; /* target name if != base */
};
static struct /* program state */
{
int ancestor; /* ancestor dir .. count */
struct
{
} atom; /* special atoms */
} state;
/*
* check if name is on omit list
*/
static int
{
register char* s;
register char* t;
register struct block* d;
{
s = name;
t = d->data;
do if (!*t)
{
if (!*s || *s == '/')
return 1;
break;
} while (*s++ == *t++);
}
return 0;
}
/*
* initialize source dir
*/
static struct rule*
{
register struct rule* d;
register int n;
struct rule* z;
if (!(d->attributes & A_directory))
{
d->attributes |= A_directory;
n = 0;
while (*s == '.' && *(s + 1) == '.' && *(s + 2) == '/')
{
s += 3;
n++;
}
if (!strmatch(s, "include|lib"))
{
z->attributes |= A_directory;
}
}
return d;
}
/*
* dump a value that may be expanded by oldmake
*/
static int
{
register int c;
register char* v;
{
col++;
}
for (;;)
switch (c = *s++)
{
case 0:
{
col = 1;
}
return col;
case '\t':
/*FALLTHROUGH*/
case ' ':
goto emit;
while (isspace(*s))
s++;
if (*s)
{
col = 8;
}
break;
case '\\':
if (sep == '\\')
c = *s++;
goto emit;
case '$':
if (isalpha(*s) || *s == '_')
{
for (v = s; isalnum(*v) || *v == '_'; v++);
c = *v;
*v = 0;
{
col += (v - s) + 3;
*(s = v) = c;
break;
}
*v = c;
c = '$';
}
/*FALLTHROUGH*/
default:
emit:
col++;
break;
}
}
/*
* dump a name keeping track of the right margin
*/
static int
{
register int n;
n = strlen(s);
{
col = 16;
}
else if (col <= 1)
col = 1;
else
{
col++;
}
col += n;
dumpvalue(0, s, 0);
return col;
}
/*
* check s for interesting cc flags
* if v!=0 then it is var for s
*/
static void
{
register char* t;
char* b;
char* u;
int n;
static int init;
b = buf;
for (;;)
{
while (*s && *s != '-')
s++;
if (!*s)
break;
for (t = s; *t; t++)
{
if (isspace(*t))
break;
if (*t == '\\' && !*++t)
break;
}
*t++ = 0;
switch (*(s + 1))
{
case 'c':
case 'U':
break;
case 'D':
for (u = s + 2; isalnum(*u); u++);
if (n = *u)
*u = 0;
if (n)
*u = n;
break;
case 'I':
pathcanon(s += 2, 0, 0);
initdir(s, ".h");
break;
case 'O':
if (!*(s + 2))
break;
/*FALLTHROUGH*/
default:
if (b != buf)
*b++ = ' ';
b = strcopy(b, s);
break;
}
s = t;
}
if (v && b > buf)
{
if (!init)
{
init = 1;
}
*b = 0;
}
}
/*
* initialize local rule info
*/
static int
{
register char* s = (char*)as;
register struct local* x;
register struct block* p;
char* t;
x->suffix = s + 1;
else
s = "";
{
r->attributes |= A_omit;
x->base = t + 1;
}
else
{
*t = 0;
*t++ = '/';
x->base = t;
}
{
s[0] = '-';
s[1] = 'l';
s[strlen(s) - 2] = 0;
}
{
r->action = 0;
r->prereqs = 0;
while (p)
{
p = p->next;
}
}
return 0;
}
/*
* clear listprereq for all prerequisites
*/
static void
clrprereqs(register struct rule* r)
{
register struct list* p;
r->attributes &= ~A_listprereq;
clrprereqs(p->rule);
}
/*
* dump the (implicit) prerequisites for r
*/
static int
{
register struct list* p;
{
r->attributes |= A_listprereq;
if (r->attributes & (A_directory))
}
return col;
}
/*
* dump an action
*/
static void
dumpaction(register struct block* p)
{
if (p) do
{
} while (p = p->next);
}
/*
* dump the rules
*/
static void
{
register int col;
register struct list* p;
{
r->attributes |= A_listtarg;
{
clrprereqs(r);
r->attributes |= A_listprereq;
col = dumpname(1, r->local.pointer ? (((struct local*)r->local.pointer)->target ? ((struct local*)r->local.pointer)->target : ((struct local*)r->local.pointer)->base) : r->name);
{
clrprereqs(p->rule);
}
dumpaction(r->action);
}
if (p->rule != r)
}
}
/*
* dump state var definition
*/
static int
{
register char* s = v->value;
register int col;
static int init;
if (*s++ == '-')
{
if (*s == 'D')
{
while (isalnum(*++s));
if (*s++ == '=')
{
if (!init)
{
init = 1;
}
v->attributes |= V_state;
col += 2;
if (*s == '"')
{
s[strlen(s) - 1] = 0;
}
else
}
else
{
if (!init)
{
init = 1;
}
v->attributes |= V_state;
}
}
else if (*s == 'U')
{
if (!init)
{
init = 1;
}
v->attributes |= V_state;
}
}
return 0;
}
/*
* dump interesting var definitions
*/
static void
dumpvar(void)
{
register struct var* v;
}
/*
* add prefix to list of dir prefixes to omit
*/
static void
{
struct block* p;
}
int
{
register struct list* p;
for (;;)
{
{
case 'd':
continue;
case 'x':
continue;
case '?':
break;
case ':':
break;
}
break;
}
if (error_info.errors)
/*
* preventive maintenance
*/
/*
* initialize
*/
/*
* scan, collect and dump
*/
dumpvar();
}