5a7ab61998-01-31Fredrik Hübinette (Hubbe) #!/usr/local/bin/pike
c064061998-05-27Fredrik Hübinette (Hubbe) // RNTCC, a front-end to WatCOM C/C++ with options similar to GCC // Written by Fredrik Hubinette.
5a7ab61998-01-31Fredrik Hübinette (Hubbe) inherit "lib.pike";
c064061998-05-27Fredrik Hübinette (Hubbe) // Verbose is default for now, this can be turned off one this // frontend has been refined to where it does not require more // debugging.
ffb38c1999-03-18Fredrik Hübinette (Hubbe) int verbose=0;
c064061998-05-27Fredrik Hübinette (Hubbe) 
686ed61998-09-01Fredrik Hübinette (Hubbe) // Temporary variable int linking_failed;
1efbb71999-03-23Fredrik Hübinette (Hubbe) // Files to remove upon exit string *tmpfiles=({}); void exit(int code) { if(getenv("CLEANUP")!="no") Array.map(tmpfiles,rm); predef::exit(code); }
686ed61998-09-01Fredrik Hübinette (Hubbe) string get_ext(string file) { sscanf(file=lower_case(reverse(file)),"%s.",file); return reverse(file); }
5a7ab61998-01-31Fredrik Hübinette (Hubbe) int compile(string *sources, string dest, string errorfile, string *cflags) { int ret;
c064061998-05-27Fredrik Hübinette (Hubbe)  mixed cmd;
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  if(!dest) { string tmp=reverse(sources[0]); sscanf(tmp,"%*s.%s",tmp); dest=reverse(tmp)+".o"; }
641d5c1998-04-09Fredrik Hübinette (Hubbe)  dest=fixpath(dest);
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  sources=Array.map(sources,fixpath);
686ed61998-09-01Fredrik Hübinette (Hubbe)  switch(get_ext(sources[0]))
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  {
686ed61998-09-01Fredrik Hübinette (Hubbe)  case "c": cmd=({ "wcc386" }) + cflags + ({"-fr"+errorfile, "-fo"+dest}) + sources; break; case "cpp": case "cc": cmd=({ "wpp386" }) + cflags + ({"-fr"+errorfile, "-fo"+dest}) + sources; break;
c064061998-05-27Fredrik Hübinette (Hubbe) 
686ed61998-09-01Fredrik Hübinette (Hubbe)  case "s": cmd=({ "wasm", "-fe"+errorfile, "-fo"+dest,})+ sources;
da5cd91998-11-05Fredrik Hübinette (Hubbe)  default: werror("Don't know how to compile %s\n",sources[0]); exit(1);
686ed61998-09-01Fredrik Hübinette (Hubbe)  }
c064061998-05-27Fredrik Hübinette (Hubbe)  if(verbose) return do_cmd(cmd); else return silent_do_cmd(cmd);
a12f271998-01-10Fredrik Hübinette (Hubbe) }
6d86081997-12-22Fredrik Hübinette (Hubbe) 
5a7ab61998-01-31Fredrik Hübinette (Hubbe) string check_errorfile(string errorfile) { object f=Stdio.File(); if(f->open(errorfile,"r")) { string data;
4588001998-10-18Fredrik Hübinette (Hubbe)  werror(data=f->read());
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  f->close(); data=replace(data,"\r",""); rm(errorfile); foreach(data/"\n", string line) { if(!strlen(line)) continue; if(search(line,"Warning")!=-1) continue; werror("Error in compilation detected. "+line+"\n"); exit(1); } }
09ca251998-01-16Fredrik Hübinette (Hubbe) }
6d86081997-12-22Fredrik Hübinette (Hubbe) 
5a7ab61998-01-31Fredrik Hübinette (Hubbe) int main(int argc, string *argv) { string target; string operation="link";
686ed61998-09-01Fredrik Hübinette (Hubbe)  string *cflags=({"-d__WIN32__","-d_WIN32"});
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  string *ldopts=({"OPTION","STACK=8m"}); string *libraries=({}); string *objects=({}); string *sources=({}); int debug,optimize; string output;
b769971998-02-27Fredrik Hübinette (Hubbe)  int share=0;
5a7ab61998-01-31Fredrik Hübinette (Hubbe) 
c064061998-05-27Fredrik Hübinette (Hubbe)  mixed *opts=Getopt.find_all_options(argv, aggregate(
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  ({"oper_pre",Getopt.NO_ARG, ({"-E"}) }),
c064061998-05-27Fredrik Hübinette (Hubbe)  ({"oper_comp",Getopt.NO_ARG, ({"-c"}) }), ({"verbose",Getopt.NO_ARG, ({"-v"}) }), ({"debug",Getopt.MAY_HAVE_ARG, ({"-g"}) }), ({"optimize",Getopt.MAY_HAVE_ARG, ({"-O"}) }), ({"include",Getopt.HAS_ARG, ({"-I"}) }), ({"link",Getopt.HAS_ARG, ({"-l"}) }), ({"share",Getopt.MAY_HAVE_ARG, ({"-s"}) }), ({"ignore",Getopt.MAY_HAVE_ARG, ({"-t"}) }),
dd990d1998-12-31Fredrik Hübinette (Hubbe)  ({"ignore",Getopt.HAS_ARG, ({"-R","-L","-r"}) }),
c064061998-05-27Fredrik Hübinette (Hubbe)  ({"warn",Getopt.MAY_HAVE_ARG, ({"-W"}) }), ({"define",Getopt.HAS_ARG, ({"-D"}) }), ({"undefine",Getopt.HAS_ARG, ({"-U"})}), ({"output",Getopt.HAS_ARG, ({"-o"}) }), ({"export",Getopt.HAS_ARG, ({"--export"}) }) ));
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  foreach(opts, mixed *option) { switch(option[0]) {
c064061998-05-27Fredrik Hübinette (Hubbe)  case "verbose":
6b48a21998-08-05Fredrik Hübinette (Hubbe)  verbose++;
c064061998-05-27Fredrik Hübinette (Hubbe)  break;
31925e1998-03-20Fredrik Hübinette (Hubbe)  case "export": ldopts+=({"export",option[1]+"_"}); break;
b769971998-02-27Fredrik Hübinette (Hubbe)  case "share": share=1;
31925e1998-03-20Fredrik Hübinette (Hubbe)  ldopts=({"SYSTEM","nt_dll","initinstance","terminstance"})+ldopts;
b769971998-02-27Fredrik Hübinette (Hubbe)  cflags+=({"-bd"}); break;
6b48a21998-08-05Fredrik Hübinette (Hubbe) 
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  case "oper_pre": operation="preprocess"; break; case "oper_comp": operation="compile"; break; case "debug":
80147f1999-03-11Fredrik Hübinette (Hubbe)  cflags+=({"-d2"}); ldopts+=({"DEBUG","WATCOM","ALL"});
6b48a21998-08-05Fredrik Hübinette (Hubbe) 
80147f1999-03-11Fredrik Hübinette (Hubbe) // cflags+=({"-d2","-hd"}); // ldopts+=({"DEBUG","DWARF"});
6b48a21998-08-05Fredrik Hübinette (Hubbe)  // cflags+=({"-d2","-hc"}); // ldopts+=({"DEBUG","CODEVIEW","OPTION","CVPACK"}); debug=1; break;
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  case "optimize": if(!option[1]) option[1]=1; switch(optimize=(int)option[1]) { case 0: optimize=0; break; case 1: cflags+=({"-ox"}); break;
6b48a21998-08-05Fredrik Hübinette (Hubbe)  case 2: cflags+=({"-otexan"}); break; case 3..: cflags+=({"-s", "-oe="+(optimize*30), "-ol+", "-oabhikmnrt"}); break;
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  } break; case "include":
c064061998-05-27Fredrik Hübinette (Hubbe)  // Avoid searching 'local' include dirs. // This is not a very pretty solution.
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  if(sscanf(option[1],"/usr/include/%*s") || sscanf(option[1],"/usr/local/%*s")) break; cflags+=({"-i"+fixpath(option[1])}); break; case "link":
c064061998-05-27Fredrik Hübinette (Hubbe)  // -lm and -lc are automatically handled by wlink
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  if(option[1]=="m" || option[1]=="c") break;
c064061998-05-27Fredrik Hübinette (Hubbe)  // We optimiza a little, no need to bring in the same // library many times in a row. if(!sizeof(libraries) || libraries[-1]!=option[1]) libraries+=({option[1]});
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  break; case "warn":
c064061998-05-27Fredrik Hübinette (Hubbe)  if(option[1]) { // This allows us to pass options to the linker if(sscanf(option[1],"l,%s",string tmp)) { // This was done for my convenience, it can be taken // out once smartlink has been fixed to not use absoute // paths for the 'uname' binary. if(sscanf(tmp,"-rpath%*s")) break; ldopts+=({tmp}); break; } } // More options should be recognized, options which are not // recognized should generate warning/error messages.
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  switch(option[1]) { case "all": cflags+=({"-wx"}); break; default: cflags+=({"-w2"}); break; } break; case "define": cflags+=({"-d"+option[1]}); break; case "undefine": cflags+=({"-u"+option[1]}); break; case "output": output=option[1]; break; } }
c064061998-05-27Fredrik Hübinette (Hubbe)  // Scan through the remaining arguments
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  argv=Getopt.get_args(argv); foreach(argv[1..], string tmp) { if(tmp[0]=='-') { werror("Unrecognized option "+tmp+".\n"); exit(1); }
c064061998-05-27Fredrik Hübinette (Hubbe)  // Recognize which files need to be compiled
686ed61998-09-01Fredrik Hübinette (Hubbe)  switch(get_ext(tmp))
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  { case "o": case "a":
686ed61998-09-01Fredrik Hübinette (Hubbe)  case "obj": case "dll": case "lib":
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  objects+=({tmp}); break; default: sources+=({tmp}); } } if(output) rm(output);
4588001998-10-18Fredrik Hübinette (Hubbe)  string errorfile="tmp"+getpid()+".err";
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  rm(errorfile);
1efbb71999-03-23Fredrik Hübinette (Hubbe)  tmpfiles+=({errorfile});
5a7ab61998-01-31Fredrik Hübinette (Hubbe) 
c064061998-05-27Fredrik Hübinette (Hubbe)  // Flags required to make the compiler behave well
6b48a21998-08-05Fredrik Hübinette (Hubbe)  cflags+=({"-bm","-zq","-sg","-5","-fpi87","-fp3"});
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  switch(operation) { default: werror("Unknown operation "+operation+".\n"); exit(1); case "compile": compile(sources,output,errorfile,cflags); break; case "preprocess": {
686ed61998-09-01Fredrik Hübinette (Hubbe)  switch(get_ext(sources[0])) { default: case "c": int ret=silent_do_cmd( ({"wcc386","-p","-fr"+errorfile}) + cflags + Array.map(sources, fixpath)); break; case "cc": case "cpp": int ret=silent_do_cmd( ({"wpp386","-p","-fr"+errorfile}) + cflags + Array.map(sources, fixpath)); break; }
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  break; } case "link":
1efbb71999-03-23Fredrik Hübinette (Hubbe)  int objnum;
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  foreach(sources, string source) {
1efbb71999-03-23Fredrik Hübinette (Hubbe)  string obj=sprintf("TMP%dX%d.obj",getpid(),objnum++);
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  compile( ({source}), obj, errorfile, cflags); objects+=({obj});
1efbb71999-03-23Fredrik Hübinette (Hubbe)  tmpfiles+=({obj});
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  check_errorfile(errorfile); }
686ed61998-09-01Fredrik Hübinette (Hubbe) // objects+=({"BINMODE.OBJ"});
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  string ldfile="TMP"+getpid()+".lk";
1efbb71999-03-23Fredrik Hübinette (Hubbe)  tmpfiles+=({ldfile});
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  if(!output) output="a.out"; rm(ldfile);
b769971998-02-27Fredrik Hübinette (Hubbe)  target=output; if(!share) target+=".exe";
c064061998-05-27Fredrik Hübinette (Hubbe)  string linkopts=("NAME "+target+" " + ldopts*" "+" "+ "FILE "+Array.map(objects,fixpath)*","+" "+ sprintf("%{LIBRARY %s %}",libraries)); Stdio.write_file(ldfile,linkopts); if(verbose) werror("DOING wlink "+linkopts+"\n");
5a7ab61998-01-31Fredrik Hübinette (Hubbe) 
31925e1998-03-20Fredrik Hübinette (Hubbe) #if 0 Process.system("cat "+ldfile); write("\n"); #endif
686ed61998-09-01Fredrik Hübinette (Hubbe)  linking_failed=0;
31925e1998-03-20Fredrik Hübinette (Hubbe) 
c064061998-05-27Fredrik Hübinette (Hubbe)  silent_do_cmd( ({"wlink","@"+ldfile }), lambda(string data)
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  { if(search(data," W1008:")!=-1)
686ed61998-09-01Fredrik Hübinette (Hubbe)  linking_failed++;
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  });
686ed61998-09-01Fredrik Hübinette (Hubbe)  if(linking_failed) exit(1);
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  } check_errorfile(errorfile); if(target) { if(!file_stat(target)) { werror("RNTCC: output file not generated.\n"); exit(1); } }
b769971998-02-27Fredrik Hübinette (Hubbe)  if(operation == "link" && !share)
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  { rm(output); Stdio.write_file(output, "#!/usr/local/bin/pike\n" "inherit \""+find_lib_location()+"\";\n" "int main(int argc, string *argv) {\n" "argv[0]+=\".exe\";\n" "argv[0]=getenv(\"NTDRIVE\")+fixpath(combine_path(getcwd(),argv[0]));\n" " exit(silent_do_cmd(argv));\n" "}\n"); chmod(output,0755); } exit(0); }