home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 14.ddi / FILTER.PAK / TASM2MSG.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  12.3 KB  |  432 lines

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