home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / Dloads / OTHERUTI / TCPP30-3.ZIP / EXAMPLES.ZIP / TASM2MSG.C < prev    next >
C/C++ Source or Header  |  1992-02-18  |  18KB  |  430 lines

  1. /*
  2.    EXAMPLE SOURCE CODE FOR TASM FILTER
  3.  
  4.    Tasm2Msg.C
  5.    Copyright (c) 1990, 1991 Borland International, Inc.
  6.    All rights reserved.
  7.  
  8.    Tasm2Msg - assembler output filter to Turbo C++ IDE message window
  9.  
  10.    This filter accepts input through the standard input stream, converts
  11.    it and outputs it to the standard output stream.  The streams are linked
  12.    through pipes, such that the input stream is the output from the assembler
  13.    being invoked, and the output stream is connected to the message window
  14.    of the Turbo C++ IDE, ie.
  15.  
  16.           tasm fname | tasm2msg | Turbo C++ message window
  17.  
  18.    Input can come from TASM, MASM 5.1 or OPTASM.  The type of assembler is
  19.    determined from analysing the lines of output from the assembler.
  20.  
  21.    Compile using Turbo C++ in the LARGE memory model
  22.  
  23.    tcc -ml tasm2msg
  24. */
  25.  
  26. #include <dir.h>
  27. #include <dos.h>
  28. #include <stdlib.h>
  29. #include <fcntl.h>
  30. #include <string.h>
  31. #include <alloc.h>
  32. #include <io.h>
  33. #include <ctype.h>
  34. #include "filter.h"
  35.  
  36. #define TRUE (1 == 1)
  37. #define FALSE !(TRUE)
  38.  
  39. /* Turbo Assembler text for conversion */
  40. char TasmWarningTxt[] = "*Warning* ";
  41. char TasmErrorTxt[]   = "**Error** ";
  42. char TasmFatalTxt[]   = "**Fatal** ";
  43.  
  44. /* Microsoft Assembler and OPTASM text for conversion */
  45. char MasmWarningText[] = "warning";
  46. char MasmErrorText[]   = "error";
  47.  
  48. char     CurFile[MAXPATH];       /* Current file in message window */
  49. unsigned BufSize,                /* Size of internal working buffer */
  50.          CurBufLen;              /* Buffer space in use */
  51. char     *InBuffer,              /* Input buffer */
  52.          *OutBuffer,             /* Output buffer */
  53.          *CurInPtr,              /* current character in input buffer */
  54.          *CurOutPtr,             /* current character in output */
  55.          *LinePtr;               /* pointer to the current character in
  56.                                     the input buffer */
  57. int      (*processor)(char *);   /* function pointer used to call the
  58.                                     appropriate conversion routine */
  59. char     Line[133];              /* static buffer to store line most recently
  60.                                     input */
  61. long int InOff;                  /* position in actual input stream */
  62. char     EndMark;                /* Used to output end of data to message
  63.                                     window */
  64.  
  65. /*************************************************************************
  66. Function  : NextChar
  67. Parameters: none
  68. Returns   : next character in input buffer or 0 on end of file
  69.  
  70. Input from the standard input stream is buffered in a global buffer InBuffer
  71. which is allocated in function main.  The function will return
  72. the next character in the buffer, reading from the input stream when the
  73. buffer becomes empty.
  74. **************************************************************************/
  75. char NextChar(void)
  76. {
  77.   if (CurInPtr < InBuffer+CurBufLen)  /* if buffer is not empty */
  78.   {
  79.     return *(CurInPtr++);             /* return next character */
  80.   }
  81.   else
  82.   {
  83.     CurInPtr = InBuffer;              /* reset pointer to front of buffer */
  84.     lseek(0,InOff,0);                 /* seek to the next section for read */
  85.     InOff += BufSize;                 /* increment pointer to next block */
  86.     if ((CurBufLen = read(0,InBuffer,BufSize)) !=0)
  87.       return NextChar();              /* recursive call merely returns
  88.                                          first character in buffer after read */
  89.     return 0;                         /* return 0 on end of file */
  90.   }
  91. }
  92.  
  93. /*************************************************************************
  94. Function  : flushOut
  95. Parameter : Size   The number of characters to be written out
  96. Returns   : nothing
  97.  
  98. Strings to be sent to the message window are buffered in a buffer called
  99. OutBuffer.  A call to this function will write out Size bytes from OutBuffer
  100. to the standard output stream and resets the output buffer pointer to the
  101. beginning of the buffer.  The output buffer is considered empty after a call
  102. to this function.
  103. *************************************************************************/
  104. void flushOut(unsigned Size)
  105. {
  106.    if (Size != 0)                /* don't flush an empty buffer */
  107.    {
  108.       CurOutPtr = OutBuffer;     /* reset pointer to beginning of buffer */
  109.       lseek(1,0,2);              /* seek output stream to end */
  110.       write(1,OutBuffer,Size);   /* write out Size bytes */
  111.    }
  112. }
  113.  
  114. /************************************************************************
  115. Function  : Put
  116. Parameters: S    pointer to bytes being put into output buffer
  117.             Len  number of bytes to be put in output buffer
  118. Returns   : nothing
  119.  
  120. Put places bytes into OutBuffer so they may be later flushed out into
  121. the standard output stream.
  122. ************************************************************************/
  123. void Put(char *S,int Len)
  124. {
  125.    int i;
  126.  
  127.    for (i = 0; i < Len; i++)
  128.    {
  129.       *CurOutPtr++ = S[i];                   /* place byte in buffer */
  130.       if (CurOutPtr >= OutBuffer+BufSize)    /* if buffer overflows */
  131.          flushOut(BufSize);                  /* flush the buffer */
  132.    }
  133. }
  134.  
  135.  
  136. /************************************************************************
  137. Function  : ProcessNonTasmLine
  138. Parameters: Line  a pointer to the current line of characters to process
  139. Returns   : 1 if line is Microsoft Assembler line
  140.             0 if line is not
  141.  
  142. Analyze line to determine if it is output from a MASM or OPTASM compatible
  143. assembler. In the case of a recognizable line, output relevant information
  144. to the message window indicating message and line number.
  145. -*----------------------------------------------------------------------*-
  146. Microsoft assembler lines which are in need of conversion are of the form:
  147.  
  148.    source-file(LINE #): message-kind message-num : message text
  149.  
  150. where message-kind is one of:  warning, error
  151. -*----------------------------------------------------------------------*-
  152. OPTASM assembler lines which are in need of conversion are of the form:
  153.  
  154.    source-file(LINE #) : message-kind message-num : message text
  155.  
  156. where message-kind is one of: Warning, Error
  157. -*----------------------------------------------------------------------*-
  158. Masm and Optasm lines differ from Tasm lines in that half the line must be
  159. scanned in order to determine if the line is valid.  For this reason all
  160. output information is stored and sent at the end when the determination of
  161. a valid line is made.
  162. ************************************************************************/
  163. int ProcessNonTasmLine(char *Line)
  164. {
  165.    char     Type;
  166.    unsigned i;
  167.    char     *s;
  168.    char     fn[MAXPATH];
  169.    int      NewFile;
  170.  
  171.    if (Line[0] == 0)                         /* Empty line, no action */
  172.       return 0;
  173.  
  174.    s = strchr(Line,'(');                     /* find ( */
  175.    if (s != NULL)                            /* if no (, invalid line */
  176.    {
  177.       memmove(fn,Line,(unsigned)(s-Line));    /* store filename */
  178.       fn[(unsigned)(s-Line)] = 0;             /* null terminate name */
  179.       memmove(Line,++s,strlen(Line));         /* shift line left */
  180.       if (strcmp(fn,CurFile) != 0)            /* if new filename */
  181.       {
  182.          NewFile = TRUE;                      /* indicate by setting flag */
  183.          strcpy(CurFile,fn);                  /* store new name */
  184.       }
  185.       else NewFile = FALSE;
  186.       s = strchr(Line,')');                   /* find the close paren */
  187.       if (s != NULL)                          /* if no ) invalid line */
  188.       {
  189.          *s = 0;                               /* isolate the line number */
  190.          i = atoi(Line);                       /* if number is found convert
  191.                                                   string to integer */
  192.          if (i != 0)
  193.          {
  194.             s++;
  195.             while (*s == ' ')                  /* optasm has space here */
  196.                s++;
  197.             if (*s != ':')                     /* strip : from line */
  198.                return 0;                       /* no :, not MASM line */
  199.             s++;
  200.             memmove(Line,s,strlen(s)+1);        /* shift line */
  201.             while (Line[0] == ' ' && Line[0] != 0)  /* strip spaces from line */
  202.                memmove(Line,&Line[1],strlen(Line));
  203.             Line[0] = tolower(Line[0]);        /* optasm uses upper case */
  204.             /* check for warning or error text from MASM, shift line if
  205.                needed. */
  206.             if ((strncmp(Line, MasmWarningText, strlen(MasmWarningText)) != 0) &&
  207.                 (strncmp(Line, MasmErrorText, strlen(MasmErrorText)) != 0))
  208.                return 0; /* not error or warning, not MASM line */
  209.  
  210.             /* strip spaces from beginning of line */
  211.             while (Line[0] == ' ' && Line[0] != 0)  /* strip spaces from line */
  212.                memmove(Line,&Line[1],strlen(Line));
  213.          }
  214.          else return 0;                   /* no line number, not MASM line */
  215.       }
  216.       else return 0;                      /* no ), not MASM line */
  217.       if (NewFile)
  218.       {
  219.          Type = MsgNewFile;               /* send new file indicated */
  220.          Put(&Type,1);                    /* Put info to output stream */
  221.          Put(CurFile,strlen(CurFile)+1);  /* along with the new name */
  222.       }
  223.       Type = MsgNewLine;                  /* set type to new line */
  224.       Put(&Type,1);                       /* indicate need for new line */
  225.       Put((char *)&i,2);                  /* put the number out */
  226.       i = 1;                              /* set column in message box */
  227.       Put((char *)&i,2);                  /* tab over to put message */
  228.       Put(Line,strlen(Line)+1);           /* output the message */
  229.    }
  230.    else return 0;                         /* no ( on line, not MASM line */
  231.  
  232.    return 1;                              /* MASM line */
  233. }
  234.  
  235. /*************************************************************************
  236. Function  : ProcessTasmLine
  237. Parameters: Line  a pointer to the current line of characters to process
  238. Returns   : 1 if line is a Turbo Assembler line
  239.             0 if line is not
  240.  
  241. Process through a line of input to determine if it is a Turbo Assembler
  242. output line and convert it to information for the Turbo C++ message window.
  243.  
  244. Turbo Assembler lines which are in need of conversion are of the form:
  245.  
  246.     message-type source-file(LINE #) message-text
  247.  
  248. where type is one of: *Warning*, **Error**, **Fatal**
  249.  
  250. TASM lines are identified by the first portion of text.  If warning,
  251. error or fatal is determined at the outset, text is output from there
  252. as it is scanned.  Any incorrect configuration will simply abort the
  253. scanning of the rest of the line.
  254. *************************************************************************/
  255. int ProcessTasmLine(char *Line)
  256. {
  257.    static int HavePutFile = FALSE;
  258.    char     Type;
  259.    unsigned i;
  260.    char     *s;
  261.    char     fn[MAXPATH];
  262.  
  263.    /* don't try to process a NULL line */
  264.    if (Line[0] == 0)
  265.       return 0;
  266.  
  267.    /* check for tasm type tags */
  268.    if ((strncmp(Line,TasmWarningTxt,strlen(TasmWarningTxt)) == 0) ||
  269.       (strncmp(Line,TasmErrorTxt,  strlen(TasmErrorTxt)) == 0) ||
  270.       (strncmp(Line,TasmFatalTxt,  strlen(TasmFatalTxt)) == 0))
  271.  
  272.    {
  273.       /* skip over type by moving string left */
  274.       memmove(Line,&Line[strlen(TasmFatalTxt)],strlen(Line));
  275.  
  276.       /* locate the first open paren '(' filename will be characters to
  277.      to the left, line number will be characters to the right up to the
  278.      close paren ')' */
  279.       s = strchr(Line,'(');                      /* find ( */
  280.       if (s != NULL)                             /* if no (, invalid line */
  281.       {
  282.      memmove(fn,Line,(unsigned)(s-Line));    /* save filename */
  283.      fn[(unsigned)(s-Line)] = 0;             /* null terminate name */
  284.      memmove(Line,++s,strlen(Line));         /* shift line left */
  285.      if (strcmp(fn,CurFile) != 0)            /* if new filename */
  286.      {
  287.             Type = MsgNewFile;                   /* indicate by sending type
  288.                             out to message window */
  289.         strcpy(CurFile,fn);
  290.         Put(&Type,1);
  291.             Put(CurFile,strlen(CurFile)+1);      /* along with the new name */
  292.         HavePutFile = TRUE;
  293.      }
  294.      Type = MsgNewLine;                      /* set type to new line */
  295.      s = strchr(Line,')');                   /* find the close paren */
  296.      if (s != NULL)
  297.      {
  298.             *s = 0;                              /* isolate number in string */
  299.             i = atoi(Line);                      /* if number is found convert
  300.                             string to integer */
  301.         if (i != 0)
  302.         {
  303.            Put(&Type,1);                       /* indicate need for new line */
  304.            Put((char *)&i,2);                  /* put the number out */
  305.            i = 1;                              /* set column in message box */
  306.            Put((char *)&i,2);                  /* tab over to put message */
  307.            s++;
  308.            memmove(Line,s,strlen(s)+1);        /* shift line */
  309.            while (Line[0] == ' ' && Line[0] != 0)  /* strip spaces from line */
  310.           memmove(Line,&Line[1],strlen(Line));
  311.            Put(Line,strlen(Line)+1);           /* output the message */
  312.                return 1;              /* TASM line */
  313.         }
  314.             return 0;                 /* invalid line number, not TASM line */
  315.      }
  316.          return 0;                    /* no ) in line, not TASM line */
  317.       }
  318.       else                            /* Fatal error, no line # or filename */
  319.       {
  320.         if( !HavePutFile )
  321.         {
  322.        /* IDE expects the first message to
  323.           be preceded by a filename.  Since
  324.           we don't have one, fake it by
  325.           sending a NULL file before the
  326.           message.
  327.        */
  328.        Type = MsgNewFile;                  /* indicate by sending type
  329.                               out to message window */
  330.        *CurFile = '\0';
  331.        Put(&Type,1);
  332.        Put(CurFile,1);                     /* along with null filename */
  333.            HavePutFile = TRUE;
  334.         }
  335.                        
  336.     Type = MsgNewLine;            /* Fake line # etc.                   */
  337.     i    = 1;
  338.     Put(&Type,1);
  339.     Put((char *)&i,2);
  340.     Put((char *)&i,2);
  341.     while (Line[0] == ' ' && Line[0] != 0)
  342.       memmove(Line,&Line[1],strlen(Line));
  343.     Put(Line,strlen(Line)+1);
  344.     return 1;
  345.       }
  346.    }
  347.    else return 0;                     /* no line start message, not TASM line */
  348. }
  349.  
  350. /**************************************************************************
  351. Function  : ProcessLine
  352. Parameters: Line    character pointer to line of input data
  353. Returns   : nothing
  354.  
  355. If line type has been determined, call correct line processor through
  356. a function pointer.  Else try testing for both Tasm style line and Masm
  357. style line to determine if either one is the input to the filter.
  358. **************************************************************************/
  359. void ProcessLine(char *Line)
  360. {
  361.     if (processor == NULL)
  362.     {
  363.        if (ProcessTasmLine(Line))            /* check for TASM line */
  364.           processor = ProcessTasmLine;
  365.        else
  366.           if (ProcessNonTasmLine(Line))      /* check MASM or OPTASM style */
  367.              processor = ProcessNonTasmLine;
  368.     }
  369.     else
  370.        processor(Line);                      /* type already determined */
  371. }
  372.  
  373.  
  374. /***********************************************************************
  375. Function  : main
  376.  
  377. Returns   : zero for successful execution
  378.             3    if an error is encountered
  379.  
  380. The main routine allocates buffers for the input and output buffer.
  381. Characters are then read from the input buffer building the line buffer
  382. that will be sent to the filter processor.  Lines are read and filtered
  383. until the end of input is reached.
  384. ***********************************************************************/
  385. int main( void )
  386. {
  387.    char c;
  388.    unsigned long core;
  389.  
  390.    setmode(1,O_BINARY);               /* set output stream to binary mode */
  391.    core = farcoreleft();
  392.    if (core > 64000U)
  393.       BufSize = 64000U;
  394.    else BufSize = (unsigned)core;     /* get available memory */
  395.                                       /* stay under 64K */
  396.    if ((CurInPtr = malloc(BufSize)) == NULL) /* allocate buffer space */
  397.       exit(3);
  398.    processor = NULL;                  /* set current processor to none */
  399.    InBuffer = CurInPtr;               /* input buffer is first half of space */
  400.    BufSize = BufSize/2;               /* output buffer is 2nd half */
  401.    OutBuffer = InBuffer + BufSize;
  402.    CurOutPtr = OutBuffer;             /* set buffer pointers */
  403.    LinePtr = Line;
  404.    CurBufLen = 0;
  405.    Put(PipeId,PipeIdLen);             /* send ID string to message window */
  406.    while ((c = NextChar()) != 0)      /* read characters */
  407.    {
  408.       if ((c == 13) || (c == 10))     /* build until line end */
  409.       {
  410.          *LinePtr = 0;
  411.          ProcessLine(Line);           /* filter the line */
  412.          LinePtr = Line;
  413.       }
  414.       /* characters are added to buffer up to 132 characters max */
  415.       else if ((FP_OFF(LinePtr) - FP_OFF(&Line)) < 132)
  416.       {
  417.          *LinePtr = c;                /* add to line buffer */
  418.          LinePtr++;
  419.       }
  420.    }
  421.    *LinePtr = 0;
  422.    ProcessLine(Line);                 /* filter last line */
  423.    EndMark = MsgEoFile;
  424.    Put(&EndMark,1);                   /* indicate end of input to
  425.                                          the message window */
  426.    flushOut((unsigned)(CurOutPtr-OutBuffer));     /* flush the buffer */
  427.    return 0;                          /* return OK */
  428. }
  429.  
  430.