home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 405.lha / Z8_CrossAsm / z8ca1.c < prev    next >
C/C++ Source or Header  |  1990-06-05  |  34KB  |  1,739 lines

  1. /* z8 Cross Assembler for Commodore Amiga.
  2.  
  3.   Written by: Bob Bush (Compuserve-73105,1332) 14-Apr-1989
  4.  
  5.   Copyright (C) 1989 R.Bush. All rights reserved.
  6.  
  7.   This program is freely distributable as long as this copyright notice
  8.   is retained. It intended for personal, non-commercial use.  
  9.  
  10.  
  11.    Brief Syntax notes:
  12.     R0 thru R15 always refer to working register set.
  13.     All other registers are addressed with the colon opertor eg.
  14.         ld r:$ff,#1  ;load absolute register 255 with a '1'
  15.         ld r:2,#0    ;load absolute register 2 with a '0'
  16.  
  17.    Additional: If this code seems somewhat sporadic it no doubt is..
  18.                Could be due to the fact that the entire program was developed
  19.            in a few days while sitting in front of a terminal (Amiga).
  20.                This happens be my favorite method of program development <:
  21.  
  22. */
  23.  
  24. /* Amiga note: Compiled with Lattice 'C' 4.0   lc -L -v -cw z8ca */
  25.  
  26. /* Modifications :
  27.  
  28.     1) allow symbols to be case sensitive.
  29.     2) allow math operations on defs.
  30.     3) fixed bug in Intel Hex file output.
  31.     4) added sorted symbol table option.
  32.     5) enabled 'DS' pseudo op.
  33.     6) Bug fixed in 'DB' evaluation which prevented spaces after
  34.        pseudo op.
  35. */
  36.    
  37. #include <string.h>
  38. #include <stdio.h>
  39.  
  40. /* #define DEBUG 1 */
  41.  
  42. struct symbol { /* symbol table entry */
  43.     struct symbol *next;
  44.     char *label;
  45.     int  value;
  46. };
  47.  
  48. #define HASHSIZE 101
  49.  
  50. struct symbol *hashtab[HASHSIZE];
  51. struct symbol **spoint;
  52.  
  53. struct def { /* entry for a define */
  54.      struct def *next;
  55.      char *label;
  56.      char *substitute;
  57. };
  58.  
  59. struct def *deftab[HASHSIZE];
  60.  
  61.  
  62. struct optable {
  63.     int dest;        /* valid operand for destination argument */
  64.     int source;        /* valid operand for source argument */
  65.     int numbytes;    /* number of bytes generated for this opcode */
  66.     int opcode;        /* the primary opcode byte */
  67.     int opr1;        /* formation rules for second byte */
  68.     int opr2;        /* formation rules for third byte */
  69. };
  70.  
  71. /* argument sub classification (8bit reg specification as working reg) */
  72.  
  73. #define WORKING 1
  74.  
  75. /* opcode formation rules for second and/or third bytes (used in optable) */
  76.  
  77. #define DESTSL4_OR_SOURCE   1
  78. #define OPCODE_OR_DESTSL4   2
  79. #define ZSOURCE         3
  80. #define ZDEST            4
  81. #define DATA8               5
  82. #define OPCODE_OR_SOURCESL4   6
  83. #define CC_OR_OP              7
  84. #define RELATIVE              8
  85. #define SOURCESL4_OR_DEST     9
  86.  
  87. /* operand address mode descriptors used in (optable) */
  88.  
  89. #define R4    1   /* working register 4 bit descriptor */
  90. #define R8    2   /* 8 bit register   */
  91. #define IR4    3   /* indirect working register - 4 bits only */
  92. #define IR8    4   /* indirect register - 8 bits */
  93. #define IRR4    5   /* indirect working register pair */
  94. #define IRR8    6   /* indirect register pair */
  95. #define XX      7   /* indexed address */
  96. #define RR8     9   /* register pair */
  97. #define IM8    10   /* immediate 8-bit data */
  98. #define DA     11   /* direct 16-bit address */
  99. #define IMP    12   /* implied operand */
  100. #define RR4    13   /* working register pair */
  101. #define CC     14   /* condition code */
  102. #define RA     15   /* relative address */
  103.  
  104.  
  105. /* syntax descriptions for opcode (used in syntax structure) */
  106.  
  107. #define DEST_SOURCE 1    /* standard (dest,source) format */
  108. #define DEST_ONLY   2   /* standard (dest) format */
  109. #define IMPLIED     3    /* implied operand (eg. NOP) */
  110. #define CREATE_JR   4    /* jump relative (eg JR NZ,DEST) */
  111. #define CREATE_DJ   5   /* djnz */
  112. #define CREATE_JP   6   /* cc jump */
  113.  
  114. #include "optab.h"
  115.  
  116. struct pseudo {
  117.     char *mne;        /* ascii mneumonic */
  118. };
  119.  
  120. struct pseudo ps[] = {
  121.     "Invalid",
  122.     "ORG",
  123.     "DB",
  124.     "DW",
  125.     "DS",
  126.     "EQU",
  127.     "DEF"
  128. };
  129.  
  130. #define PSSIZE sizeof(ps) / sizeof(ps[0])
  131.  
  132. struct cc_code {
  133.     char *mne;
  134.     int  cc_value;
  135. };
  136.  
  137. /* note: hi nibble is the condition code */
  138.  
  139. struct cc_code cc[] = {
  140.     "C",0x70,
  141.     "NC",0xf0,
  142.     "Z",0x60,
  143.     "NZ",0xe0,
  144.     "PL",0xd0,
  145.     "MI",0x50,
  146.     "OV",0x40,
  147.     "NOV",0xc0,
  148.     "EQ",0x60,
  149.     "NE",0xe0,
  150.     "GE",0x90,
  151.     "LT",0x10,
  152.     "GT",0xa0,
  153.     "LE",0x20,
  154.     "UGE",0xf0,
  155.     "ULT",0x70,
  156.     "UGT",0xb0,
  157.     "ULE",0x30
  158. };
  159.  
  160. #define CCSIZE sizeof (cc) / sizeof(cc[0])
  161.  
  162. char *args[] = {
  163.     "                                                                    ",
  164.     "                                                                    ",
  165.     "                                                                    ",
  166.     "                                                                    ",
  167.     "                                                                    ",
  168.     "                                                                    ",
  169. };
  170.     
  171. char cur_sym[40];
  172. char fbuff[101];
  173. char dbuff[101];
  174.  
  175. int pc;
  176. unsigned char bincode[25];
  177. int bincode_index = 0;
  178.  
  179. unsigned char bin_line[128];
  180. int bin_pc = 0;
  181. int bindex = 0;
  182. unsigned char checksum = 0;
  183.  
  184. int syntax_index;
  185. int arg_val,arg_type,arg_subclass;
  186. int arg1_val,arg1_type,arg1_subclass;
  187. int arg2_val,arg2_type,arg2_subclass;
  188. int radix;
  189. int pcinc;
  190. char *curline;
  191. int pass;
  192. unsigned char code_line[8];
  193. int code_line_index;
  194. int line_no;
  195. int bytes_generated;
  196.  
  197. struct symbol *lookup();
  198. struct def *lookup_def();
  199. struct def *lookup_def1();
  200. int special_def;
  201. int sym_cmp();
  202. int nsyms = 0;
  203. int sym_list = 0; /* default no symbol table listing */
  204.  
  205. FILE *fpin = NULL;
  206. FILE *fpout = NULL;
  207. char out_fname[64]; 
  208. char in_fname[64];
  209.  
  210. int listdb;
  211. int list_on;
  212. int fout_type;
  213.  
  214. /* .hex file types */
  215.  
  216. #define MOTOROLA 1
  217. #define INTEL    2
  218. #define Z8     3
  219.  
  220. char *parse_line;
  221.  
  222. main(argc,argv)
  223. int argc;
  224. char *argv[];
  225. {
  226.    int j;
  227.  
  228.    printf("\n\11z8 Cross Assembler Ver. 1.2\n");
  229.  
  230.    strcpy(in_fname,argv[1]);
  231.    strcat(in_fname,".asm");
  232.    
  233.    if(!(fpin = fopen(in_fname,"r"))) 
  234.     errexit2("Can't open input file");
  235.  
  236.    strcpy(out_fname,argv[1]);
  237.    strcat(out_fname,".hex");
  238.  
  239.    fout_type = MOTOROLA;
  240.    list_on = 0;
  241.  
  242.    if(argc > 2) 
  243.     for(j = 2; j < argc; j++)
  244.         sel_opt(argv[j]);
  245.  
  246.    bytes_generated = 0;listdb = 1;
  247.  
  248.    pass = 1; line_no = 1; pc = 0;
  249.    printf("Pass 1:\n");
  250.    while(fgets(fbuff,100,fpin)) {
  251.         strcpy(dbuff,fbuff);
  252. /*        strupr_esc(fbuff); */
  253.         curline = fbuff; /* establish current line pointer */
  254.         code_line_index = 0; pcinc = 0;
  255.             evaluate();
  256.         line_no++;
  257.    }
  258.    fclose(fpin); /* end of pass #1 */
  259.  
  260.    pass = 2; line_no = 1; pc = 0;bytes_generated = 0;
  261.  
  262.    printf("Pass 2:\n");
  263.  
  264.    if(!(fpin = fopen(in_fname,"r"))) 
  265.     errexit2("Can't re-open input file");
  266.    if(!(fpout = fopen(out_fname,"w"))) 
  267.     errexit2("Can't open output file");
  268.  
  269.    while(fgets(fbuff,100,fpin)) {
  270.         strcpy(dbuff,fbuff); /* save un-altered copy of source code */
  271. /*        strupr_esc(fbuff);    convert to upper case */
  272.         curline = fbuff;     /* establish current line pointer */
  273.         code_line_index = 0; pcinc = 0;
  274.             evaluate();          /* grunt out some code */
  275.         line_no++;
  276.    }
  277.    fclose(fpin);
  278.  
  279.    if(fout_type == Z8)
  280.        fprintf(fpout,"+\n"); /* terminate for z8 Basic loader */
  281.    else
  282.         if(fout_type == MOTOROLA)
  283.          end_m();
  284.    else
  285.     end_i(); /* INTEL */
  286.  
  287.    fclose(fpout);
  288.    printf("\n\11Assembly Complete..\n");
  289.    printf("\11%d Bytes Generated.\n",bytes_generated);
  290.  
  291.    list_symbols();
  292. }
  293.  
  294. errexit2(s) /* fatal (any:>) error exit */
  295. char *s;
  296. {
  297.     if(fpin)
  298.     fclose(fpin);
  299.     if(fpout)
  300.     fclose(fpout);
  301.     printf("\n ** Fatal Error ** at line # %d\n",line_no);
  302.     printf("%s",dbuff);
  303.     printf("%s\n",s);
  304.     printf("Assembly Terminated\n");
  305.     exit(0);
  306. }
  307.  
  308. sel_opt(s)
  309. char *s;
  310. {
  311.     if(*s++ == '-') {
  312.     switch(*s) {
  313.         case 'l': list_on = 1;
  314.               break;
  315.         case 'z': fout_type = Z8;
  316.               break;
  317.         case 'm': fout_type = MOTOROLA;
  318.               break;
  319.         case 'i': fout_type = INTEL;
  320.               break;
  321.         case 's': sym_list = 1;
  322.               break;
  323.         default:  errexit2("Invalid assembler option");
  324.               break;
  325.     }
  326.      }
  327. }
  328.  
  329.  
  330. syntax_error()
  331. {
  332.     errexit2("Syntax Error .. Unable to evaluate..");
  333. }
  334.  
  335. strupr_esc(buff)
  336. char *buff;
  337. {
  338.     while(*buff) {
  339.     if(*buff == '\'') {
  340.         buff++;
  341.         while(*buff){
  342.         if(*buff == '\'')
  343.            break;
  344.         else
  345.            buff++;
  346.         }
  347.          }
  348.     if(*buff) {
  349.        *buff = toupper(*buff); *buff++; }    
  350.     }
  351. }
  352.  
  353.  
  354. /* primary line evaluator */
  355.  
  356. evaluate()
  357. {
  358.     int status;
  359.  
  360.     if(!(status = get_token(args[0]))) {     /* get a word */
  361.         gen_line();
  362.     return(0); }             /* comment -or- blank line */
  363.  
  364.     if(checklabel(args[0],status)) {    /* create a symbol if required */
  365.         if(pass == 1) {
  366.        create_symbol(args[0],pc);
  367.        strcpy(cur_sym,args[0]);
  368.     }
  369.         if(!(status = get_token(args[0]))) {     /* get a word */
  370.        gen_line();
  371.        return(0); }                    /* comment -or- blank line */
  372.     }
  373.  
  374. /* check_defs here would allow user to create own instruction mne's */
  375. /* check_defs(args[0]);    */
  376.  
  377.     syntax_index = scankey(args[0]); /* lookup mneumonic keyword */
  378.  
  379.     if(syntax_index) {
  380.         get_token(args[1]); get_token(args[2]);
  381.         check_defs(args[1]); check_defs(args[2]); /* check for subs. */
  382.     switch(z8[syntax_index].opr_type) {
  383.         case DEST_SOURCE:
  384.              if(create_ds()) 
  385.             gen_line();
  386.              else
  387.                 syntax_error();
  388.              break;
  389.         case DEST_ONLY:
  390.              if(create_d())
  391.             gen_line();
  392.              else
  393.             syntax_error();
  394.              break;
  395.             case IMPLIED:
  396.              if(create_i())
  397.             gen_line();
  398.              else
  399.             syntax_error();
  400.              break;
  401.         case CREATE_JR:
  402.              if(create_jr())
  403.             gen_line();
  404.              else
  405.             syntax_error();
  406.              break;
  407.         case CREATE_DJ:
  408.              if(create_dj())
  409.             gen_line();
  410.              else
  411.             syntax_error();
  412.              break;
  413.         case CREATE_JP:
  414.              if(create_jp())
  415.             gen_line();
  416.              else
  417.             syntax_error();
  418.              break;
  419.     }
  420.     }
  421.     else   /* scan for pseudo op */
  422.     if((syntax_index = scan_pse(args[0])))
  423.         eval_pse(syntax_index);
  424.         else {
  425.         printf("Syntax error, %s is not a valid opcode or pseudo op\n",args[0]);
  426.         errexit2("** syntax **");
  427.         }
  428. }
  429.  
  430. /* check for define substitutions, if found replace string */
  431.  
  432. check_defs(s)
  433. char *s;
  434. {
  435.     struct def *dp;
  436.  
  437.     if(*s) {
  438.         if(!(dp = lookup_def(s)))
  439.         return(0);
  440.         else 
  441.         if(special_def) {
  442.         strcpy(s,dp->substitute);
  443.         strcat(s,args[5]);
  444.     }
  445.     else
  446.         strcpy(s,dp->substitute);
  447.     }
  448. }
  449.  
  450.  
  451.  
  452. /* evaluate a pseudo op */
  453.  
  454. eval_pse(ps_num)
  455. int ps_num;
  456. {
  457.     int equ_val,do_gen;
  458.     struct symbol *sp;
  459.  
  460.     pcinc = 0;do_gen = 1;
  461.  
  462.     switch(ps_num) {
  463.     case 1: /* org */
  464.         get_token(args[1]);
  465.         pc = eval(args[1]);
  466.             if(pass == 2) {
  467.            switch(fout_type) {
  468.             case Z8:
  469.                        fprintf(fpout,"%%%x\n",pc);
  470.                 break;
  471.             case MOTOROLA:
  472.                 flush_m();
  473.                 bin_pc = pc;
  474.                 break;
  475.             case INTEL:
  476.                 flush_i();
  477.                 bin_pc = pc;
  478.                 break;
  479.            }
  480.         }
  481.         break;
  482.     case 2: /* db */
  483.         get_db();
  484.         do_gen = 0;
  485.         break;
  486.     case 3: /* dw */
  487.         get_dw();
  488.         do_gen = 0;
  489.         break;
  490.     case 4: /* ds */
  491.         get_token(args[1]);
  492.         gen_line();
  493.         do_gen = 0;
  494.         pc+= eval(args[1]);
  495.         break;
  496.     case 5: /* equ */
  497.             if(pass == 1) { /* only do this on pass #1... */
  498.             get_token(args[1]);
  499.             equ_val = eval(args[1]);
  500.             if((sp = lookup(cur_sym)))
  501.                sp->value = equ_val;
  502.             else
  503.                printf("can't find symbol for equate \n"); 
  504.         }
  505.         break;
  506.     case 6: /* def */
  507.             if(pass == 1) {
  508.             get_token(args[1]); get_token(args[2]);
  509.             create_def(args[1],args[2]);
  510.         }
  511.         break;
  512.     }
  513.     if(do_gen)
  514.        gen_line();
  515. }
  516.  
  517. /* generate listing on pass #2 */
  518.  
  519. gen_line()
  520. {
  521.     int j;
  522.     if (pass == 2 && list_on) {
  523.         printf("%04x ",pc);
  524.         for(j=0;j<code_line_index;j++)
  525.         printf("%02x ",code_line[j]);
  526.     if(listdb)
  527.            otext(dbuff,pcinc);
  528.     else
  529.        printf("\n");
  530.     }
  531.     pc+= pcinc;
  532. }
  533.  
  534. otext(buff,num)
  535. char *buff;
  536. int num;
  537. {
  538.     switch(num) {
  539.         case 0: printf("           %s",buff);
  540.         break;
  541.     case 1: printf("        %s",buff);
  542.         break;
  543.     case 2: printf("     %s",buff);
  544.         break;
  545.     case 3: printf("  %s",buff);
  546.     }
  547. }
  548.  
  549. /* create a dest,source type code */
  550.  
  551. create_ds()
  552. {
  553.     int stat,j;
  554.  
  555.     if(is_in(args[1],'(') || is_in(args[2],'(')) {
  556.     create_idx();
  557.     return(1);
  558.     }
  559.  
  560.     stat = get_any(args[1]);
  561.     if(stat) {
  562.     arg1_val = arg_val; arg1_type = arg_type;
  563.         arg1_subclass = arg_subclass;
  564.     }
  565.     else {
  566.     printf("Eval 1 failed\n");
  567.         return(0);
  568.     }
  569.     stat = get_any(args[2]);
  570.     if(stat) {
  571.     arg2_val = arg_val; arg2_type = arg_type;
  572.         arg2_subclass = arg_subclass;
  573.     }
  574.     else {
  575.     printf("Eval 2 failed\n");
  576.         return(0);
  577.     }
  578. /* check for standard argument set */
  579.  
  580.     j = 0;
  581.     while(z8[syntax_index].otab[j].dest) {
  582.     if((arg1_type == z8[syntax_index].otab[j].dest) &&
  583.        (arg2_type == z8[syntax_index].otab[j].source)) {
  584.         build_code(z8[syntax_index].otab,j);
  585.         return(1);
  586.     }
  587.     j++;
  588.     }
  589.  
  590. /* check extended argument set #2 */
  591.     convert_arg2(); /* convert 4bit args to 8bit args */
  592.     j = 0;
  593.     while(z8[syntax_index].otab[j].dest) {
  594.     if((arg1_type == z8[syntax_index].otab[j].dest) &&
  595.        (arg2_type == z8[syntax_index].otab[j].source)) {
  596.         build_code(z8[syntax_index].otab,j);
  597.         return(1);
  598.     }
  599.     j++;
  600.     }
  601.  
  602. /* check extended argument set #1 */
  603.     convert_arg1(); /* convert 4bit args to 8bit args */
  604.     j = 0;
  605.     while(z8[syntax_index].otab[j].dest) {
  606.     if((arg1_type == z8[syntax_index].otab[j].dest) &&
  607.        (arg2_type == z8[syntax_index].otab[j].source)) {
  608.         build_code(z8[syntax_index].otab,j);
  609.         return(1);
  610.     }
  611.     j++;
  612.     }
  613.  
  614. /* syntax format not available for this opcode */
  615.  
  616.     return(0);
  617. }
  618.  
  619. /* convert 4bit arg to 8bit arg */
  620.  
  621. convert_arg1()
  622. {
  623.     switch(arg1_type) {
  624.     case R4:    arg1_type = R8;
  625.             break;
  626.     case IR4:   arg1_type = IR8;
  627.             break;
  628.     case IRR4:  arg1_type = IRR8;
  629.             break;
  630.     case RR4:   arg1_type = RR8;
  631.             break;
  632.     }
  633. }
  634.  
  635.  
  636. /* convert 4bit arg to 8bit arg */
  637.  
  638. convert_arg2()
  639. {
  640.     switch(arg2_type) {
  641.     case R4:    arg2_type = R8;
  642.             break;
  643.     case IR4:   arg2_type = IR8;
  644.             break;
  645.     case IRR4:  arg2_type = IRR8;
  646.             break;
  647.     case RR4:   arg2_type = RR8;
  648.             break;
  649.     }
  650. }
  651.     
  652.  
  653. /* create code for destination only type */
  654.  
  655. create_d()
  656. {
  657.     int stat,j;
  658.     stat = get_any(args[1]);
  659.     if(stat) {
  660.     arg1_val = arg_val; arg1_type = arg_type;
  661.         arg1_subclass = arg_subclass;
  662.     }
  663.     else {
  664.     printf("Eval 1 failed\n");
  665.         return(0);
  666.     }
  667.     j = 0;
  668.     while(z8[syntax_index].otab[j].dest) {
  669.     if((arg1_type == z8[syntax_index].otab[j].dest)) {
  670.         build_code(z8[syntax_index].otab,j);
  671.         return(1);
  672.     }
  673.     j++;
  674.     }
  675.  
  676. /* check extended argument set #1 */
  677.  
  678.     convert_arg1();
  679.     j = 0;
  680.     while(z8[syntax_index].otab[j].dest) {
  681.     if((arg1_type == z8[syntax_index].otab[j].dest)) {
  682.         build_code(z8[syntax_index].otab,j);
  683.         return(1);
  684.     }
  685.     j++;
  686.     }
  687.     return(0);
  688. }
  689.  
  690. /* create code for implied op */
  691. create_i()
  692. {
  693.     build_code(z8[syntax_index].otab,0);
  694.     return(1);
  695. }
  696.     
  697.  
  698. /* build actual code via table entry */
  699.  
  700. build_code(optab,j)
  701. struct optable optab[];
  702. int j;
  703. {
  704.     pcinc = optab[j].numbytes;
  705.     switch(optab[j].numbytes) {
  706.     case 1: switch(optab[j].opr1) {
  707.         case OPCODE_OR_DESTSL4:
  708.              generate((arg1_val<<4) | optab[j].opcode);
  709.              break;
  710.         default:
  711.              generate(optab[j].opcode);
  712.              break;
  713.         }
  714.             break;
  715.     case 2:    switch(optab[j].opr1) {
  716.             case DESTSL4_OR_SOURCE:
  717.              generate(optab[j].opcode);
  718.              generate((arg1_val<<4) | arg2_val);
  719.              break;
  720.             case ZDEST:
  721.              generate(optab[j].opcode);
  722.              if(arg1_subclass == WORKING)
  723.                 generate(0xe0 | arg1_val);
  724.              else
  725.                 generate(arg1_val);
  726.              break;
  727.             case OPCODE_OR_SOURCESL4:
  728.              generate((arg2_val << 4) | optab[j].opcode);
  729.              generate(arg1_val);
  730.              break;
  731.             case OPCODE_OR_DESTSL4:
  732.              generate((arg1_val<<4) | optab[j].opcode);
  733.              if(arg2_subclass == WORKING)
  734.                 generate(0xe0 | arg2_val);
  735.              else
  736.                 generate(arg2_val);
  737.              break;
  738.             case SOURCESL4_OR_DEST:
  739.              generate(optab[j].opcode);
  740.              generate((arg2_val<<4) | arg1_val);
  741.              break;
  742.         }
  743.         break;
  744.     case 3: generate(optab[j].opcode);
  745.         switch(optab[j].opr1) {
  746.             case ZSOURCE:
  747.              if(arg2_subclass == WORKING)
  748.                 generate(0xe0 | arg2_val);
  749.              else
  750.                 generate(arg2_val);
  751.              break;
  752.             case ZDEST:
  753.                  if(arg1_subclass == WORKING)
  754.                     generate(0xe0 | arg1_val);
  755.                  else {
  756.                 if(optab[j].dest == DA) { /* 16 bit addr */
  757.                    generate(arg1_val >> 8);    /* hi byte */
  758.                    generate(arg1_val & 0xff);  /* lo byte */
  759.                 }
  760.                 else
  761.                        generate(arg1_val);
  762.                  }
  763.              break;
  764.         }
  765.         if(optab[j].opr2) {
  766.             switch(optab[j].opr2) {
  767.                 case ZSOURCE:
  768.                  if(arg2_subclass == WORKING)
  769.                     generate(0xe0 | arg2_val);
  770.                  else
  771.                     generate(arg2_val);
  772.                  break;
  773.                 case ZDEST:
  774.                  if(arg1_subclass == WORKING)
  775.                     generate(0xe0 | arg1_val);
  776.                  else
  777.                     generate(arg1_val);
  778.                  break;
  779.             }
  780.             }
  781.         break;
  782.     
  783.     }
  784. }
  785.  
  786. /* a hack for indexed mode addressing */
  787.  
  788. create_idx()
  789. {
  790.     int ix_op,src,rindex,dest;
  791.     char *temp;
  792.  
  793.     if(pass == 1) {
  794.     pcinc = 3;    /* assume all ok for pass #1 */
  795.     return(1);
  796.     }
  797.  
  798.     pcinc = 3;    
  799.     if(is_in(args[1],'(')) {
  800.     ix_op = 0xd7;    /* dest is indexed */
  801.         temp = args[1];
  802.     while((*temp++ != '(')); /* get pointer to index register */
  803.     get_any(args[1]); /* get base register, must be r8 */
  804.     if(arg_type != R8)
  805.        errexit2("dest INDEX Base not absolute");
  806.     else
  807.         dest = arg_val;
  808.  
  809.     get_any(temp);    /* get index register */
  810.     if(arg_type != R4)
  811.         errexit2("dest INDEX must be working reg.");
  812.     else
  813.         rindex = arg_val;
  814.  
  815.         get_any(args[2]);
  816.     if(arg_type != R4)
  817.         errexit2("source must be working reg.");
  818.     else
  819.         src = arg_val;
  820.  
  821.     generate(ix_op);
  822.     generate((src << 4) | rindex);
  823.     generate(dest);
  824.     return(1);
  825.     }        
  826.     else {
  827.     if(is_in(args[2],'(')) 
  828.        ix_op = 0xc7; /* dest is r4 */
  829.     else
  830.        errexit2("Invalid index mode!");
  831.         temp = args[2];
  832.     while((*temp++ != '(')); /* get pointer to index register */
  833.     get_any(args[1]); /* get dest register, must be r4 */
  834.     if(arg_type != R4)
  835.         errexit2("dest must be working reg.");
  836.     else
  837.         dest = arg_val;
  838.     get_any(args[2]); /* get base register, must be r8 */
  839.     if(arg_type != R8)
  840.        errexit2("source INDEX Base not absolute");
  841.     else
  842.         src = arg_val;
  843.     get_any(temp);    /* get index register */
  844.     if(arg_type != R4)
  845.         errexit2("source INDEX must be working reg.");
  846.     else
  847.         rindex = arg_val;
  848.     generate(ix_op);
  849.     generate((dest << 4) | rindex);
  850.     generate(src);
  851.     return(1);
  852.     }
  853. }
  854.  
  855. is_in(s,c)
  856. char *s;
  857. char c;
  858. {
  859.     while(*s) {
  860.     if(*s == c)
  861.        return(1);
  862.     s++;
  863.     }
  864.     return(0);
  865. }
  866.  
  867.  
  868.  
  869. create_jr()
  870. {
  871.     int cc_code,cc_disp,cc_op;
  872.     int cc_addr;
  873.  
  874.     if(pass == 1) {  /* assume everything ok */
  875.     pcinc = 2;
  876.     return(1);
  877.     }
  878.  
  879.     cc_op = 0x0b;
  880.  
  881.     if(isnull(args[2])) {
  882.     cc_code = 0x80;
  883.         cc_addr = eval(args[1]); /* will bomb if can't evaluate */
  884.     }
  885.     else {
  886.      cc_addr = eval(args[2]);
  887.      if(!(cc_code = find_cc_code(args[1])))
  888.          errexit2("Condition code invalid!!");
  889.     }
  890.  
  891.     cc_disp = compute_relative(cc_addr,pc);
  892.     if((cc_disp > 127) | (cc_disp < -128)) 
  893.        errexit2("Relative branch out of range!!");
  894.  
  895.     pcinc = 2;
  896.     generate(cc_op | cc_code);
  897.     generate(cc_disp & 0xff);
  898.     return(1);
  899. }
  900.  
  901. /* create jp cc,dest */
  902. create_jp()
  903. {
  904.     int cc_code,cc_op;
  905.     int cc_addr;
  906.  
  907.     if(pass == 1) {  /* assume everything ok */
  908.     get_any(args[1]);
  909.     if(arg_type == IR4 || arg_type == IR8)
  910.        pcinc = 2;
  911.         else
  912.        pcinc = 3;
  913.     return(1);
  914.     }
  915.  
  916.  
  917.     if(isnull(args[2])) {
  918.     get_any(args[1]);
  919.     if(arg_type == IR4) {
  920.         cc_op = 0x30;
  921.         cc_addr = 0xe0 | arg_val;
  922.         generate(cc_op);
  923.         generate(cc_addr);
  924.         pcinc = 2;
  925.         return(1);
  926.         }
  927.     else
  928.         if(arg_type == IR8) {
  929.         cc_op = 0x30;
  930.         generate(cc_op);
  931.         generate(arg_val);
  932.         pcinc = 2;
  933.         return(1);
  934.         }
  935.         else 
  936.         cc_code = 0x80;
  937.             cc_addr = eval(args[1]); /* will bomb if can't evaluate */
  938.     }
  939.     else {
  940.      cc_addr = eval(args[2]);
  941.      if(!(cc_code = find_cc_code(args[1])))
  942.          errexit2("Condition code invalid!!");
  943.     }
  944.  
  945.     pcinc = 3;
  946.     cc_op = 0x0d;
  947.     generate(cc_op | cc_code);
  948.     generate(cc_addr >> 8);
  949.     generate(cc_addr & 0xff);
  950.     return(1);
  951. }
  952.  
  953.  
  954. /* create djnz code */
  955.  
  956. create_dj()
  957. {
  958.     int dj_disp,dj_op;
  959.     int dj_addr;
  960.  
  961.     if(pass == 1) {  /* assume everything ok */
  962.     pcinc = 2;
  963.     return(1);
  964.     }
  965.  
  966.     dj_op = 0x0a;
  967.  
  968.     if(!(get_any(args[1])))
  969.     errexit2("Syntax error");
  970.  
  971.     if(arg_type != R4)
  972.     errexit2("Invalid reg. spec");
  973.  
  974.     dj_addr = eval(args[2]);
  975.  
  976.     dj_disp = compute_relative(dj_addr,pc);
  977.     if((dj_disp > 127) | (dj_disp < -128)) 
  978.        errexit2("Relative branch out of range!!");
  979.  
  980.     pcinc = 2;
  981.     generate((arg_val << 4) | dj_op);
  982.     generate(dj_disp & 0xff);
  983.     return(1);
  984. }
  985.     
  986. find_cc_code(code)
  987. char *code;
  988. {
  989.     int j,cond;
  990.  
  991.     for(j = 0; j < CCSIZE;j++) {
  992.     if((cond = stricmp(code,cc[j].mne)) == 0)
  993.         return(cc[j].cc_value);
  994.     }
  995.     return(0);
  996. }
  997.  
  998.  
  999.  
  1000. compute_relative(dest,apc)
  1001. int dest;
  1002. int apc;
  1003. {
  1004.     apc += 2;
  1005.     return(dest - apc);
  1006. }
  1007.  
  1008.  
  1009. isnull(s)
  1010. char *s;
  1011. {
  1012.     if(*s)
  1013.     return(0);
  1014.     else
  1015.     return(1);
  1016. }
  1017.  
  1018. generate(val)
  1019. int val;
  1020. {
  1021.     code_line[code_line_index] = val;
  1022.     code_line_index++;
  1023.     if(pass == 2) {
  1024.     switch(fout_type) {
  1025.         case Z8:         fprintf(fpout,"%%%02x\n",val);
  1026.                      break;
  1027.         case MOTOROLA:   mout(val);
  1028.                  break;
  1029.         case INTEL:         iout(val);
  1030.                  break;
  1031.     }
  1032.     }
  1033.     bytes_generated++;
  1034. }
  1035.  
  1036. iout(val)
  1037. int val;
  1038. {
  1039.         bin_line[bindex++] = val;
  1040.         if(bindex == 32)
  1041.         flush_i();
  1042. }
  1043.  
  1044. mout(val)
  1045. int val;
  1046. {
  1047.         bin_line[bindex++] = val;
  1048.         if(bindex == 32)
  1049.         flush_m();
  1050. }
  1051.  
  1052. flush_m()
  1053. {
  1054.     int j;
  1055.  
  1056.     if(bindex) {
  1057.         fprintf(fpout,"S1");
  1058.         hexout(bindex+3);
  1059.     checksum += bindex+3;
  1060.     hexout(bin_pc >> 8);
  1061.         hexout(bin_pc & 0xff);
  1062.     checksum += (bin_pc>>8);
  1063.     checksum += (bin_pc & 0xff);
  1064.     bin_pc += bindex;
  1065.         for(j = 0; j < bindex; j++) {
  1066.         hexout(bin_line[j]);
  1067.         checksum += bin_line[j];
  1068.     }
  1069.         hexout(~checksum);
  1070.     fprintf(fpout,"\n");
  1071.         bindex = 0; checksum = 0;
  1072.     }
  1073. }
  1074.  
  1075. flush_i()
  1076. {
  1077.     int j;
  1078.  
  1079.     if(bindex) {
  1080.         fprintf(fpout,":");
  1081.         hexout(bindex);
  1082.     checksum += bindex;
  1083.     hexout(bin_pc >> 8);
  1084.         hexout(bin_pc & 0xff);
  1085.     checksum += (bin_pc>>8);
  1086.     checksum += (bin_pc & 0xff);
  1087.     hexout(0);
  1088.     checksum += 0;
  1089.     bin_pc += bindex;
  1090.         for(j = 0; j < bindex; j++) {
  1091.         hexout(bin_line[j]);
  1092.         checksum += bin_line[j];
  1093.     }
  1094.         hexout(~checksum+1);
  1095.     fprintf(fpout,"\n");
  1096.         bindex = 0; checksum = 0;
  1097.     }
  1098. }
  1099.  
  1100. end_m()
  1101. {
  1102.     flush_m();
  1103.     fprintf(fpout,"S9030000FC\n");
  1104. }
  1105.  
  1106. end_i()
  1107. {
  1108.     flush_i();
  1109.     fprintf(fpout,":00000001FF\n");
  1110. }
  1111.  
  1112. char    *hexstr = { "0123456789ABCDEF" } ;
  1113.  
  1114. hexout(byte)
  1115. int     byte;
  1116. {
  1117.  
  1118.    byte = byte & 0xff;
  1119.    fprintf(fpout,"%c%c",hexstr[byte>>4],hexstr[byte&017]);
  1120. }
  1121.  
  1122.         
  1123. get_any(st)
  1124. char *st;
  1125. {
  1126.     int tempn1;
  1127.  
  1128.     arg_subclass = 0;
  1129.  
  1130.     if(strnicmp(st,"@RR",3)== 0) { /* indirect register pair */
  1131.         if(st[3] == ':') {
  1132.        tempn1 = eval(&st[4]);
  1133.        if((tempn1 >= 0) && (tempn1 < 256)) {
  1134.         arg_val = tempn1; arg_type = IRR8;
  1135.         return(1);
  1136.        }
  1137.     }
  1138.     else {
  1139.           tempn1 = eval(&st[3]);
  1140.            if((tempn1 >= 0) && (tempn1 < 16)) {
  1141.             arg_val = tempn1; arg_type = IRR4;
  1142.             arg_subclass = WORKING;
  1143.             return(1);
  1144.                }
  1145.            else
  1146.             return(0);
  1147.          }
  1148.     }
  1149.  
  1150.     if(strnicmp(st,"RR",2)== 0) { /* register pair */
  1151.         if(st[2] == ':') {
  1152.        tempn1 = eval(&st[3]);
  1153.        if((tempn1 >= 0) && (tempn1 < 256)) {
  1154.         arg_val = tempn1; arg_type = RR8;
  1155.         return(1);
  1156.        }
  1157.     }
  1158.     else {
  1159.           tempn1 = eval(&st[2]);
  1160.            if((tempn1 >= 0) && (tempn1 < 16)) {
  1161.             arg_val = tempn1; arg_type = RR4;
  1162.             arg_subclass = WORKING;
  1163.             return(1);
  1164.                }
  1165.            else
  1166.             return(0);
  1167.         }
  1168.      }
  1169.     
  1170.  
  1171.     if(strnicmp(st,"@R",2)== 0) { /* indirect reg specifier */
  1172.         if(st[2] == ':') {
  1173.        tempn1 = eval(&st[3]);
  1174.        if((tempn1 >= 0) && (tempn1 < 256)) {
  1175.         arg_val = tempn1; arg_type = IR8;
  1176.         return(1);
  1177.        }
  1178.     }
  1179.     else {
  1180.           tempn1 = eval(&st[2]);
  1181.            if((tempn1 >= 0) && (tempn1 < 16)) {
  1182.             arg_val = tempn1; arg_type = IR4;
  1183.             arg_subclass = WORKING;
  1184.             return(1);
  1185.                }
  1186.            else
  1187.             return(0);
  1188.         }
  1189.      }
  1190.  
  1191.     if((st[0] == 'R') || st[0] == ('r')) {
  1192.         if(st[1] == ':') {
  1193.        tempn1 = eval(&st[2]);
  1194.        if((tempn1 >= 0) && (tempn1 < 256)) {
  1195.         arg_val = tempn1; arg_type = R8;
  1196.         return(1);
  1197.        }
  1198.     }
  1199.     else {
  1200.              tempn1 = eval(&st[1]);
  1201.            if((tempn1 >= 0) && (tempn1 < 16)) {
  1202.             arg_val = tempn1; arg_type = R4;
  1203.             arg_subclass = WORKING;
  1204.             return(1);
  1205.                }
  1206.            else
  1207.             return(0);
  1208.          }
  1209.      }
  1210.  
  1211.     if(st[0] == '#') {
  1212.     tempn1 = eval(&st[1]);
  1213.     if((tempn1 >= 0) && (tempn1 < 256)) {
  1214.        arg_val = tempn1; arg_type = IM8;
  1215.        return(1);
  1216.     }
  1217.     else 
  1218.             return(0);
  1219.     }
  1220.     if(st[0]) {
  1221.     tempn1 = eval(&st[0]);
  1222.     if((tempn1 >= 0) && (tempn1 < 65536)) {
  1223.        arg_val = tempn1; arg_type = DA;
  1224.        return(1);
  1225.     }
  1226.     else 
  1227.             return(0);
  1228.     }
  1229.  
  1230.  
  1231.     return(0);
  1232. }
  1233.  
  1234.  
  1235. /* scans a passed string for keyword and return index */
  1236.      
  1237. scankey(word)
  1238. char *word;
  1239. {
  1240.     int j,cond;
  1241.  
  1242.     for(j = 1; j < Z8SIZE; j++) {
  1243.     if((cond = stricmp(word,z8[j].mne)) == 0) {
  1244.        return(j);
  1245.     }
  1246.     }
  1247.     return(0);
  1248. }
  1249.  
  1250.  
  1251. /* scans a passed string for pseudo-op keyword and return index */
  1252.      
  1253. scan_pse(word)
  1254. char *word;
  1255. {
  1256.     int j,cond;
  1257.  
  1258.     for(j = 1; j < PSSIZE; j++) {
  1259.     if((cond = stricmp(word,ps[j].mne)) == 0) {
  1260.        return(j);
  1261.     }
  1262.     }
  1263.     return(0);
  1264. }
  1265.  
  1266. checklabel(s,c)
  1267. char *s;
  1268. int c;
  1269. {
  1270.     if(s[c-1] == ':') {
  1271.     s[c-1] = '\0';
  1272.     return(1);
  1273.     }
  1274.     else
  1275.         return(0);
  1276. }
  1277. /* process define word */
  1278.  
  1279. get_dw()
  1280. {
  1281.     int result;
  1282.  
  1283.     while((get_token(args[1]))) {
  1284.     result = eval(args[1]);
  1285.     generate(result>>8);
  1286.     generate(result & 0xff);
  1287.     pcinc+=2;
  1288.     gen_line();
  1289.     pcinc = 0;code_line_index = 0;
  1290.     listdb = 0; /* turn off line listing */
  1291.     }
  1292.     listdb = 1; /* turn back on line listing */
  1293. }
  1294.     
  1295.  
  1296. /* process define byte */
  1297.  
  1298. get_db()
  1299. {
  1300.     char *c;
  1301.     int result;
  1302.  
  1303.     while((get_token1(args[1]))) {
  1304.     c = args[1];
  1305.     switch(*c) {
  1306.         case '\'': /* ascii text */
  1307.             c++;
  1308.             while((*c) && (*c != '\'')) {
  1309.                 generate(*c);
  1310.                 pcinc++;c++;
  1311.                 if(pcinc == 3) {
  1312.                    gen_line();
  1313.                    pcinc = 0;code_line_index = 0;
  1314.                    listdb = 0;
  1315.                 }
  1316.             }
  1317.             break;
  1318.         default:  /* the rest */
  1319.             result = eval(args[1]);
  1320.             generate(result);pcinc++;
  1321.             if(pcinc == 3) {
  1322.                gen_line();
  1323.                pcinc = 0;code_line_index = 0;
  1324.                listdb = 0;
  1325.             }
  1326.             break;
  1327.         }
  1328.     }
  1329.     if(pcinc) {
  1330.        gen_line();
  1331.        pcinc = 0;code_line_index = 0;
  1332.     }
  1333.     listdb = 1;
  1334. }
  1335.  
  1336.     
  1337. /* extract a token from current line and copy into 's'.
  1338.    s = null string if no token is available. returns status:
  1339.    status = 0 = no token extracted ,otherwise status =
  1340.     number of characters in the token. */
  1341.  
  1342. get_token(s)
  1343. char *s;
  1344. {
  1345.     int st;
  1346.  
  1347.     st = 0;
  1348.     while(isany(*curline," ,\11\12\0")) /* skip any special chars */
  1349.          curline++;
  1350.  
  1351.     while(*curline) {
  1352.     if(isany(*curline," ,\11\12\0")) {
  1353.         *s = '\0';
  1354.         break;
  1355.         }
  1356.     else {
  1357.        if(*curline == ';') /* handle comment here */
  1358.           break;
  1359.        *s++ = *curline++; st++;
  1360.         }
  1361.     }
  1362.     *s = '\0';
  1363.     return(st);
  1364. }
  1365.  
  1366. get_token1(s)
  1367. char *s;
  1368. {
  1369.     int st;
  1370.  
  1371.     st = 0;
  1372.     while(isany(*curline," ,\11\12\0")) /* skip any special chars */
  1373.          curline++;
  1374.  
  1375.     if(*curline == '\'') {        /* start of ascii text */
  1376.     *s++ = *curline++; st++; }
  1377.  
  1378.     while(*curline) {
  1379.     if(isany(*curline,",\11\12\0")) {
  1380.         *s = '\0';
  1381.         break;
  1382.         }
  1383.     else {
  1384.        if(*curline == ';') /* handle comment here */
  1385.           break;
  1386.        *s++ = *curline++; st++;
  1387.         }
  1388.     }
  1389.     *s = '\0';
  1390.     return(st);
  1391. }
  1392.     
  1393.  
  1394. isany(c,s)
  1395. char c;
  1396. char *s;
  1397. {
  1398.     while(*s) {
  1399.     if(*s == c)
  1400.        return(1);
  1401.     s++;
  1402.     }
  1403.     return(0);
  1404. }
  1405.  
  1406. /* base routines for symbol table manipulation */
  1407.  
  1408. unsigned int hash(s)
  1409. char *s;
  1410. {
  1411.     unsigned hashval;
  1412.  
  1413.     for(hashval = 0; *s != '\0'; *s++)
  1414.     hashval = *s + 31 * hashval;
  1415.     return(hashval % HASHSIZE);
  1416. }
  1417.  
  1418. /* lookup-- look for 's' in symbol table. returns pointer to symbol
  1419.             structure -or- NULL if no match found  */
  1420.  
  1421. struct symbol *lookup(s)
  1422. char *s;
  1423. {
  1424.     struct symbol *sp;
  1425.  
  1426.     for(sp = hashtab[hash(s)]; sp != NULL; sp = sp->next)
  1427.     if(strcmp(s,sp->label) == 0)
  1428.         return(sp);
  1429.     return(NULL);
  1430. }
  1431.  
  1432. struct symbol *special_lookup(s)
  1433. char *s;
  1434. {
  1435.     char *s1;
  1436.     struct symbol *sp;
  1437.  
  1438.     s1 = args[4]; /* safe temp storage area */
  1439.  
  1440.     while(*s && (!(isany(*s,"!+-*/|&")))) 
  1441.     *s1++ = *s++;             /* copy string */
  1442.     *s1 = '\0';
  1443.     sp = lookup(args[4]);
  1444.     return(sp);
  1445. }
  1446.         
  1447.     
  1448.     
  1449. struct def *lookup_def(s)
  1450. char *s;
  1451. {
  1452.     struct def *dp;
  1453.     char *s1;
  1454.  
  1455.     special_def = 0;    
  1456.     s1=args[4];
  1457.     if(strpbrk(s,"!+-*/|&(")) {
  1458. /*    printf("Special lookup of '%s'\n",s); */
  1459.         while(*s && (!(isany(*s,"!+-*/|&(")))) 
  1460.         *s1++ = *s++;             /* copy string */
  1461.         *s1 = '\0';
  1462.     strcpy(args[5],s);            /* save remainder of arg */
  1463. /*    printf("Alternate lookup of '%s'\n",args[4]); */
  1464.         dp = lookup_def1(args[4]);
  1465.     if(dp)
  1466.        special_def = 1;            /* flag caller */
  1467. /*       printf("Found '%s'\n",args[4]); */
  1468.     return(dp);
  1469.     }
  1470.     else {
  1471.     dp = lookup_def1(s);
  1472. /*    printf("s = %s\n",s); */
  1473.     return(dp);
  1474.     }
  1475. }
  1476.  
  1477. struct def *lookup_def1(s)
  1478. char *s;
  1479. {
  1480.     struct def *dp;
  1481.     
  1482.     for(dp = deftab[hash(s)]; dp != NULL; dp = dp->next)
  1483.     if(strcmp(s,dp->label) == 0)
  1484.         return(dp);
  1485.     return(NULL);
  1486. }
  1487.  
  1488. /* create symbol--- install a symbol into table */
  1489.  
  1490. create_symbol(name,value)
  1491. char *name;
  1492. int value;
  1493. {
  1494.     struct symbol *sp;
  1495.     unsigned int hashval;
  1496.  
  1497.     if((sp = lookup(name)) == NULL) {  /* not found */
  1498.     sp = (struct symbol *) malloc(sizeof(*sp));
  1499.         if(sp == NULL || (sp->label = (char *)strdup(name)) == NULL)
  1500.         errexit2("Unable to allocte symbol table mem.");
  1501.         sp->value = value;
  1502.         hashval = hash(name);
  1503.         sp->next = hashtab[hashval];
  1504.         hashtab[hashval] = sp;
  1505.     nsyms++;
  1506.     }
  1507.     else {
  1508.     errexit2("Duplicate define");
  1509.     }
  1510.     return(1);
  1511. }
  1512.  
  1513. create_def(name,value)
  1514. char *name;
  1515. char *value;
  1516. {
  1517.     struct def *dp;
  1518.     unsigned int hashval;
  1519.  
  1520.     if((dp = lookup_def(name)) == NULL) {  /* not found */
  1521.     dp = (struct def *) malloc(sizeof(*dp));
  1522.         if(dp == NULL || (dp->label = (char *)strdup(name)) == NULL)
  1523.         errexit2("Unable to alloc symbol table mem.");
  1524.     if((dp->substitute = (char *)strdup(value)) == NULL)
  1525.         errexit2("Unable to alloc symbol table mem.");
  1526.         hashval = hash(name);
  1527.         dp->next = deftab[hashval];
  1528.         deftab[hashval] = dp;
  1529.     }
  1530.     else {
  1531.     errexit2("Duplicate def");
  1532.     }
  1533.     return(1);
  1534. }
  1535.  
  1536. list_symbols()
  1537. {
  1538.     int j,n;
  1539.     struct symbol *sp;
  1540.  
  1541.     if(!nsyms || !sym_list)
  1542.     return(0);
  1543.     if(!(spoint = (struct symbol**) malloc(sizeof(*spoint) * nsyms))) {
  1544.     printf("Not enough memory for sorted symbol table\n");
  1545.     return(0);
  1546.      }
  1547. /* make list of all pointers to symbol entrys */
  1548.     
  1549.     for(j=0,n=0; j < HASHSIZE;j++) {
  1550.     if(hashtab[j]) {
  1551.         for(sp = hashtab[j]; sp != NULL; sp = sp->next) {
  1552.         spoint[n++] = sp;
  1553.         }
  1554.         }
  1555.      }
  1556. /* sort list */
  1557.  
  1558.     qsort(spoint,nsyms,sizeof(char *),sym_cmp);  
  1559.     printf("\n\nSymbol Table:\n\n");
  1560.  
  1561. /* print list */
  1562.  
  1563.     for(j=0; j < nsyms;j++) {
  1564.     sp = spoint[j];
  1565.     printf(" %04X -- %s\n",sp->value,sp->label);
  1566.      }
  1567. }
  1568.  
  1569. sym_cmp(a1,b1)
  1570. struct symbol *a1[],*b1[];
  1571.  
  1572. {
  1573.     struct symbol *a,*b;
  1574.     a = (struct symbol *) a1[0];
  1575.     b = (struct symbol *) b1[0];
  1576.     return(strnicmp(a->label,b->label,14));
  1577. }
  1578.  
  1579. /* Main expression evaluation.
  1580.    gets the next value from parse_line buffer.
  1581.    ends up pointing to next math operator or null
  1582. */
  1583.  
  1584. get_exp_val()
  1585. {
  1586.     struct symbol *sp;
  1587.     int ret_val;
  1588.  
  1589.  
  1590. /*    while((isany(*parse_line," ")))
  1591.     parse_line++;
  1592. */  
  1593.     if((isalpha(*parse_line))) { /* better be a label!!! */
  1594.     sp = special_lookup(parse_line);
  1595.     if(!sp) {
  1596.         if(pass == 2)
  1597.         errexit2("Undefined Label");
  1598.         else {
  1599.           scan_to_next_math_op();
  1600.           return(0);
  1601.         }
  1602.         }
  1603.     else {
  1604.           scan_to_next_op();
  1605.           if(parse_line) {
  1606.          if (*parse_line  == '!') { /* handle address operator */
  1607.              parse_line++;
  1608.              if(*parse_line == 'H' || *parse_line == 'h') {
  1609.             scan_to_next_op();
  1610.             return(sp->value >> 8); }
  1611.              else
  1612.             if(*parse_line == 'L'|| *parse_line == 'l') {
  1613.                scan_to_next_op();
  1614.                return(sp->value & 0xff); }
  1615.             else
  1616.                errexit2("Invalid address operator");
  1617.          } else return(sp->value);
  1618.           } else return(sp->value);
  1619.         }
  1620.     }
  1621. /* if we made it here we better have a constant */            
  1622.            
  1623.     if(!(isany(*parse_line,"%$'0123456789")))
  1624.     errexit2("Invalid constant");
  1625.     else {
  1626.     ret_val = getval(parse_line);
  1627.     scan_to_next_op();
  1628.     return(ret_val);
  1629.     }
  1630. }
  1631.  
  1632. scan_to_next_op()
  1633. {
  1634.     while(!(isany(*parse_line,"+-*/!|&"))) {
  1635.     if(*parse_line && *parse_line != ';')
  1636.        parse_line++;
  1637.     else {
  1638.         parse_line = NULL;
  1639.         return(0);
  1640.     }
  1641.     }
  1642. }    
  1643.  
  1644. scan_to_next_math_op()
  1645. {
  1646.     while(!(isany(*parse_line,"+-*/|&"))) {
  1647.     if(*parse_line && *parse_line != ';')
  1648.        parse_line++;
  1649.     else {
  1650.         parse_line = NULL;
  1651.         return(0);
  1652.     }
  1653.     }
  1654. }    
  1655.     
  1656.  
  1657. eval(curline) /* evaluate expression */
  1658. char *curline;
  1659. {
  1660.     int left,right,operator;
  1661.     left = 0;
  1662.  
  1663.     parse_line = curline;
  1664.      
  1665.     left = get_exp_val(); /* get leftmost operand */
  1666.  
  1667.      while(parse_line) { /* get operator and next expression */
  1668.            operator = *parse_line++;
  1669.            right = get_exp_val();
  1670.            switch (operator) {
  1671.            case '+': left = left + right;
  1672.                  break;
  1673.                case '-': left = left - right;
  1674.                  break;
  1675.            case '*': left = left * right;
  1676.                  break;
  1677.            case '/': if(right > 0)
  1678.                  left = left / right;
  1679.                  break;
  1680.            case '|': left = left | right;
  1681.                  break;
  1682.            case '&': left = left & right;
  1683.                  break;
  1684.            }
  1685.       }
  1686.       return(left);
  1687. }
  1688.  
  1689. /* char digit connversion routines */
  1690.  
  1691. cvdig(ch)            /* return value of digit or -1 */
  1692. char ch;
  1693. {
  1694.  int z;
  1695.     if((z = ch) >= '0' && z <= '9') z -= '0';
  1696.            else
  1697.             if((z &= 0137) >= 'A' && z <= 'F') z -= 'A' - 10;
  1698.            else
  1699.             return (-1);
  1700.     if(z < radix)
  1701.        return(z);
  1702.  
  1703.   return (-1);
  1704. }
  1705.  
  1706. /* get numeric value from string, expects first char of string to
  1707.    be the radix specifier. % = binary, $ = hex, @ = octal '0..9' = decimal.
  1708.    returns converted value..
  1709. */
  1710.  
  1711. getval(curline)
  1712. char *curline;
  1713. {
  1714.   int j,n,k;
  1715.  
  1716.   switch(*curline)  
  1717.      { case '$':  radix = 16; curline++; break;
  1718.        case '%':  radix = 2;  curline++; break;
  1719.        case '\'': radix = 255; curline++; break;
  1720.        default:   radix = 10;
  1721.      }
  1722.  
  1723.   j = 0;k = 0;
  1724.   if(radix < 255) {
  1725.       while(*curline) {
  1726.         if((n = cvdig(*curline++)) < 0){
  1727.            curline--;
  1728.            break;}
  1729.         j = j * radix + n;
  1730.         k++;
  1731.       }
  1732.   }
  1733.   else {
  1734.     j = *curline++;
  1735.     curline++;
  1736.   }
  1737.   return(j);
  1738. }
  1739.