This repository has been archived on 2025-10-07. You can view files and clone it, but cannot push or open issues or pull requests.
Files
chibi-pc09/emu/z80pack-1.9/z80asm/z80amain.c
Amber 783d32a495 copy all local files to repo
cp/m files, sprites, circuit design
2020-05-15 09:07:45 -04:00

504 lines
9.1 KiB
C

/*
* Z80 - Assembler
* Copyright (C) 1987-2006 by Udo Munk
*
* History:
* 17-SEP-1987 Development under Digital Research CP/M 2.2
* 28-JUN-1988 Switched to Unix System V.3
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
*/
/*
* main module, handles the options and runs 2 passes over the sources
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "z80a.h"
#include "z80aglb.h"
void init(void), options(int, char *[]);
void usage(void), fatal(int, char *);
void pass1(void), p1_file(char *);
void pass2(void), p2_file(char *);
void open_o_files(char *), get_fn(char *, char *, char *);
char *get_label(char *, char *);
char *get_opcode(char *, char *);
char *get_arg(char *, char *);
extern void asmerr(int);
extern void lst_line(int, int);
extern void lst_sym(void);
extern void lst_sort_sym(int);
extern void obj_header(void);
extern void obj_end(void);
extern void obj_writeb(int);
extern struct opc *search_op(char *);
extern int put_sym(char *, int);
extern void put_label(void);
extern int copy_sym(void);
extern void n_sort_sym(int);
extern void a_sort_sym(int);
static char *errmsg[] = { /* error messages for fatal() */
"out of memory: %s", /* 0 */
"usage: z80asm -ofile -f[b|m|h] -l[file] -s[n|a] {-x} -v -dsymbol ... file ...",
"Assembly halted", /* 2 */
"can't open file %s", /* 3 */
"internal error: %s" /* 4 */
};
main(int argc, char *argv[])
{
int len;
init();
options(argc, argv);
printf("Z80 - Assembler Release %s, %s\n", REL, COPYR);
pass1();
pass2();
if (list_flag) {
switch (sym_flag) {
case 0: /* no symbol table */
break;
case 1: /* unsorted symbol table */
lst_sym();
break;
case 2: /* symbol table sorted by name */
len = copy_sym();
n_sort_sym(len);
lst_sort_sym(len);
break;
case 3: /* symbol table sorted by address */
len = copy_sym();
a_sort_sym(len);
lst_sort_sym(len);
break;
default:
break;
}
fclose(lstfp);
}
return(errors);
}
/*
* initialization
*/
void init(void)
{
errfp = stdout;
}
/*
* process options
*/
void options(int argc, char *argv[])
{
register char *s, *t;
register int i;
while (--argc > 0 && (*++argv)[0] == '-')
for (s = argv[0]+1; *s != '\0'; s++)
switch (*s) {
case 'o':
case 'O':
if (*++s == '\0') {
puts("name missing in option -o");
usage();
}
get_fn(objfn, s, OBJEXT);
s += (strlen(s) - 1);
break;
case 'l':
case 'L':
if (*(s + 1) != '\0') {
get_fn(lstfn, ++s, LSTEXT);
s += (strlen(s) - 1);
}
list_flag = 1;
break;
case 's':
case 'S':
if (*(s + 1) == '\0')
sym_flag = 1;
else if ((*(s + 1) == 'n') || (*(s + 1) == 'N'))
sym_flag = 2;
else if ((*(s + 1) == 'a') || (*(s + 1) == 'A'))
sym_flag = 3;
else {
printf("unknown option -%s\n", s);
usage();
}
s += (strlen(s) - 1);
break;
case 'x':
case 'X':
dump_flag = 1;
break;
case 'f':
case 'F':
if ((*(s + 1) == 'b') || (*(s + 1) == 'B'))
out_form = OUTBIN;
else if ((*(s + 1) == 'm') || (*(s + 1) == 'M'))
out_form = OUTMOS;
else if ((*(s + 1) == 'h') || (*(s + 1) == 'H'))
out_form = OUTHEX;
else {
printf("unknown option -%s\n", s);
usage();
}
s += (strlen(s) - 1);
break;
case 'd':
case 'D':
if (*++s == '\0') {
puts("name missing in option -d");
usage();
}
t = tmp;
while (*s)
*t++ = islower(*s) ? toupper(*s++)
: *s++;
s--;
*t = '\0';
if (put_sym(tmp, 0))
fatal(F_OUTMEM, "symbols");
break;
case 'v':
case 'V':
ver_flag = 1;
break;
default :
printf("unknown option %c\n", *s);
usage();
}
i = 0;
while ((argc--) && (i < MAXFN)) {
if ((infiles[i] = malloc(LENFN + 1)) == NULL)
fatal(F_OUTMEM, "filenames");
get_fn(infiles[i], *argv++, SRCEXT);
i++;
}
if (i == 0) {
printf("no input file given\n");
usage();
}
}
/*
* error in options, print usage
*/
void usage(void)
{
fatal(F_USAGE, NULL);
}
/*
* print error messages and abort
*/
void fatal(int i, char *arg)
{
printf(errmsg[i], arg);
putchar('\n');
exit(1);
}
/*
* Pass 1:
* - process all source files
*/
void pass1(void)
{
register int fi;
pass = 1;
pc = 0;
fi = 0;
if (!ver_flag)
puts("Pass 1");
open_o_files(infiles[fi]);
while (infiles[fi] != NULL) {
if (!ver_flag)
printf(" Read %s\n", infiles[fi]);
p1_file(infiles[fi]);
fi++;
}
if (errors) {
fclose(objfp);
unlink(objfn);
printf("%d error(s)\n", errors);
fatal(F_HALT, NULL);
}
}
/*
* Pass 1:
* - process one source file
*
* Input: name of source file
*/
void p1_file(char *fn)
{
c_line = 0;
srcfn = fn;
if ((srcfp = fopen(fn, READA)) == NULL)
fatal(F_FOPEN, fn);
while (p1_line())
;
fclose(srcfp);
if (iflevel)
asmerr(E_MISEIF);
}
/*
* Pass 1:
* - process one line of source
*
* Output: 1 line processed
* 0 EOF
*/
int p1_line(void)
{
register char *p;
register int i;
register struct opc *op;
if ((p = fgets(line, MAXLINE, srcfp)) == NULL)
return(0);
c_line++;
p = get_label(label, p);
p = get_opcode(opcode, p);
p = get_arg(operand, p);
if (strcmp(opcode, ENDFILE) == 0)
return(0);
if (*opcode) {
if ((op = search_op(opcode)) != NULL) {
i = (*op->op_fun)(op->op_c1, op->op_c2);
if (gencode)
pc += i;
} else
asmerr(E_ILLOPC);
} else
if (*label)
put_label();
return(1);
}
/*
* Pass 2:
* - process all source files
*/
void pass2(void)
{
register int fi;
pass = 2;
pc = 0;
fi = 0;
if (!ver_flag)
puts("Pass 2");
obj_header();
while (infiles[fi] != NULL) {
if (!ver_flag)
printf(" Read %s\n", infiles[fi]);
p2_file(infiles[fi]);
fi++;
}
obj_end();
fclose(objfp);
printf("%d error(s)\n", errors);
}
/*
* Pass 2:
* - process one source file
*
* Input: name of source file
*/
void p2_file(char *fn)
{
c_line = 0;
srcfn = fn;
if ((srcfp = fopen(fn, READA)) == NULL)
fatal(F_FOPEN, fn);
while (p2_line())
;
fclose(srcfp);
}
/*
* Pass 2:
* - process one line of source
*
* Output: 1 line processed
* 0 EOF
*/
int p2_line(void)
{
register char *p;
register int op_count;
register struct opc *op;
if ((p = fgets(line, MAXLINE, srcfp)) == NULL)
return(0);
c_line++;
s_line++;
p = get_label(label, p);
p = get_opcode(opcode, p);
p = get_arg(operand, p);
if (strcmp(opcode, ENDFILE) == 0) {
lst_line(pc, 0);
return(0);
}
if (*opcode) {
op = search_op(opcode);
op_count = (*op->op_fun)(op->op_c1, op->op_c2);
if (gencode) {
lst_line(pc, op_count);
obj_writeb(op_count);
pc += op_count;
} else {
sd_flag = 2;
lst_line(0, 0);
}
} else {
sd_flag = 2;
lst_line(0, 0);
}
return(1);
}
/*
* open output files:
* input is filename of source file
* list and object filenames are build from source filename if
* not given by options
*/
void open_o_files(char *source)
{
register char *p;
if (*objfn == '\0')
strcpy(objfn, source);
if ((p = strrchr(objfn, '.')) != NULL)
strcpy(p, OBJEXT);
else
strcat(objfn, OBJEXT);
if (out_form == OUTHEX)
objfp = fopen(objfn, WRITEA);
else
objfp = fopen(objfn, WRITEB);
if (objfp == NULL)
fatal(F_FOPEN, objfn);
if (list_flag) {
if (*lstfn == '\0')
strcpy(lstfn, source);
if ((p = strrchr(lstfn, '.')) != NULL)
strcpy(p, LSTEXT);
else
strcat(lstfn, LSTEXT);
if ((lstfp = fopen(lstfn, WRITEA)) == NULL)
fatal(F_FOPEN, lstfn);
errfp = lstfp;
}
}
/*
* create a filename in "dest" from "src" and "ext"
*/
void get_fn(char *dest, char *src, char *ext)
{
register int i;
register char *sp, *dp;
i = 0;
sp = src;
dp = dest;
while ((i++ < LENFN) && (*sp != '\0'))
*dp++ = *sp++;
*dp = '\0';
if ((strrchr(dest,'.') == NULL) &&
(strlen(dest) <= (LENFN - strlen(ext))))
strcat(dest, ext);
}
/*
* get labels, constants and variables from source line
* convert names to upper case and truncate length of name
*/
char *get_label(char *s, char *l)
{
register int i;
i = 0;
if (*l == LINCOM)
goto comment;
while (!isspace(*l) && *l != COMMENT && *l != LABSEP && i < SYMSIZE) {
*s++ = islower(*l) ? toupper(*l++) : *l++;
i++;
}
comment:
*s = '\0';
return(l);
}
/*
* get opcode into s from source line l
* converts to uper case
*/
char *get_opcode(char *s, char *l)
{
if (*l == LINCOM)
goto comment;
while (!isspace(*l) && *l != COMMENT && *l != LABSEP)
l++;
if (*l == LABSEP)
l++;
while (*l == ' ' || *l == '\t')
l++;
while (!isspace(*l) && *l != COMMENT)
*s++ = islower(*l) ? toupper(*l++) : *l++;
comment:
*s = '\0';
return(l);
}
/*
* get operand into s from source line l
* converts to upper case
* strings inside of 's are copied without changes
*/
char *get_arg(char *s, char *l)
{
if (*l == LINCOM)
goto comment;
while (*l == ' ' || *l == '\t')
l++;
while (*l != '\n' && *l != COMMENT) {
if (isspace(*l)) {
l++;
continue;
}
if (*l != STRSEP) {
*s++ = islower(*l) ? toupper(*l) : *l;
l++;
continue;
}
*s++ = *l++;
if (*(s - 2) == 'F') /* EX AF,AF' !!!!! */
continue;
while (*l != STRSEP) {
if (*l == '\n' || *l == '\0' || *l == COMMENT)
goto comment;
*s++ = *l++;
}
*s++ = *l++;
}
comment:
*s = '\0';
return(l);
}