/***************************************************************************
 *                                                                         *
 *   GALPORT.C                                                             *
 *                                                                         *
 *   Copyright (c) 1996-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This is the developer's utility to help developers port their         *
 *   add-on source code from Worldgroup v2.x to Worldgroup v3.x.           *
 *                                                                         *
 *   Note: will not properly line up comments in files using real TABs.    *
 *                                                                         *
 *                                                 - C. Robert 4/27/96     *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"

#define FILREV "$Revision: 3 $"

#define CTMPNAM     "GALPORT.OUT"  /* temporary filename for output        */

struct tagChange {                 /* structure for each source change     */
     CHAR *from;                   /*   from this (must begin w/ isalnum())*/
     CHAR *to;                     /*   to this                            */
} changes[]={                      /* array of source changes to make      */
     {"signed",               "INT"},
     {"int",                  "INT"},
     {"unsigned short int",   "USHORT"},
     {"unsigned int",         "UINT"},
     {"signed int",           "INT"},
     {"unsigned",             "UINT"},
     {"short int",            "SHORT"},
     {"short",                "SHORT"},
     {"unsigned short",       "USHORT"},
     {"signed short",         "SHORT"},
     {"long int",             "LONG"},
     {"long",                 "LONG"},
     {"unsigned long int",    "ULONG"},
     {"unsigned long",        "ULONG"},
     {"signed long",          "LONG"},
     {"char",                 "CHAR"},
     {"unsigned char",        "CHAR"},
     {"signed char",          "SCHAR"},
     {"double",               "DOUBLE"},
     {"float",                "FLOAT"},
     {"BOOL",                 "GBOOL"},
     {"void",                 "VOID"},
     {"STATIC",               "static"},
     {"omdbtv",               "dfaMode"},
     {"setbtv",               "dfaSetBlk"},
     {"rstbtv",               "dfaRstBlk"},
     {"qrybtv",               "dfaQuery"},
     {"qnpbtv",               "dfaQueryNP"},
     {"getbtvl",              "dfaGetLock"},
     {"obtbtvl",              "dfaAcqLock"},
     {"anpbtvlk",             "dfaAcqNPLock"},
     {"llnbtv",               "dfaLastLen"},
     {"absbtv",               "dfaAbs"},
     {"gabbtvl",              "dfaGetAbsLock"},
     {"aabbtvl",              "dfaAcqAbsLock"},
     {"stpbtvl",              "dfaStepLock"},
     {"updbtv",               "dfaUpdate"},
     {"upvbtv",               "dfaUpdateV"},
     {"dupdbtv",              "dfaUpdateDup"},
     {"insbtv",               "dfaInsert"},
     {"invbtv",               "dfaInsertV"},
     {"dinsbtv",              "dfaInsertDup"},
     {"delbtv",               "dfaDelete"},
     {"clsbtv",               "dfaClose"},
     {"crtbtv",               "dfaCreate"},
     {"cntrbtv",              "dfaCountRec"},
     {"sttbtv",               "dfaStat"},
     {"rlenbtv",              "dfaRecLen"},
     {"unlbtv",               "dfaUnlock"},
     {"wslbtv",               "dfaWasLocked"},
     {"qeqbtv",               "dfaQueryEQ"},
     {"qnxbtv",               "dfaQueryNX"},
     {"qprbtv",               "dfaQueryPR"},
     {"qgtbtv",               "dfaQueryGT"},
     {"qgebtv",               "dfaQueryGE"},
     {"qltbtv",               "dfaQueryLT"},
     {"qlebtv",               "dfaQueryLE"},
     {"qlobtv",               "dfaQueryLO"},
     {"qhibtv",               "dfaQueryHI"},
     {"gcrbtv",               "dfaAbsRec"},
     {"geqbtv",               "dfaGetEQ"},
     {"gnxbtv",               "dfaGetNX"},
     {"gprbtv",               "dfaGetPR"},
     {"ggtbtv",               "dfaGetGT"},
     {"ggebtv",               "dfaGetGE"},
     {"gltbtv",               "dfaGetLT"},
     {"glebtv",               "dfaGetLE"},
     {"globtv",               "dfaGetLO"},
     {"ghibtv",               "dfaGetHI"},
     {"aqnbtv",               "dfaAcqNX"},
     {"aqpbtv",               "dfaAcqPR"},
     {"anibtv",               "dfaAcqNXi"},
     {"apibtv",               "dfaAcqPRi"},
     {"acqbtv",               "dfaAcqEQ"},
     {"agtbtv",               "dfaAcqGT"},
     {"agebtv",               "dfaAcqGE"},
     {"altbtv",               "dfaAcqLT"},
     {"alebtv",               "dfaAcqLE"},
     {"alobtv",               "dfaAcqLO"},
     {"ahibtv",               "dfaAcqHI"},
     {"slobtv",               "dfaStepLO"},
     {"snxbtv",               "dfaStepNX"},
     {"sprbtv",               "dfaStepPR"},
     {"shibtv",               "dfaStepHI"},
     {"ulsbtv",               "dfaUnlockOne"},
     {"ulmbtv",               "dfaUnlockCur"},
     {"ulobtv",               "dfaUnlockSel"},
     {"ulabtv",               "dfaUnlockAll"},
     {"gabbtv",               "dfaGetAbs"},
     {"BTVFILE",              "DFAFILE"},
     {"aabbtv",               "dfaAcqAbs"}
};

static VOID portFile(CHAR *filnam);
static CHAR *toWord(CHAR *stg);
static CHAR *passWord(CHAR *wrdptr);

INT
main(                              /* main program loop                    */
INT argc,                          /*   number of command-line args        */
CHAR *argv[])                      /*   command-line args                  */
{
     initvid();
     printf("GALPORT -- Porting tool for Worldgroup v2.x -> v3.x "
            "source code port.\n");
     printf("Copyright (c) 1996-1997 Galacticomm, Inc.  All rights reserved.\n\n");
     if (argc != 2 || sameas(argv[1],"?") || sameas(argv[1],"/?")) {
          printf("Format: GALPORT filename\n\n");
     }
     else {
          fnmcse(argv[1]);
          if (access(argv[1],0) != -1) {
               portFile(argv[1]);
          }
          else {
               printf("Can't find %s!\n\n",argv[1]);
          }
     }
     clsvid();
     return(0);
}

static VOID
portFile(                          /* port a file now                      */
CHAR *filnam)                      /*   name of file to port               */
{
     FILE *infp,*outfp;
     CHAR outfil[GCMAXPTH],linbuf[BUFSIZ],*wrdptr;
     INT i,thislen,lastidx,lastlen;
     CHAR *to;
     INT fromlen,tolen,diff;

     printf("Porting %s...",filnam);
     if ((infp=fopen(filnam,FOPRA)) == NULL) {
          catastro("CAN'T OPEN \"%s\" FOR READ!",filnam);
     }
     fileparts(GCPART_PATH,filnam,outfil,GCMAXPTH);
     stlcat(outfil,CTMPNAM,MAXPATH);
     if ((outfp=fopen(outfil,FOPWA)) == NULL) {
          fclose(infp);
          catastro("CAN'T OPEN \"%s\" FOR WRITE!",CTMPNAM);
     }
     while (fgets(linbuf,BUFSIZ,infp) != NULL) {
          diff=0;
          wrdptr=toWord(linbuf);
          while (*wrdptr != '\0') {
               lastidx=-1;
               lastlen=0;
               for (i=0 ; i < nelems(changes) ; i++) {
                    thislen=strlen(changes[i].from);
                    if (sameto(changes[i].from,wrdptr)
                      && !isalnum(*(wrdptr+thislen))) {
                         if (lastidx == -1 || thislen > lastlen) {
                              lastidx=i;
                              lastlen=thislen;
                         }
                    }
               }
               if (lastidx != -1) {
                    to=changes[lastidx].to;
                    fromlen=lastlen;
                    tolen=strlen(to);
                    diff+=fromlen-tolen;
                    if (tolen != fromlen) {
                         if (tolen > fromlen
                           && strlen(linbuf)+(tolen-fromlen) > BUFSIZ-1) {
                              catastro("Line needing porting too long!");
                         }
                         memmove(wrdptr+tolen,wrdptr+fromlen,
                                 strlen(wrdptr+fromlen)+1);
                    }
                    if (tolen > 0) {
                         memmove(wrdptr,to,tolen);
                         wrdptr+=tolen-1;    /* if multiword to, don't look*/
                    }                        /*  to change again, skip past*/
               }
               else if (sameto("/*",wrdptr) || sameto("//",wrdptr)) {
                    if (diff > 0) {          /* add spaces in front        */
                         if (strlen(linbuf)+diff > BUFSIZ-1) {
                              catastro("Line needing porting too long!");
                         }
                         memmove(wrdptr+diff,wrdptr,strlen(wrdptr)+1);
                         memset(wrdptr,' ',diff);
                    }
                    else if (diff < 0) {     /* remove spaces from front   */
                         while (wrdptr != linbuf && diff < 0) {
                              if (*--wrdptr != ' ') {
                                   break;
                              }
                              memmove(wrdptr,wrdptr+1,strlen(wrdptr+1)+1);
                              diff++;
                         }
                    }
                    break;    /* no more porting after comment on line     */
               }
               wrdptr=toWord(passWord(wrdptr));
          }
          fputs(linbuf,outfp);
     }
     fclose(infp);
     fclose(outfp);
     unlink(filnam);
     rename(outfil,filnam);
     printf(" done.\n\n");
}

static CHAR *                      /*   ptr to beginning or word (or \0)   */
toWord(                            /* jump to beginning of next word       */
CHAR *stg)                         /*   string with word in it             */
{
     stg=skpwht(stg);
     while (*stg != '\0' && !isalnum(*stg)) {
          if (sameto("/*",stg) || sameto("//",stg)) {
               break;         /* don't skip past beginning of comments     */
          }
          stg++;
     }
     return(stg);
}

static CHAR *                      /*   ptr to char after word (or \0)     */
passWord(                          /* jump just past the end of this word  */
CHAR *wrdptr)                      /*   pointer to word to pass            */
{
     if (sameto("/*",wrdptr) || sameto("//",wrdptr)) {
          wrdptr+=2;          /* skip past beginning of comment if need be */
     }
     while (*wrdptr != '\0' && isalnum(*wrdptr)) {
          wrdptr++;
     }
     return(wrdptr);
}
