source: golgotha/src/make/i4_make.cc

Last change on this file was 80, checked in by Sam Hocevar, 14 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 46.3 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include <stdio.h>
10#include "i4_make.hh"
11#include <ctype.h>
12#include "string.cc"
13#include "error.cc"
14#include "deps.cc"
15
16#include <sys/types.h>
17#include <sys/stat.h>
18#ifdef __linux
19#include <sys/wait.h>
20#include <unistd.h>
21#define MKDIR(x) mkdir(x, 0xffff)
22#endif
23
24#ifdef _WINDOWS
25#include <direct.h>
26#include <process.h>
27#include <winsock.h>
28#define MKDIR(x) _mkdir(x)
29#endif
30
31#include "array_tree.hh"
32
33
34char *link_file="c:\\tmp\\link.lk";
35
36mk_options_struct mk_options;
37
38enum {MAX_LEN=1000};
39
40char abs_path[MAX_LEN];
41int current_build_type=0;
42
43list failed_targets;
44list files_to_clean;
45list files_to_backup;
46
47#ifdef _WINDOWS
48int my_system (const char *command, int force=0)
49{
50  char *argv[4];
51
52  if (current_build_type==BUILD_DEBUG ||
53      current_build_type==BUILD_OPT ||
54      current_build_type==BUILD_PROF ||
55      force)
56  {   
57    if (command == 0)
58      return 1;
59    argv[0] = "command";
60    argv[1] = "/c";
61    argv[2] = (char *) command;
62    argv[3] = 0;
63
64
65    OSVERSIONINFO os;
66    os.dwOSVersionInfoSize=sizeof(os);
67    GetVersionEx(&os);
68   
69    if (os.dwPlatformId==VER_PLATFORM_WIN32_NT)
70      return system(command);
71    else
72      return _spawnv(_P_WAIT, "c:\\windows\\command.com", argv);
73
74  }
75  return 0;
76}
77
78#else
79
80
81int my_system (const char *command, int force=0)
82{
83  if (current_build_type==BUILD_DEBUG ||
84      current_build_type==BUILD_OPT ||
85      current_build_type==BUILD_PROF ||
86      force)
87  {   
88    // warning- this breaks if you have a child process running already
89
90    int pid, status;
91
92    if (command == 0)
93      return 1;
94    pid = fork();
95    if (pid == -1)
96      return -1;
97    if (pid == 0)
98    {
99      char *argv[4];
100      argv[0] = "sh";
101      argv[1] = "-c";
102      argv[2] = (char*) command;
103      argv[3] = 0;
104      execv("/bin/sh", argv);
105      exit(127);
106    }
107    do
108    {
109      wait(&status);
110      return status;
111    } while(1);
112  }
113  return 0;
114}
115
116#endif
117
118
119void extract(char *fn)
120{
121  FILE *in=fopen(fn,"rb");
122  while (1)
123  {
124    unsigned char l,s1,s2,s3,s4;
125    if (fread(&l,1,1,in)!=1)
126    {
127      fclose(in);
128      exit(0);
129    }
130
131    char fn[256],buf[4096];
132    fread(fn, 1,l,in);
133    FILE *out=fopen(fn,"wb");
134    if (!out)
135    {
136      for (int i=0; i<l; i++)
137        if (fn[i]=='\\' || fn[i]=='/')
138        {
139          int old=fn[i];
140          fn[i]=0;
141          MKDIR(fn);
142          fn[i]=old;
143        }
144
145      out=fopen(fn,"wb");
146    }
147
148    if (out)
149    {
150      fread(&s1,1,1,in);     fread(&s2,1,1,in);     fread(&s3,1,1,in);     fread(&s4,1,1,in);
151      int size=(s1<<24)|(s2<<16)|(s3<<8)|(s4);
152   
153      while (size)
154      {
155        int rsize=size>sizeof(buf) ? sizeof(buf) :size;
156        fread(buf, 1,rsize,in);
157        fwrite(buf, 1, rsize, out);
158        size-=rsize;
159      }
160      fclose(out);   
161    }
162    else printf("extract: could not open %s for writing\n", fn);
163  }
164}
165
166void mk_options_struct::get(int argc, char **argv)
167{
168  int i;
169  quiet=1;
170
171  for (i=1; i<argc; i++)
172  {
173    if (strcmp(argv[i],"/k")==0 || strcmp(argv[i],"-k")==0)
174      continue_on_error=1;
175    else if (strcmp(argv[i],"/f")==0 || strcmp(argv[i],"-f")==0)
176    {
177      i++;
178      project_file=argv[i];
179    }
180    else if (strcmp(argv[i],"debug")==0)
181      build_flags|=BUILD_DEBUG;
182    else if (strcmp(argv[i],"profile")==0)
183      build_flags|=BUILD_PROF;
184    else if (strcmp(argv[i],"clean")==0)
185      build_flags|=BUILD_CLEAN;
186    else if (strcmp(argv[i],"backup")==0)
187    {
188      build_flags|=BUILD_BACKUP;
189    }
190    else if (strcmp(argv[i],"opt")==0 || strcmp(argv[i],"optimized")==0)
191      build_flags|=BUILD_OPT;
192    else if (strcmp(argv[i],"-d")==0)
193      mk_debug_on=1;
194    else if (strcmp(argv[i],"-show_deps")==0)
195      show_deps=1;
196    else if (strcmp(argv[i],"-v")==0)
197    {
198      verbose=1;
199      quiet=0;
200    }
201    else if (strcmp(argv[i],"-v1")==0)
202    {
203      verbose=0;
204      quiet=0;
205    }
206    else if (strcmp(argv[i],"-extract")==0)
207      extract(argv[i+1]);
208    else if (strcmp(argv[i],"-q")==0)
209      quiet=1;
210    else if (strcmp(argv[i],"-nl")==0 || strcmp(argv[i],"-no_libs")==0)
211      no_libs=1;
212    else if (strcmp(argv[i],"-sim_win32")==0)
213      os=OS_WIN32;
214    else if (strcmp(argv[i],"-static")==0)
215      unix_libs_are_shared=0;
216    else if (strcmp(argv[i],"-shared")==0)
217      unix_libs_are_shared=1;
218    else if (strcmp(argv[i],"-no_tmp")==0)
219      no_tmp=1;
220    else if (strcmp(argv[i],"-no_syms")==0)
221      no_syms=1;
222    else if (strcmp(argv[i],"-show_incs")==0)
223      show_includes=1;
224    else if (strcmp(argv[i],"-tmp")==0)
225    {
226      i++;
227      tmp_dir=argv[i];
228    }
229    else if ((strcmp(argv[i],"-no_compile")==0) || (strcmp(argv[i],"-nc")==0))
230      no_compile=1;   
231    else if (strcmp(argv[i],"--help")==0 ||
232             strcmp(argv[i],"-help")==0 ||
233             strcmp(argv[i],"?")==0 ||
234             strcmp(argv[i],"-?")==0)
235    {
236      printf("%s ussage :\n"
237              "%s [-f filename] [-k,q,nl,v,v1,no_libs] [debug] [opt] [clean] [backup] [targets..]\n"
238              "  -f overides default project.i4 for building\n"
239              "  -k continues on error\n"
240              "  debug build debug version of everything\n"
241              "  opt builds optimized version of everything\n"
242              "  backup backs up all the files referenced by project.i4 including\n"
243              "    headers, ram files, and .cc files (saves to backup.i4)\n"
244              "  if targets are not listed all targets list in project file are built\n"
245              "  -q quiet, shows only the file being processed, and not the actual command\n"
246              "  -v verbose show all commands executed\n"
247              "  -v1 shows verbose paths (normally simplified when show compiling\n"
248              "  -d show debug info relating to i4_make\n"
249              "  -nl causes the compilation not to use library files (where possible)\n"
250              "  -show_deps shows depdancies that are out of date\n"
251              "  -no_compile/-nc runs through the make process without compiling/linking\n"
252              "  -static  don't make libraries shared (unix only)\n"
253              "  -no_syms don't include any symbol information in the object files or exes\n"
254              "  -extract filename   extracts a backup into files (use i4_make backup)\n",
255              argv[0]);
256      exit(0);
257    }
258
259    else
260      targets_to_build+=argv[i];
261  }
262 
263  if (build_flags==0)
264    build_flags=BUILD_DEBUG | BUILD_OPT;
265
266  if (os==OS_WIN32) slash_char='\\';
267  else slash_char='/';
268}
269
270
271enum { BUF_SIZE=1024*1000 };
272char *buf=0;
273int boff=0;
274
275char *buf_alloc(char *p, int len)
276{
277  if (!buf || boff+len>BUF_SIZE)
278  {
279    buf=(char *)malloc(BUF_SIZE);
280    boff=0;
281  }
282
283  memcpy(buf+boff,p,len);
284  boff+=len;
285  return buf+boff-len;
286}
287
288
289char *get_abs_path(char *filename, int force=0);
290
291
292void add_to_backup(char *fname)
293{
294  char *full_name=get_abs_path(fname,1);   // force a full name
295
296  if (files_to_backup.find(full_name)==-1)
297    files_to_backup.add(full_name);
298}
299
300
301void pcwd()
302{
303  char buf[100];
304  getcwd(buf, 100);
305  printf("cwd = %s\n",buf);
306}
307
308char start_path[256];
309
310void set_abs_path(char *filename)
311{
312  char tmp[MAX_LEN];
313  strcpy(tmp, filename);
314
315  char *last_slash=0, *p=tmp, *q;
316  for (; *p; p++)
317    if (*p=='/' || *p=='\\')
318      last_slash=p;
319
320  if (last_slash)
321  { 
322    last_slash[1]=0;
323    strcpy(abs_path, get_abs_path(tmp));
324
325    if (mk_options.no_tmp)
326    {
327      chdir(start_path);
328      chdir(abs_path);
329    }
330  }
331
332}
333
334char *get_abs_path(char *filename, int force)
335{
336  if (mk_options.no_tmp && !force)
337    return filename;
338  else
339  {
340     
341    char tmp[MAX_LEN];
342    strcpy(tmp, abs_path);
343    char *s, *d;
344
345    if ((filename[0]=='/' || filename[0]=='\\') || (filename[1]==':'))
346      return filename;
347
348    for (s=filename, d=tmp + strlen(tmp); *s; )
349    {
350      if (s[0]=='.' && s[1]=='.' && (s[2]=='/' || s[2]=='\\'))
351      {
352        d-=2;
353        while (*d!='/' && *d!='\\')
354        {
355          d--;
356          if (d<tmp) mk_error("bad file path %s\n",filename);
357        }
358        d++;
359        s+=3;
360      }
361      else
362      {
363        while (*s && *s!='/' && *s!='\\')
364        {
365          *d=*s;
366          s++;
367          d++;
368        }
369
370        if (*s)
371        {
372          *d=*s;
373          d++;
374          s++;
375        }
376      }
377    }
378    *d=0;
379
380    for (d=tmp; *d; d++)
381      if (mk_options.os==OS_LINUX && *d=='\\')
382        *d='/';
383      else if (mk_options.os==OS_WIN32 && *d=='/')
384        *d='\\';
385 
386
387    return buf_alloc(tmp, strlen(tmp)+1);
388  }
389}
390
391enum { EXT_O,
392       EXT_LIB,
393       EXT_DLL,
394       EXT_PLUGIN,
395       EXT_EXE,
396       EXT_DEP,
397       EXT_PCH,
398       EXT_PDB,
399       EXT_RAM_FILE,
400       EXT_RC_RES
401};
402
403
404void show_command(char *cmd, int force=0)
405{
406  if (current_build_type==BUILD_DEBUG ||
407      current_build_type==BUILD_OPT ||
408      current_build_type==BUILD_PROF ||
409      force)
410  {
411    if (mk_options.verbose)
412      printf("%s",cmd);
413    else
414    {
415      for (;*cmd;)
416      {
417        if ((*cmd=='/' || *cmd=='\\') || (cmd[0]=='_' && cmd[1]=='_'))
418        {
419          char *start=cmd, *c, *d;
420          for (c=cmd; *c && *c!=' '; c++)
421            if (*c=='/' || *c=='\\')
422              start=c+1;
423            else if (c[0]=='_' && c[1]=='_')
424              start=c+2;
425     
426          for (d=start; d!=c; d++)
427            printf("%c",*d);
428
429          cmd=c;
430        }
431        else
432        {
433          printf("%c", *cmd);
434          cmd++;
435        }   
436      }
437    }
438    printf("\n");
439  }
440}
441
442char *make_out_name(char *filename, int ext_type=-1, int use_full_path=1, char *outdir=0)
443{
444  char tmp[MAX_LEN], *s, *d;
445
446  if (ext_type==-1)
447  {
448    int l=strlen(filename);
449    if (l>4)
450    {
451      if (filename[l-3]=='.' && filename[l-2]=='r' && filename[l-1]=='c')
452        ext_type=EXT_RC_RES;
453      else if (filename[l-3]=='.' && filename[l-2]=='c' && filename[l-1]=='c')
454        ext_type=EXT_O;
455      else
456      {
457        printf("make_out_name : don't know what extension to use for %s",filename);
458        exit(0);
459      }
460
461
462    } else       
463    {
464      printf("make_out_name : filename to short : %s",filename);
465      exit(0);
466
467    }
468  }
469
470  if (mk_options.no_tmp)
471  {
472    d=tmp;
473    char *start=filename;
474    for (s=filename; *s && *s!='.'; s++);
475    if (*s)
476    {
477      memcpy(d,filename, s-filename);
478      d+=s-filename;
479    }
480    else
481    {
482      strcpy(d,filename);
483      d+=strlen(d);
484    }
485    *d=0;
486  }
487  else
488  {
489    if (outdir)
490    {
491      strcpy(tmp,outdir);
492      use_full_path=0;
493    }
494    else
495    {
496      if (mk_options.tmp_dir)
497        sprintf(tmp,"%s%c", mk_options.tmp_dir, mk_options.slash_char);
498      else
499      {
500        char *t=getenv("I4_TMP");
501        if (t)
502          sprintf(tmp,"%s%c", t, mk_options.slash_char);     
503        else
504        {
505          if (mk_options.os==OS_LINUX)   
506            strcpy(tmp,"/tmp/");
507          else
508            strcpy(tmp,"c:\\tmp\\");
509        }
510      }
511   
512    }
513    d=tmp+strlen(tmp);
514
515
516    if (!use_full_path)
517    {
518      char *start=filename;
519      for (s=filename; *s; s++)
520        if (*s=='\\' || *s=='/' || *s==':')
521          start=s+1;
522
523      strcpy(d,start);
524      d+=strlen(d);
525    }
526    else
527    {
528      for (s=filename; *s; s++)
529      {
530        if (*s=='\\' || *s=='/' || *s==':')
531        {
532          d[0]=d[1]='_';
533          d++;
534        }
535        else if (*s=='.')
536        {
537          d[0]='-';
538        } else *d=*s;
539        d++;   
540      }
541    }
542  }
543 
544  if (current_build_type==BUILD_DEBUG)
545    strcpy(d,"_debug");
546  else if (current_build_type==BUILD_OPT)
547    strcpy(d,"_opt");
548  else if (current_build_type==BUILD_PROF)
549    strcpy(d,"_prof");
550  else if (current_build_type==BUILD_CLEAN)
551    strcpy(d,"_*");
552  d+=strlen(d);
553
554  if (mk_options.os==OS_LINUX)
555  {
556    switch (ext_type)
557    {
558      case EXT_O :  strcpy(d,".o"); break;
559      case EXT_LIB : 
560      {
561        if (mk_options.unix_libs_are_shared)
562          strcpy(d,".so");
563        else
564          strcpy(d,".a");
565      } break;
566
567      case EXT_DEP :  strcpy(d,".dep"); break;
568      case EXT_PLUGIN:
569      case EXT_DLL :  strcpy(d,".dll"); break;
570      case EXT_RAM_FILE : strcpy(d,".cc"); break;
571    }
572  }
573  else
574  {
575    switch (ext_type)
576    {
577      case EXT_O :  strcpy(d,".obj"); break;
578      case EXT_LIB :  strcpy(d,".lib"); break;
579      case EXT_EXE :  strcpy(d,".exe"); break;
580      case EXT_DEP :  strcpy(d,".dep"); break;
581      case EXT_PDB :  strcpy(d,".pdb"); break;
582      case EXT_PCH :  strcpy(d,".pch"); break;
583      case EXT_PLUGIN:
584      case EXT_DLL :  strcpy(d,".dll"); break;
585      case EXT_RAM_FILE : strcpy(d,".cc"); break;
586      case EXT_RC_RES :  strcpy(d,".res"); break;
587    }
588
589  }
590
591 
592  char *ret=buf_alloc(tmp, strlen(tmp)+1);
593
594  if (current_build_type==BUILD_CLEAN)
595  {
596    char *full_name=get_abs_path(ret,1);   // force a full name
597    if (files_to_clean.find(full_name)==-1)
598      files_to_clean.add(full_name);
599  }
600
601  return ret;
602}
603
604
605
606unsigned long check_sum32(void *buf, int buf_len)
607{
608  unsigned char c1=0,c2=0,c3=0,c4=0;
609  while (buf_len)
610  {
611    c1+=*((unsigned char *)buf);
612    c2+=c1;
613    buf=(void *)(((unsigned char *)buf)+1);
614    c3+=c2;
615    c4+=c3;
616    buf_len--;
617  }
618  return (c1|(c2<<8)|(c3<<16)|(c4<<24));
619}
620
621
622class mk_file_mod_node
623{
624public:
625  int left, right;
626  unsigned long checksum;
627  unsigned long mod_time;
628 
629  int operator>(const mk_file_mod_node &b) const { return  (checksum > b.checksum); }
630  int operator<(const mk_file_mod_node &b) const { return  (checksum < b.checksum); }
631  mk_file_mod_node(unsigned long checksum) : checksum(checksum) {}
632  mk_file_mod_node() {}
633};
634
635
636i4_array_tree<mk_file_mod_node, 5000> mod_tree;
637
638
639void set_mod_time(char *filename, int time_to_set)
640{
641  mk_file_mod_node n(check_sum32(filename,strlen(filename)));
642  int i=mod_tree.find(n);
643  if (i!=-1)
644  {
645    mod_tree.get(i).mod_time=time_to_set;
646    return ;
647  }
648
649  n.mod_time=time_to_set;
650  mod_tree.add(n);
651 
652}
653
654int get_mod_time(char *filename, int force_stat=0)
655{
656  mk_file_mod_node n(check_sum32(filename,strlen(filename)));
657  int i=mod_tree.find(n);
658  if (i!=-1 && !force_stat)
659    return mod_tree.get(i).mod_time;
660
661  unsigned long t;
662#ifdef _WINDOWS
663  struct _stat s;
664  if (_stat(filename, &s)==0)
665   t=s.st_mtime;
666  else
667    return 0;
668#elif __linux
669   struct stat s;
670  if (stat(filename, &s)==0)
671    t=s.st_mtime;
672  else
673    return 0;
674#else
675#error define os here
676#endif
677
678  if (i!=-1)
679    mod_tree.get(i).mod_time=t;
680
681  n.mod_time=t;
682  mod_tree.add(n);
683  return t;
684}
685
686
687enum { ALREADY_UP_TO_DATE,
688       CHANGED,
689       BUILD_ERROR,
690       NO_MORE_TARGETS
691};
692
693void clean_file(char *outname)
694{
695  char cmd[200];
696  if (outname[strlen(outname)-1]!='*')
697  {
698#ifdef _WINDOWS
699    sprintf(cmd,"del %s", outname);
700#else
701    sprintf(cmd,"rm %s", outname);
702#endif
703
704
705    show_command(cmd,1);
706
707    my_system(cmd, 1);
708  }
709}
710
711int build_file(char *filename,
712               mk_target_struct &target,
713               mk_target_struct &top_target)
714               
715{
716  char *p=filename, *last_dot=0, cmd[MAX_LEN], inc[MAX_LEN], def[MAX_LEN];
717  inc[0]=0;
718  def[0]=0;
719  int i;
720
721  for (p=filename; *p; p++)
722    if (*p=='.' && p[1]!='.')
723      last_dot=p;
724
725  if (last_dot)
726  {
727    if (strcmp(last_dot,".cc")==0)
728    {
729      char *source_name=get_abs_path(filename);
730
731      char *outname=make_out_name(source_name,EXT_O);
732      if (failed_targets.find(outname)!=-1)
733        return BUILD_ERROR;
734
735      switch (current_build_type)
736      {
737        case BUILD_BACKUP:
738        {
739          add_to_backup(source_name);
740          list *dep=get_deps(source_name, &target.inc);
741          if (dep)
742          {
743            for (i=0; i<dep->size(); i++)
744              add_to_backup((*dep)[i]);
745          }
746        } break;
747
748
749        case BUILD_OPT :
750        case BUILD_DEBUG :
751        case BUILD_PROF :
752          int rebuild=0;
753
754          int m1=get_mod_time(outname);
755          if (m1)
756          {
757            list *dep=get_deps(source_name, &target.inc);
758            if (mk_options.show_includes && dep)
759            {
760              printf( "%s\n",filename);
761              for (i=0; i<dep->size(); i++)
762                printf( "    %s\n",(*dep)[i]);
763            }
764           
765            if (dep)
766            {
767              for (i=0; !rebuild && i<dep->size(); i++)
768              {
769                int src_mod_time=get_mod_time( (*dep)[i]);
770                if (src_mod_time>m1)
771                {
772                  if (mk_options.show_deps)
773                    printf( "%s newer than %s\n", (*dep)[i], outname);
774                  rebuild=1;
775                }
776              }
777            }
778          } else rebuild=1;
779             
780          if (rebuild)
781          {
782            if (mk_options.os==OS_LINUX)
783            {
784              for (i=0; i<target.inc.size(); i++)
785                sprintf(inc+strlen(inc), "-I%s ",target.inc[i]);
786
787              for (i=0; i<target.defines.size(); i++)
788                sprintf(def+strlen(def), "-D%s ", target.defines[i]);
789
790              for (i=0; i<mk_global_defines.size(); i++)
791                sprintf(def+strlen(def), "-D%s ", mk_global_defines[i]);
792
793              char *sym_string = mk_options.no_syms ? "" : "-g ";
794             
795              sprintf(cmd, "g++ %s%s%s%s-c %s -o %s",
796                      sym_string,
797                      current_build_type==BUILD_DEBUG ? "-DDEBUG " :
798                      current_build_type==BUILD_OPT ? "-O2 " :
799                      "-O2 -pg ", // profile version
800                      def, inc, source_name, outname);
801            }
802            else
803            {
804              for (i=0; i<target.inc.size(); i++)
805                sprintf(inc+strlen(inc), "/I %s ",target.inc[i]);
806             
807              for (i=0; i<target.defines.size(); i++)
808                sprintf(def+strlen(def), "/D%s ",target.defines[i]);
809
810              for (i=0; i<mk_global_defines.size(); i++)
811                sprintf(def+strlen(def), "/D%s ",mk_global_defines[i]);
812
813              char *dll_def=(strcmp(target.target_type,"dll")==0 ||
814                             strcmp(target.target_type,"plugin")==0) ? "/DBUILDING_DLL " : "";
815             
816              sprintf(cmd, "cl /GX /EHa /D_WINDOWS %s%s%s%s/c /Tp %s /Fo%s /Fd%s",
817                      dll_def,
818                      current_build_type==BUILD_DEBUG ? "/MD /Zi /Od /DDEBUG /nologo " :
819                      current_build_type==BUILD_OPT ? "/MD /Zi /Ox /nologo " :
820                      "/MD /Zi /Ox /nologo /Gh " // profile version
821                      ,
822                      def, inc, source_name, outname,
823                      //                      make_out_name(get_abs_path(target.target), EXT_PCH),
824                      make_out_name(get_abs_path(target.target), EXT_PDB));
825
826
827            }
828
829            if (mk_options.quiet && current_build_type!=BUILD_CLEAN)
830              printf("Compiling %s (%s)\n", filename,
831                     current_build_type==BUILD_DEBUG ? "debug" :
832                     current_build_type==BUILD_OPT ? "opt" :
833                     "profile");
834            else
835              show_command(cmd);
836
837            if (mk_options.no_compile)
838            {
839              set_mod_time(outname, 0x7fffffff);
840              return CHANGED;
841            }
842            else
843            {
844              if (my_system(cmd)==0)
845              {
846                get_mod_time(outname,1);  // get time of output file
847                return CHANGED;
848              }
849              else
850              {
851                failed_targets.add(outname);
852                return BUILD_ERROR;
853              }
854            }
855
856          } else return ALREADY_UP_TO_DATE;
857          break;
858       
859      }
860
861      return ALREADY_UP_TO_DATE;
862    }
863    else if (strcmp(last_dot,".rc")==0)
864    {
865      add_to_backup(filename);
866      char *source_name=get_abs_path(filename);
867
868      char *outname=make_out_name(source_name,EXT_RC_RES);
869      if (failed_targets.find(outname)!=-1)
870        return BUILD_ERROR;
871
872     
873      if (get_mod_time(source_name)<get_mod_time(outname))
874        return ALREADY_UP_TO_DATE;
875
876      sprintf(cmd, "rc /fo%s ",outname);
877      for (i=0; i<target.inc.size(); i++)
878        sprintf(cmd+strlen(cmd), "/i %s ",target.inc[i]);
879      sprintf(cmd+strlen(cmd),"%s", source_name);
880
881      if (mk_options.quiet && current_build_type!=BUILD_CLEAN)
882        printf("Compiling %s (%s)", source_name,
883               current_build_type == BUILD_DEBUG ? "debug" :
884               current_build_type == BUILD_OPT ? "opt" :
885               "profile");
886      else
887        show_command(cmd);
888
889      if (mk_options.no_compile)
890      {
891        set_mod_time(outname, 0x7fffffff);
892        return CHANGED;
893      }
894      else
895      {
896        if (my_system(cmd)==0)
897        {
898          get_mod_time(outname, 1);
899          return CHANGED;
900        }
901        else
902        {
903          failed_targets.add(outname);
904          return BUILD_ERROR;
905        }
906      }
907    }
908    else
909      mk_error("don't know how to build files with extension '%s' : %s",last_dot, filename);
910  }
911  else
912    mk_error("don't know how to build files without extensions '%s'", filename);
913
914  return BUILD_ERROR;
915}
916
917int build_lib(int object_files_have_changed,
918              mk_target_struct &target,
919              mk_target_struct &top_target,
920              int dll=0)
921{
922  char tmp[50000];
923  int i;
924
925  if (target.src.size()==0)
926    return ALREADY_UP_TO_DATE;
927
928
929
930  char *lname=make_out_name(get_abs_path(target.target),
931                            dll ? EXT_DLL : EXT_LIB, 1, target.outdir);
932
933  if (failed_targets.find(lname)!=-1)
934    return BUILD_ERROR;
935
936  if (dll)
937  {
938    if (top_target.dlls.find(lname)==-1)
939      top_target.dlls.add(lname);
940  }
941  else if (!dll && top_target.libs.find(lname)==-1)
942    top_target.libs.add(lname);
943
944  int ltime=get_mod_time(lname);     
945  if (!ltime)
946    object_files_have_changed=1;
947
948
949  if (mk_options.os==OS_LINUX)
950  {
951    char *sym_string = mk_options.no_syms ? "" : "-g ";
952    char shared_string[100];
953   
954    if (mk_options.unix_libs_are_shared)
955      sprintf(shared_string,  "-shared -Wl,-soname,%s ", lname);
956    else
957      shared_string[0]=0;
958   
959    if (dll || mk_options.unix_libs_are_shared)
960      sprintf(tmp, "g++ %s%s -g -o %s ",
961              sym_string,
962              shared_string,
963              lname);
964    else
965      sprintf(tmp, "ar rucs %s ", lname);
966
967    char *d=tmp+strlen(tmp);
968    for (i=0; i<target.src.size(); i++)
969    {
970      char *oname=make_out_name(get_abs_path(target.src[i]));
971      sprintf(d, "%s ", oname);
972      if (!object_files_have_changed && get_mod_time(oname)>ltime)
973      {
974        if (mk_options.show_deps)
975          printf( "%s newer than %s\n",oname, lname);
976        object_files_have_changed=1;
977      }
978
979      d+=strlen(d);
980    }
981  }
982  else
983  {
984    if (dll)
985      sprintf(tmp,
986              "link /MACHINE:IX86 /DEBUG /debugtype:coff /debugtype:both /DLL "
987              "/nologo /PDB:%s /OUT:%s @%s%s",
988              make_out_name(get_abs_path(lname), EXT_PDB, 0),
989              lname, link_file,
990              mk_options.quiet ? "> c:\\tmp\\null" : "");
991    else
992      sprintf(tmp, "lib /nologo /OUT:%s @%s%s", lname, link_file,
993              mk_options.quiet ? "> c:\\tmp\\null" : "");
994    FILE *fp=fopen(link_file, "wb");
995   
996
997    for (i=0; i<target.src.size(); i++)
998    {
999      char *oname=make_out_name(get_abs_path(target.src[i]));
1000      fprintf(fp, "%s\n", oname);
1001
1002      if (!object_files_have_changed && get_mod_time(oname)>ltime)
1003      {
1004        if (mk_options.show_deps)
1005          printf( "%s newer than %s\n",oname, lname);
1006
1007        object_files_have_changed=1;
1008      }
1009
1010    }
1011
1012    if (dll)
1013    {
1014      for (i=0; i<target.libs.size(); i++)
1015      {
1016        char *oname=target.libs[i];
1017        fprintf(fp, "%s\n", oname);
1018
1019
1020        if (!object_files_have_changed && get_mod_time(oname)>ltime)
1021        {
1022          if (mk_options.show_deps)
1023            printf( "%s newer than %s\n",oname, lname);
1024
1025          object_files_have_changed=1;
1026        }
1027      }
1028
1029      if (target.def_file)
1030        sprintf(tmp+strlen(tmp), " /def:\"%s\"", target.def_file);
1031    }
1032
1033    fclose(fp);
1034  }
1035
1036
1037
1038  if (object_files_have_changed)
1039  {
1040    if (mk_options.quiet && (current_build_type!=BUILD_CLEAN && current_build_type!=BUILD_BACKUP))
1041      printf("Creating library %s\n", target.target);
1042    else
1043      show_command(tmp);
1044
1045    if (mk_options.no_compile)
1046    {
1047      set_mod_time(lname, 0x7fffffff);
1048      return CHANGED;
1049    }
1050    else
1051    {
1052      if (my_system(tmp)==0)
1053      {
1054        get_mod_time(lname, 1);  // get time of output file
1055
1056        // don't need to relink executable if using shared libraries
1057        if (mk_options.is_unix() && mk_options.unix_libs_are_shared)
1058          return ALREADY_UP_TO_DATE;
1059
1060        return CHANGED;
1061      }
1062      else
1063      {
1064        failed_targets.add(lname);       // don't try to build this again
1065        return BUILD_ERROR;
1066      }
1067    }
1068  }
1069  else
1070    return ALREADY_UP_TO_DATE;
1071}
1072
1073int build_exe(int deps_have_changed, mk_target_struct &target)
1074{
1075  char tmp[50000];
1076  int i;
1077
1078  char *ename=make_out_name(get_abs_path(target.target), EXT_EXE, 0, target.outdir);
1079  int etime=get_mod_time(ename);
1080  if (!etime)
1081    deps_have_changed=1;
1082 
1083  FILE *fp;
1084  if (mk_options.os==OS_LINUX)
1085  {
1086    char *sym_str=mk_options.no_syms ? "" : "-g ";
1087   
1088   
1089    sprintf(tmp, "g++ -rdynamic %s%s-o %s ",
1090            sym_str,
1091            current_build_type==BUILD_DEBUG ? "" :
1092            current_build_type==BUILD_OPT ? "-O2 " :
1093            "-O2 -pg ",
1094            ename);
1095  }
1096  else
1097  {
1098    sprintf(tmp, "link  /SUBSYSTEM:%s /MACHINE:IX86 /DEBUG "
1099            "/NOLOGO /PDB:%s /NODEFAULTLIB /OUT:%s @%s",       // /INCREMENTAL:NO
1100            target.app_type==WIN32_CONSOLE_APP ? "CONSOLE" : "WINDOWS",
1101            make_out_name(get_abs_path(target.target), EXT_PDB, 0),
1102            ename, link_file);
1103
1104    fp=fopen(link_file,"wb");
1105    if (!fp) mk_error("could not open %s for writing\n",link_file);
1106  }
1107
1108
1109  char *d=tmp+strlen(tmp);
1110   
1111  for (i=0; i<target.src.size(); i++)
1112  {
1113    char *oname=make_out_name(get_abs_path(target.src[i]));
1114    if (!deps_have_changed && get_mod_time(oname)>etime)
1115    {
1116      if (mk_options.show_deps)
1117        printf( "%s newer than %s\n",oname, ename);
1118      deps_have_changed=1;
1119    }
1120
1121    if (mk_options.os==OS_LINUX)
1122      sprintf(d, "%s ", oname);
1123    else
1124      fprintf(fp, "%s\n", oname);
1125
1126    d+=strlen(d);
1127  }
1128
1129
1130  for (i=target.libs.size()-1; i>=0; i--)
1131  {     
1132    if (mk_options.os==OS_LINUX)
1133      sprintf(d, "%s ", target.libs[i]);
1134    else
1135      fprintf(fp, "%s\n", target.libs[i]);
1136
1137    if (!deps_have_changed && get_mod_time(target.libs[i])>etime)
1138    {
1139      if (mk_options.show_deps)
1140        printf( "%s newer than %s\n", target.libs[i], ename);
1141      deps_have_changed=1;
1142    }
1143
1144    d+=strlen(d);
1145  }
1146
1147  if (mk_options.os==OS_WIN32)
1148    fclose(fp);
1149
1150  if (deps_have_changed)
1151  {
1152    if (current_build_type!=BUILD_CLEAN && current_build_type!=BUILD_BACKUP)
1153    {
1154      if (mk_options.quiet)
1155        printf("Linking %s\n", target.target);
1156      else
1157        printf("%s\n", tmp);
1158    }
1159
1160    if (mk_options.no_compile)
1161    {
1162      set_mod_time(ename, 0x7fffffff);
1163      return CHANGED;
1164    }
1165    else
1166    {
1167      if (my_system(tmp)==0)
1168      {
1169        get_mod_time(ename, 1);  // get time of output file
1170        return CHANGED;
1171      }
1172      else
1173        return BUILD_ERROR;
1174    }
1175  }
1176  else return ALREADY_UP_TO_DATE;
1177 
1178}
1179
1180int build_target(mk_target_struct &target,
1181                 mk_target_struct &top_target)
1182//                  list &exe_src,
1183//                  list &exe_inc,
1184//                  list &exe_def,
1185//                  list &lib_files,
1186//                  list &dll_libs)
1187{
1188  int i;
1189  int change=0;
1190
1191  if (mk_options.targets_built.find(target.target)==-1)
1192  {
1193    mk_options.targets_built.add(target.target);
1194
1195    if (strcmp(target.target_type,"list")==0)
1196    {
1197      for (i=0; i<target.src.size(); i++)       
1198      {
1199        char *fname=get_abs_path(target.src[i]);
1200        if (top_target.src.find(fname)==-1)
1201          top_target.src.add(fname);
1202      }
1203    }
1204         
1205//     if (strcmp(target.target_type,"executable")==0 || strcmp(target.target_type,"plugin")==0)
1206//     {
1207//       for (i=0; i<target.src.size(); i++)
1208//       {
1209//         char *fn=target.src[i];
1210//         if (fn[strlen(fn)-1]=='.')
1211//           printf("adding to src_file with no extension\n");
1212
1213//         target.src+=exe_src[i];
1214//       }
1215//     }
1216
1217    int ret=ALREADY_UP_TO_DATE;
1218
1219
1220    for (i=0; i<target.src.size(); i++)
1221    {
1222      mk_debug("checking depends for %s\n", target.src[i]);
1223
1224      int result=build_file(target.src[i], target, top_target);
1225      if (result==BUILD_ERROR && !mk_options.continue_on_error)
1226        return BUILD_ERROR;
1227
1228      if (result==CHANGED)
1229        change=1;
1230    }
1231         
1232    if (strcmp(target.target_type,"lib")==0)
1233    {
1234      if (mk_options.no_libs)     // they don't want to use libs, add files to top target
1235      {
1236        for (i=0; i<target.src.size(); i++)       
1237        {
1238          char *fname=get_abs_path(target.src[i]);
1239          if (top_target.libs.find(fname)==-1)
1240            top_target.libs.add(fname);
1241        }
1242      }
1243      else
1244      {
1245        switch (build_lib(change, target, top_target, 0))
1246        {
1247          case BUILD_ERROR : return BUILD_ERROR; break;
1248          case CHANGED : change=1; break;
1249        }
1250      }
1251    } 
1252
1253    if (strcmp(target.target_type,"executable")==0)
1254    {
1255      switch (build_exe(change, top_target))
1256      {
1257        case BUILD_ERROR : return BUILD_ERROR; break;
1258        case CHANGED : change=1; break;
1259      }
1260    } 
1261
1262
1263    if (strcmp(target.target_type,"dll")==0)
1264    {
1265      switch (build_lib(change, target, top_target, 1))
1266      {
1267        case BUILD_ERROR : return BUILD_ERROR; break;
1268        case CHANGED : change=1; break;
1269      }
1270    } 
1271
1272    if (strcmp(target.target_type,"plugin")==0)
1273    {
1274      switch (build_lib(change, target, top_target, 1))
1275      {
1276        case BUILD_ERROR : return BUILD_ERROR; break;
1277        case CHANGED : change=1; break;
1278      }
1279    } 
1280  }
1281   
1282
1283  if (change)
1284    return change;
1285  else
1286    return ALREADY_UP_TO_DATE;
1287
1288}
1289
1290
1291
1292
1293char skip_white(char *&p)
1294{
1295  while (*p && (*p==' ' || *p=='\n' || *p=='\t' || *p=='\r' || *p=='#' || *p==28))
1296  {
1297    if (*p=='#')
1298    {
1299      while (*p && *p!='\n')
1300        p++;           
1301    }
1302    else if (*p==' ' || *p=='\r' || *p=='\t' || *p==28)
1303      p++;
1304    else if (*p=='\n')
1305    {
1306      p++;
1307      line_on++;
1308    }
1309    else
1310    {
1311      char c=*p;
1312      p++;
1313      return c;
1314    }
1315  }
1316  return 0;
1317}
1318
1319int token_char(char p)
1320{
1321  return isalnum(p) || p=='_' || p=='.' || p=='\\' || p=='/' || p==':';
1322}
1323
1324
1325char tmp[2000];
1326
1327char *get_token(char *&p)
1328{
1329  skip_white(p);
1330  if (*p)
1331  {
1332    if (p[0]==']' || p[0]=='[' || p[0]=='=')     
1333    {
1334      tmp[0]=p[0]; tmp[1]=0; p++;
1335      return buf_alloc(tmp,2);
1336    }
1337    else if (p[0]=='"')
1338    {
1339      int len=0;
1340      char *c=tmp;
1341      p++;
1342   
1343      while (*p && *p!='"')
1344      {
1345        *(c++)=*(p++);
1346        len++;
1347      }
1348      *c=0;
1349
1350      p++;     
1351      return buf_alloc(tmp, len+1);
1352
1353
1354    } else if (token_char(*p))
1355    {
1356      int len=0;
1357      char *c=tmp;
1358     
1359      while (*p && token_char(*p))
1360      {
1361        *(c++)=*(p++);
1362        len++;
1363      }
1364      *c=0;
1365
1366      return buf_alloc(tmp, len+1);
1367    }
1368    else
1369    {
1370      mk_error("unexpected char '%c'", p[0]);
1371      return 0;
1372    }
1373  }
1374  else return 0;
1375
1376}
1377
1378void next_line(char *&p)
1379{
1380  int l=line_on;
1381  while (l==line_on)
1382  {
1383    skip_white(p);
1384    if (l==line_on)
1385      get_token(p);
1386  }
1387}
1388
1389
1390int build_ram_file(char *name, char *out_name, mk_target_struct &top_target)
1391{
1392  char *data_name=get_abs_path(name);
1393  char *cc_name=make_out_name(data_name, EXT_RAM_FILE, 1);
1394
1395  if (top_target.src.find(cc_name)==-1)
1396    top_target.src.add(cc_name);
1397 
1398  int m1=get_mod_time(cc_name);
1399  if (!m1 || m1<get_mod_time(data_name))
1400  {
1401    show_command(form("Generating ram file .cc %s", cc_name));
1402
1403    FILE *fp=fopen(data_name, "rb");
1404    if (!fp)
1405    {
1406      printf( "%s : Unable to open file to genertate ram file\n", data_name);
1407      return 0;
1408    }
1409
1410    fseek(fp, 0, SEEK_END);
1411    int fsize=ftell(fp);
1412    fseek(fp, 0, SEEK_SET);
1413
1414    unsigned char *buf=(unsigned char *)malloc(fsize);
1415    fread(buf, fsize, 1, fp);
1416   
1417    fclose(fp);
1418
1419    unsigned long id=check_sum32(cc_name, strlen(cc_name)) +
1420      check_sum32(out_name, strlen(out_name));
1421
1422    fp=fopen(cc_name, "wb");
1423    fprintf(fp, "#include \"file/ram_file_man.hh\"\n\nunsigned char i4_%x_ptr[%d]={\n",
1424            id, fsize);
1425   
1426    for (int i=0; i<fsize-1; i++)
1427    {
1428      if ((i%15)==0)
1429        fprintf(fp, "\n");
1430      fprintf(fp, "%d, ", buf[i]);
1431    }
1432    if (fsize)
1433      fprintf(fp, "%d", buf[fsize-1]);
1434
1435
1436    fprintf(fp,"};\n\ni4_openable_ram_file_info i4_%x(\"%s\", i4_%x_ptr, %d);",
1437            id, out_name, id, fsize);
1438    fclose(fp);
1439
1440    get_mod_time(cc_name, 1);
1441
1442    return CHANGED;
1443  }
1444  else return ALREADY_UP_TO_DATE;
1445}
1446
1447char *load_file(char *fn, int set_current_file)
1448{
1449  char *abs_filename=get_abs_path(fn);
1450
1451  FILE *fp=fopen(abs_filename, "rb");
1452  if (!fp) return 0;
1453 
1454  fseek(fp, 0, SEEK_END);
1455  int fsize=ftell(fp);
1456  fseek(fp, 0, SEEK_SET);
1457
1458  char *buf=(char *)malloc(fsize+1);
1459  fread(buf, fsize, 1, fp);
1460  buf[fsize]=0;
1461
1462  fclose(fp);
1463
1464  if (set_current_file)
1465  {
1466    file_on=abs_filename;
1467    line_on=0;
1468    file_contents=buf;
1469  }
1470
1471  return buf;
1472}
1473
1474int get_target(mk_target_struct &target,
1475               mk_target_struct &top_target,
1476               char *&p,
1477               char *target_name_to_match=0)
1478{
1479  int ret=ALREADY_UP_TO_DATE;
1480  while (1)
1481  {
1482    char *left_brace=get_token(p);
1483    if (left_brace)
1484    {
1485      if (strcmp(left_brace, "["))
1486        mk_error("expecting '['");
1487
1488      target.reset();
1489      target.target_type=get_token(p);
1490      target.target=get_token(p);
1491
1492      if (strcmp(get_token(p), "]"))
1493        mk_error("expecting ']'");
1494
1495    // should we use this target or skip it
1496      if (target_name_to_match && strcmp(target.target, target_name_to_match))
1497      {
1498        mk_debug("skipping section %s\n", target.target);
1499        skip_white(p);
1500        while (*p && *p!='[')
1501        {       
1502          get_token(p);
1503          skip_white(p);
1504        }   
1505      }
1506      else
1507      {
1508        mk_debug("processing section %s\n", target.target);
1509        skip_white(p);
1510        while (*p && *p!='[')
1511        {     
1512          char *t=get_token(p);
1513         
1514          if (strcmp(t, "win32")==0)
1515          {
1516            if (mk_options.os!=OS_WIN32)
1517            {
1518              mk_debug("%s : skipping line, wrong os\n", t);
1519              next_line(p);
1520            }
1521          }
1522          else if (strcmp(t, "linux")==0)
1523          {
1524            if (mk_options.os!=OS_LINUX)
1525            {
1526              mk_debug("%s : skipping line, wrong os\n", t);
1527              next_line(p);
1528            }
1529          }
1530          else if (strcmp(t, "opt")==0)
1531          {
1532            if (current_build_type!=BUILD_OPT)
1533            {
1534              mk_debug("%s : skipping line, wrong build type\n", t);
1535              next_line(p);
1536            }
1537          }
1538          else if (strcmp(t, "debug")==0)
1539          {
1540            if (current_build_type!=BUILD_DEBUG)
1541            {
1542              mk_debug("%s : skipping line, wrong build type\n", t);
1543              next_line(p);
1544            }
1545          }
1546          else if (strcmp(t, "profile")==0)
1547          {
1548            if (current_build_type!=BUILD_PROF)
1549            {
1550              mk_debug("%s : skipping line, wrong build type\n", t);
1551              next_line(p);
1552            }
1553          }
1554          else if (strcmp(t, "hostname")==0)
1555          {
1556            t=get_token(p);
1557            char name[200];
1558            gethostname(name,200);
1559            if (strcmp(t, name)!=0)
1560              next_line(p);           
1561          }
1562          else if (strcmp(t, "nothostname")==0)
1563          {
1564            t=get_token(p);
1565            char name[200];
1566            gethostname(name,200);
1567            if (strcmp(t, name)==0)
1568              next_line(p);           
1569          }         
1570          else if (strcmp(t, "link_as_windowed_app")==0)
1571            top_target.app_type=WIN32_WINDOWED_APP;
1572          else if (strcmp(t, "target_dir")==0)
1573          {
1574            char *dir=get_token(p);
1575            MKDIR(dir);
1576            target.outdir=form("%s/",dir);
1577          }
1578          else if (strcmp(t, "add_to_plugin")==0)
1579          {
1580            char *fn=get_token(p);
1581
1582            char *file=get_abs_path(fn);
1583            char *d=file+strlen(file);
1584            while (d>file && *d!='.') d--;
1585
1586            if (strcmp(top_target.target_type,"plugin")==0)
1587            {
1588              if (strcmp(d,".def")==0)
1589                top_target.def_file=file;           
1590              else if (strcmp(d,".a")==0 ||
1591                       (strstr(file, ".so")!=0) ||
1592                       strcmp(d,".lib")==0 ||
1593                       strcmp(d,".res")==0)
1594              {
1595                if (strcmp(d,".res")==0)
1596                  add_to_backup(file);
1597
1598                if (top_target.libs.find(file)==-1)
1599                  top_target.libs.add(file);
1600              }
1601              else if (top_target.src.find(file)==-1)
1602                top_target.src.add(file);
1603            }
1604          }
1605          else if (strcmp(t, "add_to_executable")==0)
1606          {
1607            char *fn=get_token(p);
1608
1609            char *file=get_abs_path(fn);
1610            char *d=file+strlen(file);
1611            while (d>file && *d!='.') d--;
1612
1613            if (strcmp(top_target.target_type,"executable")==0 ||
1614                strcmp(top_target.target_type,"plugin")==0)
1615            {
1616              if (strcmp(d,".def")==0)
1617                top_target.def_file=file;           
1618              else if (strcmp(d,".a")==0 ||
1619                       (strstr(file, ".so")!=0) ||
1620                       strcmp(d,".lib")==0 ||
1621                       strcmp(d,".res")==0)
1622              {
1623                if (strcmp(d,".res")==0)
1624                  add_to_backup(file);
1625
1626                if (top_target.libs.find(file)==-1)
1627                  top_target.libs.add(file);
1628              }
1629              else if (top_target.src.find(file)==-1)
1630                top_target.src.add(file);
1631            }
1632          }
1633          else if (strcmp(t,"backup")==0)
1634          {           
1635            char *fname=get_token(p);
1636            add_to_backup(fname);
1637          }
1638          else if (strcmp(t,"add_include_directory")==0)
1639          {
1640            char *i=get_abs_path(get_token(p), 1);
1641
1642            if (target.inc.find(i)==-1)
1643              target.inc.add(i);
1644
1645            if (top_target.inc.find(i)==-1)
1646              top_target.inc.add(i);
1647
1648            mk_debug("add_include_directory (dir=%s)\n", i);
1649          }
1650          else if (strcmp(t,"add_define")==0)
1651          {
1652            char *i=get_token(p);
1653
1654            if (target.defines.find(i)==-1)
1655              target.defines.add(i);
1656
1657            mk_debug("add_define (define=%s)\n", i);
1658          }
1659          else if (strcmp(t,"add_global_define")==0)
1660          {
1661            char *i=get_token(p);
1662
1663            if (mk_global_defines.find(i)==-1)
1664              mk_global_defines.add(i);
1665
1666            mk_debug("add_global_define (define=%s)\n", i);
1667          }
1668          else if (strcmp(t, "ram_file")==0)
1669          {
1670            char *in_name=get_token(p);
1671            int l=line_on;
1672            skip_white(p);
1673
1674            if (current_build_type==BUILD_BACKUP)
1675            {
1676              add_to_backup(in_name);
1677              if (line_on==l)
1678                get_token(p);
1679            }
1680            else
1681            {
1682              if (line_on==l)             
1683                build_ram_file(in_name, get_token(p), top_target);
1684              else
1685                build_ram_file(in_name, in_name, top_target);
1686            }
1687
1688
1689          }
1690          else if (strcmp(t, "use")==0)
1691          {
1692
1693            t=get_token(p);
1694            char *use_file=0;
1695
1696
1697            if (strcmp(t,"file")==0)
1698            {
1699              if (strcmp(get_token(p),"="))
1700                mk_error("expected = after file");
1701              use_file=get_token(p);
1702              t=get_token(p);
1703
1704              add_to_backup(use_file);
1705            }
1706
1707            mk_debug("use (file=%s) (target=%s)\n", use_file, t);
1708
1709
1710            mk_target_struct tar;
1711            int cur_line=line_on;   // save current line & file info
1712            char *cur_file=file_on;
1713            char *cur_contents=file_contents;
1714
1715            char old_abs[MAX_LEN];
1716            char *f;
1717            if (use_file)
1718            {
1719              f=load_file(use_file, 1);
1720              if (!f)
1721                mk_error("could not load project file '%s'", use_file);
1722             
1723              strcpy(old_abs, abs_path);
1724              set_abs_path(use_file);
1725            }
1726            else f=file_contents;
1727
1728
1729            if (get_target(tar, top_target, f,t)==NO_MORE_TARGETS)
1730                mk_error("could not find target '%s'", t);
1731           
1732            // add include paths to local target
1733            for (int i=0; i<tar.inc.size(); i++)
1734              if (target.inc.find(tar.inc[i])==-1)
1735                target.inc.add(tar.inc[i]);
1736
1737            ret=build_target(tar, top_target);
1738             
1739            if (use_file)
1740            {
1741              file_contents=cur_contents;
1742              file_on=cur_file;
1743              set_abs_path(old_abs);
1744            }
1745
1746            line_on=cur_line;
1747             
1748           
1749          }
1750          else
1751          {
1752            mk_debug("add to target %s\n",t);
1753            target.src.add(t);
1754          }
1755       
1756          skip_white(p);
1757        }   
1758        return ret;
1759      }
1760    }
1761    else return NO_MORE_TARGETS;
1762  }
1763}
1764
1765void backup()
1766{
1767  if (files_to_backup.size())
1768  { 
1769    FILE *out=fopen("backup.i4", "wb");
1770    if (out)
1771    {
1772      int t_files=0;
1773      for (int i=0; i<files_to_backup.size(); i++)
1774      {
1775        FILE *in=fopen(files_to_backup[i], "rb");
1776        if (in)
1777        {       
1778          char *fn=files_to_backup[i];
1779          if (fn[1]==':') fn+=2;
1780          if (fn[0]=='\\' || fn[0]=='/') fn++;       
1781
1782          unsigned char l=strlen(fn)+1, s1,s2,s3,s4;
1783          fwrite(&l, 1, 1, out);
1784          fwrite(fn, l, 1, out);
1785
1786          fseek(in, 0, SEEK_END);
1787          int size=ftell(in);
1788          fseek(in, 0, SEEK_SET);
1789          s1=(size&0xff000000)>>24;
1790          s2=(size&0xff0000)>>16;
1791          s3=(size&0xff00)>>8;
1792          s4=(size&0xff)>>0;
1793          fwrite(&s1, 1,1, out);
1794          fwrite(&s2, 1,1, out);
1795          fwrite(&s3, 1,1, out);
1796          fwrite(&s4, 1,1, out);
1797
1798          char buf[4096];
1799          int rsize=0;
1800          do
1801          {
1802            rsize=fread(buf, 1, 4096, in);
1803            fwrite(buf, rsize, 1, out);
1804          } while (rsize);
1805          t_files++;
1806          fclose(in);
1807
1808        }
1809        else printf("backup: couldn't open %s\n", files_to_backup[i]);
1810      }
1811
1812      fclose(out);
1813      printf("backed up %d files to backup.i4\n", t_files);
1814    }
1815    else printf("backup: couldn't backup.i4 for writing\n");   
1816  }
1817}
1818
1819int i4_make_main(int argc, char **argv)
1820{
1821  setbuf(stdout, 0);
1822
1823#ifdef _WINDOWS
1824
1825  mk_options.os=OS_WIN32;
1826  _getcwd(abs_path, sizeof(abs_path));
1827
1828#elif __linux
1829
1830  mk_options.os=OS_LINUX;
1831  getcwd(abs_path, sizeof(abs_path));
1832
1833#else
1834
1835  #error add new os here
1836#endif
1837
1838
1839
1840  strcat(abs_path, "/");
1841
1842  mk_options.get(argc, argv);
1843 
1844  char *file_start=load_file(mk_options.project_file, 1), *b;
1845  if (!file_start)
1846    mk_error("Project file not found : '%s'", mk_options.project_file);
1847
1848
1849  mk_target_struct target; 
1850  getcwd(start_path, 256);
1851         
1852  for (current_build_type=1; current_build_type<=BUILD_LAST; current_build_type*=2)
1853  {           
1854    if (mk_options.build_flags & current_build_type)
1855    { 
1856      if (current_build_type==BUILD_BACKUP)
1857        add_to_backup(mk_options.project_file);
1858
1859      if (!mk_options.targets_to_build.size())
1860      { 
1861        b=file_start;
1862        int ret;
1863
1864        while (ret=get_target(target, target, b)!=NO_MORE_TARGETS)
1865        {
1866          if (build_target(target, target)==BUILD_ERROR)
1867            if (!mk_options.continue_on_error)
1868            {
1869              perror("Stopping : ");
1870              exit(-1);
1871            }
1872               
1873          target.reset();
1874          mk_options.targets_built.clear();
1875        }
1876      }
1877
1878      for (int i=0; i<mk_options.targets_to_build.size(); i++)
1879      {
1880        b=file_start;
1881        if (get_target(target, target, b, mk_options.targets_to_build[i])==NO_MORE_TARGETS)
1882          mk_error("can't find target '%s' to build\n", mk_options.targets_to_build[i]);
1883        else if (build_target(target, target)==BUILD_ERROR)
1884          if (!mk_options.continue_on_error)
1885            return -1;
1886
1887        target.reset();
1888        mk_options.targets_built.clear();
1889      }
1890
1891      if (current_build_type==BUILD_CLEAN)
1892      {
1893        for (int i=0; i<files_to_clean.size(); i++)
1894          clean_file(files_to_clean[i]);
1895        files_to_clean.clear();
1896      }
1897
1898    }
1899  }
1900
1901
1902  if (mk_options.build_flags & BUILD_BACKUP)
1903    backup();
1904
1905  return 0;
1906}
1907
1908
1909int main(int argc, char **argv)
1910{
1911  return i4_make_main(argc, argv);
1912}
1913
Note: See TracBrowser for help on using the repository browser.