home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD2.mdf
/
c
/
tcpp
/
examples
/
tasm2msg.c
< prev
next >
Wrap
Text File
|
1990-06-09
|
18KB
|
408 lines
/*
BEISPIELQUELLCODE FÜR DAS TASM FILTERPROGRAMM
Tasm2Msg.C
Copyright (c) 1990 Borland International, Inc.
Alle Rechte vorbehalten.
Tasm2Msg - Nachrichtenfilter von Turbo Assembler zum Turbo C++ IDE
Nachrichtenfenster (message window).
Dieser Filter akzeptiert Eingaben über den Standard-Eingabe-Stream,
konvertiert sie und gibt sie über den Standard-Ausgabe-Stream aus.
Die Streams sind über Pipes miteinander verbunden: der
Eingabe-Stream ist die Ausgabe des Assemblers, und der
Ausgabe-Stream ist mit dem Nachrichtenfenster der Turbo C++
Entwicklungsumgebung verbunden. Der Filter wird mit folgendem
Befehl aufgerufen:
tasm fname | tasm2msg | Turbo C++-Nachrichtenfenster
Eingaben können von TASM, MASM 5.1 oder OPTASM kommen. Der Assembler-Typ
wird aus den Daten, die der Assembler bereitstellt, bestimmt.
Übersetzen Sie mit dem Speichermodell LARGE von Turbo C++:
tcc -ml tasm2msg*/
#include <dir.h>
#include <dos.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <alloc.h>
#include <io.h>
#include <ctype.h>
#include "filter.h"
#define TRUE (1 == 1)
#define FALSE !(TRUE)
/* Turbo Assembler-Text zum Konvertieren */
char TasmWarningTxt[] = "*Warning* ";
char TasmErrorTxt[] = "**Error** ";
char TasmFatalTxt[] = "**Fatal** ";
/* Microsoft Assembler-und OPTASM-Text zum Konvertieren */
char MasmWarningText[] = "warning";
char MasmErrorText[] = "error";
char CurFile[MAXPATH]; /* Aktuelle Datei im Nachrichtendenster */
unsigned BufSize, /* Größe des internen Arbeitspuffers */
CurBufLen; /* Größe des Puffers, der in Gebrauch ist */
char *InBuffer, /* Eingabepuffer */
*OutBuffer, /* Ausgabepuffer */
*CurInPtr, /* Aktuelles Zeichen im Eingabepuffer */
*CurOutPtr, /* Aktuelles Zeichen im Ausgabepuffer */
*LinePtr; /* Zeiger auf das aktuelle Zeichen im
Eingabepuffer */
int (*processor)(char *); /* Funktionszeiger für den Aufruf der
passenden Konversionsroutine */
char Line[133]; /* Statischer Puffer zum Speichern der
aktuellsten Eingabe */
long int InOff; /* Position innerhalb der Eingabedaten */
char EndMark; /* zeigt das Ende der Daten an */
/*************************************************************************
Funktion : NextChar
Parameter : keine
Rückgabe : nächstes Zeichen im Eingabepuffer oder 0 für Dateiende
Eingaben von der Standard-Eingabe werden im globalen Puffer InBuffer,
für den in main Speicher reserviert wird, abgelegt. Die Funktion gibt
das nächste Zeichen im Puffer zurück und liest weitere Eingabedaten,
wenn der Puffer leer ist.
**************************************************************************/
char NextChar(void)
{
if (CurInPtr < InBuffer+CurBufLen) /* Wenn der Puffer nicht leer ist */
{
return *(CurInPtr++); /* Gibt das nächste Zeichen zurück */
}
else
{
CurInPtr = InBuffer; /* Setzt Pointer auf Puffer-Anfang */
lseek(0,InOff,0); /* Suche nach nächstem Lesebereich */
InOff += BufSize; /* Zeigt auf den nächsten Textblock */
if ((CurBufLen = read(0,InBuffer,BufSize)) !=0)
return NextChar(); /* Rekursiver Aufruf gibt das erste
Zeichen des Puffers zurück */
return 0; /* Rückgabewert 0 bei Dateiende */
}
}
/*************************************************************************
Funktion : flushOut
Parameter : Size Anzahl der Zeichen, die geschrieben werden
Rückgabe : nichts
Strings, die zum Nachrichtenfenster geschickt werden, stehen im Puffer
OutBuffer. Ein Aufruf dieser Funktion bewirkt, daß Size-Bytes vom OutBuffer
zur Standard-Ausgabe geschrieben werden; der Zeiger des Ausgabepuffers zeigt
wieder auf den Anfang desselben. Danach wird der Ausgabepuffer als leer
angesehen.
*************************************************************************/
void flushOut(unsigned Size)
{
if (Size != 0) /* Keinen leeren Puffer herausschreiben */
{
CurOutPtr = OutBuffer; /* Zeiger auf den Puffer-Anfang positionieren */
lseek(1,0,2);
write(1,OutBuffer,Size); /* Anzahl der Bytes (Size) anzeigen */
}
}
/************************************************************************
Funktion : Put
Parameter : S Zeiger auf die Bytes, die in den Ausgabe-Puffer geschrieben
werden
Len Anzahl der Bytes, die in den Ausgabe-Puffer geschrieben
werden
Rückgabe : nichts
Put schreibt Bytes in den OutBuffer, sodaß sie später an die Standard-Aus-
gabe geschrieben werden können
************************************************************************/
void Put(char *S,int Len)
{
int i;
for (i = 0; i < Len; i++)
{
*CurOutPtr++ = S[i]; /* Byte in den Puffer schreiben */
if (CurOutPtr >= OutBuffer+BufSize) /* Wenn der Puffer voll ist, */
flushOut(BufSize); /* die Daten rausschreiben */
}
}
/************************************************************************
Funktion : ProcessNonTasmLine
Parameter : Line Zeiger auf die aktuelle Zeile, die verarbeitet werden soll
Rückgabe : 1, wenn es sich um Microsoft Assembler handelt
0, wenn nicht
Die Zeile wird daraufhin untersucht, ob es sich um einen MASM- oder OPTASM-
kompatiblen Assembler handelt. Falls die Zeile lesbar ist, wird an das Nach-
richtenfenster Information über die Nachricht und die Zeilennummer ausgege-
ben.
-*----------------------------------------------------------------------*-
Microsoft Assembler-Zeilen, die konvertiert werden, sind von der Form:
source-file(LINE #): message-kind message-num : message text
Message-kind ist entweder eine Warnung oder ein Fehler.
-*----------------------------------------------------------------------*-
OPTASM Assembler-Zeilen, die konvertiert werden, sind von der Form:
source-file(LINE #) : message-kind message-num : message text
Message-kind ist entweder eine Warnung oder ein Fehler.
-*----------------------------------------------------------------------*-
Masm- und Optasm-Zeilen unterscheiden sich von Tasm-Zeilen: die Hälfte der
Zeile muß geprüft werden, um festzustellen, ob sie gültig ist. Aus diesem
Grund wird die Information erst am Ende der Zeile weitergegeben, wenn klar
ist, ob die Zeile gültig ist oder nicht.
************************************************************************/
int ProcessNonTasmLine(char *Line)
{
char Type;
unsigned i;
char *s;
char fn[MAXPATH];
int NewFile;
if (Line[0] == 0) /* Leere Zeile, keine Aktion */
return 0;
s = strchr(Line,'('); /* ( suchen */
if (s != NULL) /* Wenn keine (, Zeile ungültig*/
{
memmove(fn,Line,(unsigned)(s-Line)); /* Dateinamen speichern */
fn[(unsigned)(s-Line)] = 0; /* Null schließt den Namen ab */
memmove(Line,++s,strlen(Line)); /* Zeile nach links bewegen */
if (strcmp(fn,CurFile) != 0) /* Wenn ein neuer Dateiname */
{
NewFile = TRUE; /* dann ein Flag setzen */
strcpy(CurFile,fn); /* Neuen Namen speichern */
}
else NewFile = FALSE;
s = strchr(Line,')'); /* Die schließende Klammer suchen */
if (s != NULL) /* Wenn keine ), Zeile ungültig */
{
*s = 0; /* Zeilennummer isolieren */
i = atoi(Line); /* Die Nummer von einem String
in ein Integer konvertieren */
if (i != 0)
{
s++;
while (*s == ' ') /* optasm hat hier ein Leerzeichen*/
s++;
if (*s != ':') /* : aus der Zeile entfernen
return 0; /* Kein :, keine MASM-Zeile */
s++;
memmove(Line,s,strlen(s)+1); /* Zeile verschieben */
while (Line[0] == ' ' && Line[0] != 0) /* Leerzeichen entfernen*/
memmove(Line,&Line[1],strlen(Line));
Line[0] = tolower(Line[0]); /* optasm verwendet Großbuch-
staben
/* Prüfen auf Warnung oder
Fehlertext von MASM, Zeile
verschieben, wenn nötig */
if ((strncmp(Line, MasmWarningText, strlen(MasmWarningText)) != 0) &&
(strncmp(Line, MasmErrorText, strlen(MasmErrorText)) != 0))
return 0; /* Kein Fehler, keine Warnung, keine MASM-Zeile */
/* Leerzeichen aus der Zeile entfernen */
while (Line[0] == ' ' && Line[0] != 0) /* Leerzeichen entfernen */
memmove(Line,&Line[1],strlen(Line));
}
else return 0; /* keine Zeilennummer, keine MASM-Zeile */
}
else return 0; /* keine ), keine MASM-Zeile */
if (NewFile)
{
Type = MsgNewFile; /* neue Datei senden */
Put(&Type,1); /* Information ausgeben */
Put(CurFile,strlen(CurFile)+1); /* zusammen mit dem neuen Namen */
}
Type = MsgNewLine; /* Neue Zeile */
Put(&Type,1); /* Zeigen, daß neue Zeile nötig */
Put((char *)&i,2); /* Nummer ausgeben */
i = 1; /* Spalte in der Nachrichtenbox */
Put((char *)&i,2); /* Nachricht ausgeben */
Put(Line,strlen(Line)+1);
}
else return 0; /* Keine (, keine MASM-Zeile */
return 1; /* MASM-Zeile */
}
/*************************************************************************
Funktion : ProcessTasmLine
Parameter : Line Zeiger auf die aktuelle Zeile, die verarbeitet wird
Rückgabe : 1, wenn es sich um eine Turbo Assembler-Zeile handelt
0, wenn nicht
Eine Eingabezeile wird daraufhin analysiert, ob es sich um eine Turbo
Assembler-Zeile handelt, und in Information für das Nachrichtenfenster
konvertiert.
Turbo Assembler-Zeilen, die konvertiert werden müssen, haben die Form:
message-type source-file(LINE #) message-text
Typ ist *Warning*, **Error** oder **Fatal**
TASM-Zeilen werden durch den Textanfang identifiziert. Wenn Warning,
Error oder Fatal vorliegen, wird der Text so ausgegeben, wie er eingelesen
worden ist. Jede falsche Konfiguration bricht das Analysieren des Restes
der Zeile einfach ab.
*************************************************************************/
int ProcessTasmLine(char *Line)
{
char Type;
unsigned i;
char *s;
char fn[MAXPATH];
/* Leere Zeilen werden nicht verarbeitet */
if (Line[0] == 0)
return 0;
/* Prüfen der Tasm-Typen */
if ((strncmp(Line,TasmWarningTxt,strlen(TasmWarningTxt)) == 0) ||
(strncmp(Line,TasmErrorTxt, strlen(TasmErrorTxt)) == 0) ||
(strncmp(Line,TasmFatalTxt, strlen(TasmFatalTxt)) == 0))
{
/* Typ überspringen: String nach links verschieben */
memmove(Line,&Line[strlen(TasmFatalTxt)],strlen(Line));
/* Die erste öffnende Klammer '(' definiert: die Zeichen zur Linken
sind ein Dateiname, die Zeichen zur Rechten (bis zur schließenden
Klammer ')') bezeichnen eine Zeilennummer. */
s = strchr(Line,'('); /* ( gefunden */
if (s != NULL) /* Ohne (: Zeile ungültig */
{
memmove(fn,Line,(unsigned)(s-Line)); /* Dateinamen speichern */
fn[(unsigned)(s-Line)] = 0; /* Null schließt Namen ab */
memmove(Line,++s,strlen(Line)); /* Zeile nach links */
if (strcmp(fn,CurFile) != 0) /* falls neuer Dateiname */
{
Type = MsgNewFile; /* Den Typ im Nachrichten-
fenster anzeigen */
strcpy(CurFile,fn);
Put(&Type,1);
Put(CurFile,strlen(CurFile)+1); /* zusammen mit dem neuen Namen */
}
Type = MsgNewLine;
s = strchr(Line,')'); /* Schließende Klammer suchen */
if (s != NULL)
{
*s = 0; /* Nummer im String isolieren */
i = atoi(Line); /* Gefundene Nummer von einem
Sring in Integer konvertieren */
if (i != 0)
{
Put(&Type,1); /* Bedarf für eine neue Zeile */
Put((char *)&i,2); /* Die Nummer ausgeben */
i = 1; /* Spalte in Nachrichtenbox def.*/
Put((char *)&i,2);
s++;
memmove(Line,s,strlen(s)+1); /* Zeile verschieben */
while (Line[0] == ' ' && Line[0] != 0) /* Leerzeichen entfernen */
memmove(Line,&Line[1],strlen(Line));
Put(Line,strlen(Line)+1); /* Nachricht ausgeben */
return 1; /* TASM-Zeile */
}
return 0; /* Zeilennummer ungültig: keine TASM-Zeile */
}
return 0; /* Keine ) in der Zeile: keine TASM-Zeile */
}
return 0; /* Keine ( in der Zeile: keine TASM-Zeile */
}
else return 0; /* Kein Zeilenanfang: keine TASM-Zeile */
}
/**************************************************************************
Funktion : ProcessLine
Parameter : Line Zeiger auf die Zeile mit den Eingabedaten
Rückgabe : nichts
Wenn der Zeilentyp bestimmt worden ist, wird die passende Verarbeitung über
einen Funktionszeiger gestartet. Im anderen Fall wird geprüft, ob es sich
um eine Tasm- oder eine Masm-Zeile handelt.
**************************************************************************/
void ProcessLine(char *Line)
{
if (processor == NULL)
{
if (ProcessTasmLine(Line)) /* Prüfen auf TASM-Zeile */
processor = ProcessTasmLine;
else
if (ProcessNonTasmLine(Line)) /* Prüfen auf MASM oder OPTASM */
processor = ProcessNonTasmLine;
}
else
processor(Line); /* Typ schon bekannt */
}
/***********************************************************************
Funktion : main
Rückgabe : 0, falls erfolgreich ausgeführt
3, falls ein Fehler aufgetreten ist
Die Routine Main reserviert Speicher für Ein- und Ausgabepuffer. Aus dem
Eingabepuffer wird zeichenweise gelesen, dann der Zeilenpuffer gefüllt,
dessen Inhalt danach analysiert wird. Es wird solange gelesen und analysiert,
bis das Ende der Eingabe erreicht ist.
***********************************************************************/
int main( void )
{
char c;
unsigned long core;
setmode(1,O_BINARY); /* Ausgabe im Binär-Modus */
core = farcoreleft();
if (core > 64000U)
BufSize = 64000U;
else BufSize = (unsigned)core; /* verfügbaren Speicher bestimmen */
/* unter 64KByte bleiben */
if ((CurInPtr = malloc(BufSize)) == NULL) /* Pufferspeicher reservieren */
exit(3);
processor = NULL; /* Verarbeitungsweise zurücksetzen */
InBuffer = CurInPtr; /* Eingabepuffer ist der erste Teil */
BufSize = BufSize/2; /* Ausgabepuffer ist der zweite Teil */
OutBuffer = InBuffer + BufSize;
CurOutPtr = OutBuffer; /* Zeiger auf Puffer initialisieren */
LinePtr = Line;
CurBufLen = 0;
Put(PipeId,PipeIdLen); /* ID-String zum Nachrichtenfenster
schicken */
while ((c = NextChar()) != 0) /* Zeichen lesen */
{
if ((c == 13) || (c == 10)) /* aufbauen, bis Zeilenende erreicht */
{
*LinePtr = 0;
ProcessLine(Line); /* Zeile analysieren */
LinePtr = Line;
}
/* Bis zu 132 Zeichen werden in den Puffer geschrieben */
else if ((FP_OFF(LinePtr) - FP_OFF(&Line)) < 132)
{
*LinePtr = c; /* zum Zeilenpuffer hinzufügen */
LinePtr++;
}
}
*LinePtr = 0;
ProcessLine(Line); /* Letzte Zeile analysieren */
EndMark = MsgEoFile;
Put(&EndMark,1); /* Eingabeende im Nachrichtenfenster
anzeigen */
flushOut((unsigned)(CurOutPtr-OutBuffer)); /* Den Puffer ausgeben */
return 0; /* OK zurückgeben */
}