home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / dev / cross / caz / src / caz.c < prev    next >
C/C++ Source or Header  |  1994-01-08  |  63KB  |  2,609 lines

  1. #define _STRICT_ANSI
  2.  
  3. #include "defs.h"
  4. #include "cazerrors.h"
  5.  
  6. /*#define DEBUG2 */    /* internal use for more debugging (print out coded MNE) */
  7. /*#define DEBUG_STRTOINT*/  /* debug strtoint() funktion */
  8.  
  9.  
  10. #define MODE_ALL    1        /* Verbose Mode: Print out all source text */
  11. #define MODE_MNE    2        /* Verbose Mode: Print out only MNE text */
  12. #define MODE_OPTION 4        /* if Verbose Mode is set via Commandline Option */
  13.  
  14. #define ACT_OBJ_ADDR(pobj) (((u_char *)(pobj->objbuffer+(pobj->actbyte-pobj->firstbyte))))
  15.  
  16. #define COPYRIGHT " ©1992-94 by Carsten Rose\n"
  17. const char *vers = "\0$VER: Z80_Assenbler 1.26ß (7 Januar 94)";
  18.  
  19. extern char *directives[];        /* declared in File 'cazmne.c' */
  20. extern struct command cmd[];    /* declared in File 'cazmne.c' */
  21.  
  22. static int        init                (struct listheader *plabel,struct objsize *pobj);
  23. static void    symboltable        (struct listheader *plabel);
  24. static int     writesymboltable    (struct listheader *plabel,char *filename);
  25. static char   *ibtoh            (u_char byte,char *pbuf);
  26. static char   *iwtoh            (unsigned short word,char *pbuf);
  27. static void    decodearg        (char *str,u_long pa);
  28. static int        strcmp_lany_rupper(char *pany,char *pupper);
  29. static void    cutend            (char *pos);
  30. static char   *skipspace        (char *pos);
  31. static char    validquote        (char quote);
  32. static void    killcomment        (char *pos);
  33. static int        expandlist        (struct listheader *plist);
  34. static struct labelitem 
  35.               *insertlabel        (struct listheader *plabel,char *name,int type,u_short value,BOOL valid);
  36. static int        dolabel            (struct listheader *plabel,struct objsize *pobjcode,char   *lname);
  37. static int        finddirective    (char *pos);
  38. static struct command
  39.               *findmne            (struct command *pcmd,char *pmne);
  40. static u_long  argtype            (struct listheader *plabel,char *pos,u_short *pshort,int mode);
  41. static int        doobjadr            (struct objsize *pobj,int n,int mode);
  42. static u_char  codebits            (u_long mask);
  43. static int        writemnedata        (struct objsize *pobj,u_long maskarg,u_short val,u_long maskcmd,u_char pos);
  44. static int        fillihbuffer        (int addr,int nbytes,u_char *pbuf);
  45. static int        dointelhex        (int addr,int size,u_char *data);
  46. static int        makecode            (struct objsize *pobj,struct command *pcmd,int mode,u_long type1,u_short val1,u_long type2,u_short val2);
  47. static int        domne            (struct listheader *plabel,struct objsize *pobj,char *ptok,int mode,u_short *pcycle);
  48. static int       pushfile            (struct item_file **pstack,char *p_filenamenew,FILE **p_fp);
  49. static int       popfile            (struct item_file **pstack,FILE **p_fp);
  50. static int        setdefaultbase    (char *pbase);
  51. static int        dodirective        (struct listheader *plabel,struct objsize *pobj,char *ptok,int direc,int mode,int *orgflag);
  52. static int        parseline        (struct listheader *plabel,struct objsize *pobj,char *pwork,int mode);
  53. static int        readsrc            (struct listheader *plabel,struct objsize *pobj,char *p_actname);
  54.  
  55. int            main             (int argc,char *argv[]);
  56.             
  57. int     lnr=0,errors=0,
  58.         debugv=FALSE,            /* debug values, set via Commandline option */ 
  59.         debugf=FALSE,            /* debug functions, set via Commandline option */ 
  60.         verbose=FALSE,            /* set via Commandline option */
  61.         intelhex=FALSE,            /* set via Commandline option */
  62.         clockcycle=FALSE,        /* set via Commandline option */
  63.         showsymbols=FALSE;        /* set via Commandline option */
  64.         default_num_base;        /* change via DEFNUM directive */
  65. char    errortext[BUFSIZ],        /* Common Buffer for Error Messages */
  66.         line[BUFSIZ],            /* Actual read Source text line (original) */
  67.         work[BUFSIZ],            /* Actual read Source text line (truncated,modified) */
  68.         actfilename[FILENAME_MAX]; /* Actual Filename of assembled Source File */
  69.  
  70. struct    listheader  ih_head;
  71. struct    listheader label;
  72. struct    objsize    object;
  73. struct  item_file    *file_stack=NULL;
  74.  
  75. BOOL    endflag=FALSE,            /* Set if END is found */
  76.         assembleflag=TRUE;        /* Normal TRUE, only if 'COND xx' xx==0 then FALSE */
  77. FILE     *fpin=NULL,*fpout=NULL;
  78.  
  79.  
  80. static void showerror(char *errpos, char *fmt , ...)
  81. {
  82.     /*
  83.      * Print parsing error:
  84.      *
  85.      *   xxxx:........................
  86.      *              ^
  87.      *   'Error Description'
  88.      */
  89.  
  90.         int i;
  91.         va_list pa;
  92.         char buffer[BUFSIZ];
  93.  
  94.     if(debugf)  puts("showerror");
  95.  
  96.         /* If there are more than 1 source files - print Filenames */
  97.     if(file_stack)
  98.         fprintf(stderr,"Error in File:%s\n",actfilename);
  99.  
  100.     fprintf(stderr,"%4d:%s",lnr,line);        /* line number and Source code line */
  101.  
  102.     i = strlen(line);
  103.  
  104.     if(!i)                /* not really needed */
  105.         return;
  106.  
  107.     if(line[i-1]!='\n')
  108.         fputs("\n",stderr);
  109.  
  110.     if(!errpos)
  111.         errpos=work;
  112.  
  113.     i = (int)(errpos - work);
  114.  
  115.     buffer[i]='\0';
  116.  
  117.     while(i--)
  118.     {
  119.         if(line[i]=='\t')
  120.             buffer[i]='\t';
  121.         else
  122.             buffer[i]=' ';
  123.     }
  124.  
  125.     fprintf(stderr,"     %s^ ",buffer);        /* mark position */
  126.  
  127.     va_start(pa,fmt);
  128.     vfprintf(stderr,fmt,pa);                /* Print Errormessage */
  129.     va_end(pa);
  130.     fputs("\n",stderr);
  131.     errors++;                        /* count errors */
  132. }
  133.  
  134. static int init(struct listheader *plabel,struct objsize *pobj)
  135. {
  136.     /*
  137.      * Init listheader
  138.      *
  139.      * RC : NULL if all went fine 
  140.      */
  141.      
  142.  
  143.     if(debugf)  puts("init");
  144.  
  145.     plabel->nitem = 0;
  146.     plabel->actitem = 0;
  147.     plabel->sizeitem = sizeof(struct labelitem);
  148.     plabel->newnitem = NEWITEMOFF;
  149.     plabel->userdata = ERROR;
  150.     plabel->list = NULL;
  151.  
  152.     ih_head.nitem = 0;
  153.     ih_head.actitem = 0;
  154.     ih_head.sizeitem = sizeof(u_char);
  155.     ih_head.newnitem = 4096;
  156.     ih_head.userdata = ERROR;
  157.     ih_head.list = NULL;
  158.  
  159.     pobj->firstbyte = ERROR;
  160.     pobj->actbyte   = ERROR;
  161.     pobj->lastbyte  = ERROR;
  162.     pobj->objbuffer = NULL;
  163.  
  164.     return(NULL);
  165. }
  166.  
  167. static void symboltable(struct listheader *plabel)
  168. {
  169.     int i;
  170.     struct labelitem *lst;
  171.     char *pltyp;
  172.  
  173.     if(debugf)  puts("symboltable");
  174.  
  175.     lst = plabel->list;
  176.     i   = plabel->actitem;
  177.     puts("Lable's:");
  178.  
  179.     while(i--)
  180.     {
  181.         switch(lst->type)
  182.         {
  183.             case L_EQU:        pltyp = "EQU";
  184.                             break;
  185.             case L_DEFL:    pltyp = "DEFL";
  186.                             break;
  187.             case L_POSITION:
  188.                             pltyp = "POSITION";
  189.                             break;
  190.             deafult:        pltyp = "unknown";
  191.                             INTERNAL_ERROR
  192.                             break;
  193.         }
  194.         
  195.         printf("Name:%-32s  Type:%-8s  Value:0x%X\n",lst->name,pltyp,lst->value);
  196.         lst++;
  197.     }
  198. }
  199.  
  200. static int writesymboltable(struct listheader *plabel,char *filename)
  201. {
  202.     /* Write all Labels as EQU definition's with associated values into
  203.      * 'filename'
  204.      *
  205.      * RC: NULL if all went fine else
  206.      *     ERROR
  207.      */
  208.  
  209.     int i;
  210.     struct labelitem *lst;
  211.     FILE   *fplabel;
  212.  
  213.     if(debugf)  puts("writesymboltable");
  214.  
  215.     lst = plabel->list;
  216.     i   = plabel->actitem;
  217.  
  218.     if(!(fplabel = fopen(filename,"wb")))    /* open file where to write Label's */
  219.     {
  220.         perror("Can't open file:");
  221.         return(ERROR);
  222.     }
  223.  
  224.     while(i--)
  225.     {
  226.         if(fprintf(fplabel,"%-32s EQU 0x%X\n",lst->name,lst->value)<0)
  227.         {
  228.             perror("Writing Labelfile failed");
  229.             fclose(fplabel);
  230.             return(ERROR);
  231.         }
  232.         lst++;
  233.     }
  234.  
  235.     fclose(fplabel);
  236.  
  237.     return(NULL);
  238. }
  239.  
  240.  
  241. static char *ibtoh(unsigned char byte,char *pbuf)
  242. {
  243.     /* Convert 'byte' in ASCII Hex Notation.
  244.      * 
  245.      * Write ASCII Hex Code (2 Chars) at '*pbuf'.
  246.      *
  247.      * RC: pbuf+2    (points to next free char)
  248.      */  
  249.  
  250.     unsigned char     low,    /* low 4 Bits of 'byte' */
  251.             high;    /* high 4 Bits of 'byte' (normalized) */
  252.  
  253.     low = 0x0F&byte;
  254.     high = (0xF0&byte)>>4;
  255.  
  256.     /* convert Integer to ASCII Hex */
  257.     *pbuf++= (high<=9) ? high+'0' : (high-0x0A)+'A';
  258.     *pbuf++= (low<=9) ? low+'0' : (low-0x0A)+'A';
  259.  
  260.     return(pbuf);
  261. }
  262.  
  263. static char *iwtoh(u_short word,char *pbuf)
  264. {
  265.     /* Convert 'word' in ASCII Hex Notation.
  266.      * 
  267.      * Write ASCII Hex Code (4 Chars) at '*pbuf'.
  268.      *
  269.      * RC: pbuf+4    (points to next free char)
  270.      */  
  271.  
  272.     char *pos;
  273.     u_char lowb,highb;
  274.  
  275.     lowb = (u_char)(word & 0xFF);
  276.     highb = (u_char)(word >> 8);
  277.  
  278.     pos=ibtoh(highb,pbuf);
  279.     pos=ibtoh(lowb,pos);
  280.  
  281.     return(pos);
  282. }
  283.  
  284. static void decodearg(char *str,u_long pa)
  285. {
  286.     char pos[256];
  287.  
  288.     if(debugf)  puts("decodearg");
  289.  
  290.     pos[0]='\0';
  291.  
  292.     if( (pa^BRA)&BRA)
  293.     {
  294.         if(!( (pa®8)^REG8))
  295.             strcat(pos,"REG8   ");
  296.         else if(!( (pa®16)^REG16))
  297.             strcat(pos,"REG16  ");
  298.         else
  299.         {
  300.             if(pa®_A)  strcat(pos,"REG_A  ");
  301.             if(pa®_B)  strcat(pos,"REG_B  ");
  302.             if(pa®_C)  strcat(pos,"REG_C  ");
  303.             if(pa®_D)  strcat(pos,"REG_D  ");
  304.             if(pa®_F)  strcat(pos,"REG_F  ");
  305.             if(pa®_H)  strcat(pos,"REG_H  ");
  306.             if(pa®_I)  strcat(pos,"REG_I  ");
  307.             if(pa®_L)  strcat(pos,"REG_L  ");
  308.             if(pa®_R)  strcat(pos,"REG_R  ");
  309.             if(pa®_AF) strcat(pos,"REG_AF ");
  310.             if(pa®_BC) strcat(pos,"REG_BC ");
  311.             if(pa®_DE) strcat(pos,"REG_DE ");
  312.             if(pa®_HL) strcat(pos,"REG_HL ");
  313.             if(pa®_SP) strcat(pos,"REG_SP ");
  314.             if(pa®_IX) strcat(pos,"REG_IX ");
  315.             if(pa®_IY) strcat(pos,"REG_IY ");
  316.         }
  317.     }
  318.     else if(pa&BRA)
  319.     {
  320.         if(!( (pa & BRANCH8) ^ BRANCH8))
  321.             strcat(pos, "BRA8  ");
  322.         else if(!( (pa & BRANCH8) ^ BRANCH4))
  323.             strcat(pos, "BRA4  ");
  324.         else
  325.         {
  326.             if(pa&BRA_Z )  strcat(pos,"BRA_Z  ");
  327.             if(pa&BRA_NZ)  strcat(pos,"BRA_NZ ");
  328.             if(pa&BRA_C )  strcat(pos,"BRA_C  ");
  329.             if(pa&BRA_NC)  strcat(pos,"BRA_NC ");
  330.             if(pa&BRA_PO)  strcat(pos,"BRA_PO ");
  331.             if(pa&BRA_PE)  strcat(pos,"BRA_PE ");
  332.             if(pa&BRA_P )  strcat(pos,"BRA_P  ");
  333.             if(pa&BRA_M )  strcat(pos,"BRA_M  ");
  334.         }
  335.     }
  336.     if(pa&IND    )
  337.         strcat(pos,"IND     ");
  338.     if(pa&UNM3    )
  339.         strcat(pos,"U3     ");
  340.     if(pa&UNM8    )
  341.         strcat(pos,"U8   ");
  342.     if(pa&UNM16    )
  343.         strcat(pos,"U16  ");
  344.     if(pa&OFF    )
  345.         strcat(pos,"OFF     ");
  346.  
  347.     if(pa&RST    )
  348.         strcat(pos,"RST     ");
  349.     if(pa&JMPREL    )
  350.         strcat(pos,"JMPR ");
  351.  
  352.  
  353.     if(! ((pa&IMODE2)^IMODE0))
  354.         strcat(pos,"IMODE0 ");
  355.     if(! ((pa&IMODE2)^IMODE1))
  356.         strcat(pos,"IMODE1 ");
  357.     if(! ((pa&IMODE2)^IMODE2))
  358.         strcat(pos,"IMODE2 ");
  359.  
  360.     fprintf(stderr,"%s:%s\n",str,pos);
  361. }
  362.  
  363. /*
  364. static int prtallcmd()
  365. {
  366.     struct command *pcmd;
  367.     char par1[BUFSIZ],par2[BUFSIZ];
  368.  
  369.     if(debugf)  puts("prtallcmd");
  370.  
  371.     pcmd = cmd;
  372.     while(pcmd->name)
  373.     {
  374.         par1[0] = par2[0] = '\0';
  375.         fprintf(stderr,"MNE:%s | %s , %s | LE:%X | BY:%d BI:%d , BY:%d BI:%d | %X %X %X %X\n",
  376.                 pcmd->name,
  377.                 decodearg(pcmd->pa1,par1),
  378.                 decodearg(pcmd->pa2,par2),
  379.                 MNELEN(pcmd->order1),
  380.                 BYTE(pcmd->order1),BIT(pcmd->order1),
  381.                 BYTE(pcmd->order2),BIT(pcmd->order2),
  382.                 pcmd->obj[0],pcmd->obj[1],pcmd->obj[2],pcmd->obj[3]);
  383.         pcmd++;
  384.     }
  385. }
  386. */
  387.  
  388.  
  389. /*
  390.  * Translate first String to upper and compare with second string.
  391.  * RC: NULL if they identical, else
  392.  *     !=NULL if they differ.
  393.  */
  394. static int strcmp_lany_rupper(char *pany,char *pupper)
  395. {
  396.     int i=0;
  397.     char c;
  398.  
  399.     while( pupper[i])
  400.     {
  401.         c = toupper(pany[i]);
  402.  
  403.         if(pupper[i]!=c)
  404.             return(c-pupper[i]);
  405.  
  406.         i++;
  407.     }
  408.     
  409.     return(pany[i]);
  410. }
  411.  
  412.  
  413. static void  cutend(char *pos)
  414. {
  415.     /*
  416.      *    Remove spaces/CR from end of String
  417.      *
  418.      *    No RC
  419.      */
  420.      
  421.     int n;
  422.     char *tmp;
  423.  
  424.     if(debugf)  puts("cutend");
  425.  
  426.     if(!pos)
  427.         INTERNAL_ERROR
  428.  
  429.     n   = strlen(pos);
  430.  
  431.     if(!n)
  432.         return;
  433.  
  434.     tmp = pos + n - 1;
  435.  
  436.     while(n-- && ((isspace(*tmp))||(*tmp=='\n')) )
  437.         *tmp--='\0';
  438. }
  439.  
  440. static char *skipspace(char *pos)
  441. {
  442.     /*
  443.      *    Skip spaces at top of String
  444.      *
  445.      *    Pointer to start of string ,or
  446.      *    NULL if the string only contains spaces
  447.      */
  448.      
  449.     if(debugf)  puts("skipspace");
  450.  
  451.     while( *pos && isspace(*pos) )
  452.         pos++;
  453.  
  454.     if(*pos)
  455.         return(pos);
  456.     else
  457.         return(NULL);
  458. }
  459.  
  460. static char validquote(char quote)
  461. {
  462.     /*
  463.      *  Check if 'quote' is a valid Z80 Assemnler quote delimiter.
  464.      *
  465.      *  RC: 'quote' if it's valid, else
  466.      *       NULL
  467.      */
  468.  
  469.     switch(quote)
  470.     {
  471.         case '\'':
  472.         case '"':
  473.         case '/': return(quote);
  474.  
  475.         default : return((char)NULL);
  476.     }
  477. }
  478.  
  479. static void killcomment(char *pos)
  480. {
  481.     /*
  482.      *    Look for a comment token ( ';'  ) and replace it with '\0'.
  483.      *
  484.      *    No RC
  485.      */
  486.     char *comment;
  487.     char *pt1;    /* take care that's ';' isn't inside a Text definition */
  488.  
  489.     if(debugf)  puts("killcomment");
  490.  
  491.     if(!(comment=strchr(pos,(int)';')))
  492.         return;     /* No Commentsign found - do nothing */
  493.  
  494.     if(!(pt1=strpbrk(pos,"\'\"/")))
  495.     {
  496.         *comment='\0';
  497.         return;
  498.     }
  499.  
  500.     if(pt1>comment)
  501.     {
  502.         *comment='\0';
  503.         return;
  504.     }
  505.  
  506.     if(pt1=strchr(pt1+1,*pt1))
  507.     {
  508.         killcomment(pt1+1);
  509.         return;
  510.     }
  511.  
  512.     *comment='\0';
  513. }    
  514.  
  515. struct labelitem *getlabel(struct listheader *plabel,char *name)
  516. {
  517.     /*
  518.      *    Search for the label 'name' in label list. 
  519.      *
  520.      *  RC = if 'name' found, a pointer to the item , else
  521.      *       NULL
  522.      */
  523.  
  524.     int n,i;
  525.     struct labelitem *pitem;
  526.     static struct labelitem ad_cnt = {0,TRUE,L_POSITION,"$"};  /* Simulate Address Counter Label */
  527.  
  528.     if(debugf)  puts("getlabel");
  529.  
  530.     if( (strlen(name)==1) && (*name == '$'))
  531.     {
  532.         ad_cnt.value = object.actbyte; /* set actual Address Counter */
  533.         return(&ad_cnt);
  534.     }
  535.  
  536.     n = plabel->actitem;                        /* get count of items */
  537.     pitem = (struct labelitem *)plabel->list;    /* get first item */
  538.  
  539.     for(i=0;i<n;i++,pitem++)                    /* check all items */
  540.     {
  541.         if(!(strcmp(name,pitem->name)))            /* compare 'name' with item */
  542.             return(pitem);                        /* Success */
  543.     }
  544.     return(NULL);                                /* Failed */
  545. }
  546.  
  547. static int expandlist(struct listheader *plist)
  548. {
  549.     /*    
  550.      * Increase table size. Delta Increase and old table are specified
  551.      * in struct 'listheader'
  552.      *
  553.      * RC: NULL if OK
  554.      *     SERIOUS if realloc fails
  555.      */
  556.  
  557.     if(debugf)  puts("expandlist");
  558.  
  559.                     /* expand table */
  560.     if(plist->list)
  561.     {
  562.         if(!(plist->list=realloc(plist->list,(plist->newnitem+plist->nitem) * plist->sizeitem )))
  563.         {
  564.             fputs("Can't allocate memory for table\n",stderr);
  565.             return(SERIOUS);
  566.         }
  567.     } 
  568.     else
  569.     {    
  570.         if(!(plist->list=malloc(plist->newnitem * plist->sizeitem)))
  571.         {
  572.             fputs("Can't allocate memory for table\n",stderr);
  573.             return(SERIOUS);
  574.         }
  575.     }
  576.     
  577.     plist->nitem += plist->newnitem;    /* actualize count of tableitems */
  578.  
  579.     return(NULL);
  580. }
  581.  
  582. static struct labelitem *insertlabel(struct listheader *plabel,char *name,int type,u_short value,BOOL valid)
  583. {
  584.     /*
  585.      *    Insert a new item in list.
  586.      *
  587.      *    RC:    Pointer to new list element, or
  588.      *        SERIOUS if expandlist() failed
  589.      */
  590.      
  591.     struct labelitem *pitem;
  592.  
  593.     if(debugf)  puts("insertlabel");
  594.  
  595.     if(plabel->actitem >= plabel->nitem)
  596.         if(expandlist(plabel))
  597.             return((struct labelitem*)SERIOUS);
  598.  
  599.     pitem = (struct labelitem *)plabel->list + plabel->actitem;    
  600.     strcpy(pitem->name,name);
  601.     pitem->type = type;
  602.     if(pitem->valid = valid)
  603.         pitem->value = value;
  604.     else
  605.         pitem->value = 0xFFFF;
  606.     (plabel->actitem)++;
  607.  
  608.     return(pitem);
  609. }
  610.  
  611. static int dolabel(struct listheader *plabel,struct objsize *pobjcode,char   *lname)
  612. {
  613.     /*
  614.      * Search for a label. 'pline' must point to supposed label without append ':'.
  615.      * Insert label name and it's objectcode position in list 'label'.
  616.      *
  617.      *    An error can occure in some of the follwing conditions:
  618.      *      if -    the name is too long (MAXLABEL),
  619.      *            declared twice, 
  620.      *            declared before any objectcode adress is set
  621.      *
  622.      *     RC: NULL if all went fine, else
  623.      *        ERROR if any described error ocured, or
  624.      *        SERIOUS if insertlabel() failed
  625.      */
  626.  
  627.     if(debugf)  puts("dolabel");
  628.  
  629.     if(strlen(lname)>MAXLABEL)
  630.     {
  631.         showerror(lname,LABEL_TOO_LONG,MAXLABEL);
  632.         return(ERROR);    
  633.     }
  634.  
  635.     if(getlabel(plabel,lname))
  636.     {
  637.         showerror(lname,LABEL_DECL_TWICE);
  638.         return(ERROR);    
  639.     }
  640.  
  641.     if(pobjcode->firstbyte == ERROR)        
  642.     {
  643.         showerror(lname,NO_ORG);
  644.         return(ERROR);    
  645.     }
  646.         /* insert label item in list */
  647.     if((int)insertlabel(plabel,lname,L_POSITION,(u_short)pobjcode->actbyte,TRUE) == SERIOUS)
  648.         return(SERIOUS);
  649.     else
  650.         return(NULL);
  651. }
  652.  
  653. static int finddirective(char *pos)
  654. {
  655.     /*
  656.      * compare 'pos' with all directives 
  657.      *
  658.      * RC: indize of directive, or
  659.      *     ERROR if not found
  660.      */
  661.  
  662.     int i;
  663.  
  664.     if(debugf)  puts("finddirective");
  665.  
  666.     i= -1;
  667.     while(directives[++i])        /* determine directive type */
  668.     {
  669.         if(!strcmp_lany_rupper(pos,directives[i]))
  670.             return(i);
  671.     }
  672.     return(ERROR);
  673. }
  674.  
  675. static struct command *findmne(struct command *pcmd,char *pmne)
  676. {
  677.     /*
  678.      *    Compare 'pmne' with Mnemomics. Starts at 'pcmd'.
  679.      *
  680.      *    RC: Pointer to command structure or
  681.      *        NULL if nothing found.
  682.      */
  683.      
  684.     if(debugf)  puts("findmne");
  685.  
  686.     while(pcmd->name && strcmp_lany_rupper(pmne,pcmd->name) )    /* search token in 'command' array */
  687.         pcmd++;
  688.  
  689.     if(!pcmd->name)    
  690.         return(NULL);        /* sorry nothing found */
  691.     else
  692.         return(pcmd);
  693. }
  694.  
  695. int strtoint(struct listheader *plabel,char *pstr,u_short *pu_short,int mode)
  696. {
  697.     /*
  698.      *    Convert 'pos' to a u_short. 'pos' could be a value , with one of the 
  699.      *  following Syntax:
  700.      *        - binary      : % at the beginning or b/B at the end 
  701.      *        - octal       : o/O at the end
  702.      *        - decimal     : without any special character or d/D at the end
  703.      *        - hexadecimal : x/X/0x/0X/# at the beginning or h/H at the end 
  704.      *      - $           : Address Counter
  705.      *  Or 'pos' could be a symbol name (constant definition) - so substitute them.
  706.      *
  707.      *  RC : NULL if the substitution were successfully
  708.      *       ERROR else
  709.      */ 
  710.      
  711.     char *tail,work[BUFSIZ],*pos;
  712.     int len,base=0,tmp=0,extension=FALSE;
  713.     struct labelitem *pitem;
  714.  
  715.     if(debugf)  puts("strtoint");
  716.  
  717.     strcpy(work,pstr);
  718.     pos = work;
  719.  
  720.     if(!(len=strlen(pos)))    /* a zerolength word is wrong Parameter */
  721.         return(ERROR);
  722.  
  723.     if( strpbrk(pos,"+-*/()"))    /* mathematical expression ? */
  724.     {
  725.         tmp = calcexpr(plabel,pos,pu_short);
  726.  
  727.         if(mode==PARSE2)
  728.             return(tmp);
  729.         else
  730.             return(NULL);
  731.     }
  732.  
  733.         /* Is there an ASCII char ? */
  734.     if(validquote(*pos))
  735.     {
  736.         if(pos[0]==pos[2])    /* must be quoted like '?' , "?" or /?/ */
  737.         {
  738.             *pu_short=(u_short)pos[1];
  739.             return(NULL);
  740.         }
  741.     }
  742.  
  743.     if(pitem=getlabel(plabel,pos))    /* is the word a label ? */
  744.     {
  745.         if(mode == PARSE2)
  746.         {
  747.             if(!(pitem->valid))
  748.                 return(ERROR);    /* Label exist, but is invalid */
  749.         }
  750.         *pu_short = pitem->value;
  751.         return(NULL);
  752.     }
  753.     
  754.     if(len==1)                /* length =1 -> must be a decimal value */
  755.     {
  756.         if(!isdigit(*pos))    /* value ? */
  757.             return(ERROR);    /*  NO, so no number (perhaps a Register)*/
  758.     }
  759.  
  760.     switch(pos[len-1])                /* are there any known extensions ? */
  761.     {
  762.         case 'b':       /* A 'b' at the end could also be be a HEX 'b': check this */
  763.         case 'B': if( toupper(pos[0])=='X' || ( (pos[0]=='0') && (toupper(pos[1])=='X')) ) 
  764.                   {
  765.                     base = 16;  
  766.                     tmp = 2;
  767.                   }
  768.                   else  
  769.                   {
  770.                       extension=TRUE;
  771.                     base = 2;
  772.                   }
  773.                   break;    
  774.         case 'o':
  775.         case 'O': base = 8;
  776.                   extension=TRUE;
  777.                   break;    
  778.         case 'h':
  779.         case 'H': base = 16;
  780.                   extension=TRUE;
  781.                   break;    
  782.     }
  783.  
  784.     
  785. #ifdef DEBUG_STRTOINT
  786.     if(base)
  787.         fprintf(stderr,"strtoint(): base=%d\n",base);
  788. #endif
  789.  
  790.     if(!base)                            
  791.     {                                /* no extensions found, so look at the beginning */
  792.         switch(pos[0])
  793.         {
  794.             case '#' :    
  795.             case 'x' : 
  796.             case 'X' :     base = 16;
  797.                            tmp = 1;    
  798.                            break;
  799.             case '0' :     if( pos[1] == 'x' || pos[1] == 'X')
  800.                            {
  801.                                base = 16;
  802.                                tmp = 2;
  803.                            }
  804.                            break;
  805.             case '%' :    base = 2;
  806.                         tmp = 1;
  807.                         break;
  808.             default     :     if(toupper(pos[len-1])=='B')
  809.                             base = 2;
  810.                         break;    
  811.         }
  812.     }
  813.     
  814.     if(extension)
  815.         pos[--len]='\0';            /* cut the extension */
  816.  
  817.     if(!base) 
  818.         base = default_num_base; /* no base specified -> take default */
  819.  
  820. #ifdef DEBUG_STRTOINT
  821.     fprintf(stderr,"strtoint(): base=%d, number=%s\n",base,&pos[tmp]);
  822. #endif
  823.  
  824.     if(!(*pu_short=(u_short)strtol(&pos[tmp],&tail,base)))    /* convert */
  825.     {
  826.         while(tmp<len)                /* NULL -> there could be a failure */
  827.         {
  828.             if(pos[tmp++]!='0')        /* if one char is not 0, that's a failure */
  829.                 return(ERROR);    
  830.         }
  831.     }
  832.     return(NULL);                    /* all went fine */
  833. }
  834.  
  835. static u_long argtype(struct listheader *plabel,char *pos,u_short *pu_short,int mode)
  836. {
  837.     /*
  838.      *    Check type of 'pos' and fill 'pu_short' with data.
  839.      *
  840.      *a)pos= numeric value => set pu_short to value
  841.      *  pos= constant definition => set pu_short to value of constant
  842.      *  pos= numeric expression  => set pu_short to result of expression
  843.      *
  844.      *b)pos is enclosed in brackets: => pos is 'IND'
  845.      *  pos is a 16-Bit Register
  846.      *  all other like a)
  847.      *
  848.      *c)pos (with or without 'IND') is IX,IY with '+' Offset, set OFF.
  849.      *  calculate Offset like an expression in a)
  850.      *
  851.      *    RC: Parameter type of 'pos', or
  852.      *        NULL if not found.
  853.      */
  854.     
  855.     u_long flag = 0L;
  856.     int  len;
  857.     char *poff,work[BUFSIZ],*pwork;
  858.  
  859.     if(debugf)  puts("argtype");
  860.  
  861.     strcpy(work,pos);
  862.     pwork=work;
  863.     
  864.     cutend(pwork);                            /* remove trailing spaces */
  865.     if(work[0] == '(')                            /* could it be indirekt ? */
  866.     {
  867.         len=strlen(work);
  868.         if( work[len-1] != ')'  )    /* look for closing bracket */
  869.         {
  870.             showerror(pos+len-1,NO_CLOSE_BRACKET);
  871.             return(NULL);    
  872.         }
  873.  
  874.         work[len-1] = '\0';            /* delete end bracket from String */
  875.         cutend(pos);                /* remove trailing spaces */
  876.  
  877.         if(!(pwork=skipspace(&pwork[1])))/* skip start bracket and leading spaces */
  878.         {
  879.             showerror(pos,NO_EXPR_INSIDE);
  880.             return(NULL);
  881.         }
  882.         flag |= IND;                        /* remark INDIREKT        */
  883. #ifdef DEBUG2
  884.     fprintf(stderr,"Argument:'%s' is Indirekt, work continued with:'%s'\n",pos,pwork); 
  885. #endif
  886.     }
  887.  
  888.     if(poff=strchr(pwork,'+'))                /* look for an offset */
  889.     {
  890.         *poff='\0';
  891.         cutend(pwork);
  892.         if(!strcmp_lany_rupper(pwork,"IX"))
  893.            flag|=REG_IX|OFF;
  894.         else if(!strcmp_lany_rupper(pwork,"IY"))
  895.            flag|=REG_IY|OFF;
  896.         else
  897.         {    /* No Offset expression, so restore all */
  898.             strcpy(work,pos);
  899.             if(flag&IND)
  900.             {
  901.                 pwork=skipspace(&work[1]);
  902.                 work[strlen(work)-1]='\0';
  903.                 cutend(pwork);
  904.             }
  905.             else
  906.                 pwork = work;
  907.         }
  908.         if(flag&OFF)
  909.             if(!(pwork=skipspace(poff+1)))
  910.             {
  911.                 showerror(pos,NO_EXPR_FOLLOWED);
  912.                 return(NULL);
  913.             }
  914.     }
  915.  
  916.         /* Check if it's an integer (or Label - substitute them) */
  917.     if(!strtoint(plabel,pwork,pu_short,mode))    /* Integer, so check the size */
  918.     {
  919.         if(debugv) fprintf(stderr,"partype: ARG:%s VALUE:%d\n",pwork,*pu_short);
  920.  
  921.         flag|=NBR|UNM16|UNM8|UNM3|RST;            /* set No Branch */
  922.         if(*pu_short > 255) 
  923.             flag &= ~(UNM8|UNM3|RST); 
  924.         else if(*pu_short > 7  ) 
  925.             flag &= ~UNM3; 
  926.         else
  927.         {
  928.             switch(*pu_short)        /* needed for Mnemomic 'IM 0/1/2' */
  929.             {
  930.                 case 0: flag|=IMODE0; break;
  931.                 case 1: flag|=IMODE1; break;
  932.                 case 2: flag|=IMODE2; break;
  933.             }
  934.         }
  935.             /* check if is Offset < 256 */
  936.         if( (flag&OFF) && (*pu_short>255))
  937.         {
  938.             showerror(pos,OFFSET_OUT_OF_RANGE);
  939.             return(NULL);
  940.         }
  941.     }
  942.  
  943.     if(!(flag&~IND)) /* Until yet nothing found -> check if it is a Register/Branch */
  944.     {
  945.         *pwork = toupper(*pwork);
  946.         len  = strlen(pwork);
  947.  
  948.         switch(len)
  949.         {
  950.         case 1:
  951.             switch(*pwork)
  952.             {
  953.                 case 'A': flag |= REG_A|NBR; break;
  954.                 case 'B': flag |= REG_B|NBR; break;
  955.                 case 'C': flag |= REG_C|NBR|BRA; break;
  956.                 case 'D': flag |= REG_D|NBR; break;
  957.                 case 'E': flag |= REG_E|NBR; break;
  958.                 case 'F': flag |= REG_F|NBR; break;
  959.                 case 'H': flag |= REG_H|NBR; break;
  960.                 case 'I': flag |= REG_I|NBR; break;
  961.                 case 'L': flag |= REG_L|NBR; break;
  962.                 case 'M': flag |= BRA_M|BRA; break;
  963.                 case 'P': flag |= BRA_P|BRA; break;
  964.                 case 'R': flag |= REG_R|NBR; break;
  965.                 case 'Z': flag |= BRA_Z|BRA; break;
  966.                 default:     showerror(pos,UNKNOWN_OPTION);
  967.                             return(NULL);    
  968.             }
  969.             break;
  970.  
  971.         case 2:
  972.             pwork[1] = toupper(pwork[1]);
  973.             switch(pwork[0])
  974.             {
  975.                 case 'A':    if( pwork[1]=='F' ) flag |= REG_AF|NBR; else flag=U_ERROR; break;
  976.                 case 'B':     if( pwork[1]=='C' ) flag |= REG_BC|NBR; else flag=U_ERROR; break;
  977.                 case 'D':     if( pwork[1]=='E' ) flag |= REG_DE|NBR; else flag=U_ERROR; break;
  978.                 case 'H':     if( pwork[1]=='L' ) flag |= REG_HL|NBR; else flag=U_ERROR; break;
  979.                 case 'I':     if( pwork[1]=='X' ) flag |= REG_IX|NBR; else 
  980.                             if( pwork[1]=='Y' ) flag |= REG_IY|NBR; else flag=U_ERROR; break;
  981.                 case 'N':     if( pwork[1]=='C' ) flag |= BRA_NC|BRA; else 
  982.                             if( pwork[1]=='Z' ) flag |= BRA_NZ|BRA; else flag=U_ERROR; break;
  983.                 case 'P':     if( pwork[1]=='O' ) flag |= BRA_PO|BRA; else 
  984.                             if( pwork[1]=='E' ) flag |= BRA_PE|BRA; else flag=U_ERROR; break;
  985.                 case 'S':     if( pwork[1]=='P' ) flag |= REG_SP|NBR; else flag=U_ERROR; break;
  986.                 default:     showerror(pos,SYNTAX_ERROR);
  987.                             return(NULL);    
  988.             }
  989.             break;
  990.         
  991.         default: if(mode==PARSE1)
  992.                     return(flag|UNM16|UNM8|UNM3|NBR);
  993.                  else
  994.                  {
  995.                     showerror(pos,UNKNOWN_ARG);
  996.                     return(NULL);
  997.                  }
  998.         }
  999.     }
  1000.     if(!flag)        
  1001.         flag=NOPAR;    /* no flag -> NOPAR */
  1002.  
  1003.     return(flag);
  1004. }
  1005.  
  1006. static int doobjadr(struct objsize *pobj,int n,int mode)
  1007. {
  1008.     /*
  1009.      *    Set virtual objectbuffer position.
  1010.      *
  1011.      *    RC: NULL if all went fine, else
  1012.      *        ERROR if 'n' < 0 or 
  1013.      *              'mode' == OBJADREL && pobj->firstbyte == ERROR
  1014.      */
  1015.  
  1016.     if(debugf)  puts("doobjadr");
  1017.  
  1018.     if(n < 0)
  1019.     {
  1020.         fprintf(stderr,"Internal ERROR.  LINE=%d\nObject Adress %d corrupt (mode=%s)",__LINE__,n,(mode==OBJADABS) ? "OBJADABS" : "OBJADREL");
  1021.         return(ERROR);
  1022.     }
  1023.  
  1024.     switch(mode)
  1025.     {
  1026.         case OBJADABS:    if(pobj->firstbyte == ERROR)
  1027.                         {
  1028.                             pobj->firstbyte = n;
  1029.                             pobj->actbyte   = n;
  1030.                             pobj->lastbyte  = n;
  1031.                             break;
  1032.                         }
  1033.                         else if (pobj->firstbyte >= n)
  1034.                         {
  1035.                             pobj->firstbyte = n;
  1036.                             pobj->actbyte   = n;
  1037.                             break;
  1038.                         }
  1039.                         else if (pobj->firstbyte < n)
  1040.                         {
  1041.                             pobj->actbyte   = n;
  1042.                             if (pobj->lastbyte < n)
  1043.                                 pobj->lastbyte   = n;
  1044.                             break;
  1045.                         }
  1046.                         else 
  1047.                             INTERNAL_ERROR
  1048.                         break;
  1049.         case OBJADREL:    if(pobj->firstbyte == ERROR)
  1050.                         {
  1051.                             showerror(work,NO_ORG);
  1052.                             return(ERROR);
  1053.                         }
  1054.                         pobj->actbyte += n;
  1055.                         if(pobj->actbyte > pobj->lastbyte)
  1056.                             pobj->lastbyte = pobj->actbyte;
  1057.                         break;
  1058.         default:        INTERNAL_ERROR
  1059.                         return(ERROR);
  1060.     }
  1061.     return(NULL);
  1062. }
  1063.  
  1064. static u_char codebits(u_long mask)
  1065. {
  1066.     u_char code=0;
  1067.  
  1068.     if(debugf)  puts("codebits");
  1069.  
  1070.     if(mask&BRA)
  1071.     {
  1072.         switch(mask&BRANCH8)
  1073.         {
  1074.             case BRA_NZ    : code = 0; break;
  1075.             case BRA_Z    : code = 1; break;
  1076.             case BRA_NC    : code = 2; break;
  1077.             case BRA_C    : code = 3; break;
  1078.             case BRA_PO    : code = 4; break;
  1079.             case BRA_PE    : code = 5; break;
  1080.             case BRA_P    : code = 6; break;
  1081.             case BRA_M     : code = 7; break;
  1082.             default        : INTERNAL_ERROR
  1083.         }
  1084.     }
  1085.     else if(mask&NBR)
  1086.     {
  1087.         switch(mask®)
  1088.         {
  1089.             case REG_A    : code = 7; break;
  1090.             case REG_B    : code = 0; break;
  1091.             case REG_C    : code = 1; break;
  1092.             case REG_D    : code = 2; break;
  1093.             case REG_E    : code = 3; break;
  1094.             case REG_H    : code = 4; break;
  1095.             case REG_L    : code = 5;    break;
  1096.  
  1097.             case REG_BC    : code = 0; break;
  1098.             case REG_DE    : code = 1; break;
  1099.             case REG_HL    : code = 2; break;
  1100.             case REG_SP    : code = 3; break;
  1101.  
  1102.             case REG_F    :
  1103.             case REG_I    :
  1104.             case REG_R    :
  1105.             case REG_AF    :
  1106.             case REG_IX    :
  1107.             case REG_IY    : code = 0; 
  1108.                           INTERNAL_ERROR    
  1109.                           break;
  1110.             default        : code = 0;
  1111.                           INTERNAL_ERROR
  1112.         }
  1113.     }
  1114.     else 
  1115.         INTERNAL_ERROR      
  1116.  
  1117.     return(code);
  1118. }
  1119.  
  1120. static int writemnedata(struct objsize *pobj,u_long maskarg,u_short val,u_long maskcmd,u_char pos)
  1121. {
  1122.     /*
  1123.      *    Write coded Data to Objectbuffer.
  1124.      *
  1125.      *    -Calculate adress of byte of objectbuffer.
  1126.      *    -If 'maskcmd' is UNM16, write a Word in Lo/Hi order .
  1127.      *    -If 'maskcmd' is UNM8, write a Byte. 
  1128.      *    -If 'maskcmd' is bit coded , determine bit position and write.
  1129.      *
  1130.      *    RC:    NULL if all went fine , else
  1131.      *        ERROR
  1132.      */
  1133.      
  1134.     u_char *tmpobj,code=0;
  1135.     int off;
  1136.  
  1137.     if(debugf)  puts("writemnedata");
  1138.  
  1139. #    ifdef DEBUG2
  1140.         fprintf(stderr,"--- pos:%X\n",pos);
  1141. #    endif
  1142.  
  1143.     if(NOE & pos)
  1144.         return(NULL);
  1145.  
  1146.     tmpobj = ACT_OBJ_ADDR(pobj) + BYTE(pos);
  1147.  
  1148.     if(maskarg&maskcmd&UNM16)
  1149.     {
  1150.         if(maskcmd&JMPREL)            /* UNM16 only set to generate jmp offset */
  1151.         {
  1152.             off=val - pobj->actbyte-2;    /* Destination - Source */
  1153.             if( off>129 || off<-126)    /* jmp not to big ? */
  1154.             {
  1155.                 showerror(NULL,JUMP_NOT_RANGE);
  1156.                 return(ERROR);
  1157.             }
  1158.             *tmpobj=(char)off; 
  1159.             return(NULL);
  1160.         }
  1161.         else
  1162.         {
  1163.             *tmpobj++ = LOBYTE(val);    /* write LO Byte */
  1164.             *tmpobj   = HIBYTE(val);    /* write HI Byte */
  1165.             return(NULL);
  1166.         }
  1167.     } 
  1168.     if(maskcmd & RST)
  1169.     {
  1170.         code= val & 0x38;    /* extract RST bits */        
  1171.         if(code^(u_char)val)
  1172.         {
  1173.             showerror(NULL,ILLEGAL_RST);
  1174.             return(ERROR);
  1175.         }
  1176.         *tmpobj |= (code>>3)<<BIT(pos);
  1177.         return(NULL);
  1178.     } 
  1179.     
  1180.     if( (maskarg&maskcmd)&(UNM8|OFF) )
  1181.     {
  1182.         *tmpobj=(u_char)val;    /* write Byte */
  1183.         return(NULL);
  1184.     }
  1185.     if( maskcmd&maskarg&UNM3)
  1186.         code = (u_char)val;
  1187.     else
  1188.         code = codebits(maskarg);
  1189.  
  1190.     *tmpobj |= code<<BIT(pos);
  1191.  
  1192.     return(NULL);
  1193. }
  1194.  
  1195. static int fillihbuffer(int addr,int nbytes,u_char *pbuf)
  1196. {
  1197.     /*
  1198.      * Make a complete row in INTELHEX format.
  1199.      * Code: ':nnaaaadddd...dddcc\n
  1200.      * Where: nn        - number of data bytes
  1201.      *        aaaa        - address
  1202.      *        dd..dd    - data bytes
  1203.      *        cc        - checksum = 0x100 - (aa + aa + nn + dd + .. + dd)
  1204.      * Everything is in ASCII, 'intelhexbuffer' is dynamically allocated.
  1205.      *
  1206.      * RC: NULL if all went fine,
  1207.      *       ERROR else.
  1208.      */
  1209.  
  1210. #define NCTRLBYTES    12 /* :nnaaaasspp\n = 12 */
  1211.  
  1212.     int datasum;
  1213.     char *pos;
  1214.  
  1215.     if(debugf)  puts("fillihbuffer");
  1216.  
  1217.     if(!nbytes)
  1218.     {
  1219.         fprintf(stderr,"Internal ERROR: nbytes=0  LINE=%d\n",__LINE__);
  1220.         return(ERROR);
  1221.     }
  1222.     
  1223.         /* take care to have enough space */
  1224.     if(ih_head.actitem+nbytes*2+NCTRLBYTES >= ih_head.nitem)
  1225.     {
  1226.         if(expandlist(&ih_head))
  1227.             return(SERIOUS);    /* should never be happen */
  1228.     }
  1229.         /* next free Position */
  1230.     pos=(char *)(((char *)ih_head.list)+ih_head.actitem);
  1231.  
  1232.     *pos++=':';                                 /* Set Start Marker */
  1233.     pos = ibtoh((unsigned char)nbytes,pos);                     /* Write data counter */
  1234.     pos = ibtoh((unsigned char)(addr>>8),pos);      /* Write High Byte Address */
  1235.     pos = ibtoh((unsigned char)(0xFF&addr),pos); /* Write Low Byte Address */
  1236.     pos = ibtoh((u_char)0,pos);                     /* Write status */
  1237.  
  1238.     datasum=(0xFF&(addr>>8))+(0xFF&addr)+nbytes; /* part of chksum */
  1239.  
  1240.     while(nbytes--)
  1241.     {
  1242.         datasum+=(int)*pbuf;
  1243.         pos = ibtoh(*pbuf++,pos);            /* Write databyte */
  1244.     }
  1245.  
  1246.     datasum=0x100-(0xFF&datasum);            /* finish chksum */
  1247.     pos = ibtoh((u_char)datasum,pos);        /* Write chksum */
  1248.     *pos++ = '\n';                            /* Close String */
  1249.     *pos = '\0';                            /* Close String */
  1250.  
  1251.     ih_head.actitem=(int)pos-(int)ih_head.list;
  1252.  
  1253.     return(NULL);
  1254. }
  1255.  
  1256. static int dointelhex(int addr,int size,u_char *data)
  1257. {
  1258.     /*
  1259.      *    Collect Data to generate INTELHEX Format.
  1260.      *  Collect a row (Maximum Databytes = MAXBYTESIH).
  1261.      *    If the row is full or is there a skip in addressing
  1262.      *   call 'fillihbuffer()' to flush buffer.
  1263.      *
  1264.      *    RC:    NULL if all went fine,
  1265.      *        ERROR else.
  1266.      */
  1267.      
  1268.     static int rowaddr=ERROR,rownbytes=0;
  1269.     static u_char rowdata[MAXBYTESIH];
  1270.  
  1271.     u_char *prowdata;
  1272.  
  1273.     if(debugf)  puts("dointelhex");
  1274.  
  1275.         /* Flush Buffer, write ENDLINE */
  1276.     if(addr==ERROR)
  1277.     {
  1278.         if(rownbytes)
  1279.             fillihbuffer(rowaddr,rownbytes,rowdata);
  1280.             
  1281.             /* take care to have enough space */
  1282.         if(ih_head.actitem+13 >= ih_head.nitem)
  1283.         {
  1284.             if(expandlist(&ih_head))
  1285.                 return(SERIOUS);    /* should never be happen */
  1286.         }
  1287.         strcpy((char *)ih_head.list+ih_head.actitem,":00000001FF\n");
  1288.         ih_head.actitem+=12;
  1289.         rowaddr=ERROR;
  1290.         rownbytes=0;
  1291.         return(NULL);
  1292.     }
  1293.     
  1294.         /* If 'addr' not continous, start a new row */
  1295.     if(addr!=(rowaddr+rownbytes))
  1296.     {
  1297.         if((rowaddr!=ERROR) && (rownbytes))
  1298.             fillihbuffer(rowaddr,rownbytes,rowdata);
  1299.         rowaddr=addr;
  1300.         rownbytes=0;
  1301.     }
  1302.  
  1303.     while(size)
  1304.     {
  1305.         prowdata= &rowdata[rownbytes];
  1306.         
  1307.             /* fill data in 'rowdata' */
  1308.         while(    (rownbytes<MAXBYTESIH) && size)
  1309.         {
  1310.             size--;
  1311.             rownbytes++;
  1312.             *prowdata++= *data++;
  1313.         }
  1314.  
  1315.             /* row full ? */
  1316.         if(rownbytes>=MAXBYTESIH)
  1317.         {
  1318.                 /* finish row, open new */
  1319.             fillihbuffer(rowaddr,rownbytes,rowdata);
  1320.             rowaddr+=rownbytes;
  1321.             rownbytes=0;
  1322.         }
  1323.     }
  1324.     return(NULL);
  1325. }
  1326.  
  1327. static int makecode(struct objsize *pobj,struct command *pcmd,int mode,u_long type1,u_short val1,u_long type2,u_short val2)
  1328. {
  1329.     /*
  1330.      *    If mode==PARSE1 then
  1331.      *        calculate object size and increase 'pobj'
  1332.      *    If mode==PARSE2
  1333.      *        Generates Object Code and write it to objbuffer
  1334.      *     
  1335.      *    RC:    NULL if all went fine, else
  1336.      *        ERROR 
  1337.      */
  1338.      
  1339.     int size,i;
  1340.     u_char dummy;
  1341.  
  1342.     if(debugf)  puts("makecode");
  1343.  
  1344.     size = MNELEN(pcmd->order1);                /* How much Bytes to write */
  1345.  
  1346.     if(mode==PARSE1)
  1347.     {
  1348.         return(doobjadr(pobj,size,OBJADREL));    /* Only increase Objectbuffer */
  1349.     }
  1350.     else if(mode==PARSE2)
  1351.     {
  1352.         for(i=0;i<size;i++)                        
  1353.         {
  1354.             if(dummy= *(ACT_OBJ_ADDR(pobj)+i) )
  1355.             {
  1356.                 showerror(NULL,DATA_OVERWRITE);
  1357.                 return(ERROR);
  1358.             }
  1359.             *(ACT_OBJ_ADDR(pobj)+i)=pcmd->obj[i];    /* copy Object Code */
  1360.         }
  1361.  
  1362. #        ifdef DEBUG2
  1363.             fprintf(stderr,"pcmd[%d]\n",(int)((char *)pcmd-(char *)cmd)/sizeof(struct command));
  1364.             fprintf(stderr,"---pcmd->order1:%X\n",pcmd->order1);
  1365. #        endif
  1366.  
  1367.         writemnedata(pobj,type1,val1,pcmd->pa1,pcmd->order1);    /* set Register/Branch Bits (Argu.1)*/
  1368.  
  1369. #       ifdef DEBUG2
  1370.             fprintf(stderr,"---pcmd->order2:%X\n",pcmd->order2);
  1371. #       endif
  1372.  
  1373.         writemnedata(pobj,type2,val2,pcmd->pa2,pcmd->order2);    /* set Register/Branch Bits (Argu.2)*/
  1374.  
  1375.         if(doobjadr(pobj,size,OBJADREL))            /* increase Objectbuffer */
  1376.             return(ERROR);
  1377.     }
  1378.     else
  1379.         INTERNAL_ERROR;
  1380.  
  1381.     return(NULL);
  1382. }
  1383.  
  1384. static int domne(struct listheader *plabel,struct objsize *pobj,char *ptok,int mode,u_short *pcycle)
  1385. {
  1386.     /*     
  1387.      *    Search for mnemomic 'ptok'.
  1388.      *    First compare mnemomic name 
  1389.      *    Check arguments (if they are allowed) 
  1390.      *    if mode==PARSE1
  1391.      *        increase 'pobj' about the size of mnemomic
  1392.      *    else if mode==PARSE2
  1393.      *        fill objbuffer with generated code
  1394.      *
  1395.      *    RC: NULL if a mnemomic was found, regardless if the parsing for successfully
  1396.      *      ERROR if no mnemomic was found
  1397.      */
  1398.  
  1399.     struct command *pcmd;    /* Pointer to actual MNE in 'caz' MNE-Array */
  1400.     char     *ptok2,            /* second Argument */
  1401.             *pend,            /* points behind last Argument (for missing arguments)*/
  1402.             *pmne;            /* points to Sourcetext MNE */
  1403.     u_long    type1,tmp1,        /* classes of 1. parsed argument */
  1404.             type2,tmp2,        /* classes of 2. parsed argument */
  1405.             f1,f2,f3,f4;    /* just for debugv */
  1406.     u_short    val1,val2;        /* if 1./2. argument is a value */
  1407.     
  1408.             /* Just to report more detailed Error Messages */
  1409.     int        arg1_ex,arg2_ex,    /* Flag if MNE need Argument1,Argumnt2 */
  1410.             arg1_nex,arg2_nex,    /* Flag if MNE don't need Argument1,Argument2 */
  1411.             arg1_ok,arg2_ok;    /* Flag if MNE Arguments and Sourcetext Arguments match */
  1412.     
  1413.     arg1_ex=arg2_ex=arg1_nex=arg2_nex=arg1_ok=arg2_ok=FALSE;
  1414.  
  1415.     if(debugf)  puts("domne");
  1416.  
  1417. #    ifdef DEBUG2
  1418.         u_long fuck1,fuck2;
  1419. #    endif
  1420.  
  1421.     pmne = ptok;                /* Mnemomic Name */
  1422.     type1 = type2 = NOPAR;
  1423.  
  1424.         /* check all appropriate prozessor mnemomics */
  1425.     if(pcmd=findmne(cmd,pmne))
  1426.     {
  1427.             /* get Arguments (type) and their value (if they have one) */
  1428.         if(ptok=strtok(NULL,","))
  1429.         {
  1430.             ptok=skipspace(ptok);
  1431.             if(ptok2=strtok(NULL,"\n"))
  1432.             {
  1433.                 ptok2=skipspace(ptok2);
  1434.                 type2=argtype(plabel,ptok2,&val2,mode);
  1435.                 pend = ptok2+strlen(ptok2);
  1436.             }            
  1437.             else
  1438.                 pend = ptok+strlen(ptok);
  1439.             
  1440.             type1=argtype(plabel,ptok,&val1,mode);
  1441.         }
  1442.         else
  1443.             pend = pmne+strlen(pmne);
  1444.  
  1445.         tmp1 = type1; /* saved to restore */
  1446.         tmp2 = type2; /* saved to restore */
  1447.         do {
  1448.                 /* Just to report more detailed Error Messages */ 
  1449.             if(pcmd->pa1&NOPAR)
  1450.                 arg1_nex=TRUE;
  1451.             else if(pcmd->pa1&~NOPAR)
  1452.                 arg1_ex=TRUE;
  1453.  
  1454.             if(pcmd->pa2&NOPAR)
  1455.                 arg2_nex=TRUE;
  1456.             else if(pcmd->pa2&~NOPAR)
  1457.                 arg2_ex=TRUE;
  1458.  
  1459.                 /* first delete all flags which not needed */
  1460.             type2&=~IMODE2;
  1461.             
  1462.             if(!(pcmd->pa1&IMODE2))
  1463.                 type1&=~IMODE2;
  1464.                 
  1465.             if(!(pcmd->pa1&BRA))
  1466.             {
  1467.                 type1&=~BRA;
  1468.                 type2&=~BRA;
  1469.             }
  1470.             if(!(pcmd->pa1&NBR))
  1471.             {
  1472.                 type1&=~NBR;
  1473.                 type2&=~NBR;
  1474.             }
  1475.                 /* check if bitpattern match with 'pcmd' */
  1476.             if(debugv)
  1477.             {
  1478.                 decodearg("Type1",type1);
  1479.                 decodearg("Cmd1",pcmd->pa1);
  1480.                 decodearg("Type2",type2);
  1481.                 decodearg("Cmd2",pcmd->pa2);
  1482.                 fputs("\n",stderr);
  1483.             }
  1484.  
  1485. /* There are two types of flags: */
  1486. /* a) flags which must be equal (masked with EXMASK) */
  1487. /* b) flags which could be equal */
  1488.  
  1489.             /* this flags determine the classes */
  1490.             /* f1,f2 are true if the classes matches */
  1491.             f1 = pcmd->pa1&type1&~EXMASK;
  1492.             f2 = pcmd->pa2&type2&~EXMASK;
  1493.  
  1494.             
  1495. #            ifdef DEBUG2
  1496.                 /* This flags must be equal */
  1497.                 fuck1 = pcmd->pa1&EXMASK;
  1498.                 fuck2 = type1&EXMASK;
  1499. #            endif
  1500.  
  1501.             /* if 'f3' is true, the flags differs */
  1502.             f3 = (pcmd->pa1&(EXMASK))^(type1&(EXMASK));
  1503.  
  1504. #           ifdef DEBUG2
  1505.                 /* This flags must be equal */
  1506.                 fuck1 = pcmd->pa2&EXMASK;
  1507.                 fuck2 = type2&EXMASK;
  1508. #           endif            
  1509.             
  1510.             /* if 'f4' is true, the flags differs */
  1511.             f4 = (pcmd->pa2&EXMASK&~(BRA|NBR))^(type2&EXMASK&~(BRA|NBR));
  1512.  
  1513.                 /* Just to report more detailed Error Messages */ 
  1514.             if(f1 &&(!f3))
  1515.                 arg1_ok = TRUE;
  1516.             if(f2 &&(!f4))
  1517.                 arg2_ok = TRUE;
  1518.  
  1519.             if( f1 && f2 && (!f3) && (!f4) )
  1520.             {
  1521. #            ifdef DEBUG2
  1522.                 fprintf(stderr,"--- found:%s,order1:%X\n",pcmd->name,pcmd->order1);
  1523. #            endif
  1524.  
  1525.                 if(!makecode(pobj,pcmd,mode,type1,val1,type2,val2))
  1526.                     *pcycle=pcmd->cycle;        /* copy Clock Cycle */
  1527.                  return(NULL);
  1528.             }
  1529.             type1 = tmp1;
  1530.             type2 = tmp2;
  1531.         } while(pcmd=findmne(++pcmd,pmne));
  1532.  
  1533.     /* This explains the User what's wrong */
  1534.  
  1535.         /* Easier handling if flag NOPAR is cleared */
  1536.         type1&=~NOPAR;
  1537.         type2&=~NOPAR;
  1538.  
  1539. /* All 'arg' - Flags: If True, the condition could be True, but don't have to be True */
  1540.         if(!arg1_ex && !arg2_ex)
  1541.         {  /* No Arguments allowed */
  1542.             if(type1 || type2)
  1543.                 showerror(ptok,TOO_MUCH_ARGUMENT);
  1544.         }
  1545.         else if(arg1_ex && !arg1_nex && !arg2_ex)
  1546.         {  /* exact 1 argument */
  1547.             if(!type1) 
  1548.                 showerror(pend,NEED_ARGUMENT);
  1549.             else if(type2)
  1550.                 showerror(ptok2,TOO_MUCH_ARGUMENT);
  1551.             else
  1552.                 showerror(ptok,WRONG_ARGUMENT);
  1553.         }
  1554.         else if(arg1_ex && !arg1_nex && arg2_ex && !arg2_nex )
  1555.         {  /* exact 2 arguments */
  1556.             if(!type1) 
  1557.                 showerror(pend,NEED_2ARGUMENT);
  1558.             else if(!type2) 
  1559.                 showerror(pend,NEED_A2ARGUMENT);
  1560.             else if(arg1_ok && arg2_ok)
  1561.                 showerror(ptok,W_ARG_COMBINATION);
  1562.             else if(!arg2_ok)
  1563.                 showerror(ptok2,WRONG_ARGUMENT);
  1564.             else if(!arg1_ok)
  1565.                 showerror(ptok,WRONG_ARGUMENT);
  1566.             else 
  1567.                 INTERNAL_ERROR         /* Do I forget a case ? */
  1568.         }
  1569.         else if(arg1_ex && !arg2_ex)
  1570.         {  /* minimal 0 arguments, maximal 1 argument */
  1571.             showerror(ptok,WRONG_ARGUMENT);
  1572.         }
  1573.         else if(!arg1_nex && arg1_ex && arg2_ex )
  1574.         {  /* minimal 1 Argument, maximal 2 arguments */
  1575.             if(!type1)
  1576.                 showerror(pend,NEED_ARGUMENT);
  1577.             else if(type2 && !arg2_ok)
  1578.                 showerror(ptok2,WRONG_ARGUMENT);
  1579.             else
  1580.                 showerror(ptok,WRONG_ARGUMENT);            
  1581.         }
  1582.         else if(arg1_ex && arg2_ex )
  1583.         {  /* minimal 0 arguments, maximal 2 arguments */
  1584.             if(arg1_ok && arg2_ok)
  1585.                 showerror(ptok,W_ARG_COMBINATION);
  1586.             else if(!arg2_ok)
  1587.                 showerror(ptok2,WRONG_ARGUMENT);
  1588.             else if(!arg1_ok)
  1589.                 showerror(ptok,WRONG_ARGUMENT);
  1590.             else
  1591.                 showerror(ptok,WRONG_ARGUMENT);            
  1592.         }
  1593.         else
  1594.             INTERNAL_ERROR         /* Do I forget a case ? */
  1595.         
  1596.         return(NULL);    /* If any MNE was found , rc=NULL */
  1597.     }
  1598.     return(ERROR);        /* If no MNE was found , rc=ERROR */ 
  1599. }
  1600.  
  1601. static int pushfile(struct item_file **pstack,char *p_filenamenew,FILE **p_fp)
  1602. {
  1603.     /* Push item on stack. Set 'pstack' to new top of stack .
  1604.      *
  1605.      * RC: NULL if all went fine,
  1606.      *     ERROR if malloc() failed() or new file can't be opened;
  1607.      */
  1608.      
  1609.     struct item_file *pnode;
  1610.     FILE *fptmp;
  1611.     
  1612.  
  1613.     if(!(fptmp=fopen(p_filenamenew,"r")))
  1614.     {    
  1615.         showerror(p_filenamenew,CANT_OPEN_FILE,p_filenamenew);
  1616.         return(ERROR);
  1617.     }
  1618.  
  1619.     if(!(pnode=(struct item_file *)malloc(sizeof(struct item_file))))
  1620.     {
  1621.         fprintf(stderr,NO_MEMORY);
  1622.         return(ERROR);
  1623.     }
  1624.  
  1625.     pnode->prev = *pstack;
  1626.     strcpy(pnode->filename,actfilename);  /* save old filename (to be push) */
  1627.     strcpy(actfilename,p_filenamenew);      /* set new filename */
  1628.     pnode->filepos = ftell(*p_fp);          /* save old fileposition */
  1629.     pnode->lnr     = lnr;                  /* save old linenumber */
  1630.     *pstack     = pnode;                  /* set new item on top of stack */
  1631.  
  1632.     lnr = 0;
  1633.  
  1634.     fclose(*p_fp);        /* close old (pushed) file */
  1635.     *p_fp=fptmp;        /* set stackpointer to new first item */
  1636.  
  1637.     return(NULL);
  1638. }
  1639.  
  1640. static int popfile(struct item_file **pstack,FILE **p_fp)
  1641. {
  1642.     /* Get topmost Element from stack. Set 'pstack' to new topmost element.
  1643.      *
  1644.      * RC: NULL if all went fine, else
  1645.      *     ERROR if 'pstack' is empty.
  1646.      */
  1647.      
  1648.     struct item_file *itemtmp;
  1649.     FILE *fptmp;    
  1650.  
  1651.         /* Empty Stack is not allowed */
  1652.     if(!*pstack)
  1653.         return(NULL);
  1654.  
  1655.         /* Open old (previous pushed) File */
  1656.     if(!(fptmp=fopen( (*pstack)->filename,"r"))) /* Open New file */
  1657.     {    
  1658.         showerror(NULL,CANT_OPEN_FILE,(*pstack)->filename);
  1659.         return(ERROR);
  1660.     }
  1661.         /* Set Filepointer to old position */
  1662.     if(NULL!=fseek(fptmp,(*pstack)->filepos,SEEK_SET))
  1663.     {    
  1664.         showerror(NULL,CANT_SEEK_FILE,(*pstack)->filepos,(*pstack)->filename);
  1665.         fclose(fptmp);
  1666.         return(ERROR);
  1667.     }
  1668.  
  1669.     fclose(*p_fp);    /* Close old File */
  1670.  
  1671.     *p_fp=fptmp;    /* Copy new FilePointer */
  1672.  
  1673.     strcpy(actfilename, (*pstack)->filename);    /* get old filename */
  1674.     lnr = (*pstack)->lnr;                        /* get old linenumber */
  1675.     
  1676.     itemtmp   =(*pstack)->prev;        /* get pointer to next item */
  1677.     free(*pstack);                    /* free topmost element */
  1678.     *pstack=itemtmp;                /* set to new topmost element */
  1679.  
  1680.     return(NULL);
  1681. }
  1682.  
  1683.  
  1684. static int setdefaultbase(char *pbase)
  1685. {
  1686.     /*
  1687.      * Determine default number base.
  1688.      * 
  1689.      * RC: NULL if all ok, else
  1690.      *     ERROR
  1691.      */
  1692.      
  1693.     switch(toupper(*pbase))
  1694.     {
  1695.         case 'H':     default_num_base = 16;
  1696.                     break;
  1697.         case 'D':     default_num_base = 10;
  1698.                     break;
  1699.         case 'O':     default_num_base = 8;
  1700.                     break;
  1701.         case 'B':     default_num_base = 2;
  1702.                     break;
  1703.         default:    showerror(pbase,UNKNOWN_BASE);
  1704.                     return(ERROR);
  1705.     }
  1706.     return(NULL);    
  1707. }
  1708.  
  1709.  
  1710. static int dodirective(struct listheader *plabel,struct objsize *pobj,char *ptok,int direc,int mode,int *orgflag)
  1711. {
  1712.     /*
  1713.      *    If mode==PARSE1
  1714.      *        increase 'pobj' about the needed space
  1715.      *    else if mode==PARSE2
  1716.      *        fill objbuffer
  1717.      *    '*orgflag' ist set to TRUE, if 'directive' is 'ORG'. This is done
  1718.      *  to determine in 'parseline()' if there is a skip in the object buffer.
  1719.      *  
  1720.      *    RC: NULL if all went fine, else
  1721.      *      ERROR 
  1722.      */
  1723.  
  1724.     u_short   adr,expr;
  1725.     char    *ntok;
  1726.     int        size=0,i,tmp,type;
  1727.     char    quote;
  1728.     u_char dummy;
  1729.     
  1730.     if(debugf)  puts("dodirective");
  1731.  
  1732.     *orgflag=FALSE;
  1733.     
  1734.     switch(direc)
  1735.     {
  1736.         case ORG :     ptok=strtok(NULL,"\n");    /* get Pointer to Adress */
  1737.                     ptok=skipspace(ptok);
  1738.                     if(strtoint(plabel,ptok,&adr,mode))    /* substitude Adress */
  1739.                     {
  1740.                         showerror(ptok,SYNTAX_ERROR);
  1741.                         return(ERROR);
  1742.                     }
  1743.                     if(doobjadr(pobj,(int)adr,OBJADABS))    /* set objectbuffer */
  1744.                         return(ERROR);
  1745.  
  1746.                         /* needed in parseline() to determine valid Object range */
  1747.                     *orgflag=TRUE;
  1748.  
  1749.                     if(mode==PARSE1)
  1750.                         return(NULL);
  1751.                     else if(mode==PARSE2)
  1752.                     {
  1753.                             /* check if Buffer is empty at new position */
  1754.                         if(dummy= *ACT_OBJ_ADDR(pobj))
  1755.                         {
  1756.                             if(pobj->actbyte == pobj->lastbyte) /* special case: org at buffer end and no code */
  1757.                                 return(NULL);
  1758.                         
  1759.                             showerror(ptok,DATA_OVERWRITE);
  1760.                             return(ERROR);
  1761.                         }
  1762.                         return(NULL);
  1763.                     }
  1764.                     break;
  1765.         case DEFS:    ptok=strtok(NULL,"\n");    /* get Pointer to Size */
  1766.                     ptok=skipspace(ptok);
  1767.                     if(strtoint(plabel,ptok,&adr,mode))    /* substitude Adress */
  1768.                     {
  1769.                         showerror(ptok,SYNTAX_ERROR);
  1770.                         return(ERROR);
  1771.                     }
  1772.                     size=adr;
  1773.                     if(mode==PARSE2)
  1774.                     {
  1775.                             /* check if Buffer is empty at new position */
  1776.                         for(i=0;i<size;i++)
  1777.                         {
  1778.                             if(dummy= *(ACT_OBJ_ADDR(pobj)+i))
  1779.                             {
  1780.                                 showerror(ptok,DATA_OVERWRITE);
  1781.                                 return(ERROR);
  1782.                             }
  1783.                         }
  1784.                         memset(ACT_OBJ_ADDR(pobj),FILL_CHAR,size);
  1785.                     }
  1786.                     return(doobjadr(pobj,size,OBJADREL));    /* increase objectbuffer */
  1787.                     break;
  1788.         case DEFW:    size=1;    /* Word == 2 Byte */
  1789.         case DEFB:    size++; /* Byte == 1 Byte */ 
  1790.                     i=0;
  1791.                     ntok=ptok+strlen(ptok);
  1792.                     while(ptok=strtok(NULL,","))    /* count more Bytes */
  1793.                     {
  1794.                         if(mode==PARSE2)
  1795.                         {
  1796.                             ptok=skipspace(ptok);
  1797.                             cutend(ptok); /* V1.24 hinzugefügt um mögliche Freiplätze nach einer 0-Zahl zuzulassen */
  1798.                             if(strtoint(plabel,ptok,&adr,mode))    /* substitude Adress */
  1799.                             {
  1800.                                 showerror(ptok,SYNTAX_ERROR);
  1801.                                 doobjadr(pobj,(i+1)*size,OBJADREL); /* successfull converted data still valid */
  1802.                                 return(ERROR);
  1803.                             }
  1804.                             if(dummy= *(ACT_OBJ_ADDR(pobj)+i))
  1805.                             {
  1806.                                 showerror(ptok,DATA_OVERWRITE);
  1807.                                 return(ERROR);
  1808.                             }
  1809.  
  1810.                             *(ACT_OBJ_ADDR(pobj)+i)=LOBYTE(adr);
  1811.  
  1812.                             if(size==2)
  1813.                             {
  1814.                                 if(dummy= *(ACT_OBJ_ADDR(pobj)+i+1))
  1815.                                 {
  1816.                                     showerror(ptok,DATA_OVERWRITE);
  1817.                                     return(ERROR);
  1818.                                 }
  1819.                                 *(ACT_OBJ_ADDR(pobj)+i+1)=HIBYTE(adr);
  1820.                             }
  1821.                         }
  1822.                         i+=size;
  1823.                     }
  1824.                     if(!i)
  1825.                     {
  1826.                         showerror(ntok,NEED_ARGUMENT);
  1827.                         return(ERROR);
  1828.                     }
  1829.                     return(doobjadr(pobj,i,OBJADREL));    /* increase objectbuffer */
  1830.                     break;
  1831.  
  1832.         case DEFM:    ptok=skipspace(ptok+strlen(ptok)+1); /* set ptok,ntok behind directive DEFM */
  1833.  
  1834.                     while(ptok)    /* step through a sequence of strings and values */
  1835.                     {
  1836.                         /* Check first char == QUOTE -> STRING */
  1837.                         if(quote=validquote(*ptok))    
  1838.                         {
  1839.                             /* determine endequote */
  1840.                             if(!(ntok=strchr(ptok+1,quote)))
  1841.                             {
  1842.                                 showerror(ptok,NO_END_QUOTE);
  1843.                                 return(ERROR);
  1844.                             }
  1845.  
  1846.                             /* add string length to sizecounter */
  1847.                             if(!(size=ntok-ptok-1)) 
  1848.                             {
  1849.                                 showerror(ptok,NO_EXPR_INSIDE);
  1850.                                 return(ERROR);
  1851.                             }
  1852.  
  1853.                             if(mode==PARSE2)
  1854.                             {
  1855.                                 for(tmp=0;tmp<size;tmp++)
  1856.                                 {
  1857.                                     if(dummy= *(ACT_OBJ_ADDR(pobj)+tmp))
  1858.                                     {
  1859.                                         showerror(ptok,DATA_OVERWRITE);
  1860.                                         return(ERROR);
  1861.                                     }
  1862.                                 }
  1863.                                 strncpy(ACT_OBJ_ADDR(pobj),ptok+1,size);
  1864.                             }
  1865.  
  1866.                             ptok=skipspace(ntok+1);    /* points to comma or NULL */
  1867.                             if(ptok)
  1868.                             {
  1869.                                 if(*ptok!=',') /* further arguments ? */
  1870.                                 {
  1871.                                     showerror(ptok,EXPECT_COMMA);
  1872.                                     return(ERROR);
  1873.                                 }
  1874.                                 if(!(ptok=skipspace(ptok+1)))    /* next argument */
  1875.                                 {
  1876.                                     showerror(ntok,NEED_ARGUMENT);
  1877.                                     return(ERROR);
  1878.                                 }
  1879.                             }
  1880.                         }
  1881.                         else
  1882.                         {          /* No String -> it must be a value */
  1883.                             size=1;
  1884.                             if(ntok=strchr(ptok,',')) /* cut folowing arguments */
  1885.                             {
  1886.                                 *ntok='\0'; /* cut string */
  1887.                                 cutend(ptok);
  1888.                                 
  1889.                                 if(!(ntok=skipspace(ntok+1))) /* next argument */
  1890.                                 {   /* ERROR: comma without an folowing argument */
  1891.                                     showerror(ptok,NEED_ARGUMENT);
  1892.                                     doobjadr(pobj,1,OBJADREL); /* successfull converted data still valid */
  1893.                                     return(ERROR);
  1894.                                 }
  1895.  
  1896.                             }
  1897.  
  1898.                             if(mode==PARSE2)
  1899.                             {
  1900.                                 if(strtoint(plabel,ptok,&adr,mode))    /* substitude Adress */
  1901.                                 {
  1902.                                     showerror(ptok,SYNTAX_ERROR);
  1903.                                     doobjadr(pobj,1,OBJADREL); /* successfull converted data still valid */
  1904.                                     return(ERROR);
  1905.                                 }    
  1906.                                 *(ACT_OBJ_ADDR(pobj))=LOBYTE(adr);
  1907.                             }
  1908.                             ptok=ntok;
  1909.                         }
  1910.                             /* Increment Object Buffer */
  1911.                         if(tmp=doobjadr(pobj,size,OBJADREL))
  1912.                             return(tmp);
  1913.                     }
  1914.  
  1915.                     return(NULL);
  1916.                     break;
  1917.         case INCLUDE:
  1918.                     ptok=strtok(NULL,"\n");    /* get Pointer to Filename */
  1919.                     ptok=skipspace(ptok);
  1920.                     return(pushfile(&file_stack,ptok,&fpin));
  1921.                     break;
  1922.         case END:    endflag=TRUE;
  1923.                     return(NULL);
  1924.                     break;
  1925.         case LIST:        /* Switch LIST (verbose) ON or OFF */
  1926.                     ptok=strtok(NULL,"\n");    /* get switch LIST_ON or LIST_OFF */
  1927.                     ptok=skipspace(ptok);
  1928.                             /* search directive ON or OFF */
  1929.                     if(!ptok || ((type=finddirective(ptok))==ERROR) || (type!=LIST_OFF && type!=LIST_ON) )
  1930.                     {                                    
  1931.                         showerror(ptok,EXP_LIST_ON_OFF);
  1932.                         return(ERROR);
  1933.                     }
  1934.                         /* check if 'verbose' already set via Commandline Option */
  1935.                     if( (verbose&MODE_OPTION) || clockcycle )
  1936.                         return(NULL); /* Commandline Options has a greater Priority */
  1937.  
  1938.                     if(type==LIST_ON)
  1939.                         verbose=MODE_ALL;
  1940.                     else if(type==LIST_OFF)
  1941.                         verbose=NULL;
  1942.                     else 
  1943.                         INTERNAL_ERROR
  1944.                     return(NULL);
  1945.                     break;
  1946.         case COND:    ptok=strtok(NULL,"\n");    /* get expression */
  1947.                     ptok=skipspace(ptok);
  1948.                     if(strtoint(plabel,ptok,&expr,PARSE2))
  1949.                     {
  1950.                         if(ntok = strpbrk(ptok,"+-*/"))
  1951.                         {
  1952.                             showerror(ptok,CANT_RESOLVE);
  1953.                             return(ERROR);
  1954.                         }
  1955.                         else
  1956.                             expr = FALSE;
  1957.                     }
  1958.                     
  1959.                     assembleflag=(BOOL)expr; /* <>0 -> TRUE, Assemble */
  1960.                     return(NULL);
  1961.                     break;
  1962.         case ENDC:    assembleflag=TRUE;
  1963.                     return(NULL);
  1964.                     break;
  1965.         case EJECT:    if(verbose || clockcycle)
  1966.                         fputs("\f",stdout);
  1967.                     return(NULL);
  1968.                     break;
  1969.         case DEFBASE: return(setdefaultbase(strtok(NULL,"\n")));
  1970.                     break;
  1971.         case MACLIST:
  1972.         case HEADING:
  1973.         case MACRO:
  1974.         case ENDM:    showerror(ptok,NOT_IMPLEMENTED);
  1975.                     return(ERROR);
  1976.                     break;
  1977.     }
  1978.     INTERNAL_ERROR
  1979.     return(ERROR);
  1980. }
  1981.  
  1982. static int parseline(struct listheader *plabel,struct objsize *pobj,char *pwork,int mode)
  1983. /* List of all Label's */
  1984. /* Structure for start,end,actual position of objectbuffer */
  1985. /* Textline to parse */
  1986. /* PARSE1 or PARSE2 */                                           
  1987. {
  1988.     /*
  1989.      *    Parse a line for mnemomics or directives.
  1990.      *    Dependent if 'mode'==PARSE1 no objectcode is generated (only the size is counted)
  1991.      *              else if 'mode'==PARSE2 objectcode is generated.
  1992.      *
  1993.      *    - if comments exist, cut them.
  1994.      *     - if labels exists, note them in 'plabel' (PARSE1)
  1995.      *    - parse the command, check the correctness, determine the needed size,
  1996.      *      increment the objectbuffer and if 'mode'==PARSE2 generate the code
  1997.      *
  1998.      *    If any errors found in the string, they will be report by 'showerror()'
  1999.      *
  2000.      *    RC: NULL or
  2001.      *        ERROR if any serious ERRORS ocured
  2002.      *
  2003.      *        BTW: A wrong 'source line' isn't an error for this function.
  2004.      *             Syntax Error's will report by showerror() during the parsing.
  2005.      */
  2006.      
  2007. #    define POSOBJ 5        /* String Postition of 'Object Code' */
  2008. #    define POSCYCLE 5    /* String Postition of 'Clock Cycle' */
  2009. #    define POSSRCV 18    /* String Postition of 'Sourceline' (verbose) */
  2010. #    define POSSRCC 12    /* String Postition of 'Sourceline' (clockcycle) */
  2011.  
  2012.     char     *ptok,
  2013.             *tmp=NULL,
  2014.             clockbuf[BUFSIZ],
  2015.             verbbuf[BUFSIZ];
  2016.  
  2017.     int direc,nmne,orgflag;
  2018.  
  2019.     u_short value=0;
  2020.     u_short cycle=0;                /* if MNE found, MNE Clock Cycle */
  2021.     struct labelitem *pitem;
  2022.     BOOL  invalid=TRUE;            /* Flag to show if a Constant definition is invalid */
  2023.  
  2024.     int i,startpos;
  2025.     
  2026.     if(debugf)  puts("parseline");
  2027.  
  2028.         /* needed in 'verbose','intelhex' or 'clockcycle' mode */
  2029.     if(mode==PARSE2 && assembleflag)
  2030.     {
  2031.         startpos= pobj->actbyte;
  2032.  
  2033.         if(verbose) 
  2034.         {
  2035.             tmp=iwtoh((u_short)startpos,verbbuf);    /* Generate Objectaddress */
  2036.             strcpy(tmp,":              ");    /* Append ':' and clean Space */
  2037.             strcpy(&verbbuf[POSSRCV],pwork);    /* save line to print out in verbose mode */
  2038.         }
  2039.         if(clockcycle) 
  2040.         {
  2041.             tmp=iwtoh((u_short)lnr,clockbuf);    /* Generate Objectaddress */
  2042.             strcpy(tmp,":              ");    /* Append ':' and clean Space */
  2043.             strcpy(&clockbuf[POSSRCC],pwork);    /* save line to print out in clockcycle mode */
  2044.         }
  2045.     }
  2046.  
  2047.     killcomment(pwork);                /* remove all comments */
  2048.     cutend(pwork);
  2049.     if(!(ptok = strtok(pwork," \t")))        /* first token, No token there ? */
  2050.     {                                        /*  NO token, so finish */
  2051.         if(verbose&MODE_ALL)
  2052.             goto ENDPARSELINE;        /* print out Comment */
  2053.         if(clockcycle&MODE_ALL)
  2054.             goto ENDPARSELINE;        /* print out Comment */
  2055.         return(NULL);                /* nothing there to parse */
  2056.     }
  2057.  
  2058.     tmp = ptok + strlen(ptok) - 1;
  2059.  
  2060.     /*** is there a label ? ***/
  2061.     if(*tmp == ':') 
  2062.     {
  2063.         if( (mode==PARSE1) && assembleflag)
  2064.         {
  2065.             *tmp = '\0';                        /* cut ':' */
  2066.             if(dolabel(plabel,pobj,ptok))        /* manage label */
  2067.                 return(ERROR);
  2068.         }
  2069.         if(!(ptok = strtok(NULL," \t")))    /* next token */
  2070.             goto ENDPARSELINE;                /* nothing more there to parse */
  2071.     }
  2072.  
  2073.     /*** is there a directive ***/
  2074.     if( (direc=finddirective(ptok)) != ERROR)        /* search directives */
  2075.     {                                    
  2076.         if( (direc == EQU || direc == DEFL))    /* EQU/DEFL need at first a symbol name */
  2077.         {                                    /* they will be handled a few lines down */
  2078.             if(!assembleflag)
  2079.                 return(NULL);                  /* don't assemble -> ignore ERRORS */    
  2080.  
  2081.             showerror(ptok,NO_SYMBOL_NAME,ptok);
  2082.             return(NULL);
  2083.         }
  2084.         else
  2085.         {
  2086.             if(dodirective(plabel,pobj,ptok,direc,mode,&orgflag))
  2087.                 return(ERROR);
  2088.                 
  2089.                 /* all done this round ? */
  2090.             if( (!assembleflag) || (mode==PARSE1) || ( (!verbose) && (!intelhex) && (!clockcycle) ) )
  2091.                 return(NULL);
  2092.  
  2093.                 /* do 'verbose' or 'intelhex' stuff */
  2094.             nmne=pobj->actbyte-startpos;
  2095.  
  2096.             if(orgflag)
  2097.             {
  2098.                 startpos= pobj->actbyte;
  2099.                 nmne = 0;
  2100.             }
  2101.  
  2102.             if(intelhex&&nmne)
  2103.                 dointelhex(startpos,nmne,ACT_OBJ_ADDR(pobj)-nmne);
  2104.                 
  2105.                 /* less or equal 4 Bytes could be shown in actual line */
  2106.             if(verbose)
  2107.             {
  2108.                 if(nmne<=4)
  2109.                 {
  2110.                     tmp= &verbbuf[POSOBJ];
  2111.                     for(i=0;i<nmne;i++)
  2112.                     {
  2113.                         *tmp=' ';
  2114.                         tmp=ibtoh(*(ACT_OBJ_ADDR(pobj)+i-nmne),++tmp);
  2115.                     }
  2116.                     *tmp=' ';
  2117.                 }
  2118.                 else
  2119.                 {
  2120.                         /* more than 4 Bytes -> show in a new row */
  2121.                     puts(verbbuf);    /* show line with source Text, but without Bytes*/
  2122.                     tmp= &verbbuf[POSOBJ];
  2123.                     for(i=0;i<nmne&& (tmp<(&verbbuf[BUFSIZ]-3));i++)
  2124.                     {
  2125.                         *tmp=' ';
  2126.                         tmp=ibtoh(*(ACT_OBJ_ADDR(pobj)+i-nmne),++tmp);
  2127.                     }
  2128.                     *tmp='\0';
  2129.                 }
  2130.             }
  2131.                 /* check if there is something to print out */
  2132.             if(verbose || clockcycle)
  2133.                 goto ENDPARSELINE;
  2134.             else 
  2135.                 return(NULL);
  2136.         }
  2137.     }
  2138.  
  2139.     if(!assembleflag)
  2140.         return(NULL);    /* don't assemble -> do nothing */
  2141.  
  2142.     tmp = ptok; /* safe old start of begin parsing for second directive search */
  2143.  
  2144.     /*** Is there Z80 Mnemomic ? ***/
  2145.     if( !(domne(plabel,pobj,ptok,mode,&cycle)))    /* look for Mnemomics, parse them */
  2146.     {
  2147.         if(mode==PARSE2)
  2148.         {
  2149.             nmne = pobj->actbyte-startpos;
  2150.  
  2151.             if(intelhex&&nmne)
  2152.                 dointelhex(startpos,nmne,ACT_OBJ_ADDR(pobj)-nmne);
  2153.  
  2154.             if(verbose)
  2155.             {
  2156.                 tmp= &verbbuf[POSOBJ];
  2157.                 for(i=0;i<nmne;i++)
  2158.                 {
  2159.                     *tmp=' ';
  2160.                     tmp=ibtoh(*(ACT_OBJ_ADDR(pobj)+i-nmne),++tmp);
  2161.                 }
  2162.                 *tmp=' ';
  2163.             }
  2164.  
  2165.             if(clockcycle)
  2166.             {
  2167.                 if(cycle<0xff)    /* branch ? */
  2168.                 {   /* NO */
  2169.                     sprintf(&clockbuf[POSCYCLE]," %2d",cycle);
  2170.                     clockbuf[POSCYCLE+3]=' ';
  2171.                 }
  2172.                 else
  2173.                 {   /* Yes */
  2174.                     sprintf(&clockbuf[POSCYCLE]," %2d/%2d",(cycle&0xff00)>>8,cycle&0xff);
  2175.                     clockbuf[POSCYCLE+6]=' ';
  2176.                 }
  2177.             }
  2178.     
  2179.         }
  2180.         goto ENDPARSELINE;
  2181.     }
  2182.  
  2183.     /*** EQU/DEFL ***/
  2184.  
  2185.     strcpy(pwork,line+(tmp-pwork));            /* restore sourceline (cutted through 'domne()' */
  2186.     killcomment(pwork);
  2187.     cutend(pwork);
  2188.     ptok=strtok(pwork," \t");                /* first token (is also 'pwork') */
  2189.     if(!(ptok=strtok(NULL," \t")))            /* second token (assummed directive) */
  2190.     {
  2191.         showerror(ptok,UNKNOWN_COMMAND,pwork);
  2192.         return(NULL);
  2193.     }
  2194.  
  2195.     if( (direc=finddirective(ptok)) != ERROR)        /* search directives */
  2196.     {                                    
  2197.         if(direc != EQU && direc != DEFL)        /* 'direc' must be EQU or DEFL */
  2198.         {
  2199.             showerror(ptok,UNKNOWN_COMMAND);
  2200.             return(NULL);
  2201.         }
  2202.         if(!(ptok=strtok(NULL,"\n")))            /* third token (constant assummed) */
  2203.         {
  2204.             showerror(pwork,EXPECT_CONSTANT);
  2205.             return(NULL);
  2206.         }
  2207.         ptok=skipspace(ptok);
  2208.  
  2209.         invalid = strtoint(plabel,ptok,&value,mode);
  2210.  
  2211.         if(mode==PARSE2)
  2212.         {
  2213.             if(invalid)        /* convert to int */
  2214.             {
  2215.                 /* Just to report a more detailed error message */
  2216.                 strtok(ptok," \t");    /* clear everything behind token */
  2217.                 if(getlabel(plabel,ptok))    /* check if Symbol name exists */
  2218.                     showerror(ptok,CANT_RESOLVE);
  2219.                 else
  2220.                     showerror(ptok,SYNTAX_ERROR);
  2221.                 return(NULL);
  2222.             }
  2223.         }
  2224.  
  2225.         if(pitem=getlabel(plabel,pwork))    /* check if Symbol name exists */
  2226.         {
  2227.             if( direc!=DEFL || pitem->type != L_DEFL )    /* directive type = EQU ? */
  2228.             {
  2229.                 if( direc != pitem->type )
  2230.                 { 
  2231.                     showerror(pwork,LABEL_DECL_EQUDEFL);    /* EQU definition can't */
  2232.                     return(NULL);                                /*  redefined */
  2233.                 }
  2234.                 if(mode==PARSE1)    /* first parse -> error */
  2235.                 {
  2236.                     showerror(pwork,LABEL_DECL_TWICE);    /* EQU definition can't */
  2237.                     return(NULL);                                /*  redefined */
  2238.                 }
  2239.             }
  2240.             if(pitem->valid = !invalid)
  2241.                 pitem->value = value;        /* -> direc == DEFL. take new value */
  2242.             goto ENDPARSELINE;
  2243.         }
  2244.         else                                /* Symbol name is new */
  2245.         {
  2246.             if(mode==PARSE2)
  2247.             {
  2248.                     /* this should never be happen */
  2249.                 INTERNAL_ERROR
  2250.                 return(ERROR);                        
  2251.             }
  2252.             if(SERIOUS==(int)insertlabel(plabel,pwork,direc,value,!invalid)) /* insert constant definition */
  2253.             {
  2254.                 showerror(pwork,NO_MEMORY);
  2255.                 return(ERROR);                        
  2256.             }
  2257.             goto ENDPARSELINE;
  2258.         }
  2259.     }
  2260.     else
  2261.     {
  2262.         showerror(ptok,UNKNOWN_COMMAND);
  2263.         return(NULL);
  2264.     }
  2265.  
  2266. ENDPARSELINE:
  2267.     if(!assembleflag)
  2268.         return(NULL);
  2269.  
  2270.     if( (mode==PARSE2) && verbose)
  2271.         puts(verbbuf);
  2272.     if( (mode==PARSE2) && clockcycle)
  2273.         puts(clockbuf);
  2274.     return(NULL);
  2275. }
  2276.  
  2277.  
  2278. static int readsrc(struct listheader *plabel,struct objsize *pobj,char *p_actfilename)
  2279. {
  2280.     /*
  2281.      *    Parse File 'fp' two times.
  2282.      *    First parse: - Count Object code size
  2283.      *                 - Fill list 'plabel' with label name and either a memory
  2284.      *                   position or a constant definition
  2285.      *    Second parse: - Allocate Object code Buffer
  2286.      *                  - fill the buffer with appropriate Object code
  2287.      *                  - use 'label' to reference all symbols
  2288.      *
  2289.      *    RC: number of object bytes if every went fine,else
  2290.      *        NULL and print an error message 
  2291.      */
  2292.     
  2293.     char *pos;    
  2294.     u_char *tmp;
  2295.     int length;
  2296.     BOOL flag=TRUE;
  2297.  
  2298.     if(debugf)  puts("readsrc");
  2299.  
  2300.     if(!(fpin=fopen(p_actfilename,"r"))) /* Open New file */
  2301.     {    
  2302.         fprintf(stderr,CANT_OPEN_FILE,p_actfilename);
  2303.         return(NULL);
  2304.     }
  2305.  
  2306.     /******************** Parse 1 ********************/
  2307.     default_num_base=10;
  2308.     fputs("Parse 1\n",stderr);
  2309.  
  2310.     while(flag)                    /* parse source file */
  2311.     {
  2312.         if(feof(fpin))            /* no more Data ? */ 
  2313.         {
  2314.             if(file_stack)            /* Are there still any source files ? */
  2315.             {
  2316.                 if(popfile(&file_stack,&fpin))
  2317.                     return(NULL);    /* Error */
  2318.             }
  2319.             else
  2320.                 flag=FALSE;                /* No, so quit while() */
  2321.  
  2322.             continue;                /* go to while() */
  2323.         }
  2324.  
  2325.         if(pos=fgets(line,BUFSIZ,fpin))    /* get next line */
  2326.         {
  2327.             strcpy(work,line);            /* 'work' is work buffer */
  2328.             lnr++;                        /* line number counting */
  2329.             if(parseline(plabel,pobj,work,PARSE1))    /* parse the line */
  2330.                 return(NULL);            /* something terrible must be happen */
  2331.  
  2332.             if(endflag)
  2333.             {
  2334.                 endflag=flag=FALSE;
  2335.                 while(file_stack)            /* Are there still any source files ? */
  2336.                 {
  2337.                     if(popfile(&file_stack,&fpin))
  2338.                         return(NULL);    /* Error */
  2339.                 }
  2340.             }
  2341.         }
  2342.     }
  2343.  
  2344.     if(errors)
  2345.         return(NULL);
  2346.         
  2347.     length=pobj->lastbyte - pobj->firstbyte;
  2348.  
  2349.     if(length)
  2350.     {    /* Just allocate Buffer, if it is really needed */
  2351.          if(!(tmp=pobj->objbuffer=(u_char *)calloc(sizeof(unsigned char),length)))
  2352.         {
  2353.             fputs("Error: Can't allocate memory for Objectbuffer\n",stderr);
  2354.             return(NULL);
  2355.         }
  2356.     }
  2357.     pobj->actbyte = pobj->firstbyte; /* Set counter to start */
  2358.  
  2359.     /******************** Parse 2 ********************/
  2360.     default_num_base=10;
  2361.     fputs("Parse 2\n",stderr);
  2362.     rewind(fpin);
  2363.     lnr=0;
  2364.     if(clockcycle)
  2365.         puts("Line: Cycle Source");
  2366.  
  2367.     flag=TRUE;
  2368.     while(flag)                    /* parse source file */
  2369.     {
  2370.         if(feof(fpin))            /* no more Data ? */ 
  2371.         {
  2372.             if(file_stack)            /* Are there still any source files ? */
  2373.             {
  2374.                 if(popfile(&file_stack,&fpin))
  2375.                     return(NULL);    /* Error */
  2376.             }
  2377.             else
  2378.                 flag=FALSE;                /* No, so quit while() */
  2379.  
  2380.             continue;                /* go to while() */
  2381.         }
  2382.  
  2383.         if(pos=fgets(line,BUFSIZ,fpin))    /* get next line */
  2384.         {
  2385.             strcpy(work,line);            /* 'work' is work buffer */
  2386.             lnr++;                        /* line number counting */
  2387.             cutend(work);
  2388.             if(parseline(plabel,pobj,work,PARSE2))    /* parse the line */
  2389.                 return(NULL);            /* something terrible must be happen */
  2390.  
  2391.             if(endflag)
  2392.             {
  2393.                 flag=FALSE;
  2394.                 while(file_stack)            /* Are there still any source files ? */
  2395.                 {
  2396.                     if(popfile(&file_stack,&fpin))
  2397.                         return(NULL);    /* Error */
  2398.                 }
  2399.             }
  2400.         }
  2401.     }
  2402.     if(intelhex)
  2403.         dointelhex(ERROR,0,NULL);
  2404.  
  2405.     if(debugv) fprintf(stderr,"generated Object Bytes:%d\n",length);    
  2406.  
  2407.     return(length);
  2408. }
  2409.  
  2410.  
  2411. static void cleanup(void)
  2412. {
  2413.     struct item_file *p_fs;
  2414.  
  2415.     if(ih_head.list)    
  2416.         free(ih_head.list);
  2417.  
  2418.     if(label.list)      
  2419.         free(label.list);
  2420.  
  2421.     if(object.objbuffer)    
  2422.         free(object.objbuffer);
  2423.  
  2424.     if(file_stack)
  2425.     {
  2426.         do {
  2427.             p_fs = file_stack->prev;
  2428.             free(file_stack);
  2429.             file_stack = p_fs;
  2430.         } while(p_fs);
  2431.     }
  2432.  
  2433.     if(fpin)              fclose(fpin);    
  2434.     if(fpout)              fclose(fpout);    
  2435.  
  2436.     return;
  2437. }
  2438.  
  2439. static void handlesig(int sig)
  2440. {
  2441.     fflush(stdout);
  2442.     puts("caz broken");
  2443.     cleanup();
  2444.     exit(RETURN_WARN);
  2445. }
  2446.  
  2447. int main(int argc,char *argv[])
  2448. {
  2449.     char    *outfile="a.out",*intelhexfile=NULL,*labelfile=NULL;
  2450.     int        length;
  2451.  
  2452.  
  2453.     signal(SIGINT,handlesig);
  2454.  
  2455.     actfilename[0] = '\0';
  2456.  
  2457.     if(debugf)  puts("main");
  2458.  
  2459.     if(argc==1)         /* check commandline arguments */
  2460.         goto USAGE;
  2461.  
  2462.     if((argc==2) && (*argv[1]=='?') )
  2463.         goto USAGE;
  2464.     
  2465.     while(--argc)
  2466.     {
  2467.         if( (**(++argv)) == '-')
  2468.         {
  2469.             switch(*((*argv)+1))
  2470.             {
  2471.                 case 'd':    debugv=TRUE;            /* Flag */
  2472.                             break;
  2473.                 case 'D':    debugf=TRUE;            /* Flag */
  2474.                             break;
  2475.                 case 'v':    verbose = MODE_OPTION+MODE_MNE;
  2476.                             break;
  2477.                 case 'V':    verbose = MODE_OPTION+MODE_ALL;        /* Flag */
  2478.                             break;
  2479.                 case 'c':    clockcycle = MODE_MNE;
  2480.                             break;
  2481.                 case 'C':    clockcycle = MODE_ALL;        /* Flag */
  2482.                             break;
  2483.                 case 's':
  2484.                 case 'S':    showsymbols=TRUE;        /* Flag */
  2485.                             break;
  2486.                 case 'o':
  2487.                 case 'O':     if(!(--argc))
  2488.                               {
  2489.                                   fprintf(stderr,"Missing filename behind '-o'\n");
  2490.                                   goto USAGE;
  2491.                               }
  2492.                               outfile = *++argv;
  2493.                               break;
  2494.                 case 'w':
  2495.                 case 'W':     if(!(--argc))
  2496.                               {
  2497.                                   fprintf(stderr,"Missing filename behind '-w'\n");
  2498.                                   goto USAGE;
  2499.                               }
  2500.                               labelfile = *++argv;
  2501.                               break;
  2502.                 case 'i':
  2503.                 case 'I':     if(!(--argc))
  2504.                               {
  2505.                                   fprintf(stderr,"Missing filename behind '-e'\n");
  2506.                                   goto USAGE;
  2507.                               }
  2508.                               intelhexfile = *++argv;
  2509.                             intelhex=TRUE;            /* Flag */
  2510.                               break;
  2511.                 case 'h':
  2512.                 case 'H':
  2513.                 case '?':    goto USAGE1;
  2514.                             break;
  2515.                 default:    fprintf(stderr,"Unknown commandline option\n");
  2516.                               goto USAGE;
  2517.             }
  2518.         }
  2519.         else
  2520.         {    
  2521.             if(actfilename[0])
  2522.                 goto USAGE;
  2523.             strcpy(actfilename,*argv);
  2524.         }
  2525.     }
  2526.     
  2527.     fputs(&vers[7],stderr);
  2528.     fputs(COPYRIGHT,stderr);
  2529.  
  2530.         /* Check if CLOCK & VERBOSE Mode is active */
  2531.     if(clockcycle && verbose)
  2532.     {
  2533.         fputs(CLOCK_OR_VERBOSE,stderr);
  2534.         goto LEAVEALL;
  2535.     }
  2536.  
  2537.     if(init(&label,&object))    /* initialize lists/buffers */
  2538.         exit(RETURN_ERROR);
  2539.     
  2540.     length=readsrc(&label,&object,actfilename);
  2541.  
  2542.     if(errors)
  2543.         fprintf(stderr,"\n\nAssembling failed.\nFound %d errors.\n",errors);
  2544.  
  2545.     if(showsymbols) 
  2546.         symboltable(&label);                        
  2547.  
  2548.     if(labelfile) 
  2549.         writesymboltable(&label,labelfile);                        
  2550.  
  2551.  
  2552.         /* if readsrc() don't generate any Objectcode, quit assembler */
  2553.     if(!length)
  2554.         goto LEAVEALL;
  2555.  
  2556.     if(!(fpout = fopen(outfile,"wb")))    /* open file where to write object code */
  2557.     {
  2558.         perror("Can't open file:");
  2559.         exit(RETURN_WARN);
  2560.     }
  2561.     if(length!=fwrite(object.objbuffer,1,length,fpout))
  2562.     {
  2563.         perror("Writing Objectfile failed");
  2564.         goto LEAVEALL;
  2565.     }
  2566.     fclose(fpout);
  2567.     fpout=NULL;
  2568.  
  2569.     if(intelhex)
  2570.     {
  2571.         if(!(fpout = fopen(intelhexfile,"wb")))    /* open file where to write INTELHEX Code */
  2572.         {
  2573.             sprintf(errortext,"Can't open file output File '%s'\n",actfilename);
  2574.             perror(errortext);
  2575.             exit(RETURN_WARN);
  2576.         }
  2577.         length=ih_head.actitem;
  2578.         if(length!=fwrite(ih_head.list,1,length,fpout))
  2579.         {
  2580.             perror("Writing INTELHEX File failed");
  2581.             goto LEAVEALL;
  2582.         }
  2583.     }
  2584.  
  2585.     goto LEAVEALL;                /* exit */
  2586.  
  2587. USAGE:
  2588.     fprintf(stderr,"USAGE: 'caz OPTIONS [assembler filename]'\n");
  2589. USAGE1:    
  2590.     fprintf(stderr,
  2591.            "%s"
  2592.            COPYRIGHT
  2593.            "\nOPTINOS are:\n\n"
  2594.            "-o [Output Filename]   File where to write the generated Objectcode.\n"
  2595.            "-d Debug Mode          Just for development of 'caz' (d=Value,D=Function).\n"
  2596.            "-v/V Verbose Mode      Print on 'stdout' generated Objectcode with\n"
  2597.            "                        with Adresses,Mnemomic,Source (v=MNE,V=ALL).\n"
  2598.            "-c/C Clock Cycle       Print on 'stdout' Clock Cycles for every Mnemomic\n"
  2599.            "-w [Filename]          Write out symbol definitions (Z80 Assembler Format).\n"
  2600.            "-s Print Symbol Table  Print out symbol definitions (more detailed). \n"
  2601.            "-i [IntelHex Filename] Generate a complete Object File in 'IntelHex'\n"
  2602.            "                        Format (used by many Eprommer).\n",&vers[7]);
  2603.     return(1);
  2604.  
  2605. LEAVEALL:
  2606.     cleanup();
  2607.     exit(RETURN_OK);
  2608. }
  2609.