home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / emulator / unix / z80pack / z80asm / z80amain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-09  |  9.3 KB  |  499 lines

  1. /*
  2.  *      Z80 - Assembler
  3.  *      Copyright (C) 1987-1992 by Udo Munk
  4.  *
  5.  *    History:
  6.  *    17-SEP-1987 Development under Digital Research CP/M 2.2
  7.  *      28-JUN-1988 Switched to Unix System V.3
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include "z80a.h"
  13. #include "z80aglb.h"
  14.  
  15. static char *errmsg[] = {               /* Fehlermeldungen fuer fatal() */
  16.     "out of memory: %s",            /* 0 */
  17.     "usage: z80asm -ofile -f[b|m|h] -l[file] -s[n|a] -v -dsymbol ... file ...",
  18.     "Assembly halted",              /* 2 */
  19.     "can't open file %s",           /* 3 */
  20.     "internal error: %s"            /* 4 */
  21. };
  22.  
  23. main(argc, argv)
  24. int argc;
  25. char *argv[];
  26. {
  27.     int len;
  28.  
  29.     init();
  30.     options(argc, argv);
  31.     printf("Z80 - Assembler Release %s, %s\n", REL, COPYR);
  32.     pass1();
  33.     pass2();
  34.     if (list_flag) {
  35.         switch (sym_flag) {
  36.         case 0:         /* keine Symboltabelle */
  37.             break;
  38.         case 1:         /* unsortierte Symboltabelle */
  39.             lst_sym();
  40.             break;
  41.         case 2:         /* nach Namen sortierte Symboltabelle */
  42.             len = copy_sym();
  43.             n_sort_sym(len);
  44.             lst_sort_sym(len);
  45.             break;
  46.         case 3:         /* nach Adressen sortierte Symboltabelle */
  47.             len = copy_sym();
  48.             a_sort_sym(len);
  49.             lst_sort_sym(len);
  50.             break;
  51.         default:
  52.             break;
  53.         }
  54.         fclose(lstfp);
  55.     }
  56.     return(errors);
  57. }
  58.  
  59. /*
  60.  *    Initialisierung
  61.  */
  62. init()
  63. {
  64.     errfp = stdout;
  65. }
  66.  
  67. /*
  68.  *    Diese Funktion bearbeitet die beim Aufruf angegebenen Options.
  69.  *      Die uebergebenen Dateinamen werden in die entsprechenden
  70.  *    Strings uebernommen.
  71.  */
  72. options(argc, argv)
  73. int argc;
  74. char *argv[];
  75. {
  76.     register char *s, *t;
  77.     register int i;
  78.     char *malloc();
  79.  
  80.     while (--argc > 0 && (*++argv)[0] == '-')
  81.         for (s = argv[0]+1; *s != '\0'; s++)
  82.             switch (*s) {
  83.             case 'o':
  84.             case 'O':
  85.                 if (*++s == '\0') {
  86.                     puts("name missing in option -o");
  87.                     usage();
  88.                 }
  89.                 get_fn(objfn, s, OBJEXT);
  90.                 s += (strlen(s) - 1);
  91.                 break;
  92.             case 'l':
  93.             case 'L':
  94.                 if (*(s + 1) != '\0') {
  95.                     get_fn(lstfn, ++s, LSTEXT);
  96.                     s += (strlen(s) - 1);
  97.                 }
  98.                 list_flag = 1;
  99.                 break;
  100.             case 's':
  101.             case 'S':
  102.                 if (*(s + 1) == '\0')
  103.                     sym_flag = 1;
  104.                 else if ((*(s + 1) == 'n') || (*(s + 1) == 'N'))
  105.                     sym_flag = 2;
  106.                 else if ((*(s + 1) == 'a') || (*(s + 1) == 'A'))
  107.                     sym_flag = 3;
  108.                 else {
  109.                     printf("unknown option -%s\n", s);
  110.                     usage();
  111.                 }
  112.                 s += (strlen(s) - 1);
  113.                 break;
  114.             case 'f':
  115.             case 'F':
  116.                 if ((*(s + 1) == 'b') || (*(s + 1) == 'B'))
  117.                     out_form = OUTBIN;
  118.                 else if ((*(s + 1) == 'm') || (*(s + 1) == 'M'))
  119.                     out_form = OUTMOS;
  120.                 else if ((*(s + 1) == 'h') || (*(s + 1) == 'H'))
  121.                     out_form = OUTHEX;
  122.                 else {
  123.                     printf("unknown option -%s\n", s);
  124.                     usage();
  125.                 }
  126.                 s += (strlen(s) - 1);
  127.                 break;
  128.             case 'd':
  129.             case 'D':
  130.                 if (*++s == '\0') {
  131.                     puts("name missing in option -d");
  132.                     usage();
  133.                 }
  134.                 t = tmp;
  135.                 while (*s)
  136.                     *t++ = islower(*s) ? toupper(*s++) : *s++;
  137.                 s--;
  138.                 *t = '\0';
  139.                 if (put_sym(tmp, 0))
  140.                     fatal(F_OUTMEM, "symbols");
  141.                 break;
  142.             case 'v':
  143.             case 'V':
  144.                 ver_flag = 1;
  145.                 break;
  146.             default :
  147.                 printf("unknown option %c\n", *s);
  148.                 usage();
  149.             }
  150.     i = 0;
  151.     while ((argc--) && (i < MAXFN)) {
  152.         if ((infiles[i] = malloc(LENFN + 1)) == NULL)
  153.             fatal(F_OUTMEM, "filenames");
  154.         get_fn(infiles[i], *argv++, SRCEXT);
  155.         i++;
  156.     }
  157.     if (i == 0) {
  158.         printf("no input file given\n");
  159.         usage();
  160.     }
  161. }
  162.  
  163. /*
  164.  *    An den Argumenten in der Befehlszeile ist was falsch,
  165.  *    Gebrauchsanleitung ausgeben und abbrechen.
  166.  */
  167. usage()
  168. {
  169.     fatal(F_USAGE, NULL);
  170. }
  171.  
  172. /*
  173.  *    Fehlermeldung ausgeben und abbrechen
  174.  */
  175. fatal(i, arg)
  176. register int i;
  177. register char *arg;
  178. {
  179.     void exit();
  180.  
  181.     printf(errmsg[i], arg);
  182.     putchar('\n');
  183.     exit(1);
  184. }
  185.  
  186. /*
  187.  *    Pass 1:
  188.  *      - Lauf ueber alle Quelldateien
  189.  */
  190. pass1()
  191. {
  192.     register int fi;
  193.  
  194.     pass = 1;
  195.     pc = 0;
  196.     fi = 0;
  197.     if (!ver_flag)
  198.         puts("Pass 1");
  199.     open_o_files(infiles[fi]);
  200.     while (infiles[fi] != NULL) {
  201.         if (!ver_flag)
  202.             printf("   Read    %s\n", infiles[fi]);
  203.         p1_file(infiles[fi]);
  204.         fi++;
  205.     }
  206.     if (errors) {
  207.         fclose(objfp);
  208.         unlink(objfn);
  209.         printf("%d error(s)\n", errors);
  210.         fatal(F_HALT, NULL);
  211.     }
  212. }
  213.  
  214. /*
  215.  *    Pass 1:
  216.  *      - Lauf ueber eine Quelldatei
  217.  *
  218.  *      Input:  Name der zu bearbeitenden Quelldatei
  219.  */
  220. p1_file(fn)
  221. char *fn;
  222. {
  223.     c_line = 0;
  224.     srcfn = fn;
  225.     if ((srcfp = fopen(fn, READA)) == NULL)
  226.         fatal(F_FOPEN, fn);
  227.     while (p1_line())
  228.         ;
  229.     fclose(srcfp);
  230.     if (iflevel)
  231.         asmerr(E_MISEIF);
  232. }
  233.  
  234. /*
  235.  *    Pass 1:
  236.  *      - Eine Zeile Quelle verarbeiten
  237.  *
  238.  *      Output: 1 Zeile verarbeitet
  239.  *              0 EOF erreicht
  240.  */
  241. p1_line()
  242. {
  243.     register char *p;
  244.     register int i;
  245.     register struct opc *op;
  246.     char *get_label(), *get_opcode(), *get_arg();
  247.     struct opc *search_op();
  248.  
  249.     if ((p = fgets(line, MAXLINE, srcfp)) == NULL)
  250.         return(0);
  251.     c_line++;
  252.     p = get_label(label, p);
  253.     p = get_opcode(opcode, p);
  254.     p = get_arg(operand, p);
  255.     if (strcmp(opcode, ENDFILE) == 0)
  256.         return(0);
  257.     if (*opcode) {
  258.         if ((op = search_op(opcode)) != NULL) {
  259.             i = (*op->op_fun)(op->op_c1, op->op_c2);
  260.             if (gencode)
  261.                 pc += i;
  262.         } else
  263.             asmerr(E_ILLOPC);
  264.     } else
  265.         if (*label)
  266.             put_label();
  267.     return(1);
  268. }
  269.  
  270. /*
  271.  *    Pass 2:
  272.  *        - Lauf ueber alle Quelldateien
  273.  */
  274. pass2()
  275. {
  276.     register int fi;
  277.  
  278.     pass = 2;
  279.     pc = 0;
  280.     fi = 0;
  281.     if (!ver_flag)
  282.         puts("Pass 2");
  283.     obj_header();
  284.     while (infiles[fi] != NULL) {
  285.         if (!ver_flag)
  286.             printf("   Read    %s\n", infiles[fi]);
  287.         p2_file(infiles[fi]);
  288.         fi++;
  289.     }
  290.     obj_end();
  291.     fclose(objfp);
  292.     printf("%d error(s)\n", errors);
  293. }
  294.  
  295. /*
  296.  *      Pass 2:
  297.  *      - Lauf ueber eine Quelldatei
  298.  *
  299.  *      Input:  Name der zu bearbeitenden Quelldatei
  300.  */
  301. p2_file(fn)
  302. char *fn;
  303. {
  304.     c_line = 0;
  305.     srcfn = fn;
  306.     if ((srcfp = fopen(fn, READA)) == NULL)
  307.         fatal(F_FOPEN, fn);
  308.     while (p2_line())
  309.         ;
  310.     fclose(srcfp);
  311. }
  312.  
  313. /*
  314.  *      Pass 2:
  315.  *      - Eine Zeile Quelle verarbeiten
  316.  *
  317.  *      Output: 1 Zeile verarbeitet
  318.  *              0 EOF erreicht
  319.  */
  320. p2_line()
  321. {
  322.     register char *p;
  323.     register int op_count;
  324.     register struct opc *op;
  325.     char *get_label(), *get_opcode(), *get_arg();
  326.     struct opc *search_op();
  327.  
  328.     if ((p = fgets(line, MAXLINE, srcfp)) == NULL)
  329.         return(0);
  330.     c_line++;
  331.     s_line++;
  332.     p = get_label(label, p);
  333.     p = get_opcode(opcode, p);
  334.     p = get_arg(operand, p);
  335.     if (strcmp(opcode, ENDFILE) == 0) {
  336.         lst_line(pc, 0);
  337.         return(0);
  338.     }
  339.     if (*opcode) {
  340.         op = search_op(opcode);
  341.         op_count = (*op->op_fun)(op->op_c1, op->op_c2);
  342.         if (gencode) {
  343.             lst_line(pc, op_count);
  344.             obj_writeb(op_count);
  345.             pc += op_count;
  346.         } else {
  347.             sd_flag = 2;
  348.             lst_line(0, 0);
  349.         }
  350.     } else {
  351.         sd_flag = 2;
  352.         lst_line(0, 0);
  353.     }
  354.     return(1);
  355. }
  356.  
  357. /*
  358.  *    Oeffnen der Ausgabedateien: Objectdatei und bei Option
  359.  *    -l der Listdatei. Der Dateiname der Quelldatei wird 
  360.  *    uebergeben. Die Dateinamen der Object- und Listdatei
  361.  *    werden, wenn nicht hinter den Optionen -l und -o angegeben,
  362.  *    aus dem Quelldateinamen erzeugt.
  363.  */
  364. open_o_files(source)
  365. register char *source;
  366. {
  367.     char *strcpy(), *strcat(), *strrchr();
  368.     register char *p;
  369.  
  370.     if (*objfn == '\0')
  371.         strcpy(objfn, source);
  372.     if ((p = strrchr(objfn, '.')) != NULL)
  373.         strcpy(p, OBJEXT);
  374.     else
  375.         strcat(objfn, OBJEXT);
  376.  
  377.     if (out_form == OUTHEX)
  378.         objfp = fopen(objfn, WRITEA);
  379.     else
  380.         objfp = fopen(objfn, WRITEB);
  381.     if (objfp == NULL)
  382.         fatal(F_FOPEN, objfn);
  383.     if (list_flag) {
  384.         if (*lstfn == '\0')
  385.             strcpy(lstfn, source);
  386.         if ((p = strrchr(lstfn, '.')) != NULL)
  387.             strcpy(p, LSTEXT);
  388.         else
  389.             strcat(lstfn, LSTEXT);
  390.         if ((lstfp = fopen(lstfn, WRITEA)) == NULL)
  391.             fatal(F_FOPEN, lstfn);
  392.         errfp = lstfp;
  393.     }
  394. }
  395.  
  396. /*
  397.  *    Einen Dateinamen in "dest" aus "src" und "ext" zusammenbauen
  398.  */
  399. get_fn(dest, src, ext)
  400. char *dest, *src, *ext;
  401. {
  402.     char *strrchr(), *strcat();
  403.     register int i;
  404.     register char *sp, *dp;
  405.  
  406.     i = 0;
  407.     sp = src;
  408.     dp = dest;
  409.     while ((i++ < LENFN) && (*sp != '\0'))
  410.         *dp++ = *sp++;
  411.     *dp = '\0';
  412.     if ((strrchr(dest,'.') == NULL) && (strlen(dest) <= (LENFN-strlen(ext))))
  413.         strcat(dest, ext);
  414. }
  415.  
  416. /*
  417.  *    Extrahieren der Labels, Konstanten und Variablen aus
  418.  *    einer Zeile Quelltext mit Umwandlung in Grosschrift
  419.  *    und Begrenzung der Laenge.
  420.  */
  421. char *get_label(s, l)
  422. register char *s, *l;
  423. {
  424.     register int i;
  425.  
  426.     i = 0;
  427.     if (*l == LINCOM)
  428.         goto comment;
  429.     while (!isspace(*l) && *l != COMMENT && *l != LABSEP && i < SYMSIZE) {
  430.         *s++ = islower(*l) ? toupper(*l++) : *l++;
  431.         i++;
  432.     }
  433. comment:
  434.     *s = '\0';
  435.     return(l);
  436. }
  437.  
  438. /*
  439.  *    Extrahieren des Op-Codes aus einer Zeile Quelltext ab der
  440.  *    uebergebenen Position. Der String wird bei der Uebertragung
  441.  *    in Grosschrift umgewandelt.
  442.  */
  443. char *get_opcode(s, l)
  444. register char *s, *l;
  445. {
  446.     if (*l == LINCOM)
  447.         goto comment;
  448.     while (!isspace(*l) && *l != COMMENT && *l != LABSEP)
  449.         l++;
  450.     if (*l == LABSEP)
  451.         l++;
  452.     while (*l == ' ' || *l == '\t')
  453.         l++;
  454.     while (!isspace(*l) && *l != COMMENT)
  455.         *s++ = islower(*l) ? toupper(*l++) : *l++;
  456. comment:
  457.     *s = '\0';
  458.     return(l);
  459. }
  460.  
  461. /*
  462.  *    Extrahieren des Operanden aus einer Zeile Quelltext ab der
  463.  *    uebergebenen Position. Der String wird bei der Uebertragung
  464.  *      in Grosschrift umgewandelt und Blanks sowie Tabs werden
  465.  *      ueberlesen. Strings, die in ' eingeschlossen sind, werden
  466.  *      ohne Aenderung kopiert.
  467.  */
  468. char *get_arg(s, l)
  469. register char *s, *l;
  470. {
  471.     if (*l == LINCOM)
  472.         goto comment;
  473.     while (*l == ' ' || *l == '\t')
  474.         l++;
  475.     while (*l != '\n' && *l != COMMENT) {
  476.         if (isspace(*l)) {
  477.             l++;
  478.             continue;
  479.         }
  480.         if (*l != STRSEP) {
  481.             *s++ = islower(*l) ? toupper(*l) : *l;
  482.             l++;
  483.             continue;
  484.         }
  485.         *s++ = *l++;
  486.         if (*(s - 2) == 'F')    /* EX AF,AF' !!!!! */
  487.             continue;
  488.         while (*l != STRSEP) {
  489.             if (*l == '\n' || *l == '\0' || *l == COMMENT)
  490.                 goto comment;
  491.             *s++ = *l++;
  492.         }
  493.         *s++ = *l++;
  494.     }
  495. comment:
  496.     *s = '\0';
  497.     return(l);
  498. }
  499.