ANSIfication; bug report 4.3BSD/bin/223
[unix-history] / usr / src / old / cpp / cpp.c
index c12bd93..5564bac 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)cpp.c 1.2 %G%";
+static char sccsid[] = "@(#)cpp.c      1.17 %G%";
 #endif lint
 
 #ifdef FLEXNAMES
 #endif lint
 
 #ifdef FLEXNAMES
@@ -8,6 +8,7 @@ static char sccsid[] = "@(#)cpp.c 1.2 %G%";
 #define        NCPS    8
 #endif
 
 #define        NCPS    8
 #endif
 
+# include "sys/param.h"
 # include "stdio.h"
 # include "ctype.h"
 /* C command
 # include "stdio.h"
 # include "ctype.h"
 /* C command
@@ -17,14 +18,14 @@ static char sccsid[] = "@(#)cpp.c 1.2 %G%";
 
 #define STATIC
 
 
 #define STATIC
 
+#define FIRSTOPEN -2
 #define STDIN 0
 #define STDIN 0
-#define STDOUT 1
-#define STDERR 2
 #define READ 0
 #define WRITE 1
 #define SALT '#'
 #define READ 0
 #define WRITE 1
 #define SALT '#'
-#ifndef BUFSIZ
-#define BUFSIZ 512
+#if !defined BUFSIZ || BUFSIZ < 8192
+#undef BUFSIZ
+#define BUFSIZ 8192
 #endif
 
 char *pbeg,*pbuf,*pend;
 #endif
 
 char *pbeg,*pbuf,*pend;
@@ -34,7 +35,7 @@ char cinit;
 
 /* some code depends on whether characters are sign or zero extended */
 /*     #if '\377' < 0          not used here, old cpp doesn't understand */
 
 /* some code depends on whether characters are sign or zero extended */
 /*     #if '\377' < 0          not used here, old cpp doesn't understand */
-#if pdp11 | vax
+#if pdp11 | vax | mc68000 | tahoe
 #define COFF 128
 #else
 #define COFF 0
 #define COFF 128
 #else
 #define COFF 0
@@ -107,11 +108,13 @@ char *ptrtab;
 #define eob(a) ((a)>=pend)
 #define bob(a) (pbeg>=(a))
 
 #define eob(a) ((a)>=pend)
 #define bob(a) (pbeg>=(a))
 
+# define cputc(a,b)    if(!flslvl) putc(a,b)
+
 char buffer[NCPS+BUFSIZ+BUFSIZ+NCPS];
 
 char buffer[NCPS+BUFSIZ+BUFSIZ+NCPS];
 
-# define SBSIZE 48000          /* std = 12000, wnj aug 1979 */
-char   sbf[SBSIZE];
-char   *savch  = sbf;
+char   *lastcopy;
+
+char *malloc(), *realloc();
 
 # define DROP 0xFE     /* special character not legal ASCII or EBCDIC */
 # define WARN DROP
 
 # define DROP 0xFE     /* special character not legal ASCII or EBCDIC */
 # define WARN DROP
@@ -146,12 +149,19 @@ STATIC    int     lineno[MAXINC];
 STATIC char    *dirs[10];      /* -I and <> directories */
 char *strdex(), *copy(), *subst(), *trmdir();
 struct symtab *stsym();
 STATIC char    *dirs[10];      /* -I and <> directories */
 char *strdex(), *copy(), *subst(), *trmdir();
 struct symtab *stsym();
-STATIC int     fin     = STDIN;
+STATIC int     fin     = FIRSTOPEN;
 STATIC FILE    *fout   = stdout;
 STATIC int     nd      = 1;
 STATIC int     pflag;  /* don't put out lines "# 12 foo.c" */
 STATIC FILE    *fout   = stdout;
 STATIC int     nd      = 1;
 STATIC int     pflag;  /* don't put out lines "# 12 foo.c" */
-STATIC int     passcom;        /* don't delete comments */
+int    passcom;        /* don't delete comments */
+int    incomment;      /* True if parsing a comment */
 STATIC int rflag;      /* allow macro recursion */
 STATIC int rflag;      /* allow macro recursion */
+STATIC int mflag;      /* generate makefile dependencies */
+STATIC char *infile;   /* name of .o file to build dependencies from */
+STATIC         FILE *mout;     /* file to place dependencies on */
+#define START 1
+#define CONT  2
+#define BACK  3
 STATIC int     ifno;
 # define NPREDEF 20
 STATIC char *prespc[NPREDEF];
 STATIC int     ifno;
 # define NPREDEF 20
 STATIC char *prespc[NPREDEF];
@@ -175,7 +185,7 @@ static jmp_buf env;
 extern FILE *_f[];
 # define symsiz 500
 # else
 extern FILE *_f[];
 # define symsiz 500
 # else
-# define symsiz 1000           /* std = 500, wnj aug 1979 */
+# define symsiz 2000           /* std = 500, wnj aug 1979 */
 # endif
 STATIC struct symtab stab[symsiz];
 
 # endif
 STATIC struct symtab stab[symsiz];
 
@@ -192,10 +202,14 @@ STATIC    struct symtab *varloc;
 STATIC struct symtab *lneloc;
 STATIC struct symtab *ulnloc;
 STATIC struct symtab *uflloc;
 STATIC struct symtab *lneloc;
 STATIC struct symtab *ulnloc;
 STATIC struct symtab *uflloc;
+STATIC struct symtab *identloc;        /* Sys 5r3 compatibility */
 STATIC int     trulvl;
 STATIC int     flslvl;
 
 STATIC int     trulvl;
 STATIC int     flslvl;
 
-sayline() {
+sayline(where)
+       int where;
+{
+       if (mflag && where==START) fprintf(mout, "%s: %s\n", infile, fnames[ifno]);
        if (pflag==0) fprintf(fout,"# %d \"%s\"\n", lineno[ifno], fnames[ifno]);
 }
 
        if (pflag==0) fprintf(fout,"# %d \"%s\"\n", lineno[ifno], fnames[ifno]);
 }
 
@@ -247,7 +261,7 @@ sayline() {
 /* buffers which are "live"; the side buffers instack[0 : inctop[ifno]]
 /* are dormant, waiting for end-of-file on the current file.
 /*
 /* buffers which are "live"; the side buffers instack[0 : inctop[ifno]]
 /* are dormant, waiting for end-of-file on the current file.
 /*
-/* space for side buffers is obtained from 'savch' and is never returned.
+/* space for side buffers is obtained from 'malloc' and is never returned.
 /* bufstack[0:fretop-1] holds addresses of side buffers which
 /* are available for use.
 */
 /* bufstack[0:fretop-1] holds addresses of side buffers which
 /* are available for use.
 */
@@ -274,7 +288,7 @@ dump() {
                        }
                        if (c==' ' && stopc==0) pblank=p1-1;
                }
                        }
                        if (c==' ' && stopc==0) pblank=p1-1;
                }
-               if (brk) sayline();
+               if (brk) sayline(CONT);
                *p2=savc; inp=p2; p1=outp; tgpscan=0;
        }
 #endif
                *p2=savc; inp=p2; p1=outp; tgpscan=0;
        }
 #endif
@@ -330,9 +344,14 @@ refill(p) register char *p; {
                                        pend=np; *np='\0'; if (plvl<0) plvl=0;
                                        return(p);
                                }
                                        pend=np; *np='\0'; if (plvl<0) plvl=0;
                                        return(p);
                                }
+                               if (trulvl || flslvl)
+                                       if (incomment)
+                                               pperror("unterminated comment");
+                                       else
+                                               pperror("missing endif");
                                inp=p; dump(); exit(exfail);
                        }
                                inp=p; dump(); exit(exfail);
                        }
-                       close(fin); fin=fins[--ifno]; dirs[0]=dirnams[ifno]; sayline();
+                       close(fin); fin=fins[--ifno]; dirs[0]=dirnams[ifno]; sayline(BACK);
                }
        }
 }
                }
        }
 }
@@ -376,6 +395,7 @@ again:
        } break;
        case '/': for (;;) {
                if (*p++=='*') {/* comment */
        } break;
        case '/': for (;;) {
                if (*p++=='*') {/* comment */
+                       incomment++;
                        if (!passcom) {inp=p-2; dump(); ++flslvl;}
                        for (;;) {
                                while (!iscom(*p++));
                        if (!passcom) {inp=p-2; dump(); ++flslvl;}
                        for (;;) {
                                while (!iscom(*p++));
@@ -385,7 +405,7 @@ again:
                                                if (!passcom) {inp=p; p=refill(p);}
                                                else if ((p-inp)>=BUFSIZ) {/* split long comment */
                                                        inp=p; p=refill(p);     /* last char written is '*' */
                                                if (!passcom) {inp=p; p=refill(p);}
                                                else if ((p-inp)>=BUFSIZ) {/* split long comment */
                                                        inp=p; p=refill(p);     /* last char written is '*' */
-                                                       putc('/',fout); /* terminate first part */
+                                                       cputc('/',fout);        /* terminate first part */
                                                        /* and fake start of 2nd */
                                                        outp=inp=p-=3; *p++='/'; *p++='*'; *p++='*';
                                                } else p=refill(p);
                                                        /* and fake start of 2nd */
                                                        outp=inp=p-=3; *p++='/'; *p++='*'; *p++='*';
                                                } else p=refill(p);
@@ -396,12 +416,13 @@ again:
                                        if (!passcom) {inp=p; p=refill(p);}
                                        else if ((p-inp)>=BUFSIZ) {/* split long comment */
                                                inp=p; p=refill(p);
                                        if (!passcom) {inp=p; p=refill(p);}
                                        else if ((p-inp)>=BUFSIZ) {/* split long comment */
                                                inp=p; p=refill(p);
-                                               putc('*',fout); putc('/',fout);
+                                               cputc('*',fout); cputc('/',fout);
                                                outp=inp=p-=2; *p++='/'; *p++='*';
                                        } else p=refill(p);
                                } else ++p; /* ignore null byte */
                        }
                endcom:
                                                outp=inp=p-=2; *p++='/'; *p++='*';
                                        } else p=refill(p);
                                } else ++p; /* ignore null byte */
                        }
                endcom:
+                       incomment--;
                        if (!passcom) {outp=inp=p; --flslvl; goto again;}
                        break;
                }
                        if (!passcom) {outp=inp=p; --flslvl; goto again;}
                        break;
                }
@@ -521,9 +542,9 @@ unfill(p) register char *p; {
        }
        if (fretop>0) np=bufstack[--fretop];
        else {
        }
        if (fretop>0) np=bufstack[--fretop];
        else {
-               np=savch; savch+=BUFSIZ;
-               if (savch>=sbf+SBSIZE) {pperror("no space"); exit(exfail);}
-               *savch++='\0';
+               np=malloc(BUFSIZ+1);
+               if (np==NULL) {pperror("no space"); exit(exfail);}
+               np[BUFSIZ]='\0';
        }
        instack[mactop]=np; op=pend-BUFSIZ; if (op<p) op=p;
        for (;;) {while (*np++= *op++); if (eob(op)) break;} /* out with old */
        }
        instack[mactop]=np; op=pend-BUFSIZ; if (op<p) op=p;
        for (;;) {while (*np++= *op++); if (eob(op)) break;} /* out with old */
@@ -569,7 +590,7 @@ doincl(p) register char *p; {
        if (ifno+1 >=MAXINC) {
                pperror("Unreasonable include nesting",0); return(p);
        }
        if (ifno+1 >=MAXINC) {
                pperror("Unreasonable include nesting",0); return(p);
        }
-       if((nfil=savch)>sbf+SBSIZE-BUFSIZ) {pperror("no space"); exit(exfail);}
+       if((nfil=malloc(BUFSIZ))==NULL) {pperror("no space"); exit(exfail);}
        filok=0;
        for (dirp=dirs+inctype; *dirp; ++dirp) {
                if (
        filok=0;
        for (dirp=dirs+inctype; *dirp; ++dirp) {
                if (
@@ -595,11 +616,12 @@ doincl(p) register char *p; {
                        filok=1; fin=fins[++ifno]; break;
                }
        }
                        filok=1; fin=fins[++ifno]; break;
                }
        }
-       if (filok==0) pperror("Can't find include file %s",filname);
+       if(filok==0){pperror("Can't find include file %s",filname);free(nfil);}
        else {
        else {
-               lineno[ifno]=1; fnames[ifno]=cp=nfil; while (*cp++); savch=cp;
+               nfil=realloc(nfil,strlen(nfil)+1);
+               lineno[ifno]=1; fnames[ifno]=nfil;
                dirnams[ifno]=dirs[0]=trmdir(copy(nfil));
                dirnams[ifno]=dirs[0]=trmdir(copy(nfil));
-               sayline();
+               sayline(START);
                /* save current contents of buffer */
                while (!eob(p)) p=unfill(p);
                inctop[ifno]=mactop;
                /* save current contents of buffer */
                while (!eob(p)) p=unfill(p);
                inctop[ifno]=mactop;
@@ -617,19 +639,22 @@ char *
 dodef(p) char *p; {/* process '#define' */
        register char *pin,*psav,*cf;
        char **pf,**qf; int b,c,params; struct symtab *np;
 dodef(p) char *p; {/* process '#define' */
        register char *pin,*psav,*cf;
        char **pf,**qf; int b,c,params; struct symtab *np;
-       char *oldval,*oldsavch;
+       char *oldval;
+       char *space, *newspace;
        char *formal[MAXFRM]; /* formal[n] is name of nth formal */
        char formtxt[BUFSIZ]; /* space for formal names */
        char *formal[MAXFRM]; /* formal[n] is name of nth formal */
        char formtxt[BUFSIZ]; /* space for formal names */
+       int opt_passcom=passcom;
+
+       passcom=0;      /* don't put comments in macro expansions */
 
 
-       if (savch>sbf+SBSIZE-BUFSIZ) {pperror("too much defining"); return(p);}
-       oldsavch=savch; /* to reclaim space if redefinition */
        ++flslvl; /* prevent macro expansion during 'define' */
        p=skipbl(p); pin=inp;
        if ((toktyp+COFF)[*pin]!=IDENT) {
        ++flslvl; /* prevent macro expansion during 'define' */
        p=skipbl(p); pin=inp;
        if ((toktyp+COFF)[*pin]!=IDENT) {
-               ppwarn("illegal macro name"); while (*inp!='\n') p=skipbl(p); return(p);
+               ppwarn("illegal macro name"); while (*inp!='\n') p=skipbl(p);
+               passcom=opt_passcom; return(p);
        }
        np=slookup(pin,p,1);
        }
        np=slookup(pin,p,1);
-       if (oldval=np->value) savch=oldsavch;   /* was previously defined */
+       if (oldval=np->value) free(lastcopy);   /* was previously defined */
        b=1; cf=pin;
        while (cf<p) {/* update macbit */
                c= *cf++; xmac1(c,b,|=); b=(b+b)&0xFF;
        b=1; cf=pin;
        while (cf<p) {/* update macbit */
                c= *cf++; xmac1(c,b,|=); b=(b+b)&0xFF;
@@ -659,7 +684,13 @@ dodef(p) char *p; {/* process '#define' */
        /* remember beginning of macro body, so that we can
        /* warn if a redefinition is different from old value.
        */
        /* remember beginning of macro body, so that we can
        /* warn if a redefinition is different from old value.
        */
-       oldsavch=psav=savch;
+       space=psav=malloc(BUFSIZ);
+       if (space==NULL) {
+               pperror("too much defining");
+               passcom=opt_passcom;
+               return(p);
+       }
+       *psav++ = '\0';
        for (;;) {/* accumulate definition until linefeed */
                outp=inp=p; p=cotoken(p); pin=inp;
                if (*pin=='\\' && pin[1]=='\n') {putc('\n',fout); continue;}    /* ignore escaped lf */
        for (;;) {/* accumulate definition until linefeed */
                outp=inp=p; p=cotoken(p); pin=inp;
                if (*pin=='\\' && pin[1]=='\n') {putc('\n',fout); continue;}    /* ignore escaped lf */
@@ -695,12 +726,22 @@ dodef(p) char *p; {/* process '#define' */
        if ((cf=oldval)!=NULL) {/* redefinition */
                --cf;   /* skip no. of params, which may be zero */
                while (*--cf);  /* go back to the beginning */
        if ((cf=oldval)!=NULL) {/* redefinition */
                --cf;   /* skip no. of params, which may be zero */
                while (*--cf);  /* go back to the beginning */
-               if (0!=strcmp(++cf,oldsavch)) {/* redefinition different from old */
+               if (0!=strcmp(++cf,space+1)) {/* redefinition different from old */
                        --lineno[ifno]; ppwarn("%s redefined",np->name); ++lineno[ifno];
                        np->value=psav-1;
                        --lineno[ifno]; ppwarn("%s redefined",np->name); ++lineno[ifno];
                        np->value=psav-1;
-               } else psav=oldsavch; /* identical redef.; reclaim space */
+               } else free(space); /* identical redef.; reclaim space */
        } else np->value=psav-1;
        } else np->value=psav-1;
-       --flslvl; inp=pin; savch=psav; return(p);
+       --flslvl; inp=pin;
+       if (np->value == psav-1) {
+               newspace = realloc(space, psav-space);
+               if (newspace==NULL) {pperror("no space"); exit(exfail);}
+               /*
+                * Adjust pointer in case this moved.
+                */
+               np->value += newspace-space;
+       }
+       passcom=opt_passcom;
+       return(p);
 }
 
 #define fasscan() ptrtab=fastab+COFF
 }
 
 #define fasscan() ptrtab=fastab+COFF
@@ -726,13 +767,13 @@ for (;;) {
                if (flslvl==0 && np->value!=0) ++trulvl;
                else ++flslvl;
        } else if (np==eifloc) {/* endif */
                if (flslvl==0 && np->value!=0) ++trulvl;
                else ++flslvl;
        } else if (np==eifloc) {/* endif */
-               if (flslvl) {if (--flslvl==0) sayline();}
+               if (flslvl) {if (--flslvl==0) sayline(CONT);}
                else if (trulvl) --trulvl;
                else pperror("If-less endif",0);
        } else if (np==elsloc) {/* else */
                if (flslvl) {
                        if (--flslvl!=0) ++flslvl;
                else if (trulvl) --trulvl;
                else pperror("If-less endif",0);
        } else if (np==elsloc) {/* else */
                if (flslvl) {
                        if (--flslvl!=0) ++flslvl;
-                       else {++trulvl; sayline();}
+                       else {++trulvl; sayline(CONT);}
                }
                else if (trulvl) {++flslvl; --trulvl;}
                else pperror("If-less else",0);
                }
                else if (trulvl) {++flslvl; --trulvl;}
                else pperror("If-less else",0);
@@ -751,24 +792,51 @@ for (;;) {
 #endif
        } else if (np==lneloc) {/* line */
                if (flslvl==0 && pflag==0) {
 #endif
        } else if (np==lneloc) {/* line */
                if (flslvl==0 && pflag==0) {
-                       char *cp, *cp2, *savestring();
-                       outp=inp=p; *--outp='#'; while (*inp!='\n') p=cotoken(p);
-                       cp = outp + 1;
-                       while (isspace(*cp) && cp < inp)
-                               cp++;
-                       while (isdigit(*cp) && cp < inp)
-                               cp++;
-                       while (*cp != '"' && cp < inp)
-                               cp++;
-                       if (cp < inp) {
-                               cp++;
-                               cp2 = cp;
-                               while (*cp2 != '"' && cp2 < inp)
-                                       cp2++;
-                               fnames[ifno] = savestring(cp, cp2);
+                       char *savestring();
+                       char filename[BUFSIZ], *cp = filename;
+                       outp=inp=p; *--outp='#';
+                       /* Find the line number.. */
+                       do {
+                               p = cotoken(p);
+                       } while (!isnum(*inp) && *inp != '\n');
+                       if (isnum(*inp))
+                               lineno[ifno] = atoi(inp)-1;
+                       /* Skip over the blank token */
+                       inp = p;
+                       if (*inp != '\n') {
+                               p = cotoken(p); inp = p;
                        }
                        }
+                       /* Add a quote if missing..  */
+                       if (*inp != '\n') {
+                               p = cotoken(p);
+                               /* Add a quote if missing..  */
+                               if (*inp == '"')
+                                       inp++;
+                               else {
+                                       dump();
+                                       *--outp = '"';
+                               }
+                               while (*inp != '\n') {
+                                       while (inp < p && *inp != '"' &&
+                                               cp < filename+sizeof(filename))
+                                               *cp++ = *inp++;
+                                       if (*inp == '"')
+                                               break;
+                                       inp = p; p = cotoken(p);
+                               }
+                               fnames[ifno] = savestring(filename, cp);
+                               /* Add a quote if missing..  */
+                               if (*inp != '"') {
+                                       dump();
+                                       *--outp = '"';
+                               }
+                       }
+                       while (*inp != '\n')
+                               p = cotoken(p);
                        continue;
                }
                        continue;
                }
+       } else if (np==identloc) {/* ident (for Sys 5r3 compat) */
+               while(*inp!='\n') p=cotoken(p);
        } else if (*++inp=='\n') outp=inp;      /* allows blank line after # */
        else pperror("undefined control",0);
        /* flush to lf */
        } else if (*++inp=='\n') outp=inp;      /* allows blank line after # */
        else pperror("undefined control",0);
        /* flush to lf */
@@ -808,7 +876,11 @@ stsym(s) register char *s; {
 struct symtab *
 ppsym(s) char *s; {/* kluge */
        register struct symtab *sp;
 struct symtab *
 ppsym(s) char *s; {/* kluge */
        register struct symtab *sp;
-       cinit=SALT; *savch++=SALT; sp=stsym(s); --sp->name; cinit=0; return(sp);
+       register char *name;
+
+       cinit=SALT; sp=stsym(s); name = malloc(strlen(sp->name)+1+1);
+       name[0] = '#'; strcpy(name+1, sp->name); sp->name = name;
+       cinit=0; return(sp);
 }
 
 /* VARARGS1 */
 }
 
 /* VARARGS1 */
@@ -881,8 +953,10 @@ char *
 subst(p,sp) register char *p; struct symtab *sp; {
        static char match[]="%s: argument mismatch";
        register char *ca,*vp; int params;
 subst(p,sp) register char *p; struct symtab *sp; {
        static char match[]="%s: argument mismatch";
        register char *ca,*vp; int params;
-       char *actual[MAXFRM]; /* actual[n] is text of nth actual */
-       char acttxt[BUFSIZ]; /* space for actuals */
+       char *actual[MAXFRM]; /* actual[n] is text of nth actual   */
+       char actused[MAXFRM]; /* for newline processing in actuals */
+       char acttxt[BUFSIZ];  /* space for actuals */
+       int  nlines = 0;
 
        if (0==(vp=sp->value)) return(p);
        if ((p-macforw)<=macdam) {
 
        if (0==(vp=sp->value)) return(p);
        if ((p-macforw)<=macdam) {
@@ -895,10 +969,10 @@ subst(p,sp) register char *p; struct symtab *sp; {
        dump();
        if (sp==ulnloc) {
                vp=acttxt; *vp++='\0';
        dump();
        if (sp==ulnloc) {
                vp=acttxt; *vp++='\0';
-               sprintf(vp,"%d",lineno[ifno]); while (*vp++);
+               (void)sprintf(vp,"%d",lineno[ifno]); while (*vp++);
        } else if (sp==uflloc) {
                vp=acttxt; *vp++='\0';
        } else if (sp==uflloc) {
                vp=acttxt; *vp++='\0';
-               sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++);
+               (void)sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++);
        }
        if (0!=(params= *--vp&0xFF)) {/* definition calls for params */
                register char **pa;
        }
        if (0!=(params= *--vp&0xFF)) {/* definition calls for params */
                register char **pa;
@@ -921,8 +995,10 @@ subst(p,sp) register char *p; struct symtab *sp; {
                                                pperror("%s: actuals too long",sp->name);
                                }
                                if (pa>= &actual[MAXFRM]) ppwarn(match,sp->name);
                                                pperror("%s: actuals too long",sp->name);
                                }
                                if (pa>= &actual[MAXFRM]) ppwarn(match,sp->name);
-                               else *pa++=ca;
+                               else { actused[pa-actual]=0; *pa++=ca; }
                        }
                        }
+                       nlines = lineno[ifno] - maclin;
+                       lineno[ifno] = maclin; /* don't count newlines here */
                }
                if (params!=0) ppwarn(match,sp->name);
                while (--params>=0) *pa++=""+1; /* null string for missing actuals */
                }
                if (params!=0) ppwarn(match,sp->name);
                while (--params>=0) *pa++=""+1; /* null string for missing actuals */
@@ -937,9 +1013,19 @@ subst(p,sp) register char *p; struct symtab *sp; {
                        ca=actual[*--vp-1];
                        while (*--ca) {
                                if (bob(p)) {outp=inp=p; p=unfill(p);}
                        ca=actual[*--vp-1];
                        while (*--ca) {
                                if (bob(p)) {outp=inp=p; p=unfill(p);}
-                               *--p= *ca;
+                               /* Actuals with newlines confuse line numbering */
+                               if (*ca == '\n' && actused[*vp-1])
+                                       if (*(ca-1) == '\\') ca--;
+                                       else *--p = ' ';
+                               else { *--p= *ca; if (*ca == '\n') nlines--; }
                        }
                        }
-               } else break;
+                       actused[*vp-1] = 1;
+               } else {
+                       if (nlines > 0 )
+                               while (nlines-- > 0)
+                                       *--p = '\n';
+                       break;
+               }
        }
        outp=inp=p;
        return(p);
        }
        outp=inp=p;
        return(p);
@@ -963,8 +1049,10 @@ STATIC char *
 copy(s) register char *s; {
        register char *old;
 
 copy(s) register char *s; {
        register char *old;
 
-       old = savch; while (*savch++ = *s++);
-       return(old);
+       old = malloc(strlen(s)+1);
+       if (old==NULL) {pperror("no space"); exit(exfail);}
+       strcpy(old, s);
+       return(lastcopy=old);
 }
 
 char *
 }
 
 char *
@@ -1045,6 +1133,7 @@ main(argc,argv)
 # else
                        switch(argv[i][1]) {
 # endif
 # else
                        switch(argv[i][1]) {
 # endif
+                               case 'M': mflag++;
                                case 'P': pflag++;
                                case 'E': continue;
                                case 'R': ++rflag; continue;
                                case 'P': pflag++;
                                case 'E': continue;
                                case 'R': ++rflag; continue;
@@ -1074,11 +1163,12 @@ main(argc,argv)
                                        continue;
                                }
                        default:
                                        continue;
                                }
                        default:
-                               if (fin==STDIN) {
+                               if (fin==FIRSTOPEN) {
                                        if (0>(fin=open(argv[i], READ))) {
                                                pperror("No source file %s",argv[i]); exit(8);
                                        }
                                        fnames[ifno]=copy(argv[i]);
                                        if (0>(fin=open(argv[i], READ))) {
                                                pperror("No source file %s",argv[i]); exit(8);
                                        }
                                        fnames[ifno]=copy(argv[i]);
+                                       infile=copy(argv[i]);
                                        dirs[0]=dirnams[ifno]=trmdir(argv[i]);
 # ifndef gcos
 /* too dangerous to have file name in same syntactic position
                                        dirs[0]=dirnams[ifno]=trmdir(argv[i]);
 # ifndef gcos
 /* too dangerous to have file name in same syntactic position
@@ -1087,15 +1177,38 @@ main(argc,argv)
        [i don't see what the problem is.  jfr]
 */
                                } else if (fout==stdout) {
        [i don't see what the problem is.  jfr]
 */
                                } else if (fout==stdout) {
-                                       extern char _sobuf[BUFSIZ];
                                        if (NULL==(fout=fopen(argv[i], "w"))) {
                                                pperror("Can't create %s", argv[i]); exit(8);
                                        if (NULL==(fout=fopen(argv[i], "w"))) {
                                                pperror("Can't create %s", argv[i]); exit(8);
-                                       } else {fclose(stdout); setbuf(fout,_sobuf);}
+                                       } else fclose(stdout);
 # endif
                                } else pperror("extraneous name %s", argv[i]);
                        }
                }
 # endif
                                } else pperror("extraneous name %s", argv[i]);
                        }
                }
-
+       if (fin == FIRSTOPEN)
+               fin = STDIN;
+
+       if (mflag) {
+               if (infile==(char *)0) {
+                       fprintf(stderr,
+                               "no input file specified with -M flag\n");
+                       exit(8);
+               }
+               tf=(char *)rindex(infile, '.');
+               if (tf==0) {
+                       fprintf(stderr, "missing component name on %s\n",
+                               infile);
+                       exit(8);
+               }
+               tf[1]='o';
+               tf=(char *)rindex(infile, '/');
+               if (tf!=(char *)0)
+                       infile = tf + 1;
+               mout=fout;
+               if (NULL==(fout=fopen("/dev/null", "w"))) {
+                       pperror("Can't open /dev/null");
+                       exit(8);
+               }
+       }
        fins[ifno]=fin;
        exfail = 0;
                /* after user -I files here are the standard include libraries */
        fins[ifno]=fin;
        exfail = 0;
                /* after user -I files here are the standard include libraries */
@@ -1124,34 +1237,12 @@ main(argc,argv)
        ifnloc=ppsym("ifndef");
        ifloc=ppsym("if");
        lneloc=ppsym("line");
        ifnloc=ppsym("ifndef");
        ifloc=ppsym("if");
        lneloc=ppsym("line");
+       identloc=ppsym("ident");        /* Sys 5r3 compatibility */
        for (i=sizeof(macbit)/sizeof(macbit[0]); --i>=0; ) macbit[i]=0;
 # if unix
        ysysloc=stsym("unix");
 # endif
        for (i=sizeof(macbit)/sizeof(macbit[0]); --i>=0; ) macbit[i]=0;
 # if unix
        ysysloc=stsym("unix");
 # endif
-# if gcos
-       ysysloc=stsym ("gcos");
-# endif
-# if ibm
-       ysysloc=stsym ("ibm");
-# endif
-# if pdp11
-       varloc=stsym("pdp11");
-# endif
-# if vax
-       varloc=stsym("vax");
-# endif
-# if interdata
-       varloc=stsym ("interdata");
-# endif
-# if tss
-       varloc=stsym ("tss");
-# endif
-# if os
-       varloc=stsym ("os");
-# endif
-# if mert
-       varloc=stsym ("mert");
-# endif
+       ysysloc=stsym(MACHINE);
        ulnloc=stsym ("__LINE__");
        uflloc=stsym ("__FILE__");
 
        ulnloc=stsym ("__LINE__");
        uflloc=stsym ("__FILE__");
 
@@ -1167,7 +1258,7 @@ main(argc,argv)
        pbeg=buffer+NCPS; pbuf=pbeg+BUFSIZ; pend=pbuf+BUFSIZ;
 
        trulvl = 0; flslvl = 0;
        pbeg=buffer+NCPS; pbuf=pbeg+BUFSIZ; pend=pbuf+BUFSIZ;
 
        trulvl = 0; flslvl = 0;
-       lineno[0] = 1; sayline();
+       lineno[0] = 1; sayline(START);
        outp=inp=pend;
        control(pend);
        return (exfail);
        outp=inp=pend;
        control(pend);
        return (exfail);