Un-ignored: the dev drive is the ground truth the restoration and emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio content). Kept in-repo for the pod-owner community. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
398 lines
12 KiB
Objective-C
398 lines
12 KiB
Objective-C
;**
|
|
;** BRIEF -- Basic Reconfigurable Interactive Editing Facility
|
|
;**
|
|
;** Written by Dave Nanian and Michael Strickman.
|
|
;**
|
|
|
|
;**
|
|
;** compile.m:
|
|
;**
|
|
;** This file contains all of the standard BRIEF macros for compiling
|
|
;** files.
|
|
;**
|
|
;** Revision history:
|
|
;** -----------------
|
|
|
|
(extern add_to_path
|
|
next_error
|
|
_check_warnings
|
|
)
|
|
|
|
;**
|
|
;** compile_it:
|
|
;**
|
|
;** This function automatically compiles the file in the current
|
|
;** buffer. It uses the "BC<extension>" environment variable to
|
|
;** determine what to do with any given file. If no "BC<extension>"
|
|
;** environment variable exists for the specific file extension being
|
|
;** compiled, compile_it checks to see if it's ".c", ".m" or ".asm". If
|
|
;** it's a macro file the "cm" macro is executed; if it's a C file, a
|
|
;** generic "cc" command is used, and if it's an ASM file, the Macro
|
|
;** Assembler is invoked.
|
|
;**
|
|
;** Other compilers can be supported very easily. Simply set a
|
|
;** "BC<extension>" environment variable to the "pass string" you
|
|
;** want to use. For example, if you wanted to call the (fictitious)
|
|
;** UnderWare C compiler, which has two passes called "under" and "ware",
|
|
;** you'd use the command:
|
|
;**
|
|
;** set bcc="under %s;ware %s"
|
|
;**
|
|
;** You must place the pass string in quotes. If you don't, compile_it
|
|
;** calls a macro named whatever is in the pass string. So, for example,
|
|
;** if you accidently set your pass string using the command:
|
|
;**
|
|
;** set bcc=under %s;ware %s
|
|
;**
|
|
;** compile_it would call a macro named "under %s;ware %s". This probably
|
|
;** isn't what you want -- but this feature can be useful if you want to
|
|
;** run some sort of custom macro for the file extension (compile_it does
|
|
;** this when compiling cm files).
|
|
;**
|
|
;** Also note that DOS requires you to double any % characters that
|
|
;** appear in a batch file. So if you were setting the BCC variable in
|
|
;** your autoexec, you would use the line:
|
|
;**
|
|
;** set bcc="under %%s;ware %%s"
|
|
;**
|
|
;** Each pass begins with the name of the executable program that does
|
|
;** that compilation pass. That is followed by the a space, the special
|
|
;** string "%s", which is replaced by the filename (with NO extension),
|
|
;** and the multiple pass separation character ";". If you want to put
|
|
;** a ";" in your pass string, use "\;".
|
|
;**
|
|
;** These special characters are very important -- don't forget them!
|
|
;** Remember that the special "%s" string is only replaced by the filename,
|
|
;** not the filename and the extension. Up to two of these can be specified
|
|
;** in any given pass. If your compiler requires the extension as well,
|
|
;** place it after this string (e.g. "cc -c %s.c").
|
|
;**
|
|
;** If you want to pass options to your compiler, you can place them
|
|
;** either before or after the "%s". Placing them before puts the option
|
|
;** before the filename, and vice versa.
|
|
;**
|
|
;** If you compiler doesn't return an error code, put an exclamation
|
|
;** point in front of the first pass string (either inside or outside the
|
|
;** quotes); this will override the current warnings_only setting and
|
|
;** automatically check for errors in the compiler output.
|
|
;**
|
|
|
|
(macro compile_it
|
|
(
|
|
(string extension
|
|
command
|
|
)
|
|
(inq_names NULL extension)
|
|
(= command (trim (ltrim (inq_environment (+ "BC" (upper extension))))))
|
|
|
|
(if (!= command "")
|
|
(
|
|
(if (index command "\"")
|
|
(
|
|
(int loc)
|
|
|
|
(while (= loc (index command "\""))
|
|
(= command (+ (substr command 1 (- loc 1)) (substr command (+ loc 1))))
|
|
)
|
|
(if (== "!" (substr command 1 1))
|
|
(returns (cc (substr command 2) extension 1))
|
|
;else
|
|
(returns (cc command extension))
|
|
)
|
|
)
|
|
;else
|
|
(if (== "!" (substr command 1 1))
|
|
(returns (execute_macro (substr command 2) 1))
|
|
;else
|
|
(returns (execute_macro command _check_warnings))
|
|
)
|
|
)
|
|
)
|
|
;else
|
|
(
|
|
(if (== extension "m")
|
|
(returns (cm))
|
|
;else
|
|
(if (== extension "asm")
|
|
(returns (cc "masm %s\\;" extension))
|
|
;else
|
|
(if (== extension "c")
|
|
(returns (cc "cc -c %s.c" extension))
|
|
;else
|
|
(
|
|
(error "Can't compile: no BC%s environment variable." (upper extension))
|
|
(returns -1)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** warnings_only:
|
|
;**
|
|
;** This macro toggles whether or not errors are searched for when a
|
|
;** compile is done and the compiler returns "no errors". Note that its
|
|
;** value is saved in the state file.
|
|
;**
|
|
|
|
(macro warnings_only
|
|
(
|
|
(int ret_code
|
|
previous_value
|
|
)
|
|
(= previous_value _check_warnings)
|
|
|
|
(if (! (= ret_code (get_parm 0 _check_warnings)))
|
|
(= _check_warnings (! _check_warnings))
|
|
)
|
|
(if (|| (! ret_code) (== (inq_called) ""))
|
|
(message "Compile warning detection %s." (if _check_warnings "on" "off"))
|
|
)
|
|
(returns previous_value)
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** cc:
|
|
;**
|
|
;** This routine compiles the file in the current buffer using the
|
|
;** passed "pass string" and the BRIEF DOS command. It needs a lot
|
|
;** of memory to run (you should have at least 256K and start with -M20)
|
|
;** so be careful!
|
|
;**
|
|
;** The "pass string" passed should be of the form:
|
|
;**
|
|
;** pass_1 %s;pass_2 %s;...pass_n %s
|
|
;**
|
|
;** The optional second parameter is an extended file type -- this is
|
|
;** used by the "cm" macro, and to compile other types of files (e.g.
|
|
;** .asm).
|
|
;**
|
|
;** If no pass string is specified, it defaults to a generic "cc"
|
|
;** command. If no extension is specified, it defaults to "c".
|
|
;**
|
|
|
|
(macro cc
|
|
(
|
|
(string file_name ;** The name of the file we're compiling.
|
|
command_line ;** The compile command line.
|
|
path ;** The path of the file we're compiling.
|
|
old_path ;** The original path we were on.
|
|
passes ;** The names of the passes.
|
|
error_file ;** The file to put error information in.
|
|
)
|
|
(int loc ;** Generic index place holder.
|
|
ret_code ;** Return code from DOS.
|
|
buffer_id ;** Buffer ID of error buffer.
|
|
check_warnings ;** Examine resule of compile for errors?
|
|
)
|
|
;**
|
|
;** We get the name of the file from inq_names (the extension is
|
|
;** put in the command_line variable so we don't have to declare too
|
|
;** many strings) and check to see if it is a C file.
|
|
;**
|
|
|
|
(if (! (get_parm 1 passes))
|
|
(= passes "c")
|
|
)
|
|
(if (! (get_parm 2 check_warnings))
|
|
(= check_warnings _check_warnings)
|
|
)
|
|
(inq_names path command_line file_name)
|
|
(= ret_code 1)
|
|
|
|
(if (== command_line passes)
|
|
(
|
|
;**
|
|
;** If the file has been modified, we want to make sure the
|
|
;** current version gets compiled, so we write it to disk.
|
|
;**
|
|
;** Note that if the user does not specify a pass string, it
|
|
;** defaults to a generic "cc" command, which works with the
|
|
;** Wizard C compiler (and a few others).
|
|
;**
|
|
|
|
(if (! (get_parm 0 passes))
|
|
(= passes "cc -c %s.c")
|
|
)
|
|
(if (inq_modified)
|
|
(
|
|
(int old_msg_level)
|
|
|
|
(= old_msg_level (inq_msg_level))
|
|
(set_msg_level 0)
|
|
(= ret_code (write_buffer))
|
|
(set_msg_level old_msg_level)
|
|
)
|
|
)
|
|
(if (>= ret_code 0)
|
|
(
|
|
;**
|
|
;** Now we parse the filename off the path string,
|
|
;** making sure to handle the possible presence of forward
|
|
;** and backward slash characters. We then replace the
|
|
;** file_name's ".c" with ".err" for redirection purposes.
|
|
;**
|
|
|
|
(= path (substr path 1 (rindex path (substr path 3 1))))
|
|
|
|
(if (> (strlen path) 3)
|
|
(= path (substr path 1 (- (strlen path) 1)))
|
|
)
|
|
(= file_name (substr file_name 1 (- (index file_name ".") 1)))
|
|
(= error_file (+ file_name ".err"))
|
|
(= ret_code 0)
|
|
|
|
;**
|
|
;** We want the .obj file to end up in the file's
|
|
;** directory, so we change to the directory where the
|
|
;** file is, saving the current directory. We also make
|
|
;** the file's drive the default drive.
|
|
;**
|
|
|
|
(getwd "" command_line)
|
|
(getwd path old_path)
|
|
(= old_path (+ (substr command_line 1 1) (substr old_path 2)))
|
|
(cd path)
|
|
(cd (substr path 1 2))
|
|
|
|
;**
|
|
;** If there is already a buffer for the error file, we
|
|
;** "create" it (create_buffer returns the ID of a buffer
|
|
;** that already existed) and then delete it immediately.
|
|
;** Note that under some very obscure circumstances, the
|
|
;** create_buffer call could fail. If it does, it'll
|
|
;** return 0, which is an invalid buffer id. We check for
|
|
;** this case since delete_buffer does not.
|
|
;**
|
|
|
|
(if (= buffer_id (create_buffer "Error File" error_file 1))
|
|
(delete_buffer buffer_id)
|
|
)
|
|
|
|
;**
|
|
;** This loop goes through each pass of the compiler,
|
|
;** checks to see if the return code was OK, and, if so,
|
|
;** continues along. If an error occurs, the loop exits
|
|
;** immediately.
|
|
;**
|
|
|
|
(while (&& (! ret_code) (strlen passes))
|
|
(
|
|
(if (= loc (search_string "[~\\\\]\\c;" passes))
|
|
(
|
|
(= command_line (substr passes 1 (- loc 1)))
|
|
(= passes (substr passes (+ loc 1)))
|
|
)
|
|
;else
|
|
(
|
|
(= command_line passes)
|
|
(= passes "")
|
|
)
|
|
)
|
|
(+= command_line (+ " >&" error_file))
|
|
|
|
(while (= loc (search_string "\\\\;" command_line))
|
|
(= command_line (+ (substr command_line 1 (- loc 1)) (substr command_line (+ loc 1))))
|
|
)
|
|
(sprintf command_line command_line file_name file_name file_name file_name file_name file_name file_name)
|
|
(message command_line)
|
|
|
|
(if (> (= ret_code (dos command_line 0)) 0)
|
|
(next_error)
|
|
;else
|
|
(if (&& (== ret_code 0) check_warnings)
|
|
(= ret_code (next_error 2))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
;**
|
|
;** Finally, we restore the old directory. If the
|
|
;** compilation did not succeed, the next_error macro
|
|
;** was called to place the cursor under the error.
|
|
;**
|
|
;** Otherwise, the temporary file is deleted and a
|
|
;** message is printed.
|
|
;**
|
|
|
|
(if (<= ret_code 0)
|
|
(
|
|
(del error_file)
|
|
|
|
(if (== ret_code 0)
|
|
(message "Compilation successful.")
|
|
)
|
|
)
|
|
)
|
|
(cd (substr old_path 3))
|
|
(cd (substr old_path 1 2))
|
|
)
|
|
)
|
|
)
|
|
;else
|
|
(error "Current buffer is not a .%s file." passes)
|
|
)
|
|
(returns ret_code)
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** cm:
|
|
;**
|
|
;** This macro compiles the macro in the current buffer (if there is one).
|
|
;** If the compilation was successful, the macro is re-loaded (or loaded, as
|
|
;** the case may be). If the compilation failed, the errorfix macro
|
|
;** is used to locate the problem in the .m file.
|
|
;**
|
|
;** Note that the "cc" macro is used to do most of the work. This macro
|
|
;** merely calls "cc" with the parameters required for compilation of a
|
|
;** macro file, then loads the file if the compilation was successful.
|
|
;**
|
|
|
|
(macro cm
|
|
(
|
|
(int check_warnings
|
|
curr_parm
|
|
)
|
|
(string command_line)
|
|
|
|
(= curr_parm 10)
|
|
|
|
(while (&& (> curr_parm 0) (! (get_parm curr_parm check_warnings)))
|
|
(-- curr_parm)
|
|
)
|
|
(if (> curr_parm 0)
|
|
(
|
|
(get_parm 0 command_line)
|
|
|
|
(if (strlen (= command_line (trim (ltrim command_line))))
|
|
(= command_line (+ " " command_line))
|
|
)
|
|
)
|
|
)
|
|
(= command_line (+ (+ "cm" command_line) " %s"))
|
|
|
|
(if (! (cc command_line "m" check_warnings))
|
|
(
|
|
(int old_msg_level)
|
|
|
|
(string name)
|
|
|
|
(inq_names name)
|
|
(= name (substr name 1 (- (strlen name) 2)))
|
|
(= old_msg_level (inq_msg_level))
|
|
(set_msg_level 3)
|
|
(delete_macro name)
|
|
(set_msg_level old_msg_level)
|
|
(load_macro name)
|
|
(message "Macro compiled and loaded.")
|
|
)
|
|
)
|
|
)
|
|
)
|