home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / program / assembler / tasm / c / EXPAND < prev    next >
Encoding:
Text File  |  1992-09-03  |  27.7 KB  |  1,225 lines

  1. /*
  2.         Macro Front-End.  EXPAND.C
  3.         R.J.P.  12/7/92
  4.         Front end for XASM
  5.         14th July 1992          Port to ARC.
  6.         17th July 1992          Change Macro listing.
  7.         17th July 1992          add Time stamp.
  8.         23rd July 1992          Fix another Macro search bug
  9.         15th August 1992        Losing Comments in +C
  10.          3rd September 1992     Fix Numerical Evaluation radix recognition.
  11. */
  12. /* Conditional(  */
  13. /*
  14.         Switches:
  15.           
  16.           /I:input_file         normal Path on both PC & Arc.
  17.           /O:output_file        "         "       "
  18.           
  19.           ** note #INCLUDE directives in source must be of the
  20.           form   DIR/DIR/../DIR/file.ext for PC 
  21.           and    DIR/DIR/../ext/file.ext for the Arc. I use the same
  22.           convention for assembler as that of the 'C' compiler, and the
  23.           Arc version of EXPAND just changes al the '/' to '.' & removes
  24.           the final .ext ....
  25.           
  26.           -C  Chop out all comments.
  27.           +M  Put in Expanded #MACRO definitions
  28.           +U  Generate Time,Date & Source file #DEFINES
  29.           /W: Generate copyright define
  30.           
  31.           #SYMBOL   [<expr>]    Generate a Symbol with a long value known to 
  32.           EXPAND  - EXPAND does not care about #DEFINE #IF etc...
  33.           Expressions allowed for #SYMBOL are more or less the same as 
  34.           in TASM, but the syntax analyser is 'normal'. All expressions
  35.           and constants are held as 'long' (32 bit integer).
  36.           
  37.           ?IF , ?ELSE , ?ENDIF operate for #SYMBOLS as #IF does for
  38.           #DEFINES...
  39.           
  40.           
  41. */
  42.            
  43. #include   <stdio.h>
  44. #include   <stdlib.h>
  45. #include   <stdarg.h>
  46. #include   <string.h>
  47. #include   <ctype.h>
  48. #include   <time.h>
  49. #include   <setjmp.h>
  50.  
  51. #undef          TRUE
  52. #undef          FALSE
  53. #undef          BOOL
  54.  
  55. #define         BOOL    unsigned char
  56. #define         TRUE    1
  57. #define         FALSE   0
  58.  
  59. #define         WS_SIZE         4096
  60.  
  61. typedef  struct {
  62.         char *fn ;
  63.         FILE *fh ;
  64.         void *pt ;
  65.         int  sln ;
  66.       } IFL ;
  67.  
  68. typedef  struct {
  69.                 char    *txt ;
  70.                 unsigned char pn ;
  71.                 void    *nx ;
  72.                 } MacSeg ;
  73.  
  74. typedef   struct {
  75.                 char   *txt ;
  76.                 void   *nx ;
  77.                 } ParamRec ;
  78.  
  79. typedef    struct {
  80.                 char   *txt ;
  81.                 long   sv ;
  82.                 void   *nx ;
  83.                 } SREC ;
  84.                 
  85. typedef  struct {
  86.         int  N;
  87.         char     *mn ;
  88.         MacSeg   *mp ;
  89.         void     *nx ;
  90.          } MLST ;
  91.  
  92. typedef   struct {
  93.         BOOL     on ;
  94.         void     *nx ;
  95.         } CONDLST ; 
  96.        
  97. IFL     *IL = 0 ;       /* In File List. */
  98. char    LB[133] ;       /* Input Char. buffer */
  99. char    CB[133] ;       /* Appended comment buffer */
  100. char    *LP ;           /* Pointer to input buffer */
  101.  
  102. MLST    *ML ;           /* List of Macro Definitions */
  103. char    *W ;            /* Pointer to macro build work-space */
  104.  
  105. SREC    *SL ;           /* Pointer to Symbol List */
  106. CONDLST *EL ;           /* Pointer to switches */
  107.  
  108. BOOL    B_Mlist     = FALSE ;       /* Listing Macros */
  109. BOOL    B_Commlist  = TRUE ;    /* Listing Comments */
  110. BOOL    B_ListOn    = TRUE ;
  111. BOOL    B_Stamp     = FALSE ;
  112.  
  113. char    F_src[65] ;             /* Primary Source file */
  114. char    F_asm[65] ;             /* Output file */
  115. char    T_copyw[25];
  116. FILE    *ALST ;                 /* Output Stream */
  117.  
  118. unsigned int Umem , UmemMax ;
  119. int     Nmacs,Smacs , Nsymbs ,Ssymbs ;
  120. jmp_buf          EvalErr ;
  121.  
  122.  
  123. /*
  124.         Forward Refs.
  125. */
  126.  
  127.  
  128. static   char  *nextc ;
  129. static   long  iexp( int ) ;
  130. static   void  Kill(void) ;
  131. static   char *NextString(void) ;
  132.  
  133.         
  134. static  SREC *SymbolSearch( char *txb , char **la )
  135. {
  136.    int     sl,sx ;
  137.    char    *cp,*Tcp ;
  138.    SREC    *S,*ST ;
  139.  
  140.    if (!SL)  return 0 ;
  141.       
  142.     for( sl = 0 , ST = 0 , S = SL; S ; S = S->nx )
  143.     {
  144.     if ( (cp = strstr( txb,S->txt) ),cp!=0 )
  145.     {
  146.       sx = strlen(S->txt) ;
  147.       if (
  148.            ( 
  149.              (!isalnum(*(cp-1)) && (*(cp-1)!='_') )
  150.              || (cp == txb)         /* Or is first line entry */
  151.            )
  152.        &&   ( !isalnum(*(cp+sx)) && (*(cp+sx)!='_') ) 
  153.        && ( sl < sx )            /* And is longer then Match */
  154.          )
  155.       {sl = sx ; ST = S ; Tcp = cp ; /* Record Symbol Hit */ }
  156.      }
  157.     }
  158. *la = Tcp ;   
  159. return ST ;
  160.  
  161.         
  162. static  SREC *SymbolMatch( char *txb )
  163. {
  164.    SREC    *S;
  165.    char  *cp ;
  166.  
  167.    if (!SL)  return 0 ;
  168.       
  169.    for( S = SL; S ; S = S->nx )
  170.    {
  171.      if ( !strncmp( txb,S->txt,strlen(S->txt) ) )
  172.      {
  173.        cp = txb+strlen(S->txt) ;
  174.         if ( !isalnum(*cp) && (*cp != '_') )   return S ;      
  175.      }
  176.    }  
  177. return 0 ;
  178.   
  179. static long ibexp(void)
  180. {
  181.   long val;
  182.   char  *cp ;
  183.   SREC  *S ;
  184.   int   ir;
  185.   
  186.   while ( isspace(*nextc)) ++nextc ;
  187.   
  188.   switch(*nextc)
  189.   { 
  190.     case '(': *nextc++=' '; val=iexp(0);
  191.       if(  *nextc!=')' ) longjmp(EvalErr,2);
  192.       *nextc++ = ' ' ;    break;
  193.   
  194.     case '+': *nextc++=' '; val=iexp(0);            break;
  195.     
  196.     case '-': *nextc++=' '; val=-iexp(0);           break;
  197.  
  198.     case '%': ir = 2 ; goto L_DECODE;
  199.  
  200.     case '$': ir = 16 ; goto L_DECODE ;
  201.      
  202.     case '@': ir = 8 ;
  203. L_DECODE:
  204.     *nextc++=' '; cp = nextc ; val = strtol(nextc,&nextc,ir) ;
  205.     while( cp != nextc ) *cp++ = ' ' ; break ;
  206.       
  207.     default: 
  208.     if(isdigit(*nextc))
  209.     {
  210.         cp = nextc ;        
  211.         val=strtol(cp,&nextc,10);
  212.         switch (toupper(*nextc))
  213.         {
  214. case 'H' : val = strtol( cp , &nextc , 16) ; break ;
  215. case 'O' : val = strtol( cp , &nextc , 8 ) ; break ;
  216. case 'B' : val = strtol( cp , &nextc , 2 ) ; break ;
  217. default:  break ;
  218.         }      
  219.          while( cp != nextc ) *cp++ = ' ' ;
  220.     }
  221.     else if ( (S = SymbolMatch(nextc)), S!=0 )
  222.     {
  223.        nextc += strlen(S->txt) ;
  224.        val    = S->sv ;
  225.     }               
  226.     else longjmp(EvalErr , 1 );
  227.   }
  228.   return val;
  229. }
  230.  
  231. static long iexp(int n)
  232. {
  233.   long a=ibexp();
  234.   
  235.   for(;;) switch(*nextc)
  236.   { 
  237.     case '+':  if(n>=1) return a;  *nextc++=' ';  a+=iexp(1);  break;
  238.     case '-':  if(n>=1) return a;  *nextc++=' ';  a-=iexp(1);  break;
  239.     case '*':  if(n>=2) return a;  *nextc++=' ';  a*=iexp(2);  break;
  240.     case '/':  if(n>=2) return a;  *nextc++=' ';  a/=iexp(2);  break;
  241.  
  242.     case '&':  if(n>=2) return a;  *nextc++=' ';  a&=iexp(2);  break;
  243.     case '|':  if(n>=2) return a;  *nextc++=' ';  a|=iexp(2);  break;
  244.     case '^':  if(n>=2) return a;  *nextc++=' ';  a^=iexp(2);  break;
  245.     case '>':  if(n>=2) return a;  
  246.                *nextc++=' ' ;
  247.                if( *nextc != '>' )
  248.                              longjmp(EvalErr,3);
  249.                *nextc++=' ';  a>>=iexp(2) ;  break ;
  250.                
  251.     case '<':  if(n>=2) return a;  
  252.                *nextc++=' ' ;
  253.                if( *nextc != '<' )
  254.                              longjmp(EvalErr,3);
  255.                *nextc++=' ';  a<<=iexp(2) ;  break ;
  256.  
  257.     case '\t' : case ' ':  nextc++; break;
  258.     default :return a;
  259.   }
  260. }
  261.  
  262. #ifdef  _ARC_
  263.  
  264. static int strnicmp (const char *sx,const char *tx,int n)
  265. {        
  266.        int   i ;
  267.               
  268.        for( ; n ; n--,sx++,tx++ )
  269.        {
  270.             i = toupper(*sx) - toupper(*tx) ;
  271.             if ( i ) return i ; 
  272.        }
  273. return 0 ;         
  274. }
  275.  
  276. static  char *PathEdit (char *Ipath)
  277.    char *cp ;
  278.    
  279. /*
  280.         Look for PC-type path name.
  281.         - The first path will be an Arc path to the 
  282.         main source-file, but the rest may be PC-style paths
  283.         from the Assembler source #includes.....
  284. */
  285.    if ( !strpbrk(Ipath,"\\/") ) return Ipath ;
  286.    
  287.    cp = strchr(Ipath,'.') ;     /* look for extension */
  288.    if ( cp ) *cp = 0 ;          /* kill it */
  289.    
  290.  
  291.    for(;;)
  292.    {
  293.      cp = strchr(Ipath,'/') ;   /*Path ?*/
  294.      if (!cp)
  295.      {  
  296.         cp = strchr(Ipath,'\\') ;  /*Path? */
  297.         if (!cp)    break ;        /* nothing.. Leave */
  298.      }
  299.      *cp = '.' ;                /* convert */
  300.    }    
  301. return  Ipath ;  
  302. }
  303.  
  304. #endif
  305.  
  306. static int  zstrlen( const char *tx)
  307. {
  308.   return strlen(tx)+2 ;
  309. }
  310.  
  311.   
  312. static  void *Umalloc( unsigned int msz )
  313. {
  314.       char *mg = malloc( msz ) ;
  315.       if (!mg)
  316.       {
  317.         fprintf(stderr,"* Insufficient Memory\n") ;
  318.         Kill() ;
  319.         exit(9) ;
  320.        }
  321. Umem += msz ;               
  322. if (Umem > UmemMax) UmemMax = Umem ;
  323. return (void *) mg ;
  324. }
  325.  
  326. static  void  Ufree( void **mpt , unsigned int msz )
  327. {
  328.      if (*mpt)
  329.      {
  330.      *mpt = 0 ;
  331.      Umem -= msz ;
  332.      free( *mpt ) ;
  333.      }
  334. }
  335.  
  336.  
  337.  
  338. char  *Ustrupr( char *s,int l)
  339. {
  340.  
  341.   char  *ss  =  s ;
  342.   while( *s && l-- )
  343.   *s++ = toupper( *s) ;
  344.   return ss ;
  345. }
  346.  
  347. char   *scan( int ac , char **av , char *tag )
  348. {
  349.   int   sl   =  strlen(tag) ;
  350.   while ( --ac )
  351.   {
  352.     if( !strncmp(tag,Ustrupr(*++av,sl),sl) )
  353.     {
  354.       if (!strlen(*av + sl) )
  355.                 return 0 ;
  356.       else
  357.                 return *av + sl  ;
  358.      }
  359.   }
  360.   return  0  ;
  361. }
  362.  
  363.  
  364. BOOL   scan_sw( int ac , char **av , char *tag )
  365. {
  366.   short   sl   =  strlen(tag) ;
  367.   while ( --ac )
  368.   {
  369.     if( !strncmp(tag,Ustrupr(*++av,sl),sl) )
  370.     {
  371.       if (!strlen(*av + sl) )
  372.                 return TRUE ;
  373.     }
  374.   }
  375.   return  FALSE  ;
  376. }
  377.  
  378.  
  379. static   BOOL  cmdline( int ac,char **av ) 
  380. {
  381.         BOOL  B_in = FALSE ;
  382.         char    *cp ;
  383.         FILE   *TF ;
  384.         
  385.         ALST  = stdout ;
  386.         
  387.         if( (cp = scan(ac,av,"/I:")),cp!=0 )
  388.         {
  389.                 strncpy(F_src,cp,64) ;
  390. #ifdef  _ARC_
  391.                 TF = fopen(PathEdit(F_src),"r") ;
  392. #else                                
  393.                 TF = fopen(F_src,"r") ;
  394. #endif
  395.                 fclose(TF) ;
  396.                 if( !TF )
  397.                 {
  398.                 fprintf(stderr,"/I: %s - Won't Open\n",F_src) ;
  399.                 return TRUE ;
  400.                 }
  401.                 B_in = TRUE ;
  402.         }       
  403.         
  404.         if( (cp = scan(ac,av,"/O:")),cp!=0 )
  405.         {
  406.                 strncpy(F_asm,cp,64) ;
  407. #ifdef  _ARC_
  408.                 ALST = fopen(PathEdit(F_asm),"w") ;
  409. #else                                
  410.                 ALST = fopen(F_asm,"w") ;
  411. #endif
  412.                 if( !ALST )
  413.                 {
  414.                 fprintf(stderr,"/O: %s - Won't Open\n",F_asm) ;
  415.                 return TRUE ;
  416.                 }
  417.         }       
  418.         
  419.         if (scan_sw(ac,av,"-C"))  B_Commlist = FALSE ;
  420.         if (scan_sw(ac,av,"+M"))  B_Mlist = TRUE ;
  421.         if (scan_sw(ac,av,"+U"))  B_Stamp = TRUE ;
  422.  
  423.         if( (cp = scan(ac,av,"/W:")),cp!=0 )
  424.                        strncpy(T_copyw,cp,24) ;  
  425. return  !B_in ;
  426. }
  427.  
  428.  
  429. static void OpError( char *fmt,...)
  430. {
  431.   va_list   argptr;
  432.   
  433.   va_start( argptr, fmt );
  434.  
  435.   fprintf(stderr,"\n%-20s  [%4d] :",IL->fn,IL->sln ) ;
  436.   vfprintf(stderr, fmt, argptr );
  437.   va_end( argptr );
  438. }
  439.  
  440. static void Kill( void)
  441. {
  442.         IFL  *ol ;
  443.         MLST  *M ;
  444.         MacSeg *P ;
  445.         MacSeg *Q ;
  446.         SREC  *S ;
  447.         CONDLST *K ;
  448.  
  449.         while ( IL )
  450.         {
  451.            fclose( IL->fh ) ;
  452.            Ufree( (void **)(&(*IL).fn) , zstrlen( IL->fn ) ) ;
  453.            ol = IL->pt ;
  454.            Ufree( (void **)&IL , sizeof(IFL) ) ;
  455.            IL = ol ;
  456.        }
  457.  
  458.         while ( SL )
  459.         {          
  460.            Ufree( (void **)(&(*SL).txt) , zstrlen( SL->txt ) ) ;
  461.            S = SL->nx ;
  462.            Ufree( (void **)&SL , sizeof(SREC) ) ;
  463.            SL = S ;
  464.         }
  465.  
  466.         while ( EL )
  467.         {          
  468.            K = EL->nx ;
  469.            Ufree( (void **)&EL , sizeof(CONDLST) ) ;
  470.            EL = K ;
  471.         }
  472.  
  473.         while( ML )
  474.         {
  475.           Ufree( (void **)(&(*ML).mn),zstrlen(ML->mn) ) ;
  476.           if( ML->mp)
  477.           {
  478.            P = ML->mp ;
  479.            while( P )
  480.            {
  481.              Ufree( (void **)(&(*P).txt),zstrlen(P->txt) ) ;
  482.              Q = P ;
  483.              P = P->nx ;
  484.              Ufree( (void **)&Q,sizeof(MacSeg) ) ;
  485.           }
  486.          }
  487.          M = ML ;
  488.          ML = ML->nx ;
  489.          Ufree((void **)&M,sizeof(MLST) ) ;
  490.       }
  491.         if (W) Ufree((void **)&W,WS_SIZE) ;
  492.  
  493.         fclose(ALST) ;        
  494. }
  495.  
  496. static int  NewOpen( char *tx)
  497. {
  498. /*
  499.         Used to open a new file, preserve the present file
  500.         and set to read from the new one.
  501. */
  502.         IFL *ol ;
  503.         FILE *tf ;
  504. #ifdef  _ARC_
  505.         if ( (tf = fopen(PathEdit(tx),"r")),tf==0)
  506. #else
  507.         if ( (tf = fopen(tx,"r")),tf==0)
  508. #endif
  509.         {OpError("*Can't open [%s%]\n",tx) ; return 1 ; }
  510.  
  511.         if (!IL)
  512.                ol = 0 ;
  513.         else
  514.                ol = IL ;
  515.  
  516.          IL = (IFL *)Umalloc(sizeof(IFL)) ;
  517.          IL->pt = ol ;
  518.          IL->fn = (char *)Umalloc( zstrlen(tx) ) ;
  519.          strcpy(IL->fn,tx) ;
  520.          IL->fh = tf ;
  521.          IL->sln = 0 ;
  522.  
  523.        return 0 ;
  524. }
  525.  
  526. static int NewClose(void)
  527. {
  528. /*
  529.         Closes the present file , and opens the previous one .
  530. */
  531.  
  532.         IFL  *ol ;
  533.  
  534.         if ( !IL ) return 2 ;
  535.         fclose( IL->fh ) ;
  536.         Ufree( (void **)(&(*IL).fn) ,zstrlen( IL->fn ) ) ;
  537.  
  538.         ol = IL->pt ;
  539.         Ufree( (void **)&IL , sizeof(IFL) ) ;
  540.  
  541.         if ( !ol )  return 1 ;
  542.         IL = ol ;
  543. return 0 ;
  544. }
  545.  
  546.  
  547. static char*  Strim( char *line )
  548. {
  549.     char *cp ;
  550.  
  551.     cp = line+strlen(line)-1 ;
  552.     for(;;) 
  553.     {
  554.     if ( !isspace(*cp) ) break ;
  555.     if( cp == line )
  556.     {  *cp = 0 ; break ;  }
  557.     else
  558.          *cp-- = 0 ;
  559.    }
  560. return line ;
  561. }
  562.  
  563.  
  564.  
  565. static int LoseWhite(void)
  566. {
  567.          while (*LP && isspace(*LP)) LP++ ;
  568.         if ( (*LP == ';') || !(*LP) )  return 1 ;
  569. return 0 ;
  570.  
  571. }
  572.  
  573. char  *RelSymbols [] = {
  574.         "!=","==",">=","<=",">","<",""
  575.                         } ;
  576.                         
  577. static int   Conditional( char *ltxt )
  578. {
  579.     CONDLST  *oc , *M ;
  580.     char     *cp;
  581.     char     **cq ;
  582.     long     cv,exv ;
  583.     int      Irel,i ;
  584.     
  585.     if (!strnicmp(ltxt,"?endif",6) )
  586.     {
  587.       if (!EL ) 
  588.       { OpError("*Extra ?endif\n%s\n",ltxt) ; Kill() ; exit(5) ; }
  589.       oc = EL->nx ;
  590.       Ufree( (void **)&EL , sizeof(CONDLST) ) ;
  591.       EL = oc ;
  592.       return  1 ;
  593.      }    
  594.  
  595.     if (!strnicmp(ltxt,"?else",5) )
  596.     {
  597.       if (!EL ) 
  598.       { OpError("*Extra ?else\n%s\n",ltxt) ; Kill() ; exit(5) ; }
  599.       EL->on  = !EL->on  ;
  600.      return  2 ;
  601.     }
  602.     
  603.     if (strnicmp(ltxt,"?if",3) )  return 0 ;
  604. /*
  605.         Hit an IF .... Evaluate the Expression.
  606.         for the momement, we are only interested in ==0 or != 0
  607. */
  608.         LP += 3 ;
  609.         strcat(LP,"     ");
  610.         cp = NextString() ;
  611.         if (!cp)
  612.         { OpError("* ?if with no expression.\n%s\n",LP) ;Kill() ;exit(5); }
  613.         nextc = cp ;
  614.         cv = iexp(0);
  615. /*
  616.         cv now holds the value of the first expression..
  617.         now, we look to see if there is a relational symbol
  618. */
  619.         Irel  =  0 ;
  620.         
  621.         cp = NextString() ;       
  622.         if( cp )
  623.         {/*1*/
  624. /*
  625.         Searching for relational symbol..
  626. */
  627.         for(i=1,cq=RelSymbols;**cq;i++,cq++)
  628.           if(!strncmp(cp,*cq,strlen(*cq)) )
  629.           { Irel = i ;  break ; }
  630.             
  631.         if (!Irel)
  632.         {
  633.           OpError("*Bad Relational Symbol [%s]\n%s\n",cp,LB) ;
  634.           Kill() ; exit(6) ;
  635.         }
  636. /*
  637.         There was a relational symbol, so there must be a further
  638.         parameter.
  639. */
  640.         cp = NextString() ;
  641.         if (!cp)
  642.         {
  643.           OpError("* ?if with no comparative value.\n%s\n",LP) ;
  644.           Kill() ; exit(6) ;
  645.         }
  646.         nextc = cp ;
  647.         exv = iexp(0);
  648.         }/*1*/
  649.                 
  650.         if (!EL)
  651.                          M = 0 ;
  652.         else
  653.                          M = EL  ;
  654.                          
  655.         EL = (CONDLST *)Umalloc(sizeof(CONDLST)) ;
  656.         EL->nx = M ;
  657.  
  658.         switch( Irel )
  659.         {        
  660. case 0:        EL->on = (cv != 0 )    ; break ;
  661. case 1:        EL->on = (cv != exv )  ; break ;
  662. case 2:        EL->on = (cv == exv )  ; break ;
  663. case 3:        EL->on = (cv >= exv)   ; break ;
  664. case 4:        EL->on = (cv <= exv)   ; break ;
  665. case 5:        EL->on = (cv >  exv)   ; break ;
  666. case 6:        EL->on = (cv <  exv)   ; break ;                
  667. default:        OpError("*Bug! in Relational Switch [%d]\n%s\n",Irel,LB) ;
  668.                 Kill() ; exit(6) ;
  669.         }        
  670. return  3 ;  
  671. }
  672.  
  673. static int  NewLine(void)
  674. {
  675. /*
  676.         Fetches the next line.
  677.         Handles any instances of #include.
  678. */
  679.     char  *csp,*cep ;
  680.  
  681.     LP = LB ;
  682.     for(;;)
  683.     {
  684.     fgets(LB,132,IL->fh) ;
  685.  
  686.     if ( feof(IL->fh) )
  687.     {
  688.       if ( NewClose() ) return 1 ;
  689.       return NewLine() ;
  690.     }
  691. /*
  692.         Process the conditional Directives, and set up
  693.         a record to say if lines are to be processed..
  694. */
  695.     if ( Conditional(LB) ) continue ;
  696.     if ( EL && !EL->on )   continue ;
  697.     break  ;
  698.     }
  699. /*
  700.         Looking for #include in col. 1 of new line.
  701. */
  702.     if (!strnicmp( LB , "#include" ,8) )
  703.     {
  704.       if ( (csp = strchr(LB,'"')),csp != 0 )
  705.       {
  706.        if ( (cep = strchr(csp+1,'"')),cep != 0 )
  707.        {
  708.          *cep = 0 ;
  709.         if ( NewOpen( csp+1 ) ) return 2  ;
  710.         return NewLine() ;
  711.        }
  712.       }
  713.       OpError("*Syntax:\n%s\n",LB) ;
  714.       return 3 ;
  715.     }
  716. /*
  717.         Chop off comments.
  718.         *Note this is a bit unsophisticated...
  719.         it will react to " ...  ;     "  for example..
  720. */       
  721.         *CB = 0  ;
  722.  
  723.         csp = LB ;
  724.         if ( (csp = strchr( LB , ';' )),csp != 0 )
  725.         {
  726.         if( B_Commlist )
  727.         {
  728.          if( csp != LB)
  729.               strcpy(CB,"\t"); /* Tab it if not @ start of line*/
  730.                    
  731.          strcat(CB,Strim(csp)) ; 
  732.          }
  733.         *csp = 0 ; /*  Truncate */
  734.         strcat(LB,"\n") ; 
  735.         }
  736.         ++IL->sln ;   /* count source lines */
  737.  
  738.         Strim(LB) ;
  739. /*
  740.         Check for some Directives.
  741. */
  742.         if( (csp = strchr(LB,'.') ) , csp == 0 ) return 0 ;
  743.         if ( !strnicmp(++csp,"LIST",4) ) B_ListOn = TRUE ;
  744.         else if ( !strnicmp(csp,"NOLIST",6)) B_ListOn = FALSE ;
  745. return 0 ;
  746. }
  747.  
  748.  
  749. static  char *NextString( void )
  750. {
  751.    char *csp ;
  752.  
  753.    if (LoseWhite() ) return (char *)0 ;
  754.    for (csp = LP;*LP;LP++)
  755.    {
  756.     if (
  757.         (*LP==',') || ( (*LP != '_') && ( isspace(*LP) ) )
  758.        )
  759.        {
  760.        *LP = 0 ;
  761.          ++LP ;
  762.        return csp ;
  763.        }
  764.    }
  765. return csp ;
  766. }
  767.  
  768.  
  769.  
  770. static void LoseTempParams( ParamRec *B)
  771. {
  772.   ParamRec *P ;
  773.  
  774.   if ( B )
  775.   {
  776.   while( B )
  777.   {
  778.         Ufree( (void **)(&(*B).txt) , zstrlen(B->txt ) ) ;
  779.         P = B->nx ;
  780.         Ufree( (void **)&B,sizeof(ParamRec) ) ;
  781.         B = P ;
  782.   }
  783.  }
  784. }
  785.  
  786. static int WhichParameter(ParamRec *B)
  787. {
  788. /*
  789.         looks for parameter in LB
  790.         if found , returns number &erases parameter.
  791. */
  792.   int   i;
  793.  
  794.   if ( !B )   return 0 ;
  795.   for ( i=1 ; B ; i++,B=B->nx )
  796.   {
  797.       if( *LP == *B->txt)
  798.                    if (!strncmp(LP,B->txt,strlen(B->txt) ) )
  799.            {
  800.                 LP += strlen(B->txt) ;
  801.                 return i ;
  802.            }
  803.   }
  804. return 0 ;
  805. }
  806.  
  807.  
  808.  
  809. static  int CkSymbolDef( void )
  810. {
  811.         SREC     *M ;
  812.         char     *cp,*cq ;
  813. /*
  814.         Looking for #SYMBOL definition start.
  815. */
  816.         for(;;)
  817.         {/*1*/
  818.         if (strnicmp(LP,"#symbol",7) ) return 0  ;
  819. /*
  820.         Found symbol key-word. check duplicate.
  821. */
  822.         ++Nsymbs ;
  823.         
  824.         LP += 7 ;
  825.         strcat(LP,"   ") ;
  826.         cp = NextString() ;
  827.  
  828.         if ( !cp )
  829.         {OpError("#SYMBOL - no name.\n") ; Kill() ;exit(1) ; }
  830.  
  831.         if ( ( M = SymbolSearch( cp , &cq) ),M !=0  )
  832.         {/*2*/
  833.  
  834. #if  0
  835. /*
  836.         We are  not Allowed to re-use Symbols...
  837. */   
  838.         { OpError("#SYMBOL - Duplicate. %s\n",M->txt); Kill() ;exit(1) ; }
  839. #endif
  840.  
  841.         }/*2*/
  842.         else
  843.         {/*2*/
  844.         if (!SL)
  845.                         M = 0 ;
  846.         else
  847.                         M = SL ;
  848.  
  849.         SL = (SREC *)Umalloc(sizeof(SREC) ) ;
  850.         SL->nx  =  M ;
  851.         SL->txt = (char *)Umalloc(zstrlen(cp)) ;
  852.         strcpy(SL->txt,cp) ;
  853. /*
  854.         now look up the Value.
  855. */
  856.         M = SL ;
  857.         }/*2*/
  858.         nextc   =  NextString() ;
  859.         M->sv  =  iexp(0) ;
  860.         if( B_Mlist) 
  861.           fprintf(ALST,";\t[%s] = %lxH (%ld)\n",M->txt,M->sv,M->sv ) ;
  862.         if ( NewLine() ) break ;
  863.      }/*1*/
  864. return  0 ;
  865. }
  866.  
  867.  
  868. static  void  CkMacroDef( void )
  869. {
  870.         MLST     *M ;
  871.         ParamRec *B = 0,*P,*Q  ;
  872.         MacSeg   *R,*S ;
  873.         char     *cp ;
  874.         char     *wp  ;
  875.         int      i ;
  876. /*
  877.         Looking for #MACRO definition start.
  878. */
  879.         for(;;)
  880.         {/*1*/
  881.           
  882.         if (strnicmp(LP,"#macro",6) ) return  ;
  883. /*
  884.         Found macro key-word. check duplicate.
  885. */
  886.         ++Nmacs ;
  887.         
  888.         LP += 6 ;
  889.         cp = NextString() ;
  890.  
  891.         if ( !cp )
  892.         { OpError("#MACRO - no name.\n") ; Kill() ; exit(1) ; }
  893.  
  894.         if (ML)
  895.         {/*2*/
  896.            M = ML ;
  897.            while( M )
  898.            {/*3*/
  899.            if ( !strncmp(M->mn,cp,strlen(cp)) )
  900.             {/*4*/
  901.                 OpError("#MACRO - Duplicate %s\n%s\n",cp,LB) ;
  902.                 Kill() ;  exit(2) ;
  903.             }/*4*/
  904.                 M = M->nx  ;
  905.            }/*3*/
  906.         }/*2*/
  907.  
  908. /*
  909.         Ok.. not a duplicate.  create a new macro record.
  910. */
  911.         *W = 0 ;
  912.         wp = W ;
  913.         if (!ML)
  914.                         M = 0 ;
  915.         else
  916.            M = ML ;
  917.  
  918.            ML = (MLST *)Umalloc(sizeof (MLST)) ;
  919.            ML->nx  =  M ;
  920.            ML->mn  =  (char *)Umalloc(zstrlen(cp) ) ;
  921.            strcpy(ML->mn,cp) ;
  922.            ML->mp  = R = 0 ;
  923.            ML->N = 0 ;
  924. /*
  925.         now look up the parameters.
  926. */
  927.         cp = NextString() ;
  928.  
  929.         while ( cp )
  930.         {/*2*/
  931.         ++ML->N ;
  932.         Q = (ParamRec *)Umalloc(sizeof(ParamRec)) ;
  933.         if (!B)
  934.                         B = P = Q ;
  935.         else
  936.                         P->nx = Q ;
  937.  
  938.         Q->nx  = 0 ;
  939.         Q->txt = (char *)Umalloc( zstrlen(cp) ) ;
  940.         strcpy (Q->txt,cp) ;
  941.         P = Q ;
  942.         cp = NextString() ;
  943.         }/*2*/
  944.  
  945.         while ( !NewLine() )
  946.         {/*2*/
  947.         if ( !*LB  ) continue ;
  948.         strcat(LB,"\n") ; 
  949. /*
  950.         reading Macro definition.
  951. */
  952.         if (!strnicmp( LB , "#mend" ,5) )
  953.         {/*3*/
  954. /*
  955.         Save the end of the Macro text.
  956.         Deal with the case of a no-parameter macro
  957. */
  958.         S = (MacSeg *)Umalloc( sizeof(MacSeg) ) ;
  959.         if ( !ML->mp )
  960.                            ML->mp = R = S ;
  961.                 else
  962.                            R->nx = S ;
  963.  
  964.         S->txt = (char *)Umalloc( zstrlen(W) ) ;
  965.         strcpy(S->txt,W) ;
  966.         S->nx = 0 ;
  967.         S->pn = 0 ; /* flag no parameter */
  968.  
  969.         LoseTempParams( B ) ;
  970.         break ;  /* return to outer loop for another line */
  971.         }/*3*/
  972.         else
  973. /*
  974.         Process the Macro Text in LP by searching for
  975.         parameter tokens and creating sections of text
  976.         numbered with the parameters to bracket the real
  977.         parameters when they come..
  978. */
  979.         if( B_Mlist) fprintf(ALST,";\t[%s] |\t%s",ML->mn,LB) ;
  980.  
  981.         while ( *LP )
  982.         {/*3*/
  983.         if ( (i = WhichParameter( B )),i !=0 )
  984.         {/*4*/
  985. /*
  986.         found a Parameter, so create a new Record
  987. */
  988.         S = (MacSeg *)Umalloc(sizeof(MacSeg)) ;
  989.         S->txt = (char *)Umalloc( zstrlen(W) ) ;
  990.         S->pn = i ;             /* Parameter following */
  991.         S->nx = 0 ;
  992.         strcpy(S->txt,W) ;      /* text before */
  993.         *W = 0 ;                /* clear text accumulator */
  994.         wp = W ;
  995.         if( !ML->mp)
  996.                 ML->mp = S ;    /* create head pointer */
  997.         else
  998.                 R->nx = S ;     /* append to chain */
  999.         R = S ;
  1000.         }/*4*/
  1001.         else
  1002.         {/*4*/
  1003.           *wp++ = *LP++ ;       /* add to accumulator */
  1004.           *wp = 0 ;
  1005.         }/*4*/
  1006.         }/*3*/  /* Parameter sections */
  1007.         }/*2*/ /*macro Body*/
  1008.                 
  1009.         if ( !NewLine() )  return  ;
  1010.         }/*1*/
  1011. }
  1012.  
  1013. static  char *GetParameter( unsigned char n,ParamRec *B)
  1014. {
  1015.     if (!n) return "" ;     /* null parameter */
  1016.     while (--n)
  1017.     {
  1018.       B=B->nx ;
  1019.       if( !B )
  1020.       { OpError("*SW err GetParameter\n") ; Kill() ; exit(5) ; }
  1021.   }
  1022. return B->txt ;         /* Parameter text */
  1023. }
  1024.  
  1025.  
  1026.  
  1027. static void  SymbolEdit( char *sytx )
  1028. {
  1029.         SREC   *S ;
  1030.         char   *cp,*cb ;
  1031.         char   w[133] ;
  1032.  
  1033.         for(;;)
  1034.         {
  1035.         if ( (S=SymbolSearch(sytx , &cp) ),S==0 ) return ;
  1036. /*
  1037.         Found Symbol in source line.  cp points to start.
  1038.         length of symbol to be edited out is in the record...
  1039. */
  1040.         cb = cp ;
  1041.         cp += strlen(S->txt) ;
  1042.         strcpy(w,cp) ;
  1043.         sprintf(cb,"0%lxH",S->sv) ;
  1044.         strcat(cb,w) ;
  1045.         ++Ssymbs ;               
  1046.         }
  1047. }
  1048.  
  1049.  
  1050. static   void  SymbolFixup( void )
  1051. {   SymbolEdit( LB ) ;  }
  1052.  
  1053.  
  1054. static int  MacroFixup( void )
  1055. {
  1056.         char    *cp,*Tcp ;
  1057.         MLST    TM ;
  1058.         MLST    *M ,*MT ;
  1059.         ParamRec *B = 0,*P,*Q  ;
  1060.         MacSeg   *S ;
  1061.         int      sl,sx ;
  1062.  
  1063.         if (!ML)   return 0 ;
  1064. /*
  1065.         Macros have been defined..
  1066.         look for them.
  1067. */
  1068.  
  1069.    for( sl = 0 , MT = 0 , M = ML; M ; M = M->nx )
  1070.    {/*1*/
  1071.     if ( (cp = strstr( LP,M->mn) ),cp!=0 )
  1072.     {
  1073.       sx = strlen(M->mn) ;
  1074.       if (
  1075.            ( isspace(*(cp-1))       /* Has White space before */
  1076.              || (cp == LP)         /* Or is first line entry */
  1077.            )
  1078.        &&  (
  1079.               isspace(*(cp+sx))       /* And has white Space after */
  1080.              || !*(cp+sx)             /* or is end-of string */
  1081.            )               
  1082.        && ( sl < sx )            /* And is longer then Match */
  1083.           )
  1084.       {
  1085.          sl = sx ; MT = M ; Tcp = cp ; /* Record Macro Hit */
  1086.       }
  1087.      }
  1088.    }/*1*/
  1089.     if ( !MT )  return 0 ;
  1090.        
  1091. /*
  1092.         Found Macro in source line.
  1093. */
  1094.      fprintf(ALST,";\t*M\t%s%s\n",LP ,
  1095.      ( !B_Mlist && B_ListOn )? "\n\t.NOLIST" : "" ) ;
  1096.  
  1097.      ++Smacs ;          /* Another Macro */
  1098.      LP = Tcp ;         /* Point to the Name */
  1099.      cp = NextString() ;  /* goto first Parameter */
  1100.  
  1101.      TM.nx = 0 ;
  1102.      TM.mn = (char *)Umalloc(zstrlen(cp)) ;
  1103.      strcpy(TM.mn,cp) ;
  1104.      TM.mp = 0 ;
  1105.      TM.N = 0 ;
  1106. /*
  1107.         now look up the parameters.
  1108. */
  1109.         cp = NextString() ;
  1110.  
  1111.         while ( cp )
  1112.         {/*1*/
  1113.         ++TM.N ;
  1114.         Q = (ParamRec *)Umalloc(sizeof(ParamRec)) ;
  1115.  
  1116.         if (!B)
  1117.                          B = P = Q ;
  1118.         else
  1119.                          P->nx  = Q ;
  1120.         Q->nx  = 0 ;
  1121.         Q->txt = (char *)Umalloc(zstrlen( cp )) ;
  1122.         strcpy (Q->txt,cp) ;
  1123.         P = Q ;
  1124.         cp = NextString() ;
  1125.         }/*1*/
  1126. /*
  1127.         All parameters of current Macro found.
  1128.         First compare number of parameters..
  1129. */
  1130.         if (MT->N  != TM.N)
  1131.         {/*1*/
  1132.         OpError("*Incorrect # Params :%s (%d)\n%s\n",MT->mn,MT->N,LB) ;
  1133.         LoseTempParams (B ) ; Kill() ; exit(4) ;
  1134.         }/*1*/
  1135. /*
  1136.          do the substitution...
  1137. */
  1138.         S = MT->mp ;   /* pointer to parts */
  1139.         while( S )
  1140.         {
  1141.  
  1142.         sprintf(W,"%s%s",S->txt,GetParameter(S->pn,B) ) ;
  1143.         SymbolEdit(W) ;
  1144.         fprintf(ALST,"%s",W) ;
  1145.         S = S->nx ;
  1146.         }
  1147.  
  1148.         LoseTempParams(B) ;
  1149.         
  1150.      fprintf(ALST,"%s",
  1151.        ( !B_Mlist && B_ListOn )? "\t.LIST\n" : "" ) ;
  1152.  
  1153.         return  1 ;
  1154.  
  1155. return 0 ;
  1156. }
  1157.  
  1158. static void Time_Date_Stamp(void)
  1159. {
  1160.    time_t tv ;
  1161.    struct tm  *tpt ;
  1162.    char * cp ;
  1163.    
  1164.    time( &tv ) ;
  1165.    tpt = localtime( &tv ) ;
  1166.   
  1167.    fprintf(ALST,"#DEFINE\tDATE__\t\x22%s\x22\n"  ,Strim(asctime(tpt) ) ) ;  
  1168.    cp = strrchr( F_src ,'\\') ;
  1169.    fprintf(ALST,"#DEFINE\tFILE__\t\x22%s\x22\n"  ,(cp)?++cp:F_src) ;     
  1170. }
  1171.  
  1172. int main (int ac,char **av )
  1173. {
  1174. fprintf(stderr,"Macro Expansion For TASM  R.J.P. V:3.5  3rd September 1992\n") ;
  1175.  
  1176.         if ( cmdline(ac,av) )
  1177.         {
  1178.         fprintf(stderr,"Syntax : EXPAND /I:infile /O:outfile [-C] [+M]\n") ;
  1179.         return 1;
  1180.         }
  1181.  
  1182.    NewOpen( F_src ) ;
  1183.    
  1184.    W  = (char *)Umalloc( 4096  ) ; /* general work space */
  1185.    if( B_Stamp )
  1186.                 Time_Date_Stamp() ;
  1187.  
  1188.    if (*T_copyw )
  1189.     fprintf(ALST,"#DEFINE\tCOPYW__\t\x22%s\x22\n" ,T_copyw ) ;
  1190.     
  1191.    if (setjmp(EvalErr) )
  1192.    {
  1193.      OpError("#SYMBOL - Evaluation.\n%s\n" ,LB) ;
  1194.      Kill() ;     exit( 6 ) ;
  1195.    }
  1196.    
  1197.  
  1198.    while ( !NewLine()  )
  1199.    {
  1200.       if (!LoseWhite() )
  1201.       {/*1*/
  1202.         if (!CkSymbolDef() )
  1203.         {/*2*/
  1204.           SymbolFixup() ;
  1205.           CkMacroDef() ;
  1206.           if(!MacroFixup() )
  1207.           {/*3*/
  1208.              sprintf(W,"%s%s",LB,CB ) ;
  1209.              if(*W) fprintf(ALST,"%s\n",W) ;
  1210.           }/*3*/
  1211.          }/*2*/
  1212.        }/*1*/
  1213.       else if (B_Commlist)  fprintf(ALST,"%s\n",CB ) ;
  1214.                                
  1215.     }
  1216. Kill() ;
  1217. fprintf(stderr,
  1218.            "Macros:%d, Found %d Symbols:%d Used %d Memory %u. Bytes\n"
  1219.                 ,Nmacs,Smacs,Nsymbs,Ssymbs, UmemMax ) ;                
  1220. return 0 ;
  1221. }
  1222.