1$ ! 2$ ! Set up to compile GCC on VMS. 3$ ! 4$ ! Set the def dir to proper place for use in batch. Works for interactive too. 5$flnm = f$enviroment("PROCEDURE") ! get current procedure name 6$set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")' 7$ ! 8$set symbol/scope=(nolocal,noglobal) 9$if f$trnlnm("IFILE$").nes."" then close/noLog ifile$ 10$ ! 11$ echo = "write sys$output" 12$ ! 13$ arch_indx = 1 + ((f$getsyi("CPU").ge.128).and.1) ! vax==1, alpha==2 14$ arch = f$element(arch_indx,"|","|vax|alpha|") 15$ ! 16$ if f$search("config.h") .nes. "" then delete config.h.* 17$ if arch .eqs. "vax" 18$ then 19$ copy [.config.'arch']xm-vms.h []config.h 20$ echo "Linked `config.h' to `[.config.''arch']xm-vms.h'." 21$else 22$ open/write cfile []config.h 23$ write cfile "#include "+"""config/"+arch+"/xm-"+arch+".h"+""" 24$ write cfile "#include "+"""config/"+arch+"/xm-vms.h"+""" 25$ close cfile 26$ echo "Created `config.h'." 27$ endif 28$ ! 29$ if f$search("tconfig.h") .nes. "" then delete tconfig.h.* 30$ create []tconfig.h 31$DECK 32/* tconfig.h == config.h :: target and host configurations are the same */ 33#include "config.h" 34$EOD 35$ echo "Created `tconfig.h'. 36$ ! 37$ if f$search("hconfig.h") .nes. "" then delete hconfig.h.* 38$ create []hconfig.h 39$DECK 40/* hconfig.h == config.h :: host and target configurations are the same */ 41#include "config.h" 42$EOD 43$ echo "Created `hconfig.h'. 44$ ! 45$ if f$search("tm.h") .nes. "" then delete tm.h.* 46$ ! 47$ edit/tpu/nojournal/nosection/nodisplay/command=sys$input - 48 [.config.'arch']vms.h /output=[]tm.h 49$DECK 50! 51! Copy file, changing lines of the form 52! #include "vax/*" 53! or 54! #include "alpha/*" 55! into 56! #include "config-*" 57! 58 file := CREATE_BUFFER("file", GET_INFO(COMMAND_LINE, "file_name")); 59 targ := LINE_BEGIN & '#include' & SPAN(ASCII(32)+ASCII(9)) 60 & '"' & ('vax' | 'alpha') & '/'; 61 rang := CREATE_RANGE(BEGINNING_OF(file), END_OF(file)); 62 LOOP 63 incl := SEARCH_QUIETLY(targ, FORWARD, EXACT, rang); 64 EXITIF incl = 0; 65 POSITION(BEGINNING_OF(incl)); 66 ERASE(incl); 67 COPY_TEXT('#include "config-'); 68 rang := CREATE_RANGE(END_OF(incl), END_OF(file)); 69 ENDLOOP; 70 WRITE_FILE(file, GET_INFO(COMMAND_LINE, "output_file")); 71 QUIT 72$ EOD 73$ echo "Generated `tm.h' from `[.config.''arch']vms.h'." 74$ ! 75$ !crude hack to allow compiling from [.cp] subdirectory 76$ if f$search("config-''arch'.h") .nes. "" then delete config-'arch'.h;* 77$ copy [.config.'arch']'arch'.h []config-'arch'.h 78$ echo "Linked `config-''arch'.h' to `[.config.''arch']''arch'.h' for `tm.h'." 79$ ! 80$ call make_lang_incl "options.h" 81$ ! 82$ call make_lang_incl "specs.h" 83$ ! 84$ if arch .eqs. "vax" 85$ then 86$ if f$search("''arch'.md") .nes. "" then delete 'arch'.md;* 87$ copy [.config.'arch']'arch'.md []'arch'.md 88$ echo "Copied `''arch'.md' from `[.config.''arch']''arch'.md'." 89$ endif 90$ ! 91$ if f$search("aux-output.c") .nes. "" then delete aux-output.c.* 92$ copy [.config.'arch']'arch'.c []aux-output.c 93$ echo "Linked `aux-output.c' to `[.config.''arch']''arch'.c'. 94$ ! 95$ ! 96$ ! 97$ ! Create the file version.opt, which helps identify the executable. 98$ ! 99$search version.c version_string,"="/match=and/output=t.tmp 100$open ifile$ t.tmp 101$read ifile$ line 102$close ifile$ 103$delete t.tmp; 104$line=f$element(1,"""",line) !extract the portion between 1st & 2nd quotes 105$! Format of 'line' is "name-nn.nn.nn[.nn] [date text]" (without the quotes). 106$! We want "name-nn.nn.nn[.nn][-date]"; "-date" suffix is optional. 107$id = f$element(1,"-",line) !strip "name-" prefix 108$if id.eqs."-" then id = line !no prefix found? 109$id = f$element(0," ",id) + "-" + f$element(1," ",id) !first two tokens 110$id = id - "- " !in case 2nd token was empty 111$if f$length(id).gt.15 then id = f$extract(0,15,id) !length limitation 112$! 113$open/write ifile$ version.opt 114$write ifile$ "ident="+""""+id+"""" 115$close ifile$ 116$purge version.opt 117$! 118$! 119$! create linker options files that lists all of the components for all 120$! possible compilers. We do this by editing the file Makefile.in, and 121$! generating the relevant files from it. 122$! 123$! 124$! Make a copy of the makefile if the sources are on a disk that is NFS 125$! mounted on a unix machine. 126$if f$search("Makefile.in").eqs."" .and. f$search("$M$akefile.in").nes."" - 127 then copy $M$akefile.in Makefile.in 128$! This should be automated across all front-end subdirectories. 129$! For now, it's hardcoded. 130$if f$search("[.cp]Makefile.in").eqs."" .and. f$search("[.cp]$M$akefile.in").nes."" - 131 then copy [.cp]$M$akefile.in [.cp]Makefile.in 132$! 133$! 134$echo "Now processing Makefile.in to generate linker option files." 135$edit/TPU/noJournal/noSection/noDisplay/Command=sys$input: Makefile.in - 136 /Start_Position=('arch_indx') ! 1 for vax, 2 for alpha 137!! 138VARIABLE makefile_buf, opt_file_buf, complist_buf, extra_compilers; ! Globals. 139VARIABLE arch; ! String 'vax' or 'alpha', set in configure_makefile(). 140 141!! 142PROCEDURE process_makefile( ) 143 ! 144 ! Interpret Makefile.in and subsidiary Make-lang.in templates. 145 ! 146 LOCAL range1, cmark, makefilename; 147 148 makefilename := GET_INFO (COMMAND_LINE, 'FILE_NAME'); ! "Makefile.in" 149 makefile_buf := CREATE_BUFFER ("makefile", makefilename); 150 opt_file_buf := CREATE_BUFFER ("opt_file"); 151 complist_buf := CREATE_BUFFER ("complist"); 152 extra_compilers := CREATE_ARRAY; 153 ! 154 SET (NO_WRITE, makefile_buf, ON); ! Used as workspace; don't save it. 155 SET (OUTPUT_FILE, complist_buf, "compilers.list"); 156 ! 157 ! Make some textual substitutions. 158 ! 159 configure_makefile (); 160 ! 161 ! Collect a list of supported compilers (``COMPILERS=xxx'' macro). 162 ! 163 identify_compilers (); 164 ! 165 ! Plus other known compilers described by Make-lang.in makefile fragments. 166 ! Add new entries as needed; args are (target name, subdirectory name). 167 ! 168 additional_compiler ("cc1plus", "cp"); 169 ! 170 WRITE_FILE (complist_buf); ! Now save "compilers.list". 171 ! 172 ! Add to this list, as required. The file "Makefile.in" is searched for 173 ! a tag that looks like "LINE_BEGIN + 'tag + (optional space) + "="". 174 ! The contents are assumed to be a list of object files, and from this 175 ! list a VMS linker options file is generated. 176 ! 177 generate_option_file ("OBJS", "=", "independent.opt"); 178 generate_option_file ("LIB2FUNCS", "=", "libgcc2.list"); 179 generate_option_file ("CXX_LIB2FUNCS", "=", "libgcc2-cxx.list"); 180 ! 181 ! Now change OBJS in the Makefile, so each language specific options file 182 ! does not pick up all of the language independent files. 183 ! 184 POSITION (BEGINNING_OF (makefile_buf)); 185 COPY_TEXT ("OBJS="); ! New copy with empty value, seen before real OBJS. 186 SPLIT_LINE; 187 ! 188 ! Lastly, process each compiler-specific object dependency list. 189 ! 190 POSITION (BEGINNING_OF (complist_buf)); 191 LOOP 192 cmark := MARK (NONE); 193 EXITIF (cmark = END_OF (complist_buf)); 194 ! The current line contains the name of a compiler target, such as "cc1". 195 MESSAGE (CURRENT_LINE); ! Give some interactive feedback. 196 generate_option_file (CURRENT_LINE, ":", CURRENT_LINE + "-objs.opt"); 197 POSITION (cmark); 198 MOVE_VERTICAL (1); ! Go to the next line. 199 ENDLOOP; 200ENDPROCEDURE; !process_makefile 201!! 202 203PROCEDURE process_objc_lib( ) 204 ! 205 ! Interpret objc/Makefile, after finishing the top makefile. 206 ! 207 ON_ERROR 208 [TPU$_OPENIN]: 209 MESSAGE ("Cannot load objc/Makefile for ""ObjClib""; skipping it."); 210 RETURN; 211 ENDON_ERROR; 212 213 ERASE (makefile_buf); !discard top Makefile 214 POSITION (END_OF (makefile_buf)); 215 READ_FILE ("[.objc]Make-lang.in"); !load objc one 216 MESSAGE ("objclib"); 217 pat_replace (ASCII(9), " "); !change any <tab> to <space> 218 generate_option_file ("OBJC_O", "=", "objc-objs.opt"); 219 POSITION (BEGINNING_OF (makefile_buf)); 220 ! Join any continuation lines; we want the header list to be one line. 221 pat_replace ("\" & LINE_END, ); 222 generate_option_file ("OBJC_H", "=", "objc-hdrs.list"); 223ENDPROCEDURE; !process_objc_lib 224!! 225 226PROCEDURE configure_makefile( ) 227 ! 228 ! Plug in some values normally handled by `configure'. Rather than 229 ! replacing the dummy entries, insert the real entries before them. 230 ! 231 IF (GET_INFO (COMMAND_LINE, 'START_RECORD') <> 2) THEN 232 arch := 'vax'; 233 ELSE 234 arch := 'alpha'; 235 ENDIF; 236 POSITION (BEGINNING_OF (makefile_buf)); 237 COPY_TEXT ("target=" + arch + "-vms"); SPLIT_LINE; 238 COPY_TEXT ("out_file=aux-output.c"); SPLIT_LINE; ! 'arch'/'arch'.c 239 COPY_TEXT ("out_object_file=aux-output.o"); SPLIT_LINE; ! aux-output.obj 240 COPY_TEXT ("md_file=" + arch + ".md"); SPLIT_LINE; ! 'arch'/'arch'.md 241 COPY_TEXT ("tm_file=tm.h"); SPLIT_LINE; ! 'arch'/tm-vms.h 242 pat_replace ("@" & 243 SPAN("abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ#~0123456789") 244 & "@", ); ! strip `configure' dummy values 245ENDPROCEDURE; !configure_makefile 246!! 247 248PROCEDURE identify_compilers( ) 249 ! 250 ! Retrieve the list of supported compilers from Makefile.in, and put them 251 ! into file "compilers.list", one per line, for subsequent access from DCL. 252 ! 253 LOCAL range1; 254 255 ! Strip most comments from the makefile, to speed up subsequent processing. 256 POSITION (BEGINNING_OF (makefile_buf)); 257 pat_replace (LINE_BEGIN & "#" & REMAIN & LINE_END, ); 258 pat_replace ("$(exeext)", ); 259 pat_replace ("@all_compilers@", ); 260!# ! Convert directory references to VMS syntax (actually, just strip it). 261!# pat_replace (" $(srcdir)/", " "); 262 ! Look up the ``COMPILERS=cc1 xyzzy'' Makefile macro and put 263 ! its ``cc1 xyzzy'' value into the compilers buffer. 264 POSITION (BEGINNING_OF (complist_buf)); 265!#--at some point we may want to add this-- 266!# recursive_fetch_tag ("CCCP", "="); ! Include the preprocessor. 267!# POSITION (END_OF (complist_buf)); 268 recursive_fetch_tag ("COMPILERS", "="); 269 ! Convert all spaces into newlines, then remove any blank lines. 270 pat_replace (SPAN(" "), LINE_END); 271 pat_replace (LINE_BEGIN & LINE_END, ); 272ENDPROCEDURE; !identify_compilers 273!! 274 275PROCEDURE additional_compiler( cname, subdir ) 276 ! 277 ! Load Make-lang.in for compiler CNAME from SUBDIR and append it to the 278 ! end of Makefile.in's buffer. Add CNAME to the "compilers.list" buffer. 279 ! 280 ON_ERROR 281 ! Don't abort if user removes the supporting subdirectory for a 282 ! language she's not interested in. 283 [TPU$_OPENIN]: 284 MESSAGE ("Cannot load " + subdir + "/Make-lang.in for " 285 + '"' + cname + '"' + "; skipping it."); 286 RETURN; 287 ENDON_ERROR; 288 289 POSITION (END_OF (makefile_buf)); 290 SPLIT_LINE; ! Separate with a blank line. 291 READ_FILE ("[." + subdir + "]Make-lang.in"); ! Load Makefile fragment. 292 ! Make sure that $(xxx_OTH_SRCS) expands to empty string by renaming $(it) 293 pat_replace ("_OTH_SRCS)", "_OTH_SRCS_dummy_)"); 294 ! Convert subdirectory references into VMS syntax. 295 pat_replace ("$(srcdir)/" + subdir + "/", "[." + subdir + "]"); 296 297 ! Temporary? hack for cp/Make-lang.in's mishandling of "input.c". 298 IF (subdir = 'cp') THEN 299 pat_replace ("[.cp]input.c", ); ! Discard this text. 300 ENDIF; 301 302 ! Add this name to compilers.list. 303 POSITION (END_OF (complist_buf)); 304 COPY_TEXT (cname); 305 ! Make array entry indexed by compiler's file name; its value is arbitrary. 306 extra_compilers{cname} := subdir; 307ENDPROCEDURE; !additional_compiler 308!! 309 310PROCEDURE generate_option_file( tag_name, punct, outfile_name ) 311 ! 312 ! Produce a file listing the names of particular object files, for use 313 ! as input to the linker and also for use in finding source names by 314 ! make-cc1.com. Generally, any name suffix will be suppressed. 315 ! 316 LOCAL range1, range2; 317 318 POSITION (BEGINNING_OF (opt_file_buf)); 319 recursive_fetch_tag (tag_name, punct); 320 ! First fix up for subdirectory/Make-lang.in. 321 IF (pat_replace ("stamp-objlist" & (SPAN(" ")|LINE_END), " ") > 0) THEN 322 recursive_fetch_tag ("stamp-objlist", ":"); 323 ENDIF; 324 ! Now fix up a few things in the output buffer. 325 pat_replace ("Makefile" & (SPAN(" ")|LINE_END), " "); 326!# FILL (CURRENT_BUFFER, " ", 1, 80, 0); ! Condense things a bit. 327 pat_replace ("." & ("o"|"c"|"y") & ((SPAN(" ")&LINE_END)|LINE_END), LINE_END); 328 pat_replace ("." & ("o"|"c"|"y") & SPAN(" "), ","); 329 pat_replace (".h" & (SPAN(" ")|LINE_END), ".h,"); 330 ! Remove trailing commas, if present. 331 pat_replace ("," & ((SPAN(" ")&LINE_END)|LINE_END), LINE_END); 332 ! Get rid of spaces and blank lines. 333 pat_replace (SPAN(" "), LINE_END); 334 pat_replace (LINE_BEGIN & LINE_END, ); 335 ! Second fix up for subdirectory/Make-lang.in; 336 ! avoid "sticky defaults" when linker processes the resulting options file. 337 IF (extra_compilers{outfile_name - "-objs.opt"} <> TPU$K_UNSPECIFIED) THEN 338 POSITION (BEGINNING_OF (opt_file_buf)); 339 range1 := CREATE_RANGE (MARK (NONE), END_OF (CURRENT_BUFFER), NONE); 340 LOOP 341 range2 := SEARCH_QUIETLY (LINE_BEGIN | ",", FORWARD, EXACT, range1); 342 EXITIF (range2 = 0); 343 POSITION (BEGINNING_OF (range2)); 344 IF (CURRENT_CHARACTER = ",") THEN MOVE_HORIZONTAL (1); ENDIF; 345 ! If it's not already "[.subdir]name", explicitly make it "[]name". 346 IF (CURRENT_CHARACTER <> "[") THEN COPY_TEXT ("[]"); ENDIF; 347 MOVE_HORIZONTAL (1); 348 MODIFY_RANGE (range1, MARK (NONE), END_OF (range1)); 349 ENDLOOP; 350 ENDIF; 351 ! Now write the output file. 352 SET (OUTPUT_FILE, opt_file_buf, outfile_name); 353 WRITE_FILE (opt_file_buf); 354 ERASE (opt_file_buf); ! Clear buffer out for next opt_file pass. 355ENDPROCEDURE; !generate_option_file 356!! 357 358PROCEDURE recursive_fetch_tag( tag_n, punct ) 359 ! 360 ! Look up TAG_N, copy it to OPT_FILE_BUF, and then translate any $(...) 361 ! definitions that appear. The translation is put at the current point. 362 ! 363 LOCAL mark1, mark2, range1, tag_range, tag_string; 364 365 fetch_tag (tag_n, punct); 366 ! Substitute any makefile symbols $(...). 367 POSITION (BEGINNING_OF (CURRENT_BUFFER)); 368 LOOP 369 range1 := SEARCH_QUIETLY ("$(" & 370 SPAN("abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ#~0123456789") 371 & ")", FORWARD, EXACT); 372 EXITIF (range1 = 0); 373 POSITION (BEGINNING_OF (range1)); 374 MOVE_HORIZONTAL (2); ! Past opening "$(". 375 mark1 := MARK (NONE); 376 POSITION (END_OF (range1)); 377 MOVE_HORIZONTAL (-1); ! In front of closing ")". 378 mark2 := MARK (NONE); 379 tag_range := CREATE_RANGE (mark1, mark2, NONE); 380 POSITION (END_OF (range1)); 381 tag_string := STR (tag_range); 382 ERASE (range1); 383 fetch_tag (tag_string, "="); 384 POSITION (BEGINNING_OF (CURRENT_BUFFER)); 385 ENDLOOP; 386ENDPROCEDURE; !recursive_fetch_tag 387!! 388 389PROCEDURE fetch_tag( tag_n, punct ) 390 ! 391 ! Looks up the translation of a tag, and inserts it at the current location 392 ! in the buffer. 393 ! 394 LOCAL mark0, mark1, mark2, range2; 395 396 mark0 := MARK (NONE); ! Remember where we started; restore before return. 397 POSITION (BEGINNING_OF (makefile_buf)); 398 ! The tag definition always starts in the first column, and might have 399 ! optional space(es) before "=" or ":" punctuation. 400 range2 := SEARCH_QUIETLY (LINE_BEGIN & tag_n & ((SPAN(" ") & punct) | punct), 401 FORWARD, EXACT); 402 IF (range2 = 0) THEN 403 POSITION (mark0); 404 RETURN; 405 ENDIF; 406 POSITION (END_OF (range2)); 407 MOVE_HORIZONTAL (1); ! Move beyond "TAG=". 408 mark1 := MARK (NONE); 409 POSITION (BEGINNING_OF (range2)); 410 LOOP 411 MOVE_VERTICAL (1); 412 MOVE_HORIZONTAL (-2); 413 EXITIF (CURRENT_CHARACTER <> "\"); 414 ERASE_CHARACTER (1); 415 MOVE_HORIZONTAL (1); 416 ENDLOOP; 417 MOVE_HORIZONTAL (1); 418 mark2 := MARK (NONE); 419 range2 := CREATE_RANGE (mark1, mark2, NONE); 420 POSITION (mark0); 421 IF (LENGTH (range2) <> 0) THEN 422 COPY_TEXT (range2); 423 ENDIF; 424ENDPROCEDURE; !fetch_tag 425!! 426 427PROCEDURE pat_replace( oldstring, newstring ) 428 ! 429 ! Replace all occurrences of a pattern. 430 ! 431 LOCAL range1, range2, kill_it, count; 432 433 count := 0; 434 kill_it := (GET_INFO (newstring, 'TYPE') = UNSPECIFIED); ! Omitted arg. 435 range1 := CREATE_RANGE (BEGINNING_OF (CURRENT_BUFFER), 436 END_OF (CURRENT_BUFFER), NONE); 437 LOOP 438 range2 := SEARCH_QUIETLY (oldstring, FORWARD, EXACT, range1); 439 EXITIF (range2 = 0); 440 count := count + 1; 441 POSITION (BEGINNING_OF (range2)); 442 ERASE (range2); 443 IF (newstring = LINE_END) THEN 444 SPLIT_LINE; 445 ELSE IF (NOT kill_it) THEN 446 COPY_TEXT (newstring); 447 ENDIF; ENDIF; 448 MODIFY_RANGE (range1, MARK (NONE), END_OF (range1)); 449 ENDLOOP; 450 RETURN count; 451ENDPROCEDURE; !pat_replace 452!! 453 454! 455! This is the main routine. 456! 457process_makefile (); 458process_objc_lib (); !this uses a different makefile 459QUIT; ! All done; don't write any modified buffers. 460!! 461$ echo "" 462$! 463$! Remove excessive versions of the option files... 464$! 465$ purge *.opt,*.list 466$! 467$! 468$! 469$ if f$search("config.status") .nes. "" then delete config.status.* 470$ create config.status 471$ open/append ifile$ config.status 472$ write ifile$ "Links are now set up for use with a ''arch' running VMS." 473$ close ifile$ 474$ type config.status 475$ echo "" 476$! 477$ exit 478$ 479$! 480$! Construct a header file based on subdirectory contents 481$! 482$make_lang_incl: subroutine 483$ if f$search(p1).nes."" then delete 'p1';* 484$ create 'p1' !empty file with ordinary text-file attributes 485$ open/Append ifile$ 'p1' 486$ write ifile$ "/* ''p1' */" 487$ hfile = f$search("[]''p1'") 488$ topdir = f$parse(hfile,,,"DIRECTORY") - "]" 489$lang_incl_loop: 490$ hfile = f$search("[.*]lang-''p1'") 491$ if hfile.eqs."" then goto lang_incl_done 492$ dir = f$parse(hfile,,,"DIRECTORY") - "]" 493$! convert absolute path to relative one, yielding "[.subdir]" 494$ dir = "[" + f$edit(dir - topdir,"LOWERCASE") + "]" 495$ write ifile$ "#include ""''dir'lang-''p1'""" 496$ goto lang_incl_loop 497$lang_incl_done: 498$ close ifile$ 499$ echo "Created `''p1''." 500$ endsubroutine !make_lang_incl 501