home *** CD-ROM | disk | FTP | other *** search
- /*
- 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 */
- }