home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / APIEXT.ZIP / APIEXT.C < prev    next >
C/C++ Source or Header  |  1988-04-18  |  16KB  |  480 lines

  1. /*
  2.  *  Module Name:    apiext.c    API conversion M extensions by Byron Dazey
  3.  *
  4.  *  Description:
  5.  *  ----------------------------------------------------------------------
  6.  *  APIEXT is an M extension written by Byron Dazey to help developers
  7.  *  convert from the all uppercase OS/2 API convention using the include
  8.  *  file "doscalls.h" used by C 4.5 to the mixed case API convention using
  9.  *  "os2.h" used in the newer C 5.1 product.
  10.  *
  11.  *  By default,  these functions assume the existence of the file
  12.  *  "os2api.lst" in the current directory.  This file contains the API's
  13.  *  in their mixed case form and is sectioned off in groups by the #define
  14.  *  names that need to be defined to include them (called INCL's).
  15.  *  Lines in this file that start with a semi-colon are comments,
  16.  *  lines that start with a "#" are INCL's. Other lines are assumed to
  17.  *  be OS/2 API's in their mixed case form.  For example:
  18.  *
  19.  *  ----------os2api.lst------------
  20.  *  ;comments here            <- This is a comment line
  21.  *  #INCL_DOSPROCESS            <- This is a #define
  22.  *  DosExecPgm                <-
  23.  *  DosExit                <- These are API's for INCL_DOSPROCESS
  24.  *
  25.  *  If required, the text switch "apilist" can be set to the path and
  26.  *  file name of the file that contains the API's.  If used, this switch
  27.  *  must contain at least the file name portion of the location of this
  28.  *  list.  For instance:
  29.  *
  30.  *  apilist:c:\init\apilist.txt      or
  31.  *  apilist:apilist.txt
  32.  *
  33.  *  would be valid, but not:
  34.  *
  35.  *  apilist:c:\init
  36.  *
  37.  *
  38.  *  This extension needs to be "loaded" into the editor to be used.  This
  39.  *  can be done in the TOOLS.INI file by adding the following lines:
  40.  *
  41.  *  [mep]
  42.  *    load:apiext
  43.  *
  44.  *  for OS/2 or:
  45.  *
  46.  *  [m]
  47.  *    load:apiext.exe
  48.  *
  49.  *  for DOS.
  50.  *
  51.  *  To use in OS/2, copy the file APIEXT.DLL to somewhere on your LIBPATH
  52.  *  and edit your TOOLS.INI file as described above.  Invoke MEP on the
  53.  *  file to convert and press alt+2 or alt+1 (unless you have re-assigned
  54.  *  these keys).
  55.  *
  56.  *  To use in DOS, copy the file APIEXT.EXE to somewhere on your PATH and
  57.  *  edit your TOOLS.INI file as described above.  Invoke M on the file to
  58.  *  convert and press alt+2 or alt+1 (unless you have re-assigned these
  59.  *  keys).  I had trouble with my version of M not finding the apiext.exe
  60.  *  file on the path.  If this happens, copy apiext.exe to your current
  61.  *  directory or fully qualify the pathname in the "load:" statement in
  62.  *  TOOLS.INI (ex. load:c:\tools\bin\apiext.exe).
  63.  *
  64.  *  The format of the routines, data structures and several calls used are
  65.  *  documented in the manual for the editor in the chapter on "Writing M
  66.  *  Extensions".
  67.  *
  68.  *  Make File
  69.  *  ----------------------------------------------------------------------
  70.  *  # makefile for the apiext M extension
  71.  *
  72.  *  apiext.obj:  $*.c
  73.  *    cl /W3 /Gs /c /Asfu $*.c
  74.  *
  75.  *  # make OS/2 version -----------------------------------
  76.  *
  77.  *  apiext.dll: exthdrp.obj $*.obj
  78.  *    link /NOD /NOI $**,$*,nul,clibcep doscalls,$*.def;
  79.  *
  80.  *  # make DOS version ------------------------------------
  81.  *
  82.  *  apiext.exe: exthdr.obj $*.obj
  83.  *    link /NOD /NOI $**,$*,nul,clibcer api;
  84.  *
  85.  *  Change Log
  86.  *  ----------------------------------------------------------------------
  87.  *  04/18/88    0.10    BDD    Initial Release
  88.  *
  89.  */
  90.  
  91. #include <ext.h>        /*for M extensions            */
  92. #include <string.h>        /*for C library string functions    */
  93.  
  94. #define INCL_DOSPROCESS     /*for DosBeep                */
  95. #define INCL_DOSFILEMGR     /*for DosQFileMode            */
  96. #include <os2.h>
  97.  
  98. #undef TRUE            /*defined in os2.h            */
  99. #define TRUE    -1
  100. #define FALSE    0
  101. #define NULL    ((char *) 0)
  102.  
  103.                 /*printed on startup            */
  104. #define LOADMESSAGE \
  105.     "API Conversion M Extensions Version 0.10 Are Now Loaded."
  106.                 /*regular expression for searching for    */
  107.                 /* "#include <doscalls.h>"        */
  108. #define REGEXPDOSCALLS \
  109.     "^\\\\#include:b[\\\"<][dD][oO][sS][cC][aA][lL][lL][sS].[hH][\\\">]"
  110.                 /*regular expression for searching for    */
  111.                 /* "#include <subcalls.h>"        */
  112. #define REGEXPSUBCALLS \
  113.     "^\\\\#include:b[\\\"<][sS][uU][bB][cC][aA][lL][lL][sS].[hH][\\\">]"
  114.  
  115. flagType pascal EXTERNAL ConvertAPI(unsigned int, ARG far *, flagType);
  116. flagType pascal EXTERNAL InsertAPIIncl(unsigned int, ARG far *, flagType);
  117. flagType pascal EXTERNAL SwApiList(char far *);
  118. flagType WhenLoaded(void);
  119.  
  120. char chBuf[128];        /*line buffer                */
  121. char CmdBuf[128];        /*command buffer            */
  122. PFILE pListFile;        /*API list file pointer         */
  123. PFILE pCurFile;         /*current file pointer            */
  124. LINE l;             /*line counter                */
  125. LINE qLines;            /*number of lines in the list file    */
  126. char InclStr[33] = "";        /*save area for the INCL        */
  127. COL xCur;            /*saved column of the cursor        */
  128. LINE yCur;            /*saved line of the cursor        */
  129.                 /*API list file name            */
  130. char ListFileName[128] = "os2api.lst";
  131. unsigned FileAttr;        /*used by DosQFileMode            */
  132. flagType NewIncl;        /*TRUE if we are on a new INCL        */
  133.  
  134. /*
  135.  *  Function Name:  ConvertAPI
  136.  *
  137.  *  Extension: convertapi
  138.  *
  139.  *  Description
  140.  *  ----------------------------------------------------------------------
  141.  *  This extension is used to convert all the occurances of an OS/2 API
  142.  *  to its mixed case equivalent.  The os2api.lst file is read and all the
  143.  *  API's listed are searched for without regard for case and globally
  144.  *  replaced with the case as found in the os2api.lst file.  Because the
  145.  *  length of the API is not changing, comments should not need to be
  146.  *  lined up again.
  147.  *
  148.  *  This extension will search through the current file for where the
  149.  *  include file "doscalls.h" is being included and replace it with a
  150.  *  line including "os2.h".  If "doscalls.h" is not found then it will
  151.  *  add the include for "os2.h" at the beginning of the file.
  152.  *
  153.  *  This line can be in any of the following forms, with the case of
  154.  *  "doscalls.h" and the number of spaces after "include" not being
  155.  *  important:
  156.  *
  157.  *  #include <doscalls.h>
  158.  *  #include "doscalls.h"
  159.  *  #include        <DOSCALLS.H>
  160.  *
  161.  *
  162.  *  These will be replaced with:
  163.  *
  164.  *  #include <os2.h>
  165.  *
  166.  *
  167.  *  A line including "subcalls.h" will also be searched for in a similiar
  168.  *  manner and will be deleted if found.
  169.  *
  170.  *  This extension will then search for the API's in each group in the
  171.  *  os2api.lst file and if an API for a certain "INCL" is found, it will
  172.  *  insert an appropriate #define statement for it before the include for
  173.  *  "os2.h".  For example, if "DosExecPgm" is found in the file, the
  174.  *  following will be added to the file:
  175.  *
  176.  *  #define INCL_DOSPROCESS
  177.  *  #include <os2.h>
  178.  *
  179.  *  WARNING!
  180.  *  API's that appear in comments and conditionally compiled sections of
  181.  *  code will be converted.  In addition, if any function or variable has
  182.  *  been named with part of an API's name, it will be converted to mixed
  183.  *  case also.    For instance, the user function "xDOSEXIT" would be
  184.  *  converted to "xDosExit".  This could also result in more #define
  185.  *  statements than are strictly necessary.  This is not a C preprocessor!
  186.  *
  187.  *  This function is not blinding fast.  It must invoke a global search
  188.  *  and replace on each OS/2 API and this can take a while for large
  189.  *  source files.  It is, however, much faster than doing it by hand and
  190.  *  should only need to be done once.
  191.  *
  192.  *
  193.  *  Parameters:
  194.  *  Name        Type        Description
  195.  *  --------------- --------------- --------------------------------------
  196.  *  argData        unsigned int    Value of the keystroke pressed
  197.  *  pArg        ARG far *        Argument type specific data
  198.  *  fMeta        flagType        TRUE if META was pressed
  199.  *
  200.  *  Returns:    flagType
  201.  *  Description
  202.  *  ----------------------------------------------------------------------
  203.  *  TRUE for a successful operation or FALSE if an error occurred.
  204.  *
  205.  */
  206.  
  207. flagType pascal EXTERNAL ConvertAPI(argData, pArg, fMeta)
  208. unsigned int argData;
  209. ARG far * pArg;
  210. flagType fMeta;
  211. {
  212.                 /*check for existence of list file    */
  213.     if (DosQFileMode(ListFileName, &FileAttr, 0L)) {
  214.  
  215.     strcpy(chBuf, "CONVERTAPI: The list file \"");
  216.     strcat(chBuf, ListFileName);
  217.     strcat(chBuf, "\" was not found!");
  218.     DoMessage(chBuf);
  219.     DosBeep(1200L, 100L);
  220.  
  221.     return (FALSE);     /*return failure            */
  222.     }
  223.                 /*make file buffer for list file    */
  224.     pListFile = AddFile(ListFileName);
  225.                 /*read list file into the M buffer    */
  226.     FileRead(ListFileName, pListFile);
  227.                 /*get length of list file        */
  228.     qLines = FileLength(pListFile);
  229.                 /*get a handle to the current file    */
  230.     pCurFile = FileNameToHandle("", "");
  231.  
  232.                 /*search for the old subcalls.h include */
  233.                 /*line in the source            */
  234.     strcpy(CmdBuf, "mark arg arg \"");
  235.     strcat(CmdBuf, REGEXPSUBCALLS);
  236.     strcat(CmdBuf, "\" psearch");
  237.     if (fExecute(CmdBuf))    /*found! delete line            */
  238.     fExecute("ldelete");
  239.  
  240.                 /*search for the old doscalls.h include */
  241.                 /*line in the source            */
  242.     strcpy(CmdBuf, "mark arg arg \"");
  243.     strcat(CmdBuf, REGEXPDOSCALLS);
  244.     strcat(CmdBuf, "\" psearch");
  245.     if (fExecute(CmdBuf))    /*found! (replace with os2.h)        */
  246.     fExecute("arg ldelete \"#include <os2.h>\" begline");
  247.     else            /*not found! (put at top of file)    */
  248.     fExecute("mark linsert \"#include <os2.h>\"");
  249.  
  250.     GetCursor(&xCur, &yCur);    /*save position in file         */
  251.  
  252.     NewIncl = TRUE;        /*should not be necessary because first */
  253.                 /*non-comment line in os2api.lst should */
  254.                 /*be a new INCL             */
  255.  
  256.                 /*loop through the list file        */
  257.     for (l = 0; l < qLines; l++) {
  258.  
  259.                 /*get the next line            */
  260.     GetLine(l, chBuf, pListFile);
  261.  
  262.     if (*chBuf == ';')    /*skip if a comment line        */
  263.         continue;
  264.  
  265.     if (*chBuf == '#') {    /*is it an INCL?            */
  266.  
  267.                 /*save it without the '#',        */
  268.         strcpy(InclStr, &chBuf[1]);
  269.         NewIncl = TRUE;    /*reset flag                */
  270.         continue;        /*and go on                */
  271.     }
  272.  
  273.     DoMessage(chBuf);    /*display API                */
  274.  
  275.                 /*do a case insensitive global search    */
  276.                 /*and replace on the API        */
  277.     strcpy(CmdBuf, "mark replace \"");
  278.     strcat(CmdBuf, chBuf);
  279.     strcat(CmdBuf, "\" arg emacsnewl \"");
  280.     strcat(CmdBuf, chBuf);
  281.     strcat(CmdBuf, "\" arg emacsnewl");
  282.  
  283.                 /*API found and first one for the INCL? */
  284.     if (fExecute(CmdBuf) && NewIncl) {
  285.  
  286.                 /*go to saved file position        */
  287.         MoveCur((COL) 0, yCur);
  288.  
  289.                 /*insert a #define for the INCL     */
  290.         strcpy(CmdBuf, "linsert \"#define ");
  291.         strcat(CmdBuf, InclStr);
  292.         strcat(CmdBuf, "\"");
  293.         fExecute(CmdBuf);
  294.  
  295.         yCur++;        /*increment saved file position because */
  296.                 /*we just added a line            */
  297.  
  298.         NewIncl = FALSE;    /*reset flag so we only add one define    */
  299.                 /*per INCL                */
  300.     }
  301.     }
  302.  
  303.     fExecute("mark");        /*go to the top of the file        */
  304.  
  305.     RemoveFile(pListFile);    /*remove temporary list file        */
  306.  
  307.     DosBeep(1200L, 50L);
  308.     DoMessage("CONVERTAPI: Complete.");
  309.  
  310.     return TRUE;        /*return success            */
  311. }
  312.  
  313. /*
  314.  *  Function Name:  InsertAPIIncl
  315.  *
  316.  *  Extension: insertapiincl
  317.  *
  318.  *  Description
  319.  *  ----------------------------------------------------------------------
  320.  *  This extension will search for the API's in each group in the
  321.  *  os2api.lst file and if an API for a certain "INCL" is found, it will
  322.  *  insert an appropriate #define statement for it at the top of the file.
  323.  *  For example, if "DosExecPgm" is found in the file, the following will
  324.  *  be added to the top of the file:
  325.  *
  326.  *  #define INCL_DOSPROCESS
  327.  *
  328.  *  This functionality is also included in the convertapi function.  It is
  329.  *  repeated in this function so that a programmer can find all the names
  330.  *  of the INCL's that must be defined for a converted program that has
  331.  *  undergone some development/maintenance since being converted.  In some
  332.  *  cases it would be useful to know if all the INCL's being defined still
  333.  *  need to be.
  334.  *
  335.  *  WARNING:
  336.  *  API's that appear in comments or in conditional sections of code will
  337.  *  still be considered when searching.  In addition, if any function or
  338.  *  variable has been named with part of an OS/2 API's name, it will be
  339.  *  considered a match.  For instance, if there is a function named
  340.  *  xDosExecPgm then INCL_DOSPROCESS will be included.    This could result
  341.  *  in more #defines than are strictly necessary.
  342.  *
  343.  *
  344.  *  Parameters:
  345.  *  Name        Type        Description
  346.  *  --------------- --------------- --------------------------------------
  347.  *  argData        unsigned int    Value of the keystroke pressed
  348.  *  pArg        ARG far *        Argument type specific data
  349.  *  fMeta        flagType        TRUE if META was pressed
  350.  *
  351.  *  Returns:    flagType
  352.  *  Description
  353.  *  ----------------------------------------------------------------------
  354.  *  TRUE for a successful operation or FALSE if an error occurred.
  355.  *
  356.  */
  357.  
  358. flagType pascal EXTERNAL InsertAPIIncl(argData, pArg, fMeta)
  359. unsigned int argData;
  360. ARG far * pArg;
  361. flagType fMeta;
  362. {
  363.                 /*check for existence of list file    */
  364.     if (DosQFileMode(ListFileName, &FileAttr, 0L)) {
  365.  
  366.     strcpy(chBuf, "INSERTAPIINCL: The list file \"");
  367.     strcat(chBuf, ListFileName);
  368.     strcat(chBuf, "\" was not found!");
  369.     DoMessage(chBuf);
  370.     DosBeep(1200L, 100L);
  371.  
  372.     return (FALSE);     /*return failure            */
  373.     }
  374.                 /*make file buffer for list file    */
  375.     pListFile = AddFile(ListFileName);
  376.                 /*read list file into the M buffer    */
  377.     FileRead(ListFileName, pListFile);
  378.                 /*get length of list file        */
  379.     qLines = FileLength(pListFile);
  380.  
  381.     yCur = (LINE) 0;        /*save position at top of file        */
  382.  
  383.                 /*loop through the list file        */
  384.     for (l = 0; l < qLines; l++) {
  385.  
  386.                 /*get the next line            */
  387.     GetLine(l, chBuf, pListFile);
  388.  
  389.     if (*chBuf == ';')    /*skip if a comment line        */
  390.         continue;
  391.  
  392.     if (*chBuf == '#') {    /*is it an INCL?            */
  393.  
  394.                 /*save it without the '#',        */
  395.         strcpy(InclStr, &chBuf[1]);
  396.         DoMessage(InclStr); /*display it,
  397.         continue;        /*and go on                */
  398.     }
  399.  
  400.                 /*it is an API.  Go to top of file and    */
  401.                 /*search for it             */
  402.     strcpy(CmdBuf, "mark arg \"");
  403.     strcat(CmdBuf, chBuf);
  404.     strcat(CmdBuf, "\" psearch");
  405.  
  406.     if (fExecute(CmdBuf)) { /*found!                */
  407.  
  408.                 /*go to saved file position        */
  409.         MoveCur((COL) 0, yCur);
  410.                 /*insert a #define for the INCL     */
  411.         strcpy(CmdBuf, "linsert \"#define ");
  412.         strcat(CmdBuf, InclStr);
  413.         strcat(CmdBuf, "\"");
  414.         fExecute(CmdBuf);
  415.  
  416.         yCur++;        /*increment saved file position because */
  417.                 /*we just added a line            */
  418.  
  419.                 /*skip the remaining API's for the INCL */
  420.         for (; l < qLines; l++) {
  421.  
  422.         GetLine(l, chBuf, pListFile);
  423.  
  424.                 /*found next INCL?            */
  425.         if (*chBuf == '#') {
  426.  
  427.             strcpy(InclStr, &chBuf[1]);
  428.             DoMessage(InclStr);
  429.             break;
  430.         }
  431.         }
  432.     }
  433.     }
  434.  
  435.     fExecute("mark");        /*go to the top of the file        */
  436.  
  437.     RemoveFile(pListFile);    /*remove temporary list file        */
  438.  
  439.     DosBeep(1200L, 30L);
  440.     DoMessage("INSERTAPIINCL: Complete.");
  441.  
  442.     return TRUE;        /*return success            */
  443. }
  444.  
  445. /*
  446.  *  Standard M extension structures and initialization function follows.
  447.  *
  448.  */
  449.  
  450. flagType pascal EXTERNAL SwApiList(str)
  451. char far *str;
  452. {
  453.     strcpy(ListFileName, str);    /*update the list file name and path    */
  454.     return TRUE;
  455. }
  456.  
  457. struct swiDesc    swiTable[] =
  458. {
  459.     {"apilist", SwApiList, SWI_SPECIAL},
  460.     {NULL, NULL, (int) NULL}
  461. };
  462.  
  463. struct cmdDesc    cmdTable[] =
  464. {
  465.     {"convertapi", ConvertAPI, 0, NOARG},
  466.     {"insertapiincl", InsertAPIIncl, 0, NOARG},
  467.     {NULL, NULL, (unsigned) NULL, (unsigned) NULL}
  468. };
  469.  
  470. flagType WhenLoaded ()
  471. {
  472.                 /*set convertapi key            */
  473.     SetKey("convertapi", "alt+2");
  474.                 /*set insertapiincl key         */
  475.     SetKey("insertapiincl", "alt+1");
  476.     DoMessage(LOADMESSAGE);    /*display loaded message        */
  477.  
  478.     return TRUE;
  479. }
  480.