MACRO Macroparser für TurboAss
Dieses Programm hatte ich eigentlich nur für mich als Tool geschrieben, es ist **N I C H T** ausgereift, sollte mir nur die Arbeit etwas erleichtern. Wenn jemand unbedingt MACROs für TurboAss benötigt, kann dieses kleine Programm vielleicht etwas nützlich sein. Der Quellcode in TurboC liegt bei, falls jemand was ändern möchte.
MACRO ist ein Preprozesseor für TurboAss. Er ermöglicht in TurboAss Includedateinen, Makrobibliotheken und Macros einzubinden und zu verarbeiten. Da TurboAss eine integrierten Syntax-Check hat, müssen die Macro-Quellfiles mit einem anderen ASCII-Editor (z.B. Tempus) erstellt werden. MACRO.TTP erzeugt einen ASCII-File der dann von TurboAss eingelesen und übersetzt werden kann.
MACRO ist kein MACROASSEMBLER, sondern nur ein Tool für TurboAss!!
1. Leistungsmerkmale
- INCLUDE Dateien in ASCII auch rekursiv
- MACROBIBLIOTHEKEN in ASCII auch rekursiv
- INCLUDE Dateien koenne MACROBIBIOTHEKEN und MACROBIBILIOTHEKEN können INCLUDE Datein aufrufen.
- MACROS können beliebig viel Parameter enthalten.
- MACROS können rekursiv defininert und aufgerufen werden.
- MACROS können lokale Labels enthalten
- Betriebssystemaufrufe sind als SYSCALLs bereits eingebunden
- Segmente TEXT, DATA, und BSS werden automatisch separiert und im Quellfile zusammengefügt.
- Konstanten werden am Anfang der Quellprogrammes alphabetisch sortiert geschrieben.
2. Erstellen eines Quelltextes für TurboAss
Der Quelltext wird mittels eine beliebigen Texteditors erstellt. in diesem Quelltext können beliebige Aufrufe für Include-Dateien, Macrobibliotheken, Makrodefitinitionen, Makoraufrufe und Systemcalls stehen.
Die öbersetzung für TurboAss erfolgt durch den Aufruf von MACRO.TTP.
MACRO Quelldatei Zieldatei [ MACLIB1 [..MACLIBm]]
Beispiel: Eingabe der Quelldatei HALLO.ASM mit bel. Editor
;DEMO für MACRO Print "HALLO WELT" und warte auf eine Taste
;@Macro WrtStr Text_Adress
pea \Text_Adress
;@@cconws
;endm
DATA
Msg:
.dc.b "HALLO WELT",$0d,$0a,0
.EVEN
TEXT
Start:
; ---- Aufruf des Macros WrtStr ----
;+WrtStr Msg
; ---- Warte auf Taste, realisiert durch GEMDOS 1 ----
;@@cconin
; ---- Beende das Programm durch Gemdos 0 ----
;@@pterm0
END
öbersetzt wird das Programm nun durch den Aufruf:
MACRO DEMO.ASM DEMO.S
Als Ergebnis erhält man:
TEXT
;DEMO für MACRO Print "HALLO WELT" und warte auf eine Taste
Start:
; ---- Aufruf des Macros WrtStr ----
pea Msg
move.w #$09,-(sp)
trap #1
addq.l #$06,sp
; ---- Warte auf Taste, realisiert durch GEMDOS 1 ----
move.w #$01,-(sp)
trap #1
addq.l #$02,sp
; ---- Beende das Programm durch Gemdos 0 ----
move.w #$00,-(sp)
trap #1
DATA
Msg:
.dc.b "HALLO WELT",$0d,$0a,0
.EVEN
END
Diese Datei kann nun in TurboAss eingelesen und übersetzt werden
3. Einbinden von Include-Dateien und Macro-Bibiliotheken
Include-Dateien und Macrobibliotheken müssen im ASCII-Code vorliegen. Es können keine tokenisierten *.SRC-Dateien von TurboAss eingebunden werden.
Eine Includedatei wird durch die Anweisung
;INCLUDE "DATEIname"
im .ASM-File an dieser Stelle eingebunden.
Eine Macrobibliothek kann entweder in der Kommandozeile hinter dem Zielnamen eingegeben werden
z.B.
MACRO DEMO.ASM DEMO.S Mymaro1.MAX Mymacro2.MAX
oder innerhalb des .ASM-Files durch den Aufruf
;MACLIB "DATEIname"
Includedateien können andere Includedateine oder Macrobibliotheken aufrufen. Macrobibliotheken können ebenfalls ander Macrobibliotheken oder Includedateien aufrufen.
4. Definition von MACROs
Ein Macro wird immer durch den Aufruf
;@MACRO Name [Parameter1 Parameter2 ... Parametern]
definiert. Danach wird der Assembler-Code normal geschrieben. Wenn man in eine Assembleranweisung eine Parameter aus der Definitiationszeile einfügen will, geschieht es wie folgt:
ASSEMBLER-Anweisung \Parametername
z.B. ein Macro soll einen String mir anschiessendem CRTLF ausgeben:
DATA
CRTLF: .dc.b $0d, $0a, 0
EVEN
Msg: .dc.b "HALLO WELT",0
EVEN
;@MACRO WrtStr Adresse
pea \Adresse
;@@CCONWS
;ENDM
;@MACRO WrtLn Adresse
;+WrtStr \Adresse
;+WrtStr CRTLF
;ENDM
Der Aufruf heist dann:
;+WrtLn Msg
Macros müssen immer durch die Anweisung
;ENDM
beendet werden.
Es kann auch vorkommen, dass ein Macro interne Labels benötigt, diese werden durch ./.name gekennzeichnet. Die Definition eines lokalen Labels erfolgt durch:
;./.name:
Beispiel: Ein Speichebereich von n Longworten ab Adresse x soll mit NULL initialsiert werden
BSS
MyBuffer: .ds.l 100
;@MACRL ClrMem Size Adresse
move.w #\Size,d0
lea \Adresse,a0
bra ./.x1
;./.x0:
clr.l (a0)+
;./.x1:
dbra d0,./.x0
;ENDM
Der Aufruf im Hauptprogramm ist dann:
;+ClrMem 100 MyBuffer
Die Labels werden beim 1. Aufruf in
x 0_0000
und
x1_0000
expandiert, beim 2. Aufruf in x0_0001 und x1_0001 etc. Bei jedem Macro das lokale Labels aufruft wird der Labelpostfix im 1 incrementiert. Die Darstellung des Postfix ist immer Hex. z.B. x0_002a: beim 43. Aufruf. Es können daher nur maximal 32000 mal lokale Labels expandiert werden.
5. SYSCALLS
Syscalls sind Primitivmacros, die bereits eingebaut sind. Sie beziehen sich auf die mechanische Ebene der Betriebssystemaufrufe BIOS, XBIOS und GEMDOS.
Ein Betriebssystem Aufruf legt seine Parameter auf dem Stack ab, das muss man noch selbst tun. Dann wird der Funktionscode auf dem Stack abgelegt, der Trap aufgerufen und danach der Stack bereinigt. Diese Aufgabe übernimmt der SYSCALL.
Ein wird durch die Anweisung:
;@@Name erzeugt.
Beispiel: Ein Zeichen von Tastatur einlesen
;@@CCONIN
erzeugt:
move.w #1,-(sp)
trap #1
addq.l #2,sp
oder der eine Spur auf der Floppy formatieren
;@@FLOPFMT
erzeugt:
move.w #$0a,-(sp)
trap #14
lea $1a(sp),sp
Die Namen der Syscalls entspechen den Systemnamen des Betriebssystems.
Liste der implementieren Syscalls
NAME Code SYSTEM Länge
---------------------------------------------
GETMPB 0 BIOS 6
BCONSTAT 1 BIOS 4
BCONIN 2 BIOS 4
BCONOUT 3 BIOS 6
RWABS 4 BIOS 14
SETEXE 5 BIOS 8
TICKALL 6 BIOS 2
GETBPB 7 BIOS 4
BCOSTAT 8 BIOS 4
MEDIACH 9 BIOS 4
DRVMAP 10 BIOS 2
KBSHIFT 11 BIOS 4
INITMOUS 0 XBIOS 12
SSBRK 1 XBIOS 6
PHYSBASE 2 XBIOS 2
LOGBASE 3 XBIOS 2
GETREZ 4 XBIOS 2
SETSCREEN 5 XBIOS 12
SETPALETTE 6 XBIOS 6
SETCOLOR 7 XBIOS 6
FLOPRD 8 XBIOS 20
FLOPWR 9 XBIOS 20
FLOPFMT 10 XBIOS 26
MIDIWS 12 XBIOS 8
MFPINT 13 XBIOS 8
IOREC 14 XBIOS 4
RSCONF 15 XBIOS 14
KEYTBL 16 XBIOS 14
RANDOM 17 XBIOS 2
PROTOPT 18 XBIOS 14
FLOPVER 19 XBIOS 20
SCRDMP 20 XBIOS 2
CURSCONF 21 XBIOS 6
SETTIME 22 XBIOS 6
GETTIME 23 XBIOS 2
BIOSKEY 24 XBIOS 2
IKBDWS 25 XBIOS 8
JDISINT 26 XBIOS 4
JENABINT 27 XBIOS 4
GIGACESS 28 XBIOS 6
OFFGIBIT 29 XBIOS 4
ONGIBIT 30 XBIOS 4
XBTIMER 31 XBIOS 12
DOSOUND 32 XBIOS 6
SETPRT 33 XBIOS 4
KDBVBASE 34 XBIOS 2
KBRATE 35 XBIOS 6
PRTBLK 36 XBIOS 6
VSYNC 37 XBIOS 2
SUPEXEC 38 XBIOS 6
PUNTAES 39 BIOS 2
BLITMODE 64 XBIOS 4
PTERM0 0 GEMDOS 0
CCONIN 1 GEMDOS 2
CCONOUT 2 GEMDOS 4
CAUXIN 3 GEMDOS 2
CAUXOUT 4 GEMDOS 4
CPRNOUT 5 GEMDOS 4
CRAWIO 6 GEMDOS 4
CRAWCIN 7 GEMDOS 2
CNECIN 8 GEMDOS 2
CCONWS 9 GEMDOS 6
CCONRS 10 GEMDOS 6
CCONIS 11 GEMDOS 2
DSETDRV 14 GEMDOS 4
CCONOS 16 GEMDOS 2
CPRNOS 17 GEMDOS 2
CAIXIS 18 GEMDOS 2
CAUXOS 19 GEMDOS 2
DGETDRV 25 GEMDOS 2
FSETDTA 26 GEMDOS 6
SUPER 32 GEMDOS 6
TGETDATE 42 GEMDOS 2
TSETDATE 43 GEMDOS 4
TGETTIME 44 GEMDOS 2
TSETTIME 45 GEMDOS 4
FGETDTA 47 GEMDOS 2
SVERSION 48 GEMDOS 2
PTERMRES 49 GEMDOS 8
DFREE 54 GEMDOS 8
DCREATE 57 GEMDOS 6
DDELETE 58 GEMDOS 6
DSETPATH 59 GEMDOS 6
FCREATE 60 GEMDOS 8
FOPEN 61 GEMDOS 8
DCLOSE 62 GEMDOS 4
FREAD 63 GEMDOS 12
FWRITE 64 GEMDOS 12
FDELETE 65 GEMDOS 6
FSEEK 66 GEMDOS 10
FATTRIB 67 GEMDOS 10
FDUP 69 GEMDOS 4
FFORCE 70 GEMDOS 6
DGETPATH 71 GEMDOS 8
MALLOC 72 GEMDOS 6
MFREE 73 GEMDOS 6
MSHRINK 74 GEMDOS 12
PEXEC 75 GEMDOS 16
PTERM 76 GEMDOS 0
FSFIRST 78 GEMDOS 8
FSNEXT 79 GEMDOS 2
FRENAME 86 GEMDOS 12
FDATETIME 87 GEMDOS 10
Bei Fragen stehe ich gern zur Verfügung:
Uwe Kornnagel Bartningstrasse 12 6100 Darmstadt (06151) 71 52 94
FIDO Uwe Kornnagel 2:249/7.2384 Zerbe
Zerberus UWE_Kornnagel@SYSDA.ZER
GeoNet GEO1:U.Kornnagel
Telebox IDN112
macro.c
/*
MACRO-PARSER Version 1.01 (C) Uwe Kornnagel
-----------------------------------------------
Include-Dateien, Macrobibiliotheken und Macroexpansion
für TURBOASS (C) Sîren Hellwig, Markus Fritze
Compiler: TurboC 2.0
Copyright Vermerk: Es gelten die gleichen Bedingungen wie
für TURBOASS.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "syslib.h"
#define STRLEN 82 /* Stringlänge eines Eingabezeilenbuffers */
#define NAMLEN 18 /* Stringlänge eines Namensfeldbuffers */
#define MAXSTR (STRLEN-2) /* maximale Stringlänge einer Zeile */
#define MAXNAM (NAMLEN-2) /* maximale Stringlänge eines Namens */
/* Schlüsselworte für MACRO */
#define SYSCALL ";@@" /* Internes Macro SYSCALL */
#define INCLUDE ";INCLUDE" /* Aufruf einer Include-Datei */
#define MACLIB ";MACLIB" /* Aufruf einer Macro-Bibiliothek */
#define MAC_DEF ";@MACRO" /* Definition eines MACROS */
#define MAC_END ";ENDM" /* Ende des Makrokîrpers"
#define MAC_CALL ";+" /* Aufruf eines MACROS */
#define PARA_DEF '\\' /* Kennung für Parameteraufruf */
#define LABEL_DEF "./." /* Kennung für lokale Labels */
#define TEXT_DEF "TEXT" /* Schlüsselwort für Text-Segment */
#define DATA_DEF "DATA" /* Schlüsselwort für Data-Segment */
#define BSS_DEF "BSS" /* Schlüsselwort für Bss-Segment */
#define END_DEF "END" /* Schlüsselwort für Source-Ende */
#define EQU_DEF ".EQU" /* Schlüsselwort Konstante zuweisen */
/* erkennt Trennzeichen für Dateinamen bei INCLUDE und MACLIB */
#define is_deli(a) ( isspace(a) || ( a == '\'') || ( a == '\"'))
/* erkennt gültige Zeichen für Labels, Macronamen und Parameter */
#define is_valid(a) ( isalnum(a) || ( a == '_' ) || ( a == '$') )
/* Struktur zur Verwaltung von Lokalen Labels im Macro */
#define LOC_LABEL struct P_STRUCT
LOC_LABEL
{
char name[NAMLEN];
int cnt;
LOC_LABEL *next;
};
#define P_LEN sizeof(LOC_LABEL)
#define NEW_P(a) a=(LOC_LABEL *) malloc(P_LEN)
/* Strukturen zum verwalten der Source und der Macros */
#define SYSLIB struct S_CALL
#define SOURCE struct S_STRUCT
#define MACRO struct M_STRUCT
MACRO
{
char name[NAMLEN];
SOURCE *source;
MACRO *next;
} *m_first, *m_last;
#define M_LEN sizeof(MACRO)
#define NEW_M(a) a=(MACRO *) malloc(M_LEN)
SOURCE
{
int is_macro;
char line[STRLEN];
SOURCE *next;
} *s_first, *s_last, *z_first, *z_last, *t_first, *t_last,
*d_first, *d_last, *b_first, *b_last;
#define S_LEN sizeof(SOURCE)
#define NEW_S(a) a = (SOURCE *) malloc(S_LEN)
#define LINK(a,b,c) if (!b) b=a; else c->next=a; c = a
int errx; /* Error-Counter */
int wrnx; /* Warnungs-Counter */
int lokal; /* Counter für lokale Labels */
int segment; /* Segment-Flagg */
/* Funktions-definitionen */
void fatal( int nbr, char *s );
void gen_code( SOURCE *Adr );
SOURCE *free_source( SOURCE *Adr );
SOURCE *add_source( char *line );
void free_macro( void );
void add_macro( SOURCE *source, char *name );
void get_file(char *name );
void check_name( char *o_name, char *i_name );
MACRO *find_macro( char *name );
void scan_macro( void );
void splitt( char *token, char *rest, char *line );
int is_local( char *lbl );
void expand( SOURCE *Adr );
void z_sort( void );
/* Fehlerabbruchroutine bei fatalen Fehlern */
void fatal( int nbr, char *s )
{
static char *errmsg[] =
{ "Speicher ist voll %s\n",
"Datei %s nicht gesunden!\n",
"Datei %s kann nicht beschrieben werden!\n",
"Syntax MACRO Quellfile Zielfile [Maclib .. [Maclib]]%s\n",
"Quellcode-Ende innerhalb einer Mareodefinition erreicht%s\n",
""
};
printf(errmsg[nbr],s);
printf("***FATALER Fehler: Programmabbruch, bitte Taste drücken ");
getchar();
exit(0);
}
SOURCE *free_source( SOURCE *Adr )
{
SOURCE *curr, *link;
curr = Adr;
while ( curr )
{
link = curr->next;
free(curr);
curr = link;
}
return NULL;
}
SOURCE *add_source( char *line )
{
SOURCE *curr;
NEW_S(curr);
if ( !curr ) fatal(0,"!");
memset(curr,0,S_LEN );
strcpy(curr->line,line);
return curr;
}
void free_macro( void )
{
MACRO *curr, *link;
curr = m_first;
while ( curr )
{
link = curr->next;
free( curr );
curr = link;
}
m_first = m_last = NULL;
}
void add_macro( SOURCE *source, char *name )
{
MACRO *curr;
char Name[NAMLEN];
NEW_M(curr);
if ( !curr ) fatal(0,"!");
memset(curr,0,M_LEN);
check_name( Name,name );
strcpy(curr->name,Name);
curr->source = source;
LINK( curr, m_first, m_last );
}
void my_exit( void )
{
free_source( s_first );
free_source( z_first );
free_source( t_first );
free_source( d_first );
free_source( b_first );
free_macro();
}
void get_file(char *name )
{
FILE *f;
SOURCE *curr;
char line[STRLEN], x[STRLEN], *c, *c1;
f = fopen(name,"r");
if( !f ) fatal(1,name);
printf(" Including Datei %s\n",name);
while ( !feof(f) )
{
memset(line,0,STRLEN);
fgets( line,STRLEN,f);
c = line; while( *c ) if ( (*c == 9) || (*c > 0x1f)) c++; else *c=0;
if ( !feof(f) )
{
strcpy(x,line);
strupr(x);
c = strstr(x,INCLUDE );
c1 = strstr(x,MACLIB);
if ( c1 && !c ) c = c1;
if ( c )
{
while ( !is_deli(*c) ) c++;
while ( is_deli(*c) ) c++;
c1 = x;
while ( !is_deli(*c) ) *c1++ = *c++;
*c1=0;
get_file( x );
} else
{
curr = add_source( line );
LINK( curr, s_first, s_last );
}
}
}
fclose(f);
}
void check_name( char *o_name, char *i_name )
{
char new_name[NAMLEN];
strncpy( new_name,i_name,MAXNAM );
if ( strlen(i_name) > MAXNAM )
{
printf("***WARNUNG: %s Name zu lang gekürzt (%s)\n",i_name,
new_name);
wrnx++;
}
strcpy( o_name, new_name );
}
MACRO *find_macro( char *name )
{
MACRO *curr, *fm;
char Name[NAMLEN];
curr = m_first;
fm = NULL;
check_name( Name, name );
while( curr && !fm )
{
if( !strcmp(curr->name,Name) ) fm = curr;
curr = curr->next;
}
return fm;
}
void scan_macro( void )
{
SOURCE *curr;
char name[STRLEN], *c, *x;
int cnt;
cnt = 0;
curr = s_first;
while( curr )
{
strcpy(name,curr->line);
strupr(name);
c = strstr(name,MAC_DEF);
if ( c )
{
x = name;
c = curr->line +( c - name );
while (*c && !is_deli(*c) ) c++;
while (*c && is_deli(*c) ) c++;
while (*c && !is_deli(*c) ) *x++ = *c++;
*x = 0;
x = name;
check_name( name, x );
if ( find_macro(name) )
{
printf("***FEHLER: %s MACRO doppelt definiert\n",name);
errx++;
} else
{
add_macro(curr, name );
cnt++;
while ( curr && !strstr(name,MAC_END) )
{
curr->is_macro = 1;
curr = curr->next;
if ( !curr ) fatal(4,"!");
strcpy(name,curr->line);
strupr(name);
}
curr->is_macro = 1;
}
}
if (curr) curr = curr->next;
}
}
void splitt( char *token, char *rest, char *line )
{
char dummy[STRLEN], *c, *x;
memset(dummy,0,STRLEN);
strcpy(dummy,line);
*token = *rest = 0;
c = dummy;
x = token;
while (*c && is_deli(*c) ) c++;
while (*c && !is_deli(*c)) *x++ = *c++;
*x = 0;
strcpy(rest,c);
x = token;
check_name( token, x );
}
int is_local( char *lbl )
{
if(strstr(lbl,LABEL_DEF)) return 1;
return 0;
}
void expand( SOURCE *Adr )
{
SOURCE *first, *last, *curr, *heap;
MACRO *mc;
LOC_LABEL *pfirst, *plast, *pcurr;
char name[STRLEN], rest[STRLEN], line[STRLEN], *c, *xx;
char a_name[STRLEN], a_rest[STRLEN], a_line[STRLEN];
char m_name[STRLEN], m_rest[STRLEN], m_line[STRLEN];
char x_par[STRLEN], *x;
int locdef = 0;
first = last = curr = heap = NULL;
pfirst = plast = pcurr = NULL;
strcpy(line,Adr->line);
xx = strstr(line,";+")+2;
splitt(name,rest,xx );
mc = find_macro(name);
if ( !mc )
{
printf("***FEHLER: %s MACRO ist nicht definiert.\n",Adr->line);
errx++;
return;
}
/* MACRO in lokalen HEAP einlesen */
curr = mc->source;
strcpy(line,curr->line);
strupr(line);
while( curr && !strstr(line,MAC_END) )
{
heap = add_source( curr->line );
LINK( heap, first, last );
curr = curr->next;
strcpy(line,curr->line);
strupr(line);
}
/* Positionier Aufrufstring auf 1. Parameter */
strcpy(a_line,Adr->line);
splitt( a_name,a_rest,a_line);
strcpy( a_line,a_rest );
splitt( a_name,a_rest,a_line);
/* Positioniere Definitionsstring auf 1. Parameter */
strcpy( m_line,mc->source->line);
splitt( m_name,m_rest,m_line);
strcpy( m_line,m_rest );
splitt( m_name,m_rest,m_line);
strcpy( m_line,m_rest );
splitt( m_name,m_rest,m_line);
/* exmandiere die PARAMETER */
while( strlen(m_name) && strlen(a_name) )
{
curr = first->next;
while ( curr )
{
strcpy(line,curr->line);
memset(x_par,0,STRLEN);
x_par[0] = PARA_DEF;
strcat(x_par,m_name);
c = strstr(line,x_par);
if (c)
{
*c = 0;
strcpy(name,line);
c++;
while( is_valid(*c) ) c++;
strcpy( rest,c);
strcpy( line,name );
strcat( line,a_name );
strcat( line,rest);
strcpy( curr->line, line );
}
curr = curr->next;
}
strcpy( m_line,m_rest );
splitt( m_name,m_rest,m_line);
strcpy( a_line,a_rest );
splitt( a_name,a_rest,a_line);
}
/* Teste ob lokale Labels vorhanden sind und definiere sie */
curr = first->next;
while( curr )
{
if( is_local(curr->line) )
{
locdef = 1;
if (*curr->line == ';')
{
c = curr->line;
while ( *c && !is_valid(*c) ) c++;
x = name;
while ( *c && is_valid(*c) ) *x++ = *c++;
*x = 0;
NEW_P(pcurr);
if ( !pcurr ) fatal (0,"!");
memset(pcurr,0,P_LEN);
strncpy(pcurr->name,name,(NAMLEN-1));
pcurr->cnt = lokal;
LINK( pcurr, pfirst, plast);
strcpy(rest,c);
sprintf(line,"%s_%04X%s\000",pcurr->name,pcurr->cnt,rest);
strcpy( curr->line,line);
}
}
curr = curr->next;
}
/* expandiere die Lokalen Labels */
if (locdef)
{
curr = first->next;
while( curr )
{
while( is_local(curr->line) )
{
c = strstr(curr->line,LABEL_DEF);
*c = 0;
strcpy(a_name,curr->line);
c +=3;
x=name;
while( is_valid(*c) ) *x++ = *c++;
*x = 0;
pcurr = pfirst;
while ( pcurr && strcmp(pcurr->name,name) )
{
pcurr = pcurr->next;
}
if ( !pcurr )
{
printf("***FEHLER: %s ist kein lokales Label\n",name);
sprintf(curr->line,"%s <---Fehler\000",a_rest);
errx++;
} else
{
strcpy(a_rest,c);
sprintf(m_name,"%s_%04X\000",pcurr->name,pcurr->cnt);
strcpy(line,a_name);
strcat(line,m_name);
strcat(line,a_rest);
strcpy(curr->line,line);
}
}
curr = curr->next;
}
/* Lokale Labels vom HEAP freigeben */
pcurr = pfirst;
while( pcurr )
{
plast = pcurr->next;
free( pcurr );
pcurr = plast;
}
pfirst = plast = pcurr = NULL;
lokal++;
}
/* generiere den expandierten Code vom Lokalen Heap in die
entsprechenden Output-Queues
*/
gen_code( first->next );
/* gib lokalen Heap wieder frei */
first = last = free_source( first );
}
void gen_code( SOURCE *Adr )
{
SOURCE *curr, *heap;
char line[STRLEN], name[STRLEN], rest[STRLEN], *c;
int x1, y1;
/* Beginne mit Codegenerierung ab Adresse */
curr = Adr;
while(curr)
{
if (!curr->is_macro && strstr(curr->line,SYSCALL) )
{
c = strstr(curr->line,SYSCALL)+3;
strcpy( name,c );
strupr(name);
x1 = y1 = 0;
while ( syslib[x1].name[0] && !y1 )
{
if (!strcmp(name,syslib[x1].name) ) y1 = x1;
x1++;
}
if ( y1 )
{
sprintf(line," move.w #$%02x,-(sp)\000",syslib[y1].fnc);
heap = add_source(line);
LINK(heap,t_first,t_last);
sprintf(line," trap #%d\000",syslib[y1].trap);
heap = add_source(line);
LINK(heap,t_first,t_last);
if (syslib[y1].size )
{
if ( syslib[y1].size > 8 )
sprintf(line," lea $%02x(sp),sp\000",syslib[y1].size);
else
sprintf(line," addq.l #$%02x,sp\000",syslib[y1].size);
heap = add_source(line);
LINK(heap,t_first,t_last);
}
curr->is_macro = 1;
} else
{
printf("***FEHLER: %s ist kein SYSCALL\n",name);
errx++;
}
}
if ( !curr->is_macro )
{
if (strstr(curr->line,";+") )
{
/* Macro expandieren */
expand(curr);
} else
{
heap = add_source(curr->line);
heap->is_macro = 0;
/* Bestimme die SEGMENT-Queue */
strcpy( line, curr->line );
strupr(line);
splitt( name, rest, line );
if (!strcmp(name,TEXT_DEF))
{
segment = 0;
heap->is_macro = 1;
} else
{
if (!strcmp(name,DATA_DEF))
{
segment = 1;
heap->is_macro = 1;
} else
{
if (!strcmp(name,BSS_DEF))
{
segment = 2;
heap->is_macro = 1;
} else
{
if ( !strcmp(name,END_DEF) )
{
heap->is_macro = 1;
} else if (strstr(line,EQU_DEF))
{
x1 = segment;
segment = 3;
}
}
}
}
/* Sourceline an Segmentqueue anfügen */
switch ( segment )
{
case 0: LINK(heap,t_first,t_last); break;
case 1: LINK(heap,d_first,d_last); break;
case 2: LINK(heap,b_first,b_last); break;
case 3: LINK(heap,z_first,z_last);
segment = x1; break;
}
}
}
/* naechte Zeile */
if( curr ) curr = curr->next;
}
}
void z_sort( void )
{
SOURCE *curr, *link;
char dummy[STRLEN];
curr = z_first;
while ( curr )
{
link = curr->next;
while( link )
{
if (strcmp(curr->line,link->line) > 0)
{
strcpy( dummy, link->line );
strcpy( link->line, curr->line );
strcpy( curr->line, dummy );
}
link = link->next;
}
curr = curr->next;
}
}
void main( int argc, char *argv[] )
{
int i;
FILE *f;
SOURCE *curr;
atexit(my_exit);
s_first = s_last = z_first = z_last = t_first =
t_last = d_first = d_last = b_first = b_last = NULL;
m_first = m_last = NULL;
errx = wrnx = lokal = 0;
puts("MACRO V1.01: Macroparser (c) 1990 Uwe Kornnagel\n");
if ( argc < 3 ) fatal(3,"!");
get_file( argv[1] );
if ( argc > 3 ) for( i=3; i<argc; get_file(argv[i++]));
scan_macro();
gen_code( s_first );
printf (" %d Fehler und %d Warnungen\n",errx,wrnx);
if (errx) exit(0);
f=fopen(argv[2],"w");
if ( z_first )
{
z_sort();
fprintf(f,"; Definition aller Konatanten\n");
curr = z_first;
while (curr)
{
if ( !curr->is_macro ) fprintf(f,"%s\n",curr->line );
curr = curr->next;
}
}
if ( t_first )
{
curr = t_first;
fprintf(f,"\n%s\n",TEXT_DEF);
while (curr)
{
if ( !curr->is_macro ) fprintf(f,"%s\n",curr->line );
curr = curr->next;
}
}
if ( d_first )
{
curr = d_first;
fprintf(f,"\n%s\n",DATA_DEF);
while (curr)
{
if ( !curr->is_macro ) fprintf(f,"%s\n",curr->line );
curr = curr->next;
}
}
if ( b_first )
{
curr = b_first;
fprintf(f,"\n%s\n",BSS_DEF);
while (curr)
{
if ( !curr->is_macro ) fprintf(f,"%s\n",curr->line );
curr = curr->next;
}
}
fprintf(f,"\n%s\n",END_DEF);
fclose(f);
exit(0);
}
SYSLIB.H
struct SYSLIB
{
char name[17];
char fnc;
char trap;
char size;
} syslib[] =
{
"GETMPB",0,13,6,
"BCONSTAT",1,13,4,
"BCONIN",2,13,4,
"BCONOUT",3,13,6,
"RWABS",4,13,14,
"SETEXE",5,13,8,
"TICKALL",6,13,2,
"GETBPB",7,13,4,
"BCOSTAT",8,13,4,
"MEDIACH",9,13,4,
"DRVMAP",10,13,2,
"KBSHIFT",11,13,4,
"INITMOUS",0,14,12,
"SSBRK",1,14,6,
"PHYSBASE",2,14,2,
"LOGBASE",3,14,2,
"GETREZ",4,14,2,
"SETSCREEN",5,14,12,
"SETPALETTE",6,14,6,
"SETCOLOR",7,14,6,
"FLOPRD",8,14,20,
"FLOPWR",9,14,20,
"FLOPFMT",10,14,26,
"MIDIWS",12,14,8,
"MFPINT",13,14,8,
"IOREC",14,14,4,
"RSCONF",15,14,14,
"KEYTBL",16,14,14,
"RANDOM",17,14,2,
"PROTOPT",18,14,14,
"FLOPVER",19,14,20,
"SCRDMP",20,14,2,
"CURSCONF",21,14,6,
"SETTIME",22,14,6,
"GETTIME",23,14,2,
"BIOSKEY",24,14,2,
"IKBDWS",25,14,8,
"JDISINT",26,14,4,
"JENABINT",27,14,4,
"GIGACESS",28,14,6,
"OFFGIBIT",29,14,4,
"ONGIBIT",30,14,4,
"XBTIMER",31,14,12,
"DOSOUND",32,14,6,
"SETPRT",33,14,4,
"KDBVBASE",34,14,2,
"KBRATE",35,14,6,
"PRTBLK",36,14,6,
"VSYNC",37,14,2,
"SUPEXEC",38,14,6,
"PUNTAES",39,14,2,
"BLITMODE",64,14,4,
"PTERM0",0,1,0,
"CCONIN",1,1,2,
"CCONOUT",2,1,4,
"CAUXIN",3,1,2,
"CAUXOUT",4,1,4,
"CPRNOUT",5,1,4,
"CRAWIO",6,1,4,
"CRAWCIN",7,1,2,
"CNECIN",8,1,2,
"CCONWS",9,1,6,
"CCONRS",10,1,6,
"CCONIS",11,1,2,
"DSETDRV",14,1,4,
"CCONOS",16,1,2,
"CPRNOS",17,1,2,
"CAIXIS",18,1,2,
"CAUXOS",19,1,2,
"DGETDRV",25,1,2,
"FSETDTA",26,1,6,
"SUPER",32,1,6,
"TGETDATE",42,1,2,
"TSETDATE",43,1,4,
"TGETTIME",44,1,2,
"TSETTIME",45,1,4,
"FGETDTA",47,1,2,
"SVERSION",48,1,2,
"PTERMRES",49,1,8,
"DFREE",54,1,8,
"DCREATE",57,1,6,
"DDELETE",58,1,6,
"DSETPATH",59,1,6,
"FCREATE",60,1,8,
"FOPEN",61,1,8,
"DCLOSE",62,1,4,
"FREAD",63,1,12,
"FWRITE",64,1,12,
"FDELETE",65,1,6,
"FSEEK",66,1,10,
"FATTRIB",67,1,10,
"FDUP",69,1,4,
"FFORCE",70,1,6,
"DGETPATH",71,1,8,
"MALLOC",72,1,6,
"MFREE",73,1,6,
"MSHRINK",74,1,12,
"PEXEC",75,1,16,
"PTERM",76,1,0,
"FSFIRST",78,1,8,
"FSNEXT",79,1,2,
"FRENAME",86,1,12,
"FDATETIME",87,1,10,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0,
"",0,0,0
};