Next: , Previous: C Macros, Up: Operations


6.2.8 Changing Scm

When writing C-code for SCM, a precaution is recommended. If your routine allocates a non-cons cell which will not be incorporated into a SCM object which is returned, you need to make sure that a SCM variable in your routine points to that cell as long as part of it might be referenced by your code.

In order to make sure this SCM variable does not get optimized out you can put this assignment after its last possible use:

     SCM_dummy1 = foo;

or put this assignment somewhere in your routine:

     SCM_dummy1 = (SCM) &foo;

SCM_dummy variables are not currently defined. Passing the address of the local SCM variable to any procedure also protects it. The procedure scm_protect_temp is provided for this purpose.

— Function: void scm_protect_temp (SCM *ptr)

Forces the SCM object ptr to be saved on the C-stack, where it will be traced for GC.

Also, if you maintain a static pointer to some (non-immediate) SCM object, you must either make your pointer be the value cell of a symbol (see errobj for an example) or (permanently) add your pointer to sys_protects using:

— Function: SCM scm_gc_protect (SCM obj)

Permanently adds obj to a table of objects protected from garbage collection. scm_gc_protect returns obj.

To add a C routine to scm:

  1. choose the appropriate subr type from the type list.
  2. write the code and put into scm.c.
  3. add a make_subr or make_gsubr call to init_scm. Or put an entry into the appropriate iproc structure.

To add a package of new procedures to scm (see crs.c for example):

  1. create a new C file (foo.c).
  2. at the front of foo.c put declarations for strings for your procedure names.
              static char s_twiddle_bits[]="twiddle-bits!";
              static char s_bitsp[]="bits?";
    
  3. choose the appropriate subr types from the type list in code.doc.
  4. write the code for the procedures and put into foo.c
  5. create one iproc structure for each subr type used in foo.c
              static iproc subr3s[]= {
                      {s_twiddle-bits,twiddle-bits},
                      {s_bitsp,bitsp},
                      {0,0} };
    
  6. create an init_<name of file> routine at the end of the file which calls init_iprocs with the correct type for each of the iprocs created in step 5.
              void init_foo()
              {
                init_iprocs(subr1s, tc7_subr_1);
                init_iprocs(subr3s, tc7_subr_3);
              }
    

    If your package needs to have a finalization routine called to free up storage, close files, etc, then also have a line in init_foo like:

              add_final(final_foo);
    

    final_foo should be a (void) procedure of no arguments. The finals will be called in opposite order from their definition.

    The line:

              add_feature("foo");
    

    will append a symbol 'foo to the (list) value of slib:features.

  7. put any scheme code which needs to be run as part of your package into Ifoo.scm.
  8. put an if into Init5e7.scm which loads Ifoo.scm if your package is included:
              (if (defined? twiddle-bits!)
                  (load (in-vicinity (implementation-vicinity)
                                     "Ifoo"
                                     (scheme-file-suffix))))
    

    or use (provided? 'foo) instead of (defined? twiddle-bits!) if you have added the feature.

  9. put documentation of the new procedures into foo.doc
  10. add lines to your Makefile to compile and link SCM with your object file. Add a init_foo\(\)\; to the INITS=... line at the beginning of the makefile.

These steps should allow your package to be linked into SCM with a minimum of difficulty. Your package should also work with dynamic linking if your SCM has this capability.

Special forms (new syntax) can be added to scm.

  1. define a new MAKISYM in scm.h and increment NUM_ISYMS.
  2. add a string with the new name in the corresponding place in isymnames in repl.c.
  3. add case clause to ceval() near i_quasiquote (in eval.c).

New syntax can now be added without recompiling SCM by the use of the procedure->syntax, procedure->macro, procedure->memoizing-macro, and defmacro. For details, See Syntax.