home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / filter.pak / TASM2MSG.C < prev    next >
C/C++ Source or Header  |  1997-07-23  |  13KB  |  440 lines

  1. /*
  2.    Tasm2Msg.C      copyright (c) 1993 Borland International
  3. */
  4.  
  5. #include "ToolApi.H"  // Borland IDE tool dll interface
  6. #include "filtrc.h"
  7.  
  8. #include <stdlib.h>
  9. #include <ctype.h>
  10. #include <mem.h>
  11. #include <dos.h>
  12. #include <dir.h>
  13. #include <string.h>
  14.  
  15. #include <windows.h>
  16.  
  17. // Name the intermediate "PIPE" through which output will be captured
  18. #define PIPEID "C:\\$$PIPE$$.TC$"
  19.  
  20. /* Declare an array of function pointers to store the IDE tool API */
  21. IDE_ToolAPIFunc IDE_ToolAPI[IDE_NumFunctions];
  22.  
  23. /* Global variables use to parse program output */
  24. HINSTANCE  globInst;
  25.  
  26. /* Turbo Assembler text for conversion */
  27. char TasmWarningTxt[] = "*Warning* ";
  28. char TasmErrorTxt[]   = "**Error** ";
  29. char TasmFatalTxt[]   = "**Fatal** ";
  30.  
  31. /* Microsoft Assembler and OPTASM text for conversion */
  32. char MasmWarningText[] = "warning";
  33. char MasmErrorText[]   = "error";
  34.  
  35. char     CurFile[MAXPATH];       /* Current file in message window */
  36.  
  37. FileHandle Pipefh;
  38.  
  39. HMEM       hBuffer;
  40. LPSTR      Buffer;
  41. WORD       curpos;
  42. WORD       bufLen;
  43.  
  44. char       inLine[133];
  45. LPSTR      lineptr;
  46.  
  47. int      (*processor)(char *);   /* function pointer used to call the
  48.                     appropriate conversion routine */
  49.  
  50. int numFatals   = 0;
  51. int numErrors   = 0;
  52. int numWarnings = 0;
  53.  
  54. /*
  55.   InitBuffer - allocate memory for filtering the piped output to the IDE
  56. */
  57. void InitBuffer( void )
  58. {
  59.   hBuffer = IDE_memalloc( MEM_MOVEABLE, 8192 );
  60.   Buffer = IDE_memlock( hBuffer );
  61.   bufLen = 0;
  62.   curpos = 0;
  63. }
  64.  
  65. /*
  66.   ReleaseBuffer - cleanup allocated buffers and open file handles
  67. */
  68. void ReleaseBuffer( void )
  69. {
  70.   IDE_memunlock( hBuffer );
  71.   IDE_memfree( hBuffer );
  72.   IDE_Close( Pipefh );
  73.   IDE_Delete( PIPEID );
  74. }
  75.  
  76. /*
  77.    nextchar - returns the next character from the pipe input
  78.  
  79.    returns: next character from the pipe associated with handle Pipefh
  80. */
  81. char nextchar( void )
  82. {
  83.   if (curpos < bufLen)
  84.   {
  85.     return Buffer[curpos++];
  86.   }
  87.   Buffer[0] = '\0';
  88.   bufLen = IDE_Read( Pipefh, Buffer, 7000 );
  89.   if (bufLen == 0)
  90.     return 0;
  91.   curpos = 0;
  92.   return nextchar();
  93. }
  94.  
  95. /*
  96.   GetLine - get the next line of text from the pipe
  97.  
  98.   returns: far pointer to string containing next line of text from the current opened
  99.        pipe file
  100. */
  101. LPSTR GetLine( void )
  102. {
  103.   char ch;
  104.   int  count;
  105.  
  106.   lineptr = inLine;
  107.   count = 0;
  108.   while (((ch = nextchar()) != '\x0D') && (ch != '\x0A') && (ch != 0) && (count<133))
  109.   {
  110.     *lineptr = ch;
  111.     lineptr++;
  112.      count++;
  113.   }
  114.   if (count == 133)
  115.   {
  116.      strcpy( &inLine[125], "......" );
  117.   }
  118.   if ((lineptr == inLine) && (ch == 0))
  119.   {
  120.     return NULL;
  121.   }
  122.   *lineptr = '\0';
  123.   return inLine;
  124. }
  125.  
  126. /************************************************************************
  127. Function  : ProcessNonTasmLine
  128. Parameters: Line  a pointer to the current line of characters to process
  129. Returns   : 1 if line is Microsoft Assembler line
  130.             0 if line is not
  131.  
  132. Analyze line to determine if it is output from a MASM or OPTASM compatible
  133. assembler. In the case of a recognizable line, output relevant information
  134. to the message window indicating message and line number.
  135. -*----------------------------------------------------------------------*-
  136. Microsoft assembler lines which are in need of conversion are of the form:
  137.  
  138.    source-file(LINE #): message-kind message-num : message text
  139.  
  140. where message-kind is one of:  warning, error
  141. -*----------------------------------------------------------------------*-
  142. OPTASM assembler lines which are in need of conversion are of the form:
  143.  
  144.    source-file(LINE #) : message-kind message-num : message text
  145.  
  146. where message-kind is one of: Warning, Error
  147. -*----------------------------------------------------------------------*-
  148. Masm and Optasm lines differ from Tasm lines in that half the line must be
  149. scanned in order to determine if the line is valid.  For this reason all
  150. output information is stored and sent at the end when the determination of
  151. a valid line is made.
  152. ************************************************************************/
  153. int ProcessNonTasmLine(char *Line)
  154. {
  155.    unsigned i;
  156.    char     *s;
  157.    char     fn[MAXPATH];
  158.    Msg M;
  159.  
  160.    if (Line[0] == 0)                         /* Empty line, no action */
  161.       return 0;
  162.  
  163.    s = strchr(Line,'(');                     /* find ( */
  164.    if (s != NULL)                            /* if no (, invalid line */
  165.    {
  166.       memmove(fn,Line,(unsigned)(s-Line));    /* store filename */
  167.       fn[(unsigned)(s-Line)] = 0;             /* null terminate name */
  168.       memmove(Line,++s,strlen(Line));         /* shift line left */
  169.       if (strcmp(fn,CurFile) != 0)            /* if new filename */
  170.       {
  171.          strcpy(CurFile,fn);                  /* store new name */
  172.       }
  173.       s = strchr(Line,')');                   /* find the close paren */
  174.       if (s != NULL)                          /* if no ) invalid line */
  175.       {
  176.          *s = 0;                               /* isolate the line number */
  177.          i = atoi(Line);                       /* if number is found convert
  178.                                                   string to integer */
  179.          if (i != 0)
  180.          {
  181.             s++;
  182.             while (*s == ' ')                  /* optasm has space here */
  183.                s++;
  184.             if (*s != ':')                     /* strip : from line */
  185.                return 0;                       /* no :, not MASM line */
  186.             s++;
  187.             memmove(Line,s,strlen(s)+1);        /* shift line */
  188.             while (Line[0] == ' ' && Line[0] != 0)  /* strip spaces from line */
  189.                memmove(Line,&Line[1],strlen(Line));
  190.             Line[0] = tolower(Line[0]);        /* optasm uses upper case */
  191.             /* check for warning or error text from MASM, shift line if
  192.                needed. */
  193.         if (strncmp(Line, MasmWarningText, strlen(MasmWarningText)) != 0)
  194.         {
  195.            if (strncmp(Line, MasmErrorText, strlen(MasmErrorText)) != 0)
  196.            {
  197.          return 0; /* not error or warning, not MASM line */
  198.            }
  199.            else
  200.            {
  201.          numErrors++;  // increase number of numErrors posted
  202.            }
  203.         }
  204.             else
  205.             {
  206.               numWarnings++;
  207.             }
  208.  
  209.             /* strip spaces from beginning of line */
  210.             while (Line[0] == ' ' && Line[0] != 0)  /* strip spaces from line */
  211.                memmove(Line,&Line[1],strlen(Line));
  212.          }
  213.          else return 0;                   /* no line number, not MASM line */
  214.       }
  215.       else return 0;                      /* no ), not MASM line */
  216.  
  217.        M.message = Line;
  218.        M.filename = CurFile;
  219.        M.column = 1;
  220.        M.line = i;
  221.  
  222.        IDE_PostMessage( CUR_MSG_GROUP, &M );
  223.    }
  224.    else return 0;                         /* no ( on line, not MASM line */
  225.  
  226.    return 1;                              /* MASM line */
  227. }
  228.  
  229. /*************************************************************************
  230. Function  : ProcessTasmLine
  231. Parameters: Line  a pointer to the current line of characters to process
  232. Returns   : 1 if line is a Turbo Assembler line
  233.             0 if line is not
  234.  
  235. Process through a line of input to determine if it is a Turbo Assembler
  236. output line and convert it to information for the Turbo C++ message window.
  237.  
  238. Turbo Assembler lines which are in need of conversion are of the form:
  239.  
  240.     message-type source-file(LINE #) message-text
  241.  
  242. where type is one of: *Warning*, **Error**, **Fatal**
  243.  
  244. TASM lines are identified by the first portion of text.  If warning,
  245. error or fatal is determined at the outset, text is output from there
  246. as it is scanned.  Any incorrect configuration will simply abort the
  247. scanning of the rest of the line.
  248. *************************************************************************/
  249. int ProcessTasmLine(char *Line)
  250. {
  251.    unsigned   i;
  252.    char       *s;
  253.    char       fn[MAXPATH];
  254.    Msg        M;
  255.    int        lineHasErrorText = FALSE;
  256.  
  257.    /* don't try to process a NULL line */
  258.    if (Line[0] == 0)
  259.       return 0;
  260.  
  261.    /* check for tasm type tags */
  262.    if (strncmp(Line,TasmFatalTxt,  strlen(TasmFatalTxt)) == 0)
  263.    {
  264.      lineHasErrorText = TRUE;
  265.      numFatals++;
  266.    }
  267.    
  268.    if (strncmp(Line,TasmErrorTxt,  strlen(TasmErrorTxt)) == 0)
  269.    {
  270.      lineHasErrorText = TRUE;
  271.      numErrors++;
  272.    }
  273.  
  274.    if (strncmp(Line,TasmWarningTxt,strlen(TasmWarningTxt)) == 0)
  275.    {
  276.      numWarnings++;
  277.      lineHasErrorText = TRUE;
  278.    }
  279.      
  280.    if ( lineHasErrorText )
  281.    {
  282.       /* set fn to something */
  283.       fn[0] = '\0';
  284.  
  285.       /* skip over type by moving string left */
  286.       memmove(Line,&Line[strlen(TasmFatalTxt)],strlen(Line));
  287.  
  288.       /* locate the first open paren '(' filename will be characters to
  289.      to the left, line number will be characters to the right up to the
  290.      close paren ')' */
  291.       s = strchr(Line,'(');                      /* find ( */
  292.       if (s != NULL)                             /* if no (, invalid line */
  293.       {
  294.      memmove(fn,Line,(unsigned)(s-Line));    /* save filename */
  295.      fn[(unsigned)(s-Line)] = 0;             /* null terminate name */
  296.      memmove(Line,++s,strlen(Line));         /* shift line left */
  297.      if (strcmp(fn,CurFile) != 0)            /* if new filename */
  298.      {
  299.         strcpy(CurFile,fn);
  300.      }
  301.      s = strchr(Line,')');                   /* find the close paren */
  302.      if (s != NULL)
  303.      {
  304.         *s = 0;                              /* isolate number in string */
  305.         i = atoi(Line);                      /* if number is found convert
  306.                             string to integer */
  307.         if (i != 0)
  308.         {
  309.            s++;
  310.            memmove(Line,s,strlen(s)+1);        /* shift line */
  311.            while (Line[0] == ' ' && Line[0] != 0)  /* strip spaces from line */
  312.               memmove(Line,&Line[1],strlen(Line));
  313.            M.message = Line;
  314.            M.filename = CurFile;
  315.            M.column = 1;
  316.            M.line = i;
  317.  
  318.            IDE_PostMessage( CUR_MSG_GROUP, &M );
  319.            return 1;              /* TASM line */
  320.         }
  321.         return 0;                 /* invalid line number, not TASM line */
  322.      }
  323.      return 0;                    /* no ) in line, not TASM line */
  324.       }
  325.       else                            /* Fatal error, no line # or filename */
  326.       {
  327.           CurFile[0] = '\0';
  328.     while (Line[0] == ' ' && Line[0] != 0)
  329.       memmove(Line,&Line[1],strlen(Line));
  330.     M.message = Line;
  331.     M.filename = CurFile;
  332.     M.column = 1;
  333.     M.line = 1;
  334.  
  335.     IDE_PostMessage( CUR_MSG_GROUP, &M );
  336.     return 1;
  337.       }
  338.    }
  339.    else return 0;                     /* no line start message, not TASM line */
  340. }
  341.  
  342. /*
  343.   ProcessLine - dissect line of input and post it as a message to the IDE
  344.  
  345.   Input:  LPSTR line    the line to dissect and post
  346. */
  347. void ProcessLine( LPSTR Line )
  348. {
  349.     if (processor == NULL)
  350.     {
  351.        if (ProcessTasmLine(Line))            /* check for TASM line */
  352.       processor = ProcessTasmLine;
  353.        else
  354.       if (ProcessNonTasmLine(Line))      /* check MASM or OPTASM style */
  355.              processor = ProcessNonTasmLine;
  356.     }
  357.     else
  358.        processor(Line);                      /* type already determined */
  359. }
  360.  
  361. /*
  362.   FilterToIDE - Open the pipe output from the program, read and post each line
  363.         to the IDE
  364. */
  365. void FilterToIDE( void )
  366. {
  367.   LPSTR line;
  368.   
  369.   Pipefh = IDE_Open( PIPEID, 0 );
  370.  
  371.   if (Pipefh < 0)
  372.   {
  373.     char error[100];
  374.     LoadString( globInst, IDS_CANNOTFILTER, error, sizeof(error));
  375.     IDE_ErrorBox( error );
  376.     numFatals++;
  377.     return;
  378.   }
  379.  
  380.   InitBuffer();
  381.  
  382.   while ((line = GetLine()) != NULL)
  383.   {
  384.     ProcessLine( line );
  385.   }
  386.  
  387.   ReleaseBuffer();
  388. }
  389.  
  390. /*
  391.    Run  -  exported entry point to the filter DLL
  392.  
  393.    Input:  pTransferBlock TransBlock    contains information about the program to
  394.                     be run, its command line, and the IDE tool API
  395. */
  396. int far pascal _export Run( pTransferBlock TransBlock )
  397. {
  398.   // Store the IDE tool API
  399.   memcpy( IDE_ToolAPI, TransBlock->IDE_ToolAPI, sizeof(IDE_ToolAPI) );
  400.  
  401.   // Try to run program capturing output to an intermediate file
  402.   IDE_CaptureToPipe( TransBlock->program,
  403.              TransBlock->cmdline,
  404.              PIPEID );
  405.  
  406.   // post the captured output to the IDE
  407.   FilterToIDE();
  408.  
  409.   // return appropriate code for 
  410.   if (numFatals)
  411.   {
  412.     return toolFatalError;
  413.   }
  414.   if (numErrors)
  415.   {
  416.     return toolErrors;
  417.   }
  418.   if (numWarnings)
  419.   {
  420.     return toolWarnings;
  421.   }
  422.   
  423.   return toolSuccess;
  424. }
  425.  
  426. #pragma argsused
  427. int far pascal LibMain( HINSTANCE hInstance, WORD wDataSegment,
  428.             WORD wHeapSize, LPSTR lpszCmdLine )
  429. {
  430.   globInst = hInstance;
  431.   return 1;
  432. }
  433.  
  434. #pragma argsused
  435. int FAR PASCAL WEP ( int bSystemExit )
  436. {
  437.     return 1;
  438. }
  439.  
  440.