home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / tcpp / examples / tasm2msg.c < prev    next >
Text File  |  1990-06-09  |  18KB  |  408 lines

  1. /*
  2.    BEISPIELQUELLCODE FÜR DAS TASM FILTERPROGRAMM
  3.  
  4.    Tasm2Msg.C
  5.    Copyright (c) 1990 Borland International, Inc.
  6.    Alle Rechte vorbehalten.
  7.  
  8.    Tasm2Msg - Nachrichtenfilter von Turbo Assembler zum Turbo C++ IDE
  9.               Nachrichtenfenster (message window).
  10.  
  11.    Dieser Filter akzeptiert Eingaben über den Standard-Eingabe-Stream,
  12.    konvertiert sie und gibt sie über den Standard-Ausgabe-Stream aus.
  13.    Die Streams sind über Pipes miteinander verbunden: der
  14.    Eingabe-Stream ist die Ausgabe des Assemblers, und der
  15.    Ausgabe-Stream ist mit dem Nachrichtenfenster der Turbo C++
  16.    Entwicklungsumgebung verbunden. Der Filter wird mit folgendem
  17.    Befehl aufgerufen:
  18.  
  19.               tasm fname | tasm2msg | Turbo C++-Nachrichtenfenster
  20.  
  21.    Eingaben können von TASM, MASM 5.1 oder OPTASM kommen. Der Assembler-Typ
  22.    wird aus den Daten, die der Assembler bereitstellt, bestimmt.
  23.  
  24.    Übersetzen Sie mit dem Speichermodell LARGE von Turbo C++:
  25.  
  26.    tcc -ml tasm2msg*/
  27.  
  28. #include <dir.h>
  29. #include <dos.h>
  30. #include <stdlib.h>
  31. #include <fcntl.h>
  32. #include <string.h>
  33. #include <alloc.h>
  34. #include <io.h>
  35. #include <ctype.h>
  36. #include "filter.h"
  37.  
  38. #define TRUE (1 == 1)
  39. #define FALSE !(TRUE)
  40.  
  41. /* Turbo Assembler-Text zum Konvertieren */
  42. char TasmWarningTxt[] = "*Warning* ";
  43. char TasmErrorTxt[]   = "**Error** ";
  44. char TasmFatalTxt[]   = "**Fatal** ";
  45.  
  46. /* Microsoft Assembler-und OPTASM-Text zum Konvertieren */
  47. char MasmWarningText[] = "warning";
  48. char MasmErrorText[]   = "error";
  49.  
  50. char     CurFile[MAXPATH];       /* Aktuelle Datei im Nachrichtendenster */
  51. unsigned BufSize,                /* Größe des internen Arbeitspuffers */
  52.          CurBufLen;              /* Größe des Puffers, der in Gebrauch ist */
  53. char     *InBuffer,              /* Eingabepuffer */
  54.          *OutBuffer,             /* Ausgabepuffer */
  55.          *CurInPtr,              /* Aktuelles Zeichen im Eingabepuffer */
  56.          *CurOutPtr,             /* Aktuelles Zeichen im Ausgabepuffer */
  57.          *LinePtr;               /* Zeiger auf das aktuelle Zeichen im
  58.                                     Eingabepuffer */
  59. int      (*processor)(char *);   /* Funktionszeiger für den Aufruf der
  60.                                     passenden Konversionsroutine */
  61. char     Line[133];              /* Statischer Puffer zum Speichern der
  62.                                     aktuellsten Eingabe */
  63. long int InOff;                  /* Position innerhalb der Eingabedaten */
  64. char     EndMark;                /* zeigt das Ende der Daten an */
  65.  
  66. /*************************************************************************
  67. Funktion  : NextChar
  68. Parameter : keine
  69. Rückgabe  : nächstes Zeichen im Eingabepuffer oder 0 für Dateiende
  70.  
  71. Eingaben von der Standard-Eingabe werden im globalen Puffer InBuffer,
  72. für den in main Speicher reserviert wird, abgelegt. Die Funktion gibt
  73. das nächste Zeichen im Puffer zurück und liest weitere Eingabedaten,
  74. wenn der Puffer leer ist.
  75. **************************************************************************/
  76. char NextChar(void)
  77. {
  78.   if (CurInPtr < InBuffer+CurBufLen)  /* Wenn der Puffer nicht leer ist */
  79.   {
  80.     return *(CurInPtr++);             /* Gibt das nächste Zeichen zurück */
  81.   }
  82.   else
  83.   {
  84.     CurInPtr = InBuffer;              /* Setzt Pointer auf Puffer-Anfang */
  85.     lseek(0,InOff,0);                 /* Suche nach nächstem Lesebereich */
  86.     InOff += BufSize;                 /* Zeigt auf den nächsten Textblock */
  87.     if ((CurBufLen = read(0,InBuffer,BufSize)) !=0)
  88.       return NextChar();              /* Rekursiver Aufruf gibt das erste
  89.                                          Zeichen des Puffers zurück */
  90.     return 0;                         /* Rückgabewert 0 bei Dateiende */
  91.   }
  92. }
  93.  
  94. /*************************************************************************
  95. Funktion  : flushOut
  96. Parameter : Size   Anzahl der Zeichen, die geschrieben werden
  97. Rückgabe  : nichts
  98.  
  99. Strings, die zum Nachrichtenfenster geschickt werden, stehen im Puffer
  100. OutBuffer. Ein Aufruf dieser Funktion bewirkt, daß Size-Bytes vom OutBuffer
  101. zur Standard-Ausgabe geschrieben werden; der Zeiger des Ausgabepuffers zeigt
  102. wieder auf den Anfang desselben. Danach wird der Ausgabepuffer als leer
  103. angesehen.
  104. *************************************************************************/
  105. void flushOut(unsigned Size)
  106. {
  107.    if (Size != 0)              /* Keinen leeren Puffer herausschreiben */
  108.    {
  109.       CurOutPtr = OutBuffer;  /* Zeiger auf den Puffer-Anfang positionieren */
  110.       lseek(1,0,2);
  111.       write(1,OutBuffer,Size); /* Anzahl der Bytes (Size) anzeigen */
  112.    }
  113. }
  114.  
  115. /************************************************************************
  116. Funktion  : Put
  117. Parameter : S    Zeiger auf die Bytes, die in den Ausgabe-Puffer geschrieben
  118.                  werden
  119.             Len  Anzahl der Bytes, die in den Ausgabe-Puffer geschrieben
  120.                  werden
  121. Rückgabe  : nichts
  122.  
  123. Put schreibt Bytes in den OutBuffer, sodaß sie später an die Standard-Aus-
  124. gabe geschrieben werden können
  125. ************************************************************************/
  126. void Put(char *S,int Len)
  127. {
  128.    int i;
  129.  
  130.    for (i = 0; i < Len; i++)
  131.    {
  132.       *CurOutPtr++ = S[i];                  /* Byte in den Puffer schreiben */
  133.       if (CurOutPtr >= OutBuffer+BufSize)   /* Wenn der Puffer voll ist, */
  134.          flushOut(BufSize);                 /* die Daten rausschreiben */
  135.    }
  136. }
  137.  
  138.  
  139. /************************************************************************
  140. Funktion  : ProcessNonTasmLine
  141. Parameter : Line  Zeiger auf die aktuelle Zeile, die verarbeitet werden soll
  142. Rückgabe  : 1, wenn es sich um Microsoft Assembler handelt
  143.             0, wenn nicht
  144.  
  145. Die Zeile wird daraufhin untersucht, ob es sich um einen MASM- oder OPTASM-
  146. kompatiblen Assembler handelt. Falls die Zeile lesbar ist, wird an das Nach-
  147. richtenfenster Information über die Nachricht und die Zeilennummer ausgege-
  148. ben.
  149. -*----------------------------------------------------------------------*-
  150. Microsoft Assembler-Zeilen, die konvertiert werden, sind von der Form:
  151.  
  152.    source-file(LINE #): message-kind message-num : message text
  153.  
  154. Message-kind ist entweder eine Warnung oder ein Fehler.
  155. -*----------------------------------------------------------------------*-
  156. OPTASM Assembler-Zeilen, die konvertiert werden, sind von der Form:
  157.  
  158.    source-file(LINE #) : message-kind message-num : message text
  159.  
  160. Message-kind ist entweder eine Warnung oder ein Fehler.
  161. -*----------------------------------------------------------------------*-
  162. Masm- und Optasm-Zeilen unterscheiden sich von Tasm-Zeilen: die Hälfte der
  163. Zeile muß geprüft werden, um festzustellen, ob sie gültig ist. Aus diesem
  164. Grund wird die Information erst am Ende der Zeile weitergegeben, wenn klar
  165. ist, ob die Zeile gültig ist oder nicht.
  166. ************************************************************************/
  167. int ProcessNonTasmLine(char *Line)
  168. {
  169.    char     Type;
  170.    unsigned i;
  171.    char     *s;
  172.    char     fn[MAXPATH];
  173.    int      NewFile;
  174.  
  175.    if (Line[0] == 0)                         /* Leere Zeile, keine Aktion */
  176.       return 0;
  177.  
  178.    s = strchr(Line,'(');                     /* ( suchen */
  179.    if (s != NULL)                            /* Wenn keine (, Zeile ungültig*/
  180.    {
  181.       memmove(fn,Line,(unsigned)(s-Line));    /* Dateinamen speichern */
  182.       fn[(unsigned)(s-Line)] = 0;             /* Null schließt den Namen ab */
  183.       memmove(Line,++s,strlen(Line));         /* Zeile nach links bewegen */
  184.       if (strcmp(fn,CurFile) != 0)            /* Wenn ein neuer Dateiname */
  185.       {
  186.          NewFile = TRUE;                      /* dann ein Flag setzen */
  187.          strcpy(CurFile,fn);                  /* Neuen Namen speichern */
  188.       }
  189.       else NewFile = FALSE;
  190.       s = strchr(Line,')');               /* Die schließende Klammer suchen */
  191.       if (s != NULL)                      /* Wenn keine ), Zeile ungültig */
  192.       {
  193.          *s = 0;                          /* Zeilennummer isolieren */
  194.          i = atoi(Line);                  /* Die Nummer von einem String
  195.                                              in ein Integer konvertieren */
  196.          if (i != 0)
  197.          {
  198.             s++;
  199.             while (*s == ' ')             /* optasm hat hier ein Leerzeichen*/
  200.                s++;
  201.             if (*s != ':')                     /* : aus der Zeile entfernen
  202.                return 0;                       /* Kein :, keine MASM-Zeile */
  203.             s++;
  204.             memmove(Line,s,strlen(s)+1);       /* Zeile verschieben */
  205.             while (Line[0] == ' ' && Line[0] != 0)  /* Leerzeichen entfernen*/
  206.                memmove(Line,&Line[1],strlen(Line));
  207.             Line[0] = tolower(Line[0]);        /* optasm verwendet Großbuch-
  208.                                                   staben
  209.                                                /* Prüfen auf Warnung oder
  210.                                                   Fehlertext von MASM, Zeile
  211.                                                   verschieben, wenn nötig */
  212.             if ((strncmp(Line, MasmWarningText, strlen(MasmWarningText)) != 0) &&
  213.                 (strncmp(Line, MasmErrorText, strlen(MasmErrorText)) != 0))
  214.                return 0; /* Kein Fehler, keine Warnung, keine MASM-Zeile */
  215.  
  216.             /* Leerzeichen aus der Zeile entfernen */
  217.             while (Line[0] == ' ' && Line[0] != 0)  /* Leerzeichen entfernen */
  218.                memmove(Line,&Line[1],strlen(Line));
  219.          }
  220.          else return 0;              /* keine Zeilennummer, keine MASM-Zeile */
  221.       }
  222.       else return 0;                 /* keine ), keine MASM-Zeile */
  223.       if (NewFile)
  224.       {
  225.          Type = MsgNewFile;               /* neue Datei senden */
  226.          Put(&Type,1);                    /* Information ausgeben */
  227.          Put(CurFile,strlen(CurFile)+1);  /* zusammen mit dem neuen Namen */
  228.       }
  229.       Type = MsgNewLine;                  /* Neue Zeile */
  230.       Put(&Type,1);                       /* Zeigen, daß neue Zeile nötig */
  231.       Put((char *)&i,2);                  /* Nummer ausgeben */
  232.       i = 1;                              /* Spalte in der Nachrichtenbox */
  233.       Put((char *)&i,2);                  /* Nachricht ausgeben */
  234.       Put(Line,strlen(Line)+1);
  235.    }
  236.    else return 0;                         /* Keine (, keine MASM-Zeile */
  237.  
  238.    return 1;                              /* MASM-Zeile */
  239. }
  240.  
  241. /*************************************************************************
  242. Funktion  : ProcessTasmLine
  243. Parameter : Line  Zeiger auf die aktuelle Zeile, die verarbeitet wird
  244. Rückgabe  : 1, wenn es sich um eine Turbo Assembler-Zeile handelt
  245.             0, wenn nicht
  246.  
  247. Eine Eingabezeile wird daraufhin analysiert, ob es sich um eine Turbo
  248. Assembler-Zeile handelt, und in Information für das Nachrichtenfenster
  249. konvertiert.
  250.  
  251. Turbo Assembler-Zeilen, die konvertiert werden müssen, haben die Form:
  252.  
  253.     message-type source-file(LINE #) message-text
  254.  
  255. Typ ist *Warning*, **Error** oder **Fatal**
  256.  
  257. TASM-Zeilen werden durch den Textanfang identifiziert. Wenn Warning,
  258. Error oder Fatal vorliegen, wird der Text so ausgegeben, wie er eingelesen
  259. worden ist. Jede falsche Konfiguration bricht das Analysieren des Restes
  260. der Zeile einfach ab.
  261. *************************************************************************/
  262. int ProcessTasmLine(char *Line)
  263. {
  264.    char     Type;
  265.    unsigned i;
  266.    char     *s;
  267.    char     fn[MAXPATH];
  268.  
  269.    /* Leere Zeilen werden nicht verarbeitet */
  270.    if (Line[0] == 0)
  271.       return 0;
  272.  
  273.    /* Prüfen der Tasm-Typen */
  274.    if ((strncmp(Line,TasmWarningTxt,strlen(TasmWarningTxt)) == 0) ||
  275.       (strncmp(Line,TasmErrorTxt,  strlen(TasmErrorTxt)) == 0) ||
  276.       (strncmp(Line,TasmFatalTxt,  strlen(TasmFatalTxt)) == 0))
  277.  
  278.    {
  279.       /* Typ überspringen: String nach links verschieben */
  280.       memmove(Line,&Line[strlen(TasmFatalTxt)],strlen(Line));
  281.  
  282.       /* Die erste öffnende Klammer '(' definiert: die Zeichen zur Linken
  283.          sind ein Dateiname, die Zeichen zur Rechten (bis zur schließenden
  284.          Klammer ')') bezeichnen eine Zeilennummer. */
  285.       s = strchr(Line,'(');                      /* ( gefunden */
  286.       if (s != NULL)                             /* Ohne (: Zeile ungültig */
  287.       {
  288.          memmove(fn,Line,(unsigned)(s-Line));    /* Dateinamen speichern */
  289.          fn[(unsigned)(s-Line)] = 0;             /* Null schließt Namen ab */
  290.          memmove(Line,++s,strlen(Line));         /* Zeile nach links */
  291.          if (strcmp(fn,CurFile) != 0)            /* falls neuer Dateiname */
  292.          {
  293.             Type = MsgNewFile;                   /* Den Typ im Nachrichten-
  294.                                                     fenster anzeigen */
  295.             strcpy(CurFile,fn);
  296.             Put(&Type,1);
  297.             Put(CurFile,strlen(CurFile)+1); /* zusammen mit dem neuen Namen */
  298.          }
  299.          Type = MsgNewLine;
  300.          s = strchr(Line,')');              /* Schließende Klammer suchen */
  301.          if (s != NULL)
  302.          {
  303.             *s = 0;                         /* Nummer im String isolieren */
  304.             i = atoi(Line);                 /* Gefundene Nummer von einem
  305.                                                Sring in Integer konvertieren */
  306.             if (i != 0)
  307.             {
  308.                Put(&Type,1);                /* Bedarf für eine neue Zeile */
  309.                Put((char *)&i,2);           /* Die Nummer ausgeben */
  310.                i = 1;                       /* Spalte in Nachrichtenbox def.*/
  311.                Put((char *)&i,2);
  312.                s++;
  313.                memmove(Line,s,strlen(s)+1);        /* Zeile verschieben */
  314.                while (Line[0] == ' ' && Line[0] != 0)  /* Leerzeichen entfernen */
  315.                   memmove(Line,&Line[1],strlen(Line));
  316.                Put(Line,strlen(Line)+1);           /* Nachricht ausgeben */
  317.                return 1;              /* TASM-Zeile */
  318.             }
  319.             return 0;            /* Zeilennummer ungültig: keine TASM-Zeile */
  320.          }
  321.          return 0;               /* Keine ) in der Zeile: keine TASM-Zeile */
  322.       }
  323.       return 0;                  /* Keine ( in der Zeile: keine TASM-Zeile */
  324.    }
  325.    else return 0;                /* Kein Zeilenanfang: keine TASM-Zeile */
  326. }
  327.  
  328. /**************************************************************************
  329. Funktion  : ProcessLine
  330. Parameter : Line   Zeiger auf die Zeile mit den Eingabedaten
  331. Rückgabe  : nichts
  332.  
  333. Wenn der Zeilentyp bestimmt worden ist, wird die passende Verarbeitung über
  334. einen Funktionszeiger gestartet. Im anderen Fall wird geprüft, ob es sich
  335. um eine Tasm- oder eine Masm-Zeile handelt.
  336. **************************************************************************/
  337. void ProcessLine(char *Line)
  338. {
  339.     if (processor == NULL)
  340.     {
  341.        if (ProcessTasmLine(Line))            /* Prüfen auf TASM-Zeile */
  342.           processor = ProcessTasmLine;
  343.        else
  344.           if (ProcessNonTasmLine(Line))      /* Prüfen auf MASM oder OPTASM */
  345.              processor = ProcessNonTasmLine;
  346.     }
  347.     else
  348.        processor(Line);                      /* Typ schon bekannt */
  349. }
  350.  
  351.  
  352. /***********************************************************************
  353. Funktion  : main
  354.  
  355. Rückgabe  : 0, falls erfolgreich ausgeführt
  356.             3, falls ein Fehler aufgetreten ist
  357.  
  358. Die Routine Main reserviert Speicher für Ein- und Ausgabepuffer. Aus dem
  359. Eingabepuffer wird zeichenweise gelesen, dann der Zeilenpuffer gefüllt,
  360. dessen Inhalt danach analysiert wird. Es wird solange gelesen und analysiert,
  361. bis das Ende der Eingabe erreicht ist.
  362. ***********************************************************************/
  363. int main( void )
  364. {
  365.    char c;
  366.    unsigned long core;
  367.  
  368.    setmode(1,O_BINARY);               /* Ausgabe im Binär-Modus */
  369.    core = farcoreleft();
  370.    if (core > 64000U)
  371.       BufSize = 64000U;
  372.    else BufSize = (unsigned)core;     /* verfügbaren Speicher bestimmen */
  373.                                       /* unter 64KByte bleiben */
  374.    if ((CurInPtr = malloc(BufSize)) == NULL) /* Pufferspeicher reservieren */
  375.       exit(3);
  376.    processor = NULL;                  /* Verarbeitungsweise zurücksetzen */
  377.    InBuffer = CurInPtr;               /* Eingabepuffer ist der erste Teil */
  378.    BufSize = BufSize/2;               /* Ausgabepuffer ist der zweite Teil */
  379.    OutBuffer = InBuffer + BufSize;
  380.    CurOutPtr = OutBuffer;             /* Zeiger auf Puffer initialisieren */
  381.    LinePtr = Line;
  382.    CurBufLen = 0;
  383.    Put(PipeId,PipeIdLen);             /* ID-String zum Nachrichtenfenster
  384.                                          schicken */
  385.    while ((c = NextChar()) != 0)      /* Zeichen lesen */
  386.    {
  387.       if ((c == 13) || (c == 10))     /* aufbauen, bis Zeilenende erreicht */
  388.       {
  389.          *LinePtr = 0;
  390.          ProcessLine(Line);           /* Zeile analysieren */
  391.          LinePtr = Line;
  392.       }
  393.       /* Bis zu 132 Zeichen werden in den Puffer geschrieben */
  394.       else if ((FP_OFF(LinePtr) - FP_OFF(&Line)) < 132)
  395.       {
  396.          *LinePtr = c;                /* zum Zeilenpuffer hinzufügen */
  397.          LinePtr++;
  398.       }
  399.    }
  400.    *LinePtr = 0;
  401.    ProcessLine(Line);                 /* Letzte Zeile analysieren */
  402.    EndMark = MsgEoFile;
  403.    Put(&EndMark,1);                   /* Eingabeende im Nachrichtenfenster
  404.                                          anzeigen */
  405.    flushOut((unsigned)(CurOutPtr-OutBuffer));     /* Den Puffer ausgeben */
  406.    return 0;                          /* OK zurückgeben */
  407. }
  408.