Category : Miscellaneous Language Source Code
Archive   : BRIEFSRC.ZIP
Filename : COMPILE.M

 
Output of file : COMPILE.M contained in archive : BRIEFSRC.ZIP
;**
;** 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" environment variable to
;** determine what to do with any given file. If no "BC"
;** 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" 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.
;**

(macro compile_it
(
(string extension
command
)
(inq_names NULL extension)
(= command (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))))
)
(cc command extension)
)
;else
(execute_macro command)
)
)
;else
(
(if (== extension "m")
(cm)
;else
(if (== extension "asm")
(cc "masm %s\\;" extension)
;else
(if (== extension "c")
(cc "cc -c %s.c" extension)
;else
(error "Can't compile: no BC%s environment variable." (upper extension))
)
)
)
)
)
)
)

;**
;** 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"))
)
(return 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, which works with the Wizard C compiler and a few others. 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.
)
;**
;** We get the name of the file from inq_names (the extension is
;** put in the command_line variable so we didn't have to declare too
;** many strings) and check to see if it is a C file.
;**

(if (! (get_parm 1 passes))
(= passes "c")
)
(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 "C Errors" 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)
(= ret_code (dos command_line 0))
)
)

;**
;** Finally, we restore the old directory. If the
;** compilation did not succeed, the next_error macro
;** is called to place the cursor under the error.
;**
;** Otherwise, the temporary file is deleted and a
;** message is printed.
;**

(if (> ret_code 0)
(next_error)
;else
(
(if (|| (< ret_code 0) (|| (! _check_warnings) (! (next_error 2))))
(
(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
(
(string command_line)

(get_parm 0 command_line)
(= command_line (trim (ltrim command_line)))

(if (strlen command_line)
(= command_line (+ " " command_line))
)
(= command_line (+ (+ "cm" command_line) " %s"))

(if (! (cc command_line "m"))
(
(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.")
)
)
)
)


  3 Responses to “Category : Miscellaneous Language Source Code
Archive   : BRIEFSRC.ZIP
Filename : COMPILE.M

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/