home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / C / SASC6571.LZX / extras / smfind / smcomm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-24  |  6.1 KB  |  208 lines

  1. /*-------------------------------------------------------------------*/
  2. /* Copyright (c) 1993 SAS Institute, Inc.  All Rights Reserved.      */
  3. /* Author: Doug Walker                                               */
  4. /* Support: walker                                                   */
  5. /*-------------------------------------------------------------------*/
  6.  
  7. #include <string.h>
  8. #include <dos/dos.h>
  9. #include <rexx/rxslib.h>
  10. #include <exec/memory.h>
  11. #include <proto/exec.h>
  12. #include <proto/dos.h>
  13.  
  14. #include "smcomm.h"
  15.  
  16. /* NAME:    LaunchSCMSG                                           */
  17. /* PURPOSE: Invoke the SCMSG utility if it is not already running */
  18.  
  19. static struct MsgPort *LaunchSCMSG(void)
  20. {
  21.    static int scmsg_launched;  // If non-zero, we've tried once already
  22.    struct MsgPort *smport;
  23.    BPTR fh1, fh2;
  24.    int i;
  25.  
  26.    if(!(smport = FindPort("SC_SCMSG")))
  27.    {
  28.       if(scmsg_launched) return(NULL);  // Tried once and failed; give it up
  29.  
  30.       fh1 = Open("nil:", MODE_NEWFILE);
  31.       fh2 = Open("nil:", MODE_NEWFILE);
  32.       Execute("run >nil: <nil: sc:c/scmsg", fh1, fh2);
  33.       Close(fh1);
  34.       Close(fh2);
  35.       for(i=0; i<15; i++)
  36.       {
  37.          Delay(20);  // 0.4 seconds delay
  38.          if(smport = FindPort("SC_SCMSG")) break;
  39.       }
  40.    }
  41.    scmsg_launched = 1;
  42.    return(smport);
  43. }
  44.  
  45. /* NAME:    CreateRexxMsg2                                                */
  46. /* PURPOSE: Create a RexxMsg structure in order to communicate with SCMSG */
  47.  
  48. static struct RexxMsg *CreateRexxMsg2(struct MsgPort *rport, 
  49.                                       char *file, 
  50.                                       char *comm)
  51. {
  52.     struct RexxMsg *rm;
  53.     
  54.     rm = AllocMem(sizeof(struct RexxMsg), MEMF_CLEAR | MEMF_PUBLIC);
  55.     if (!rm) return NULL;
  56.     rm->rm_CommAddr = comm;
  57.     rm->rm_FileExt = file;
  58.     rm->rm_Node.mn_ReplyPort = rport;
  59.     rm->rm_Node.mn_Length = 128;
  60.     return rm;
  61. }
  62.  
  63. /* NAME:    DeleteRexxMsg2                                  */
  64. /* PURPOSE: Delete a previously allocated RexxMsg structure */
  65.  
  66. static void DeleteRexxMsg2(struct RexxMsg *rm)
  67. {
  68.     FreeMem(rm, sizeof(struct RexxMsg));
  69. }
  70.  
  71. static char msgline[512];
  72.  
  73. /* NAME:    DoSCMSG                                     */
  74. /* PURPOSE: Perform the actual communication with SCMSG */
  75.  
  76. static int DoSCMSG(char *line)
  77. {
  78.    struct MsgPort *scmport, *rport;
  79.    struct RexxMsg *RXMsg;
  80.    int rc = 0;
  81.  
  82.    LaunchSCMSG();  // Run SCMSG if it's not already running
  83.  
  84.    /* Create the REXX reply port */
  85.    if(!(rport = CreatePort(NULL, 0L)))
  86.       return(-1);
  87.  
  88.    if((RXMsg=CreateRexxMsg2(rport, "scm", "SC_SCMSG")) != NULL)
  89.    {
  90.       RXMsg->rm_Action = RXCOMM;
  91.       RXMsg->rm_Args[0] = line;
  92.       RXMsg->rm_Args[1] = (void *)strlen(line);
  93.       Forbid();
  94.       /* We do this under Forbid() to prevent SCMSG from exiting */
  95.       /* before our message gets there                           */
  96.       if(scmport = FindPort("SC_SCMSG"))
  97.       {
  98.          PutMsg(scmport, (struct Message *)RXMsg);
  99.          Permit();
  100.  
  101.          /* Wait for SCMSG's reply */
  102.          while(GetMsg(rport) == NULL)
  103.             WaitPort(rport);
  104.       }
  105.       else
  106.       {
  107.          Permit();
  108.          rc = -1;
  109.       }
  110.    }
  111.  
  112.    // Free up the REXX reply port
  113.    FreeSignal((long)(rport->mp_SigBit));
  114.    DeletePort(rport);
  115.  
  116.    if(RXMsg) DeleteRexxMsg2(RXMsg);
  117.  
  118.    return(rc);
  119. }
  120.  
  121. static int addtext(char *to, char *from, int quotes)
  122. {
  123.    int i, j;
  124.    if(quotes)
  125.    {
  126.       *to = '\"';
  127.       i = 1;
  128.    }
  129.    else
  130.       i = 0;
  131.    j = strlen(from);
  132.    memcpy(to+i, from, j);
  133.    i += j;
  134.    if(quotes) to[i++] = '\"';
  135.    to[i] = ' ';
  136.    return(i+1);
  137. }
  138.  
  139. /* NAME:    AddSCMSG                                                    */
  140. /* PURPOSE: Add a new message to the SCMSG list                         */
  141. /* NOTES:   We must construct the message from the provided components, */
  142. /*             then call DoSCMSG to do the communications work.         */
  143.  
  144. int AddSCMSG(char *cunit, char *file, int line, char *msg)
  145. {
  146.    int save_char, save_pos = 0;
  147.    int len;
  148.    if(strlen(file) + strlen(msg) + strlen(cunit) + 20 > sizeof(msgline))
  149.       return(-1);  // Message too long
  150.  
  151.    // Construct the message
  152.    strcpy(msgline, "newmsg ");
  153.    len = strlen(msgline);
  154.    len += addtext(msgline+len, cunit, 1);
  155.    len += addtext(msgline+len, file, 1);
  156.    len += stci_d(msgline+len, line);
  157.    msgline[len++] = ' ';
  158.    len += addtext(msgline+len, "0 \"\" 0 ", 0);
  159.  
  160.    /* If you want anything but informational messages, you need to change */
  161.    /* the line below to add something other than "Info 0".  For example,  */
  162.    /* to add error number 1156, use "Error 1156".  Use "Error", "Warning",*/
  163.    /* or "Info" for the message class, and any integer less than 32767 for*/
  164.    /* the message number.                                                 */
  165.    len += addtext(msgline+len, "Info 0 ", 0);
  166.  
  167.    if(strlen(msg) > sizeof(msgline) - len - 2)
  168.    {
  169.       save_pos = sizeof(msgline) - len - 2;
  170.       save_char = msg[save_pos];
  171.       msg[save_pos] = 0;
  172.    }
  173.  
  174.    len += addtext(msgline+len, msg, 0);
  175.  
  176.    if(save_pos)
  177.       msg[save_pos] = save_char;
  178.  
  179.    msgline[len-1] = 0;
  180.  
  181.    return DoSCMSG(msgline);
  182. }
  183.  
  184. /* NAME:    ClearSCMSG                                                        */
  185. /* PURPOSE: Get rid of the results of the previous call to SCMSG that has     */
  186. /*             the specified "compilation unit".  When the compiler does      */
  187. /*             this, the "compilation unit" represents the C source file      */
  188. /*             being compiled; i.e. when foo.c gets recompiled, all previous  */
  189. /*             messages from foo.c disappear.  Other utilities such as smfind */
  190. /*             can name their compilation units as they see fit and clear     */
  191. /*             them at a single shot with ClearSCMSG.                         */
  192.  
  193. int ClearSCMSG(char *cunit)
  194. {
  195.    // No need for Forbid()/Permit() here; if the port does exist, then
  196.    // DoSCMSG will Forbid() at the appropriate time.  We check for the
  197.    // port's existence before calling just so we don't invoke SCMSG
  198.    // if it's not already invoked.
  199.    if(FindPort("SC_SCMSG"))
  200.    {
  201.       strcpy(msgline, "newbld \"");
  202.       strcpy(msgline+8, cunit);
  203.       strcpy(msgline+strlen(msgline), "\"");
  204.       return DoSCMSG(msgline);
  205.    }
  206.    return(0);
  207. }
  208.