8cd4432000-06-28Henrik Grubbström (Grubba) #!/usr/local/bin/pike // -*- Pike -*- // RNTECL, a front-end to Intel ECL with options similar to GCC // Written by Fredrik Hubinette & Henrik Grubbström. inherit "lib.pike"; // Verbose is default for now, this can be turned off one this // frontend has been refined to where it does not require more // debugging. int verbose=1; // Temporary variable int linking_failed; // Files to remove upon exit string *tmpfiles=({}); void exit(int code) { if(getenv("CLEANUP")!="no") Array.map(tmpfiles,rm); predef::exit(code); } string get_ext(string file) { sscanf(file=lower_case(reverse(file)),"%s.",file); return reverse(file); } string remove_ext(string file) { sscanf(file=reverse(file),"%*s.%s",file,file); return reverse(file); } int main(int argc, string *argv) { string *ldopts=({"-INCREMENTAL:no"}); string *cflags=({ "-Wp64", "-D__WIN32__", "-D_WIN32", "-D__NT__", // "-D__STDC__", "-nologo", }); string target="exe"; int debug,optimize,share; string output, wantfile; mixed *opts=Getopt.find_all_options(argv, aggregate( ({"oper_pre",Getopt.NO_ARG, ({"-E"}) }), ({"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"}) }), ({"ignore",Getopt.HAS_ARG, ({"-R","-L","-r"}) }), ({"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"}) }) )); foreach(opts, mixed *option) { switch(option[0]) { case "verbose": verbose++; ldopts+=({"-VERBOSE:lib"}); break; case "export": // fixme // ldopts+=({"export",option[1]+"_"}); break; case "share": // fixme switch(option[1]) { case "hare": share=1; target="dll"; break; case "tatic": /* Not yet implemented */ break; } break; case "oper_pre": cflags+=({ "-E" }); target="-"; break; case "oper_comp": target="obj"; cflags+=({ "-c" }); break; case "debug": cflags+=({ "-Z7", "-FR", // "-Yd", }); debug=1; break; case "optimize": if(!option[1]) option[1]=1; switch(optimize=(int)option[1]) { case 0: optimize=0; break; case 1: cflags+=({"-O1"}); break; case 2: cflags+=({"-O2"}); break; case 3..: break; } break; case "include": // Avoid searching 'local' include dirs. // This is not a very pretty solution. if(sscanf(option[1],"/usr/include/%*s") || sscanf(option[1],"/usr/local/%*s")) break; cflags+=({"-I"+fixpath(option[1])}); break; case "link": // -lm and -lc are automatically handled ? if(option[1]=="m" || option[1]=="c") break; // We optimiza a little, no need to bring in the same // library many times in a row. // if(cflags[-1]!=option[1]+".lib") // if(search(cflags,option[1]+".lib")!=-1) cflags-=({option[1]+".lib"}); cflags+=({option[1]+".lib"}); break; case "warn": 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; cflags+=({tmp}); break; } } // More options should be recognized, options which are not // recognized should generate warning/error messages. switch(option[1]) { case "all": cflags+=({"-W4"}); break; default: cflags+=({"-W3"}); break; } break; case "define": cflags+=({"-D"+option[1]}); break; case "undefine": cflags+=({"-U"+option[1]}); break; case "output": output=option[1]; break; } } // Scan through the remaining arguments argv=Getopt.get_args(argv); cflags+=Array.map(argv[1..],fixpath); foreach(argv[1..], string tmp) { if(tmp[0]=='-') { werror("Unrecognized option "+tmp+".\n"); exit(1); } } switch(target) { case "exe": if(!output) output="a.out"; cflags+=({"-Fe"+fixpath(output)+".exe"}); // cflags+=({"-MT" + (debug?"d":"") }); wantfile=output+".exe"; break; case "obj": if(!output) output=remove_ext(argv[1])+".o"; cflags+=({"-Fo"+fixpath(output)}); wantfile=output; break; case "dll": if(output) cflags+=({"-Fe"+fixpath(output)}); else output=remove_ext(argv[1])+".dll"; // cflags+=({"-MD" + (debug?"d":"") }); wantfile=output; break; case "-": } cflags+=({"-MT" + (debug?"d":"") }); if(output) rm(output); array(string) cmd=({"ecl"})+cflags; switch(target) { case "exe": case "dll": if(debug) { array libs=({"libc.lib","libcd.lib", "libcmt.lib","libcmtd.lib", "msvcrt.lib","msvcrtd.lib"}); string lib=(debug?"libcmtd.lib":"libcmt.lib"); libs-=({ lib }); for(int e=0;e<sizeof(libs);e++) ldopts+=({"-nodefaultlib:"+libs[e]}); cmd+=({"-link", // "-PDB:NONE", "-DEBUGTYPE:BOTH", "-DEBUG", }) +ldopts; } } int ret; if(verbose && target!="-") { ret=do_cmd(cmd); }else{ int first_line=1; // ecl.exe echoes the file name of the file we are compiling // first, we need to get rid of that to make configure behave ret=silent_do_cmd(cmd, lambda(string line) { if(first_line) { array x=line/"\n"; if(sizeof(x)>1) { line=x[1..]*"\n"; first_line=0; }else{ return; } } write(line); },1); } if(ret) { werror("ECL returned error code %d.\n",ret); exit(ret); } if(wantfile) { if(!file_stat(wantfile)) { werror("RNTECL: output file not generated (%s).\n",wantfile); exit(1); } } if(target=="exe" && !share) { 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" " int ret=silent_do_cmd(argv);\n" " exit(ret);\n" "}\n"); chmod(output,0755); } exit(ret); }