
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

int slashdrivesub(char *ln)
/*
 * replaces \\c\ with c:\, returns change in string length
 * this version required for older cygwins
 */
{
   char *sp, *lp=ln, ctmp;
   int nrep=0;
   do
   {
      sp = strstr(lp, "\\\\");
      if (sp && strlen(sp) > 3)
      {
         if (sp[2] == 'a' || sp[2] == 'b' || sp[2] == 'c' || sp[2] == 'd' ||
             sp[2] == 'e' || sp[2] == 'f' || sp[2] == 'g' || sp[2] == 'h')
         {
            if (sp[3] == '\\')
            {
               ctmp = sp[2];
               sp[0] = sp[2];
               sp[1] = ':';
               sp[2] = '\\';
               for (lp=sp+3; *lp = lp[1]; lp++);
               lp = sp + 3;
               nrep++;
            }
            else lp = sp + 2;
         }
         else lp = sp + 2;
      }
      else lp = sp + 2;
   }
   while (sp);
   return(-nrep);
}

int cygdrivesub(char *ln)
/*
 * replaces \cygdrive\c\ with c:\, returns change in string length
 * this version works cygnus version 1.1.0
 */
{
   char *sp;
   int i=0;

   while(sp = strstr(ln, "\\cygdrive\\"))
   {
      i++;
      sp[0] = sp[10];
      sp[1] = ':';
      sp[2] = '\\';
      sp += 3;
      while (*sp = sp[9]) sp++;
   }
   return( slashdrivesub(ln) - (i*9) );
}

void slashsub(char *ln)
/*
 * changes forward slash of unix to backslash of windoze
 */
{
   int i;
   for (i=0; ln[i]; i++) if (ln[i] == '/') ln[i] = '\\';
}

void doto2dotobj(char *ln)
/*
 * changes all occurences of unix's .o extension to windoze-friendly obj
 */
{
   char ln2[4096];
   int i, j=0;
   for (i=0; ln[i]; i++)
   {
      ln2[j++] = ln[i];
      if (ln[i] == '.' && ln[i+1] == 'o' && isspace(ln[i+2]))
      {
         ln2[j] = 'o';
         ln2[j+1] = 'b';
         ln2[j+2] = 'j';
         ln2[j+3] = ln[i+2];
         j += 4;
         i += 2;
      }
   }
   ln2[j] = '\0';
   sprintf(ln, "%s", ln2);
}

#ifdef DEBUG

#define system SYSTEM
int system(char *ln)
{
   fprintf(stdout, "%s\n", ln);
   return(0);
}

#endif

typedef struct wOrDs WORDS;
struct wOrDs
{
   char *word;
   WORDS *next;
};

void KillWords(WORDS *wp)
{
   WORDS *wpn;

   while (wp)
   {
      free(wp->word);
      wpn = wp->next;
      free(wp);
      wp = wpn;
   }
}

WORDS *AddWord(WORDS *wbas, char *wrd, int wlen)
{
   WORDS *wp;
   int i;

   wp = malloc(sizeof(WORDS));
   assert(wp);
   wp->word = malloc( (wlen+1) * sizeof(char) );
   for (i=0; i != wlen; i++) wp->word[i] = wrd[i];
   wp->word[i] = '\0';
   wp->next = wbas;
   return(wp);
}

WORDS *AddFile(WORDS *wbase, char *fnam)
{
   int i, len;
   len = strlen(fnam);
   assert(len > 2);
   if (fnam[len-1] = 'f' && fnam[len-2] == '.');
   {
      for (i=len-3; i > 0; i--)
      {
         if (fnam[i] == ' ' || fnam[i] == '/' || fnam[i] == '\\')
         {
            i++;
            break;
         }
      }
      wbase = AddWord(wbase, fnam+i, len-i-2);
   }
   return(wbase);
}

int RenameFiles(WORDS *wbase)
{
   WORDS *wp;
   char ln[4096];

   for (wp=wbase; wp; wp = wp->next)
   {
      sprintf(ln, "MOVE %s.obj %s.o\n", wp->word, wp->word);
      fprintf(stdout, "%s", ln);
      if (system(ln)) return(1);
   }
   return(0);
}

main(int nargs, char **args)
{
   char ln[4096], *cptr=NULL;
   int i, j, k, ierr, ic;
   int COMP=0, RENAME=0;
   WORDS *wbase=NULL;

   ic = sprintf(ln, "\"%s\" ", DEFDF);
   slashsub(ln);
   ic += sprintf(ln+ic, "/iface:cref ");

   for (i=1; i < nargs; i++)
   {
      if (args[i][0] == '-')  /* compiler flag */
      {
         if (args[i][1] == 'o') /* handle renaming, guess exe not .obj */
         {
            RENAME = 1;
            k = strlen(args[++i]);
            j = sprintf(ln+ic, "/Fe%s.exe ", args[i]);
            cptr = ln+ic;
            slashsub(ln+ic+3);
         }
         else if (args[i][1] == 'l') /* library to link against */
         {
            j = sprintf(ln+ic, "/link:DEFAULTLIB:%s", &args[i][2]);
            slashsub(ln+ic+17);
         }
         else
         {
            if (args[i][1] == 'c') COMP=1;
            j = sprintf(ln+ic, "/%s ", &args[i][1]);
            slashsub(ln+ic+1);
         }
      }
      else  /* must be files, not flags */
      {
         j = sprintf(ln+ic, "%s ", args[i]);
         if (j > 3 && ln[ic+j-2] == 'f' && ln[ic+j-3] == '.')
         { /* add this file to list of files to be moved to .o */
            wbase = AddFile(wbase, args[i]);
         }
         slashsub(ln+ic);
      }
      ic += j;
   }
   sprintf(ln+ic, "\n");
   cygdrivesub(ln);
   if (RENAME && COMP) /* gotta use different rename command if not exe */
   {
      cptr = strstr(ln, "/Fe");
      assert(cptr);
      cptr[2] = 'o';
      cptr = strstr(cptr, ".exe");
      assert(cptr);
      cptr[0] = cptr[1] = cptr[2] = cptr[3] = ' ';
   }
   fprintf(stdout, "%s", ln);
   ierr = system(ln);
   if (!ierr && COMP && !RENAME) /* rename the .obj to .o */
      ierr = RenameFiles(wbase);
   KillWords(wbase);
   exit(ierr);
}
