File contents
/*
* Macro expanseur de macros "a la Motorola"
* ecrit par Zohra Bellahsene pour le transport du
* systeme Le_Lisp 68K sur SM90.
* [adapte pour VAX par Jerome Chailloux 15-Fev-83]
*/
/* variables globales */
# define MAXMAC 2000
# define MAXMEM 30000
# define MAXPAR 20
# include <stdio.h>
struct stligne {
char *etiquette;
char *codop;
char *paramv [MAXPAR];
};
struct descripm {
char *nom;
char *corps;
};
struct descripm pmac [MAXMAC];
struct descripm *entc = pmac;
char *ptc, *pts;
char *index();
char mem [MAXMEM];
char *memp = mem;
char *salloc ();
/*
* allocation dynamique de la mem.
* pour y stocker le corps d'une macro
*/
putmacro (c)
{
if (memp >= MAXMEM + mem) nonmem ();
*memp++ = c;
}
/*
* fonction delimitant un champ
*/
char *champ (firstexp)
int firstexp;
{
char c, *ptd = pts;
while (*ptc != '\n' && *ptc != '\t' && *ptc != ' ') {
/* decodage du type de l'operande */
if (firstexp == 0) {
switch (*ptc) {
case '#':
/* argument immediat */
*pts++ = '$';
ptc++;
continue;
case '$':
/* constante hexadecimale */
if ((*++ptc>='0' && *ptc<='9') ||
(*ptc>='A' && *ptc<='F')) {
*pts++ = '0';
*pts++ = 'x';
--ptc;
while ((*++ptc>='0' && *ptc<='9') ||
(*ptc>='A' && *ptc<='F'))
*pts++ = *ptc;
} else {
*pts++ = '$';
*pts++ = *ptc++;
}
continue;
}
};
switch (*ptc) {
case ',':
/* argument suivant */
*pts++ = *ptc++;
break;
case '*':
/* compteur d'assemblage */
*pts++ = '*';
ptc++;
break;
case '(':
*pts++ = *ptc++;
break;
case ')':
*pts++ = *ptc++;
break;
case '<':
/* argument completement quote */
while (*++ptc!='>') {
if (*ptc == '\n') merr(5);
*pts++ = *ptc;
}
++ptc;
break;
case '\'':
/* constante ASCII (sans doublement!) */
*pts++ = '"';
ptc++;
while (*ptc != '\'') *pts++ = *ptc++;
*pts++ = '"';
ptc++;
break;
case 'A':
/* accumulateurs de LLM3 */
ptc++;
if (*ptc == '1' || *ptc == '2' ||
*ptc == '3' || *ptc == '4') {
*pts++ = 'r';
*pts++ = *ptc++;
} else *pts++ = 'a';
break;
default:
while (*ptc != '\n' && *ptc != ' ' &&
*ptc != '\t' && *ptc != ',' &&
*ptc != '(' && *ptc!= ')' ) {
if (*ptc>='A' && *ptc<='Z') {
*pts++ = *ptc++ + 'a' - 'A';
} else {
*pts++ = *ptc++;
}
}
}
}
/* saute tous les espaces, toutes les tabulations
pret pour l'US suivante */
while (*ptc == ' ' || *ptc == '\t')
ptc++;
/* termine la chaine champ */
*pts++ = ' ';
return (ptd);
}
/*
* recupere le caractere suivant d'une chaine ASCII
* dont les ' sont doubles
*/
getquote ()
{
char c;
c = *++ptc;
if (c == '\'') {
if ( *++ptc == '\'') {
return (c);
}
return(NULL);
}
if (!c || c=='\n') {
merr(6);
return(NULL);
}
return(c);
}
/*
* decomposition d'une ligne en champs
*/
decompligne(ligne, tchampp, copie, firstexp)
char *ligne, *copie;
struct stligne *tchampp;
int firstexp;
{ int i;
char *pit;
char *pat;
ptc = ligne;
pts = copie;
tchampp->etiquette = champ (firstexp);
tchampp->codop = champ (firstexp);
pit = champ (firstexp);
/* detecter les . arguments mais pas en 1ere position! */
if ((pat = index(tchampp->codop, '.')) && pat != tchampp->codop)
{
tchampp->paramv[0] = pat + 1;
*pat = ' ';
} else
tchampp->paramv[0] = "";
for (i = 1; i < MAXPAR; i++) /* remplacer les , par des */
{
tchampp->paramv[i] = pit;
while (*pit != ',' && *pit != ' ')
pit++;
if (*pit == ',') *pit++ = ' ';
}
}
/*
* fonction recherchant le nom d'une macro
* dans le descrip. des macros
*/
struct descripm *ismacro (tchampp)
struct stligne *tchampp;
{
struct descripm *macp;
for (macp = pmac; macp < entc; macp++)
{
if (strcmp (tchampp->codop, macp->nom) == 0)
return (macp);
}
return (NULL);
}
/*
* message d'erreur pour signaler
* des parametres de macro incorrects
*/
merr (n)
int n;
{
fprintf (stderr, "erreur no %d parametre incorrect \n",n);
exit (1);
}
/*
* teste s'il y a au moins un \@,
* le remplace par l'etiq. courante
*/
getetiq (macp)
struct descripm *macp;
{
static int etiqcount;
char c;
char *car;
car = macp->corps;
while ((c = *car) != ' ')
{
if ((c = *car++) == '\\')
{
if ((c = *car++) == '@')
return (++etiqcount);
}
}
return (0);
}
/*
* expanse un appel de macro
*/
expandmacro (macp, tchampp)
struct descripm *macp;
struct stligne *tchampp;
{
char c, ligne[120], *chaine;
int dansif;
char *corps;
int etiq;
corps = macp->corps;
etiq = getetiq (macp);
chaine = ligne;
dansif = 0;
while ((c = *corps) != ' ')
{
if ((c = *corps++) == '\\') {
/* remplacer le nom des parametres par leur valeur */
if ((c = *corps) >= '0' && c <= '9') {
sprintf(chaine, "%s", tchampp->paramv[c-'0']);
chaine += strlen(chaine);
} else
if ((c = *corps) == '@' ) {
/* remplacer les \@ par l'etiquette courante */
sprintf(chaine, ".%d", etiq);
chaine += strlen(chaine);
}
else
/* parametre incorrect */
merr (7);
++corps;
}
else
*chaine++ = c;
if (c == '\n')
{
*chaine++ = ' ';
dansif = recurmacro(ligne, dansif, 1);
chaine = ligne;
}
}
}
/*
* definition d'une macro
*/
defmacro(tchampp)
struct stligne *tchampp;
{
struct stligne tchamp;
char *p, c;
char copie[120], ligne[120];
strcpy (entc->nom = salloc(strlen(tchampp->etiquette) + 1),
tchampp->etiquette);
entc->corps = memp;
/* memoriser le corps de la macro */
while( fgets(ligne, sizeof ligne, stdin) )
{
decompligne(ligne, &tchamp, copie, 0);
if ( strcmp ( tchamp.codop, "endm" ) == 0 )
break;
p = ligne;
while( c = *p++ )
{
putmacro (c);
}
}
entc++;
}
/*
* allocation dynamique de la memoire
*/
char *salloc (N)
{
char *p;
p = memp;
if ( (memp += N) <= mem + MAXMEM)
return (p);
nonmem ();
}
/*
* message de debordement memoire
*/
nonmem ()
{
fprintf (stderr, " plus d'espace memoire disponible \n");
exit (1);
}
/*
* procedure recursive principale
*/
recurmacro(chaine,dansif,firstexp)
char *chaine;
{
int i;
struct stligne tchamp;
char copie[120];
struct descripm *macp;
if (*chaine =='*' || *chaine =='\n') {
return(dansif);
}
decompligne(chaine, &tchamp, copie, firstexp);
if (strcmp(tchamp.codop, "equ") == 0) {
if (strcmp(tchamp.paramv[1], "*") == 0)
printf("%s:\n",tchamp.etiquette); else
printf("\t.set\t%s,%s\n",tchamp.etiquette,
tchamp.paramv[1]);
return(dansif);
}
if (strcmp(tchamp.codop, "endc") == 0)
return(0);
if (strcmp(tchamp.codop, "ifeq")==0 ||
strcmp(tchamp.codop, "ifne")==0)
return ( ifeqne(equal(tchamp.codop, "ifeq"),
tchamp.paramv[1]) );
if (strcmp(tchamp.codop, "ifc")==0 ||
strcmp(tchamp.codop, "ifnc")==0 )
return (equal(tchamp.paramv[1], tchamp.paramv[2]) !=
equal(tchamp.codop, "ifc") );
if (dansif)
return(dansif);
if (strcmp (tchamp.codop, "macro") == 0) {
defmacro (&tchamp);
return(dansif);
}
if (*tchamp.etiquette)
printf("%s:\n",tchamp.etiquette);
/* La recursion est enlevee temporairement !!! */
if (((macp = ismacro (&tchamp)) != NULL) && (firstexp == 0)) {
expandmacro (macp, &tchamp);
} else {
if (!*tchamp.codop)
return (dansif); else {
if (!firstexp) {
fprintf (stderr,
"***** ce n'est pas une macro %s\n",
tchamp.codop);}
printf("\t%s",tchamp.codop);
for (i = 1; i < MAXPAR; i++) {
if (*tchamp.paramv[i]) {
if (i != 1) printf(",");
else printf("\t");
printf("%s",tchamp.paramv[i]);
}
}
}
printf("\n");
}
return(dansif);
}
/*
* programme principal
*/
main ()
{
int dansif;
int firstexp;
char ligne[120];
dansif = 0;
firstexp = 0;
while (fgets(ligne, sizeof ligne, stdin) != NULL) {
/*
printf("#%s",ligne);
*/
dansif = recurmacro(ligne, dansif, firstexp);
}
}
equal(a,b)
{
return (!strcmp(a,b));
}
ifeqne(iseqne, string)
{
return( iseqne==0 );
}