home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-09-03 | 27.7 KB | 1,225 lines |
- /*
- Macro Front-End. EXPAND.C
- R.J.P. 12/7/92
- Front end for XASM
- 14th July 1992 Port to ARC.
- 17th July 1992 Change Macro listing.
- 17th July 1992 add Time stamp.
- 23rd July 1992 Fix another Macro search bug
- 15th August 1992 Losing Comments in +C
- 3rd September 1992 Fix Numerical Evaluation radix recognition.
- */
- /* Conditional( */
- /*
- Switches:
-
- /I:input_file normal Path on both PC & Arc.
- /O:output_file " " "
-
- ** note #INCLUDE directives in source must be of the
- form DIR/DIR/../DIR/file.ext for PC
- and DIR/DIR/../ext/file.ext for the Arc. I use the same
- convention for assembler as that of the 'C' compiler, and the
- Arc version of EXPAND just changes al the '/' to '.' & removes
- the final .ext ....
-
- -C Chop out all comments.
- +M Put in Expanded #MACRO definitions
- +U Generate Time,Date & Source file #DEFINES
- /W: Generate copyright define
-
- #SYMBOL [<expr>] Generate a Symbol with a long value known to
- EXPAND - EXPAND does not care about #DEFINE #IF etc...
- Expressions allowed for #SYMBOL are more or less the same as
- in TASM, but the syntax analyser is 'normal'. All expressions
- and constants are held as 'long' (32 bit integer).
-
- ?IF , ?ELSE , ?ENDIF operate for #SYMBOLS as #IF does for
- #DEFINES...
-
-
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <string.h>
- #include <ctype.h>
- #include <time.h>
- #include <setjmp.h>
-
- #undef TRUE
- #undef FALSE
- #undef BOOL
-
- #define BOOL unsigned char
- #define TRUE 1
- #define FALSE 0
-
- #define WS_SIZE 4096
-
- typedef struct {
- char *fn ;
- FILE *fh ;
- void *pt ;
- int sln ;
- } IFL ;
-
- typedef struct {
- char *txt ;
- unsigned char pn ;
- void *nx ;
- } MacSeg ;
-
- typedef struct {
- char *txt ;
- void *nx ;
- } ParamRec ;
-
- typedef struct {
- char *txt ;
- long sv ;
- void *nx ;
- } SREC ;
-
- typedef struct {
- int N;
- char *mn ;
- MacSeg *mp ;
- void *nx ;
- } MLST ;
-
- typedef struct {
- BOOL on ;
- void *nx ;
- } CONDLST ;
-
- IFL *IL = 0 ; /* In File List. */
- char LB[133] ; /* Input Char. buffer */
- char CB[133] ; /* Appended comment buffer */
- char *LP ; /* Pointer to input buffer */
-
- MLST *ML ; /* List of Macro Definitions */
- char *W ; /* Pointer to macro build work-space */
-
- SREC *SL ; /* Pointer to Symbol List */
- CONDLST *EL ; /* Pointer to switches */
-
- BOOL B_Mlist = FALSE ; /* Listing Macros */
- BOOL B_Commlist = TRUE ; /* Listing Comments */
- BOOL B_ListOn = TRUE ;
- BOOL B_Stamp = FALSE ;
-
- char F_src[65] ; /* Primary Source file */
- char F_asm[65] ; /* Output file */
- char T_copyw[25];
- FILE *ALST ; /* Output Stream */
-
- unsigned int Umem , UmemMax ;
- int Nmacs,Smacs , Nsymbs ,Ssymbs ;
- jmp_buf EvalErr ;
-
-
- /*
- Forward Refs.
- */
-
-
- static char *nextc ;
- static long iexp( int ) ;
- static void Kill(void) ;
- static char *NextString(void) ;
-
-
- static SREC *SymbolSearch( char *txb , char **la )
- {
- int sl,sx ;
- char *cp,*Tcp ;
- SREC *S,*ST ;
-
- if (!SL) return 0 ;
-
- for( sl = 0 , ST = 0 , S = SL; S ; S = S->nx )
- {
- if ( (cp = strstr( txb,S->txt) ),cp!=0 )
- {
- sx = strlen(S->txt) ;
- if (
- (
- (!isalnum(*(cp-1)) && (*(cp-1)!='_') )
- || (cp == txb) /* Or is first line entry */
- )
- && ( !isalnum(*(cp+sx)) && (*(cp+sx)!='_') )
- && ( sl < sx ) /* And is longer then Match */
- )
- {sl = sx ; ST = S ; Tcp = cp ; /* Record Symbol Hit */ }
- }
- }
- *la = Tcp ;
- return ST ;
- }
-
-
- static SREC *SymbolMatch( char *txb )
- {
- SREC *S;
- char *cp ;
-
- if (!SL) return 0 ;
-
- for( S = SL; S ; S = S->nx )
- {
- if ( !strncmp( txb,S->txt,strlen(S->txt) ) )
- {
- cp = txb+strlen(S->txt) ;
- if ( !isalnum(*cp) && (*cp != '_') ) return S ;
- }
- }
- return 0 ;
- }
-
- static long ibexp(void)
- {
- long val;
- char *cp ;
- SREC *S ;
- int ir;
-
- while ( isspace(*nextc)) ++nextc ;
-
- switch(*nextc)
- {
- case '(': *nextc++=' '; val=iexp(0);
- if( *nextc!=')' ) longjmp(EvalErr,2);
- *nextc++ = ' ' ; break;
-
- case '+': *nextc++=' '; val=iexp(0); break;
-
- case '-': *nextc++=' '; val=-iexp(0); break;
-
- case '%': ir = 2 ; goto L_DECODE;
-
- case '$': ir = 16 ; goto L_DECODE ;
-
- case '@': ir = 8 ;
- L_DECODE:
- *nextc++=' '; cp = nextc ; val = strtol(nextc,&nextc,ir) ;
- while( cp != nextc ) *cp++ = ' ' ; break ;
-
- default:
- if(isdigit(*nextc))
- {
- cp = nextc ;
- val=strtol(cp,&nextc,10);
- switch (toupper(*nextc))
- {
- case 'H' : val = strtol( cp , &nextc , 16) ; break ;
- case 'O' : val = strtol( cp , &nextc , 8 ) ; break ;
- case 'B' : val = strtol( cp , &nextc , 2 ) ; break ;
- default: break ;
- }
- while( cp != nextc ) *cp++ = ' ' ;
- }
- else if ( (S = SymbolMatch(nextc)), S!=0 )
- {
- nextc += strlen(S->txt) ;
- val = S->sv ;
- }
- else longjmp(EvalErr , 1 );
- }
- return val;
- }
-
- static long iexp(int n)
- {
- long a=ibexp();
-
- for(;;) switch(*nextc)
- {
- case '+': if(n>=1) return a; *nextc++=' '; a+=iexp(1); break;
- case '-': if(n>=1) return a; *nextc++=' '; a-=iexp(1); break;
- case '*': if(n>=2) return a; *nextc++=' '; a*=iexp(2); break;
- case '/': if(n>=2) return a; *nextc++=' '; a/=iexp(2); break;
-
- case '&': if(n>=2) return a; *nextc++=' '; a&=iexp(2); break;
- case '|': if(n>=2) return a; *nextc++=' '; a|=iexp(2); break;
- case '^': if(n>=2) return a; *nextc++=' '; a^=iexp(2); break;
- case '>': if(n>=2) return a;
- *nextc++=' ' ;
- if( *nextc != '>' )
- longjmp(EvalErr,3);
- *nextc++=' '; a>>=iexp(2) ; break ;
-
- case '<': if(n>=2) return a;
- *nextc++=' ' ;
- if( *nextc != '<' )
- longjmp(EvalErr,3);
- *nextc++=' '; a<<=iexp(2) ; break ;
-
- case '\t' : case ' ': nextc++; break;
- default :return a;
- }
- }
-
- #ifdef _ARC_
-
- static int strnicmp (const char *sx,const char *tx,int n)
- {
- int i ;
-
- for( ; n ; n--,sx++,tx++ )
- {
- i = toupper(*sx) - toupper(*tx) ;
- if ( i ) return i ;
- }
- return 0 ;
- }
-
- static char *PathEdit (char *Ipath)
- {
- char *cp ;
-
- /*
- Look for PC-type path name.
- - The first path will be an Arc path to the
- main source-file, but the rest may be PC-style paths
- from the Assembler source #includes.....
- */
- if ( !strpbrk(Ipath,"\\/") ) return Ipath ;
-
- cp = strchr(Ipath,'.') ; /* look for extension */
- if ( cp ) *cp = 0 ; /* kill it */
-
-
- for(;;)
- {
- cp = strchr(Ipath,'/') ; /*Path ?*/
- if (!cp)
- {
- cp = strchr(Ipath,'\\') ; /*Path? */
- if (!cp) break ; /* nothing.. Leave */
- }
- *cp = '.' ; /* convert */
- }
- return Ipath ;
- }
-
- #endif
-
- static int zstrlen( const char *tx)
- {
- return strlen(tx)+2 ;
- }
-
-
- static void *Umalloc( unsigned int msz )
- {
- char *mg = malloc( msz ) ;
- if (!mg)
- {
- fprintf(stderr,"* Insufficient Memory\n") ;
- Kill() ;
- exit(9) ;
- }
- Umem += msz ;
- if (Umem > UmemMax) UmemMax = Umem ;
- return (void *) mg ;
- }
-
- static void Ufree( void **mpt , unsigned int msz )
- {
- if (*mpt)
- {
- *mpt = 0 ;
- Umem -= msz ;
- free( *mpt ) ;
- }
- }
-
-
-
- char *Ustrupr( char *s,int l)
- {
-
- char *ss = s ;
- while( *s && l-- )
- *s++ = toupper( *s) ;
- return ss ;
- }
-
- char *scan( int ac , char **av , char *tag )
- {
- int sl = strlen(tag) ;
- while ( --ac )
- {
- if( !strncmp(tag,Ustrupr(*++av,sl),sl) )
- {
- if (!strlen(*av + sl) )
- return 0 ;
- else
- return *av + sl ;
- }
- }
- return 0 ;
- }
-
-
- BOOL scan_sw( int ac , char **av , char *tag )
- {
- short sl = strlen(tag) ;
- while ( --ac )
- {
- if( !strncmp(tag,Ustrupr(*++av,sl),sl) )
- {
- if (!strlen(*av + sl) )
- return TRUE ;
- }
- }
- return FALSE ;
- }
-
-
- static BOOL cmdline( int ac,char **av )
- {
- BOOL B_in = FALSE ;
- char *cp ;
- FILE *TF ;
-
- ALST = stdout ;
-
- if( (cp = scan(ac,av,"/I:")),cp!=0 )
- {
- strncpy(F_src,cp,64) ;
- #ifdef _ARC_
- TF = fopen(PathEdit(F_src),"r") ;
- #else
- TF = fopen(F_src,"r") ;
- #endif
- fclose(TF) ;
- if( !TF )
- {
- fprintf(stderr,"/I: %s - Won't Open\n",F_src) ;
- return TRUE ;
- }
- B_in = TRUE ;
- }
-
- if( (cp = scan(ac,av,"/O:")),cp!=0 )
- {
- strncpy(F_asm,cp,64) ;
- #ifdef _ARC_
- ALST = fopen(PathEdit(F_asm),"w") ;
- #else
- ALST = fopen(F_asm,"w") ;
- #endif
- if( !ALST )
- {
- fprintf(stderr,"/O: %s - Won't Open\n",F_asm) ;
- return TRUE ;
- }
- }
-
- if (scan_sw(ac,av,"-C")) B_Commlist = FALSE ;
- if (scan_sw(ac,av,"+M")) B_Mlist = TRUE ;
- if (scan_sw(ac,av,"+U")) B_Stamp = TRUE ;
-
- if( (cp = scan(ac,av,"/W:")),cp!=0 )
- strncpy(T_copyw,cp,24) ;
- return !B_in ;
- }
-
-
- static void OpError( char *fmt,...)
- {
- va_list argptr;
-
- va_start( argptr, fmt );
-
- fprintf(stderr,"\n%-20s [%4d] :",IL->fn,IL->sln ) ;
- vfprintf(stderr, fmt, argptr );
- va_end( argptr );
- }
-
- static void Kill( void)
- {
- IFL *ol ;
- MLST *M ;
- MacSeg *P ;
- MacSeg *Q ;
- SREC *S ;
- CONDLST *K ;
-
- while ( IL )
- {
- fclose( IL->fh ) ;
- Ufree( (void **)(&(*IL).fn) , zstrlen( IL->fn ) ) ;
- ol = IL->pt ;
- Ufree( (void **)&IL , sizeof(IFL) ) ;
- IL = ol ;
- }
-
- while ( SL )
- {
- Ufree( (void **)(&(*SL).txt) , zstrlen( SL->txt ) ) ;
- S = SL->nx ;
- Ufree( (void **)&SL , sizeof(SREC) ) ;
- SL = S ;
- }
-
- while ( EL )
- {
- K = EL->nx ;
- Ufree( (void **)&EL , sizeof(CONDLST) ) ;
- EL = K ;
- }
-
- while( ML )
- {
- Ufree( (void **)(&(*ML).mn),zstrlen(ML->mn) ) ;
- if( ML->mp)
- {
- P = ML->mp ;
- while( P )
- {
- Ufree( (void **)(&(*P).txt),zstrlen(P->txt) ) ;
- Q = P ;
- P = P->nx ;
- Ufree( (void **)&Q,sizeof(MacSeg) ) ;
- }
- }
- M = ML ;
- ML = ML->nx ;
- Ufree((void **)&M,sizeof(MLST) ) ;
- }
- if (W) Ufree((void **)&W,WS_SIZE) ;
-
- fclose(ALST) ;
- }
-
- static int NewOpen( char *tx)
- {
- /*
- Used to open a new file, preserve the present file
- and set to read from the new one.
- */
- IFL *ol ;
- FILE *tf ;
- #ifdef _ARC_
- if ( (tf = fopen(PathEdit(tx),"r")),tf==0)
- #else
- if ( (tf = fopen(tx,"r")),tf==0)
- #endif
- {OpError("*Can't open [%s%]\n",tx) ; return 1 ; }
-
- if (!IL)
- ol = 0 ;
- else
- ol = IL ;
-
- IL = (IFL *)Umalloc(sizeof(IFL)) ;
- IL->pt = ol ;
- IL->fn = (char *)Umalloc( zstrlen(tx) ) ;
- strcpy(IL->fn,tx) ;
- IL->fh = tf ;
- IL->sln = 0 ;
-
- return 0 ;
- }
-
- static int NewClose(void)
- {
- /*
- Closes the present file , and opens the previous one .
- */
-
- IFL *ol ;
-
- if ( !IL ) return 2 ;
- fclose( IL->fh ) ;
- Ufree( (void **)(&(*IL).fn) ,zstrlen( IL->fn ) ) ;
-
- ol = IL->pt ;
- Ufree( (void **)&IL , sizeof(IFL) ) ;
-
- if ( !ol ) return 1 ;
- IL = ol ;
- return 0 ;
- }
-
-
- static char* Strim( char *line )
- {
- char *cp ;
-
- cp = line+strlen(line)-1 ;
- for(;;)
- {
- if ( !isspace(*cp) ) break ;
- if( cp == line )
- { *cp = 0 ; break ; }
- else
- *cp-- = 0 ;
- }
- return line ;
- }
-
-
-
- static int LoseWhite(void)
- {
- while (*LP && isspace(*LP)) LP++ ;
- if ( (*LP == ';') || !(*LP) ) return 1 ;
- return 0 ;
-
- }
-
- char *RelSymbols [] = {
- "!=","==",">=","<=",">","<",""
- } ;
-
- static int Conditional( char *ltxt )
- {
- CONDLST *oc , *M ;
- char *cp;
- char **cq ;
- long cv,exv ;
- int Irel,i ;
-
- if (!strnicmp(ltxt,"?endif",6) )
- {
- if (!EL )
- { OpError("*Extra ?endif\n%s\n",ltxt) ; Kill() ; exit(5) ; }
- oc = EL->nx ;
- Ufree( (void **)&EL , sizeof(CONDLST) ) ;
- EL = oc ;
- return 1 ;
- }
-
- if (!strnicmp(ltxt,"?else",5) )
- {
- if (!EL )
- { OpError("*Extra ?else\n%s\n",ltxt) ; Kill() ; exit(5) ; }
- EL->on = !EL->on ;
- return 2 ;
- }
-
- if (strnicmp(ltxt,"?if",3) ) return 0 ;
- /*
- Hit an IF .... Evaluate the Expression.
- for the momement, we are only interested in ==0 or != 0
- */
- LP += 3 ;
- strcat(LP," ");
- cp = NextString() ;
- if (!cp)
- { OpError("* ?if with no expression.\n%s\n",LP) ;Kill() ;exit(5); }
- nextc = cp ;
- cv = iexp(0);
- /*
- cv now holds the value of the first expression..
- now, we look to see if there is a relational symbol
- */
- Irel = 0 ;
-
- cp = NextString() ;
- if( cp )
- {/*1*/
- /*
- Searching for relational symbol..
- */
- for(i=1,cq=RelSymbols;**cq;i++,cq++)
- if(!strncmp(cp,*cq,strlen(*cq)) )
- { Irel = i ; break ; }
-
- if (!Irel)
- {
- OpError("*Bad Relational Symbol [%s]\n%s\n",cp,LB) ;
- Kill() ; exit(6) ;
- }
- /*
- There was a relational symbol, so there must be a further
- parameter.
- */
- cp = NextString() ;
- if (!cp)
- {
- OpError("* ?if with no comparative value.\n%s\n",LP) ;
- Kill() ; exit(6) ;
- }
- nextc = cp ;
- exv = iexp(0);
- }/*1*/
-
- if (!EL)
- M = 0 ;
- else
- M = EL ;
-
- EL = (CONDLST *)Umalloc(sizeof(CONDLST)) ;
- EL->nx = M ;
-
- switch( Irel )
- {
- case 0: EL->on = (cv != 0 ) ; break ;
- case 1: EL->on = (cv != exv ) ; break ;
- case 2: EL->on = (cv == exv ) ; break ;
- case 3: EL->on = (cv >= exv) ; break ;
- case 4: EL->on = (cv <= exv) ; break ;
- case 5: EL->on = (cv > exv) ; break ;
- case 6: EL->on = (cv < exv) ; break ;
- default: OpError("*Bug! in Relational Switch [%d]\n%s\n",Irel,LB) ;
- Kill() ; exit(6) ;
- }
- return 3 ;
- }
-
- static int NewLine(void)
- {
- /*
- Fetches the next line.
- Handles any instances of #include.
- */
- char *csp,*cep ;
-
- LP = LB ;
- for(;;)
- {
- fgets(LB,132,IL->fh) ;
-
- if ( feof(IL->fh) )
- {
- if ( NewClose() ) return 1 ;
- return NewLine() ;
- }
- /*
- Process the conditional Directives, and set up
- a record to say if lines are to be processed..
- */
- if ( Conditional(LB) ) continue ;
- if ( EL && !EL->on ) continue ;
- break ;
- }
- /*
- Looking for #include in col. 1 of new line.
- */
- if (!strnicmp( LB , "#include" ,8) )
- {
- if ( (csp = strchr(LB,'"')),csp != 0 )
- {
- if ( (cep = strchr(csp+1,'"')),cep != 0 )
- {
- *cep = 0 ;
- if ( NewOpen( csp+1 ) ) return 2 ;
- return NewLine() ;
- }
- }
- OpError("*Syntax:\n%s\n",LB) ;
- return 3 ;
- }
- /*
- Chop off comments.
- *Note this is a bit unsophisticated...
- it will react to " ... ; " for example..
- */
- *CB = 0 ;
-
- csp = LB ;
- if ( (csp = strchr( LB , ';' )),csp != 0 )
- {
- if( B_Commlist )
- {
- if( csp != LB)
- strcpy(CB,"\t"); /* Tab it if not @ start of line*/
-
- strcat(CB,Strim(csp)) ;
- }
- *csp = 0 ; /* Truncate */
- strcat(LB,"\n") ;
- }
- ++IL->sln ; /* count source lines */
-
- Strim(LB) ;
- /*
- Check for some Directives.
- */
- if( (csp = strchr(LB,'.') ) , csp == 0 ) return 0 ;
- if ( !strnicmp(++csp,"LIST",4) ) B_ListOn = TRUE ;
- else if ( !strnicmp(csp,"NOLIST",6)) B_ListOn = FALSE ;
- return 0 ;
- }
-
-
- static char *NextString( void )
- {
- char *csp ;
-
- if (LoseWhite() ) return (char *)0 ;
- for (csp = LP;*LP;LP++)
- {
- if (
- (*LP==',') || ( (*LP != '_') && ( isspace(*LP) ) )
- )
- {
- *LP = 0 ;
- ++LP ;
- return csp ;
- }
- }
- return csp ;
- }
-
-
-
- static void LoseTempParams( ParamRec *B)
- {
- ParamRec *P ;
-
- if ( B )
- {
- while( B )
- {
- Ufree( (void **)(&(*B).txt) , zstrlen(B->txt ) ) ;
- P = B->nx ;
- Ufree( (void **)&B,sizeof(ParamRec) ) ;
- B = P ;
- }
- }
- }
-
- static int WhichParameter(ParamRec *B)
- {
- /*
- looks for parameter in LB
- if found , returns number &erases parameter.
- */
- int i;
-
- if ( !B ) return 0 ;
- for ( i=1 ; B ; i++,B=B->nx )
- {
- if( *LP == *B->txt)
- if (!strncmp(LP,B->txt,strlen(B->txt) ) )
- {
- LP += strlen(B->txt) ;
- return i ;
- }
- }
- return 0 ;
- }
-
-
-
- static int CkSymbolDef( void )
- {
- SREC *M ;
- char *cp,*cq ;
- /*
- Looking for #SYMBOL definition start.
- */
- for(;;)
- {/*1*/
- if (strnicmp(LP,"#symbol",7) ) return 0 ;
- /*
- Found symbol key-word. check duplicate.
- */
- ++Nsymbs ;
-
- LP += 7 ;
- strcat(LP," ") ;
- cp = NextString() ;
-
- if ( !cp )
- {OpError("#SYMBOL - no name.\n") ; Kill() ;exit(1) ; }
-
- if ( ( M = SymbolSearch( cp , &cq) ),M !=0 )
- {/*2*/
-
- #if 0
- /*
- We are not Allowed to re-use Symbols...
- */
- { OpError("#SYMBOL - Duplicate. %s\n",M->txt); Kill() ;exit(1) ; }
- #endif
-
- }/*2*/
- else
- {/*2*/
- if (!SL)
- M = 0 ;
- else
- M = SL ;
-
- SL = (SREC *)Umalloc(sizeof(SREC) ) ;
- SL->nx = M ;
- SL->txt = (char *)Umalloc(zstrlen(cp)) ;
- strcpy(SL->txt,cp) ;
- /*
- now look up the Value.
- */
- M = SL ;
- }/*2*/
- nextc = NextString() ;
- M->sv = iexp(0) ;
- if( B_Mlist)
- fprintf(ALST,";\t[%s] = %lxH (%ld)\n",M->txt,M->sv,M->sv ) ;
- if ( NewLine() ) break ;
- }/*1*/
- return 0 ;
- }
-
-
- static void CkMacroDef( void )
- {
- MLST *M ;
- ParamRec *B = 0,*P,*Q ;
- MacSeg *R,*S ;
- char *cp ;
- char *wp ;
- int i ;
- /*
- Looking for #MACRO definition start.
- */
- for(;;)
- {/*1*/
-
- if (strnicmp(LP,"#macro",6) ) return ;
- /*
- Found macro key-word. check duplicate.
- */
- ++Nmacs ;
-
- LP += 6 ;
- cp = NextString() ;
-
- if ( !cp )
- { OpError("#MACRO - no name.\n") ; Kill() ; exit(1) ; }
-
- if (ML)
- {/*2*/
- M = ML ;
- while( M )
- {/*3*/
- if ( !strncmp(M->mn,cp,strlen(cp)) )
- {/*4*/
- OpError("#MACRO - Duplicate %s\n%s\n",cp,LB) ;
- Kill() ; exit(2) ;
- }/*4*/
- M = M->nx ;
- }/*3*/
- }/*2*/
-
- /*
- Ok.. not a duplicate. create a new macro record.
- */
- *W = 0 ;
- wp = W ;
- if (!ML)
- M = 0 ;
- else
- M = ML ;
-
- ML = (MLST *)Umalloc(sizeof (MLST)) ;
- ML->nx = M ;
- ML->mn = (char *)Umalloc(zstrlen(cp) ) ;
- strcpy(ML->mn,cp) ;
- ML->mp = R = 0 ;
- ML->N = 0 ;
- /*
- now look up the parameters.
- */
- cp = NextString() ;
-
- while ( cp )
- {/*2*/
- ++ML->N ;
- Q = (ParamRec *)Umalloc(sizeof(ParamRec)) ;
- if (!B)
- B = P = Q ;
- else
- P->nx = Q ;
-
- Q->nx = 0 ;
- Q->txt = (char *)Umalloc( zstrlen(cp) ) ;
- strcpy (Q->txt,cp) ;
- P = Q ;
- cp = NextString() ;
- }/*2*/
-
- while ( !NewLine() )
- {/*2*/
- if ( !*LB ) continue ;
- strcat(LB,"\n") ;
- /*
- reading Macro definition.
- */
- if (!strnicmp( LB , "#mend" ,5) )
- {/*3*/
- /*
- Save the end of the Macro text.
- Deal with the case of a no-parameter macro
- */
- S = (MacSeg *)Umalloc( sizeof(MacSeg) ) ;
- if ( !ML->mp )
- ML->mp = R = S ;
- else
- R->nx = S ;
-
- S->txt = (char *)Umalloc( zstrlen(W) ) ;
- strcpy(S->txt,W) ;
- S->nx = 0 ;
- S->pn = 0 ; /* flag no parameter */
-
- LoseTempParams( B ) ;
- break ; /* return to outer loop for another line */
- }/*3*/
- else
- /*
- Process the Macro Text in LP by searching for
- parameter tokens and creating sections of text
- numbered with the parameters to bracket the real
- parameters when they come..
- */
- if( B_Mlist) fprintf(ALST,";\t[%s] |\t%s",ML->mn,LB) ;
-
- while ( *LP )
- {/*3*/
- if ( (i = WhichParameter( B )),i !=0 )
- {/*4*/
- /*
- found a Parameter, so create a new Record
- */
- S = (MacSeg *)Umalloc(sizeof(MacSeg)) ;
- S->txt = (char *)Umalloc( zstrlen(W) ) ;
- S->pn = i ; /* Parameter following */
- S->nx = 0 ;
- strcpy(S->txt,W) ; /* text before */
- *W = 0 ; /* clear text accumulator */
- wp = W ;
- if( !ML->mp)
- ML->mp = S ; /* create head pointer */
- else
- R->nx = S ; /* append to chain */
- R = S ;
- }/*4*/
- else
- {/*4*/
- *wp++ = *LP++ ; /* add to accumulator */
- *wp = 0 ;
- }/*4*/
- }/*3*/ /* Parameter sections */
- }/*2*/ /*macro Body*/
-
- if ( !NewLine() ) return ;
- }/*1*/
- }
-
- static char *GetParameter( unsigned char n,ParamRec *B)
- {
- if (!n) return "" ; /* null parameter */
- while (--n)
- {
- B=B->nx ;
- if( !B )
- { OpError("*SW err GetParameter\n") ; Kill() ; exit(5) ; }
- }
- return B->txt ; /* Parameter text */
- }
-
-
-
- static void SymbolEdit( char *sytx )
- {
- SREC *S ;
- char *cp,*cb ;
- char w[133] ;
-
- for(;;)
- {
- if ( (S=SymbolSearch(sytx , &cp) ),S==0 ) return ;
- /*
- Found Symbol in source line. cp points to start.
- length of symbol to be edited out is in the record...
- */
- cb = cp ;
- cp += strlen(S->txt) ;
- strcpy(w,cp) ;
- sprintf(cb,"0%lxH",S->sv) ;
- strcat(cb,w) ;
- ++Ssymbs ;
- }
- }
-
-
- static void SymbolFixup( void )
- { SymbolEdit( LB ) ; }
-
-
- static int MacroFixup( void )
- {
- char *cp,*Tcp ;
- MLST TM ;
- MLST *M ,*MT ;
- ParamRec *B = 0,*P,*Q ;
- MacSeg *S ;
- int sl,sx ;
-
- if (!ML) return 0 ;
- /*
- Macros have been defined..
- look for them.
- */
-
- for( sl = 0 , MT = 0 , M = ML; M ; M = M->nx )
- {/*1*/
- if ( (cp = strstr( LP,M->mn) ),cp!=0 )
- {
- sx = strlen(M->mn) ;
- if (
- ( isspace(*(cp-1)) /* Has White space before */
- || (cp == LP) /* Or is first line entry */
- )
- && (
- isspace(*(cp+sx)) /* And has white Space after */
- || !*(cp+sx) /* or is end-of string */
- )
- && ( sl < sx ) /* And is longer then Match */
- )
- {
- sl = sx ; MT = M ; Tcp = cp ; /* Record Macro Hit */
- }
- }
- }/*1*/
- if ( !MT ) return 0 ;
-
- /*
- Found Macro in source line.
- */
- fprintf(ALST,";\t*M\t%s%s\n",LP ,
- ( !B_Mlist && B_ListOn )? "\n\t.NOLIST" : "" ) ;
-
- ++Smacs ; /* Another Macro */
- LP = Tcp ; /* Point to the Name */
- cp = NextString() ; /* goto first Parameter */
-
- TM.nx = 0 ;
- TM.mn = (char *)Umalloc(zstrlen(cp)) ;
- strcpy(TM.mn,cp) ;
- TM.mp = 0 ;
- TM.N = 0 ;
- /*
- now look up the parameters.
- */
- cp = NextString() ;
-
- while ( cp )
- {/*1*/
- ++TM.N ;
- Q = (ParamRec *)Umalloc(sizeof(ParamRec)) ;
-
- if (!B)
- B = P = Q ;
- else
- P->nx = Q ;
- Q->nx = 0 ;
- Q->txt = (char *)Umalloc(zstrlen( cp )) ;
- strcpy (Q->txt,cp) ;
- P = Q ;
- cp = NextString() ;
- }/*1*/
- /*
- All parameters of current Macro found.
- First compare number of parameters..
- */
- if (MT->N != TM.N)
- {/*1*/
- OpError("*Incorrect # Params :%s (%d)\n%s\n",MT->mn,MT->N,LB) ;
- LoseTempParams (B ) ; Kill() ; exit(4) ;
- }/*1*/
- /*
- do the substitution...
- */
- S = MT->mp ; /* pointer to parts */
- while( S )
- {
-
- sprintf(W,"%s%s",S->txt,GetParameter(S->pn,B) ) ;
- SymbolEdit(W) ;
- fprintf(ALST,"%s",W) ;
- S = S->nx ;
- }
-
- LoseTempParams(B) ;
-
- fprintf(ALST,"%s",
- ( !B_Mlist && B_ListOn )? "\t.LIST\n" : "" ) ;
-
- return 1 ;
-
- return 0 ;
- }
-
- static void Time_Date_Stamp(void)
- {
- time_t tv ;
- struct tm *tpt ;
- char * cp ;
-
- time( &tv ) ;
- tpt = localtime( &tv ) ;
-
- fprintf(ALST,"#DEFINE\tDATE__\t\x22%s\x22\n" ,Strim(asctime(tpt) ) ) ;
- cp = strrchr( F_src ,'\\') ;
- fprintf(ALST,"#DEFINE\tFILE__\t\x22%s\x22\n" ,(cp)?++cp:F_src) ;
- }
-
- int main (int ac,char **av )
- {
- fprintf(stderr,"Macro Expansion For TASM R.J.P. V:3.5 3rd September 1992\n") ;
-
- if ( cmdline(ac,av) )
- {
- fprintf(stderr,"Syntax : EXPAND /I:infile /O:outfile [-C] [+M]\n") ;
- return 1;
- }
-
- NewOpen( F_src ) ;
-
- W = (char *)Umalloc( 4096 ) ; /* general work space */
- if( B_Stamp )
- Time_Date_Stamp() ;
-
- if (*T_copyw )
- fprintf(ALST,"#DEFINE\tCOPYW__\t\x22%s\x22\n" ,T_copyw ) ;
-
- if (setjmp(EvalErr) )
- {
- OpError("#SYMBOL - Evaluation.\n%s\n" ,LB) ;
- Kill() ; exit( 6 ) ;
- }
-
-
- while ( !NewLine() )
- {
- if (!LoseWhite() )
- {/*1*/
- if (!CkSymbolDef() )
- {/*2*/
- SymbolFixup() ;
- CkMacroDef() ;
- if(!MacroFixup() )
- {/*3*/
- sprintf(W,"%s%s",LB,CB ) ;
- if(*W) fprintf(ALST,"%s\n",W) ;
- }/*3*/
- }/*2*/
- }/*1*/
- else if (B_Commlist) fprintf(ALST,"%s\n",CB ) ;
-
- }
- Kill() ;
- fprintf(stderr,
- "Macros:%d, Found %d Symbols:%d Used %d Memory %u. Bytes\n"
- ,Nmacs,Smacs,Nsymbs,Ssymbs, UmemMax ) ;
- return 0 ;
- }
-