/***********************************************************************
* *
* 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 oldmake makefile on stdout
*/
static const char usage[] =
"[-?\n@(#)$Id: mamold (AT&T Research) 1989-03-22 $\n]"
"[+NAME?mamold - make abstract machine to oldmake makefile conversion filter]"
"[+DESCRIPTION?\bmamold\b reads MAM (Make Abstract Machine) target and"
" prerequisite file descriptions from the standard input and writes"
" an equivalent \bgmake\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. Recursive makefiles"
" are not converted; each makefile level must be converted separately.]"
"[d:debug?]#[level]"
"[g:graph?Verify the dependency graph but do not generate a makefile on"
" the standard output.]"
"[h:header?Use \atext\as instead of the default for the generated makefile"
" header.]#[text]"
"[x:omit?Omit pathnames with directory \aprefix\a.]#[prefix]"
"[+SEE ALSO?\bmamnew\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>
#include <stdio.h>
{
};
/*
* clear listprereq for all prerequisites
*/
static void
{
register struct list* p;
r->attributes &= ~A_listprereq;
clrprereqs(p->rule);
clrprereqs(p->rule);
}
/*
* dump a value that may be expanded by oldmake
*/
static int
{
register int c;
register char* v;
int dollar;
int escape = 0;
int quote = 0;
if (sep)
{
col++;
}
for (;;)
switch (c = *s++)
{
case 0:
{
col = 1;
}
return col;
case ' ':
case '\t':
goto emit;
while (isspace(*s))
s++;
if (*s)
{
col = 8;
}
break;
case '#':
col += 8;
break;
case '<':
if (sep == '\t' && *s == c)
goto emit;
case '\'':
goto emit;
case '\\':
if (*s != '$' && *s != '\'')
goto emit;
s++;
escape = -1;
/*FALLTHROUGH*/
case '$':
escape++;
dollar = 1;
if (isalpha(*s) || *s == '_')
{
for (v = s; isalnum(*v) || *v == '_'; v++);
c = *v;
*v = 0;
{
col += (v - s) + 3;
*(s = v) = c;
escape = 0;
break;
}
*v = c;
}
if (escape)
{
escape = 0;
if (!quote)
switch (*s)
{
case '{':
if (*(v = s + 1))
v++;
while (isalnum(*v) || *v == '_')
v++;
switch (*v)
{
case ':':
case '-':
case '+':
break;
default:
dollar = 0;
break;
}
break;
case '$':
s--;
do
{
col++;
} while (*++s == '$');
break;
default:
col++;
break;
}
}
else
dollar = 0;
c = '$';
if (dollar)
{
col++;
}
/*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;
}
else if (col++ > 1)
dumpvalue(0, s, 0);
return col;
}
/*
* dump an action
*/
static void
{
if (p)
{
for (;;)
{
if (!(p = p->next))
break;
}
}
}
/*
* dump r and its implicit prerequisites
*/
static int
{
register struct block* d;
register struct list* p;
if (!(r->attributes & A_listprereq))
{
r->attributes |= A_listprereq;
return col;
}
return col;
}
/*
* dump the rules
*/
static void
{
register int col;
register struct list* p;
{
r->attributes |= A_listtarg;
{
clrprereqs(r);
r->attributes |= A_listprereq;
{
clrprereqs(p->rule);
}
dumpaction(r->action);
}
if (p->rule != r)
if (p->rule != r)
}
}
/*
* dump var definition
*/
static int
{
register char* s;
register char* t;
register int c;
if (*v->value)
{
s = t = v->value;
while (c = *t++ = *s++)
{
if (c == '\\')
{
if (!(*t++ = *s++))
break;
}
else if (c == '"')
t--;
}
}
return 0;
}
/*
* add prefix to list of dir prefixes to omit
*/
static void
{
int n;
struct block* p;
}
int
{
register struct list* p;
for (;;)
{
{
case 'd':
continue;
case 'g':
continue;
case 'h':
continue;
case 'x':
continue;
case '?':
break;
case ':':
break;
}
break;
}
if (error_info.errors)
/*
* initialize
*/
omit("/");
/*
* scan, collect and dump
*/
{
}
}