1 /* $Header$ */
2 
3 /*
4  *   Copyright (c) 1999, 2002 Michael J. Roberts.  All Rights Reserved.
5  *
6  *   Please see the accompanying license file, LICENSE.TXT, for information
7  *   on using and copying this software.
8  */
9 /*
10 Name
11   tcmake.h - TADS 3 Compiler "Make" Engine
12 Function
13   The "Make" engine doesn't have a main program entrypoint; instead,
14   this class is meant to make it easy to write a main entrypoint.  The
15   program main function must parse command line arguments, read a config
16   file, get the parameters from a dialog, or use whatever other OS-specific
17   mechanism it desires to obtain the compilation parameters.  Given the
18   parameters, this class makes it easy to compile the program.
19 
20   To compile a TADS 3 program, create a CTcMake object, then perform
21   the following steps:
22 
23    - set the build options (source/symbol/object paths, debug mode,
24      error options, etc)
25 
26    - add a module object for each source file
27 
28    - set the image file name
29 
30    - invoke build()
31 
32 Notes
33 
34 Modified
35   07/11/99 MJRoberts  - Creation
36 */
37 
38 #ifndef TCMAKE_H
39 #define TCMAKE_H
40 
41 #include "t3std.h"
42 
43 /* ------------------------------------------------------------------------ */
44 /*
45  *   String buffer object
46  */
47 class CTcMakeStr
48 {
49 public:
CTcMakeStr()50     CTcMakeStr() { buf_ = 0; }
~CTcMakeStr()51     ~CTcMakeStr() { lib_free_str(buf_); }
52 
53     /* get the string */
get()54     const textchar_t *get() const { return (buf_ != 0 ? buf_ : ""); }
55 
56     /* set the string */
set(const textchar_t * str)57     void set(const textchar_t *str)
58         { set(str, str == 0 ? 0 : strlen(str)); }
set(const textchar_t * str,size_t len)59     void set(const textchar_t *str, size_t len)
60     {
61         lib_free_str(buf_);
62         buf_ = lib_copy_str(str, len);
63     }
64 
65     /* check to see if the string has been set - returns true if so */
is_set()66     int is_set() const { return buf_ != 0; }
67 
68 private:
69     /* our string buffer */
70     textchar_t *buf_;
71 };
72 
73 /* ------------------------------------------------------------------------ */
74 /*
75  *   Module source types.  This tells us how we resolved the given name of
76  *   the module to a filename.
77  */
78 enum tcmod_source_t
79 {
80     /* "normal" - the module is found on the ordinary search path */
81     TCMOD_SOURCE_NORMAL = 1,
82 
83     /* the module comes from the system library */
84     TCMOD_SOURCE_SYSLIB = 2,
85 
86     /* the module comes from a specific user library */
87     TCMOD_SOURCE_LIB = 3
88 };
89 
90 
91 /*
92  *   Module list entry.  Each module is represented by one of these
93  *   entries.
94  *
95  *   A module defines a source file and its directly derived files: a
96  *   symbol file, and an object file.
97  */
98 class CTcMakeModule
99 {
100 public:
CTcMakeModule()101     CTcMakeModule()
102     {
103         /* not in a list yet */
104         nxt_ = 0;
105 
106         /* presume we won't need recompilation */
107         needs_sym_recompile_ = FALSE;
108         needs_obj_recompile_ = FALSE;
109 
110         /* by default, include all modules in the compilation */
111         exclude_ = FALSE;
112 
113         /* presume the module is from the ordinary search path */
114         source_type_ = TCMOD_SOURCE_NORMAL;
115     }
~CTcMakeModule()116     ~CTcMakeModule() { }
117 
118     /* get/set the next list entry */
get_next()119     CTcMakeModule *get_next() const { return nxt_; }
set_next(CTcMakeModule * nxt)120     void set_next(CTcMakeModule *nxt) { nxt_ = nxt; }
121 
122     /*
123      *   Set the module name.  This will fill in the source, symbol, and
124      *   object filenames with names derived from the source name if those
125      *   names are not already defined.  If any of the names are already
126      *   explicitly defined, this won't affect them.
127      */
128     void set_module_name(const textchar_t *modname);
129 
130     /*
131      *   Get/set the original module name.  The original module name is the
132      *   name as it was given on the command line, in the library source, or
133      *   wherever else it was originally specified.  This is the name before
134      *   conversion to local filename conventions and before resolving to a
135      *   specific directory; this is useful in debugging records because it
136      *   can be more portable than the resolved filename.
137      */
get_orig_name()138     const textchar_t *get_orig_name() const { return orig_name_.get(); }
set_orig_name(const textchar_t * name)139     void set_orig_name(const textchar_t *name) { orig_name_.set(name); }
140 
141     /* get/set the source filename */
get_source_name()142     const textchar_t *get_source_name() const { return src_.get(); }
set_source_name(const textchar_t * fname)143     void set_source_name(const textchar_t *fname) { src_.set(fname); }
144 
145     /*
146      *   Get/set the "search" source filename.  This is the filename we use
147      *   when we're trying to find the file in a search path.  In some cases,
148      *   this might not be identical to the given filename; for example, when
149      *   we assume a relative path for a file, we won't use the assumed
150      *   relative path in the search name, since we only assumed the relative
151      *   path because we thought that would tell us where the file is.
152      */
get_search_source_name()153     const textchar_t *get_search_source_name() const
154     {
155         /*
156          *   if there's an explicit search name, use it; otherwise, simply
157          *   use the normal source name
158          */
159         if (search_src_.get() != 0 && search_src_.get()[0] != '\0')
160             return search_src_.get();
161         else
162             return src_.get();
163     }
set_search_source_name(const textchar_t * fname)164     void set_search_source_name(const textchar_t *fname)
165         { search_src_.set(fname); }
166 
167     /* get/set the symbol filename */
get_symbol_name()168     const textchar_t *get_symbol_name() const { return sym_.get(); }
set_symbol_name(const textchar_t * fname)169     void set_symbol_name(const textchar_t *fname) { sym_.set(fname); }
170 
171     /* get/set the object filename */
get_object_name()172     const textchar_t *get_object_name() const { return obj_.get(); }
set_object_name(const textchar_t * fname)173     void set_object_name(const textchar_t *fname) { obj_.set(fname); }
174 
175     /* get/set the symbol file recompilation flag */
get_needs_sym_recompile()176     int get_needs_sym_recompile() const { return needs_sym_recompile_; }
set_needs_sym_recompile(int flag)177     void set_needs_sym_recompile(int flag) { needs_sym_recompile_ = flag; }
178 
179     /* get/set the object file recompilation flag */
get_needs_obj_recompile()180     int get_needs_obj_recompile() const { return needs_obj_recompile_; }
set_needs_obj_recompile(int flag)181     void set_needs_obj_recompile(int flag) { needs_obj_recompile_ = flag; }
182 
183     /* get/set the exclusion flag */
is_excluded()184     int is_excluded() const { return exclude_; }
set_excluded(int exc)185     void set_excluded(int exc) { exclude_ = exc; }
186 
187     /* get/set the library member URL */
get_url()188     const char *get_url() const { return url_.get(); }
set_url(const char * url)189     void set_url(const char *url) { url_.set(url); }
190 
191     /* get the module's source type */
get_source_type()192     tcmod_source_t get_source_type() const { return source_type_; }
193 
194     /* set the module's source to the system library */
set_from_syslib()195     void set_from_syslib() { source_type_ = TCMOD_SOURCE_SYSLIB; }
196 
197     /*
198      *   set the module's source to the given library, specified via
199      *   URL-style library path (so a module in library 'bar' that was in
200      *   turn in library 'foo' will have library path 'foo/bar')
201      */
set_from_lib(const textchar_t * libname,const textchar_t * url)202     void set_from_lib(const textchar_t *libname, const textchar_t *url)
203     {
204         /* save the library's name and URL */
205         lib_name_.set(libname);
206         lib_url_.set(url);
207 
208         /* remember that we're from a library */
209         source_type_ = TCMOD_SOURCE_LIB;
210     }
211 
212     /* get our library URL */
get_from_lib()213     const textchar_t *get_from_lib() const { return lib_name_.get(); }
214 
215 protected:
216     /* next entry in the list */
217     CTcMakeModule *nxt_;
218 
219     /* source filename */
220     CTcMakeStr src_;
221 
222     /* path-searching source filename */
223     CTcMakeStr search_src_;
224 
225     /* the original name, before local file path resolution */
226     CTcMakeStr orig_name_;
227 
228     /* symbol filename */
229     CTcMakeStr sym_;
230 
231     /* object filename */
232     CTcMakeStr obj_;
233 
234     /* flag: requires recompilation of symbol/object file */
235     int needs_sym_recompile_;
236     int needs_obj_recompile_;
237 
238     /*
239      *   flag: module is excluded from compilation (this is set when a
240      *   module is included by a library and then explicitly excluded from
241      *   the build)
242      */
243     int exclude_;
244 
245     /*
246      *   Library member URL - this is the URL-style string naming the module
247      *   if it is a member of a library.  This is not used except for
248      *   library members.  This value is formed by adding the library prefix
249      *   for each enclosing sublibrary (not including the top-level library,
250      *   included from the command line or equivalent) to the "source:"
251      *   variable value that included this module from its library.  A
252      *   library prefix is formed by adding the library prefix for each
253      *   enclosing sublibrary to the "library:" variable name that included
254      *   the library, plus a terminating "/".
255      */
256     CTcMakeStr url_;
257 
258     /* the name of the enclosing library */
259     CTcMakeStr lib_name_;
260 
261     /*
262      *   library URL - this is the URL to our enclosing library, not
263      *   including the module name itself
264      */
265     CTcMakeStr lib_url_;
266 
267     /* the source of the module */
268     enum tcmod_source_t source_type_;
269 };
270 
271 /* ------------------------------------------------------------------------ */
272 /*
273  *   Search path list entry - each entry in this list is a directory that
274  *   we'll search for a certain type of file (#include files, source files)
275  */
276 class CTcMakePath
277 {
278 public:
CTcMakePath(const textchar_t * path)279     CTcMakePath(const textchar_t *path)
280     {
281         /* remember the path */
282         path_.set(path);
283 
284         /* we're not in a list yet */
285         nxt_ = 0;
286     }
287 
288     /* get/set the path */
get_path()289     const textchar_t *get_path() const { return path_.get(); }
set_path(const textchar_t * path)290     void set_path(const textchar_t *path) { path_.set(path); }
291 
292     /* get/set the next list entry */
get_next()293     CTcMakePath *get_next() const { return nxt_; }
set_next(CTcMakePath * nxt)294     void set_next(CTcMakePath *nxt) { nxt_ = nxt; }
295 
296 protected:
297     /* our path string */
298     CTcMakeStr path_;
299 
300     /* next include path in the list */
301     CTcMakePath *nxt_;
302 };
303 
304 
305 /* ------------------------------------------------------------------------ */
306 /*
307  *   Preprocessor symbol definition or undefinition item
308  */
309 class CTcMakeDef
310 {
311 public:
CTcMakeDef(const textchar_t * sym,const textchar_t * expan,int is_def)312     CTcMakeDef(const textchar_t *sym, const textchar_t *expan, int is_def)
313     {
314         /* remember the symbol and its expansion */
315         sym_.set(sym);
316         expan_.set(expan);
317 
318         /* remember whether it's a definition or un-definition */
319         is_def_ = (is_def != 0);
320 
321         /* not in a list yet */
322         nxt_ = 0;
323     }
324 
325     /* get my symbol */
get_sym()326     const textchar_t *get_sym() const { return sym_.get(); }
327 
328     /* get my expansion text */
get_expan()329     const textchar_t *get_expan() const { return expan_.get(); }
330 
331     /* get my define/undefine flag */
is_def()332     int is_def() const { return is_def_ != 0; }
333 
334     /* get/set the next list entry */
get_next()335     CTcMakeDef *get_next() const { return nxt_; }
set_next(CTcMakeDef * nxt)336     void set_next(CTcMakeDef *nxt) { nxt_ = nxt; }
337 
338 protected:
339     /* next in the list */
340     CTcMakeDef *nxt_;
341 
342     /* the symbol to define or undefine */
343     CTcMakeStr sym_;
344 
345     /* the expansion text */
346     CTcMakeStr expan_;
347 
348     /* flag: true -> define the symbol, false -> undefine it */
349     unsigned int is_def_ : 1;
350 };
351 
352 
353 /* ------------------------------------------------------------------------ */
354 /*
355  *   The program maintenance facility class.  The program main entrypoint
356  *   constructs one of these objects, sets its parameters, then calls the
357  *   "build()" entrypoint to carry out the build instructions.
358  *
359  *   The caller should not initialize or use compiler globals.  This
360  *   object owns the compiler globals, and will create and destroy
361  *   compiler globals in the course of its processing.
362  */
363 class CTcMake
364 {
365 public:
366     CTcMake();
367     ~CTcMake();
368 
369     /*
370      *   Set the default source file character set.  Source and header
371      *   files that don't specify a character set (using a #charset
372      *   directive at the very start of the file) will be read using this
373      *   character set.  If this isn't specified, we'll use the default
374      *   character set obtained from the OS.
375      */
set_source_charset(const textchar_t * charset)376     void set_source_charset(const textchar_t *charset)
377     {
378         /* delete any previous character set string */
379         lib_free_str(source_charset_);
380 
381         /* store the new character set name */
382         source_charset_ = lib_copy_str(charset);
383     }
384 
385     /*
386      *   turn on/off source-level debugging - we'll generate the extra
387      *   information necessary for debugging the program
388      */
set_debug(int debug)389     void set_debug(int debug) { debug_ = debug; }
390 
391     /* set preprocess-only mode */
set_pp_only(int pp_only)392     void set_pp_only(int pp_only) { pp_only_ = pp_only; }
393 
394     /* set list-include-files mode */
set_list_includes(int f)395     void set_list_includes(int f) { list_includes_mode_ = f; }
396 
397     /* set "clean" mode */
set_clean_mode(int f)398     void set_clean_mode(int f) { clean_mode_ = f; }
399 
400     /*
401      *   set test reporting mode - in this mode, we suppress path names in
402      *   filenames in progress reports, so that the output is independent of
403      *   local path conventions
404      */
set_test_report_mode(int flag)405     void set_test_report_mode(int flag) { test_report_mode_ = flag; }
406 
407     /* set quoted filenames mode for error messages */
set_err_quoted_fnames(int flag)408     void set_err_quoted_fnames(int flag) { quoted_fname_mode_ = flag; }
409 
410     /*
411      *   turn on/off linking - by default, we'll compile and link, but the
412      *   linking phase can be turned off so we just compile sources to
413      *   object files
414      */
set_do_link(int do_link)415     void set_do_link(int do_link) { do_link_ = do_link; }
416 
417     /*
418      *   turn on preinit mode - by default, we'll run preinit if and only
419      *   if we're not in debug mode
420      */
set_preinit(int preinit)421     void set_preinit(int preinit)
422     {
423         preinit_ = preinit;
424         explicit_preinit_ = TRUE;
425     }
426 
427     /* turn verbose error messages on or off */
set_verbose(int verbose)428     void set_verbose(int verbose) { verbose_ = verbose; }
429 
430     /* turn error number display on or off */
set_show_err_numbers(int show)431     void set_show_err_numbers(int show) { show_err_numbers_ = show; }
432 
433     /* turn all warning messages on or off */
set_warnings(int show)434     void set_warnings(int show) { show_warnings_ = show; }
435 
436     /* turn pedantic messages on or off */
set_pedantic(int show)437     void set_pedantic(int show) { pedantic_ = show; }
438 
439     /*
440      *   Set the list of warning messages to suppress.  The caller is
441      *   responsible for maintaining this memory, keeping it valid as long as
442      *   we have a reference to it and deleting the memory when it's no
443      *   longer needed.  We merely keep a reference to the caller's memory.
444      */
set_suppress_list(const int * lst,size_t cnt)445     void set_suppress_list(const int *lst, size_t cnt)
446     {
447         /* remember the caller's suppress list */
448         suppress_list_ = lst;
449         suppress_cnt_ = cnt;
450     }
451 
452     /* set the constant pool data XOR mask */
set_data_xor_mask(uchar mask)453     void set_data_xor_mask(uchar mask) { data_xor_mask_ = mask; }
454 
455     /* add a #include path entry */
456     void add_include_path(const textchar_t *path);
457 
458     /* add a #include path entry, if it's not already in our list */
459     void maybe_add_include_path(const textchar_t *path);
460 
461     /* add a source file path */
462     void add_source_path(const textchar_t *dir);
463 
464     /*
465      *   add a system include/source file path - system paths are always
466      *   searched after all of the regular paths, so effectively the items
467      *   in these lists come after all items in the add_include_path and
468      *   add_source_path lists, respectively
469      */
470     class CTcMakePath *add_sys_include_path(const textchar_t *dir);
471     class CTcMakePath *add_sys_source_path(const textchar_t *dir);
472 
473     /*
474      *   Set the symbol file directory.  Any symbol file that doesn't have
475      *   an absolute path will default to this directory.
476      */
set_symbol_dir(const textchar_t * dir)477     void set_symbol_dir(const textchar_t *dir) { symdir_.set(dir); }
478 
479     /*
480      *   Set the object file directory.  Any object file that doesn't have
481      *   an absolute path will default to this directory.
482      */
set_object_dir(const textchar_t * dir)483     void set_object_dir(const textchar_t *dir) { objdir_.set(dir); }
484 
485     /* set the assembly listing file */
set_assembly_listing(osfildef * fp)486     void set_assembly_listing(osfildef *fp) { assembly_listing_fp_ = fp; }
487 
488     /*
489      *   Set the image file name
490      */
set_image_file(const textchar_t * fname)491     void set_image_file(const textchar_t *fname) { image_fname_.set(fname); }
492 
493     /* get the image filename */
get_image_file()494     const char *get_image_file() const { return image_fname_.get(); }
495 
496     /*
497      *   Add a module (a module defines a source file and its directly
498      *   derived files: a symbol file and an object file).
499      *
500      *   Once a module has been added to our list, we own the module.
501      *   We'll delete the module object when we're deleted.
502      */
503     void add_module(CTcMakeModule *mod);
504     void add_module_first(CTcMakeModule *mod);
505 
506     /* get the head and tail of the module list */
get_first_module()507     CTcMakeModule *get_first_module() const { return mod_head_; }
get_last_module()508     CTcMakeModule *get_last_module() const { return mod_tail_; }
509 
510     /*
511      *   Add a module by filename.  src_name must be specified, but
512      *   sym_name and obj_name can be null, in which case we'll use the
513      *   standard algorithm to derive these names from the source file
514      *   name.
515      */
add_module(const char * src_name,const char * sym_name,const char * obj_name)516     CTcMakeModule *add_module(const char *src_name,
517                               const char *sym_name,
518                               const char *obj_name)
519         { return add_module(src_name, sym_name, obj_name, FALSE); }
520 
521     /* add a module at the head of the module list */
add_module_first(const char * src_name,const char * sym_name,const char * obj_name)522     CTcMakeModule *add_module_first(const char *src_name,
523                                     const char *sym_name,
524                                     const char *obj_name)
525         { return add_module(src_name, sym_name, obj_name, TRUE); }
526 
527 
528     /* add a module at either the start or end of the module list */
529     CTcMakeModule *add_module(const char *src_name, const char *sym_name,
530                               const char *obj_name, int first);
531 
532     /*
533      *   Add a preprocessor symbol definition.  If the expansion text is
534      *   null, we'll set the expansion text to "1" by default.
535      */
536     void def_pp_sym(const textchar_t *sym, const textchar_t *expan);
537 
538     /*
539      *   Un-define a preprocessor symbol.
540      */
541     void undef_pp_sym(const textchar_t *sym);
542 
543     /* look up a preprocessor symbol definition */
544     const char *look_up_pp_sym(const textchar_t *sym, size_t sym_len);
545 
546     /*
547      *   Build the program.  This can be invoked once the options are set
548      *   and all of the modules have been added.  This routine checks
549      *   dependencies and performs the build:
550      *
551      *   - for each source file, generates a symbol file if the symbol file
552      *   is not up to date
553      *
554      *   - after creating all symbol files: for each source file, compiles
555      *   the source to an object file if the object file isn't up to date
556      *
557      *   - after creating all object files: links the object files to create
558      *   an image file, if the image file isn't up to date
559      *
560      *   If any errors occur, we'll stop after the step in which the errors
561      *   occur.  For example, if errors occur compiling an object file,
562      *   we'll stop after finishing with the object file and will not
563      *   proceed to any additional object file compilations.
564      *
565      *   The 'host_interface' object must be provided by the caller.  This
566      *   tells the compiler how to report error messages and otherwise
567      *   interact with the host environment.
568      *
569      *   Fills in '*error_count' and '*warning_count' with the number of
570      *   errors and warnings, respectively, that occur during the
571      *   compilation.
572      *
573      *   If 'force_build' is set, we'll build all derived files (symbols,
574      *   objects, and image), regardless of whether it appears necessary
575      *   based on file times.
576      *
577      *   'argv0' is the main program's argv[0], if available; a null pointer
578      *   can be passed in if argv[0] is not available (for example, if we're
579      *   not running in a command-line environment and the program's
580      *   executable filename is not available)
581      */
582     void build(class CTcHostIfc *host_interface,
583                int *error_count, int *warning_count,
584                int force_build, int force_link,
585                class CRcResList *res_list,
586                const textchar_t *argv0);
587 
588     /*
589      *   Write our build configuration information to a symbol file.  The
590      *   symbol file builder calls this to give us a chance to insert our
591      *   build configuration information into the symbol file.  We include
592      *   all of the information we will need when re-loading the symbol file
593      *   to determine if the symbol file is up-to-date, so that we can
594      *   determine if we must rebuild the symbol file from the source or can
595      *   use it without rebuilding.
596      */
597     void write_build_config_to_sym_file(class CVmFile *fp);
598 
599     /*
600      *   Compare our build configuration to the information saved in an
601      *   symbol file.  Returns true if the configuration in the symbol file
602      *   matches our current configuration, false if not.  A false return
603      *   indicates that recompilation is necessary, because something in the
604      *   configuration has changed.
605      */
606     int compare_build_config_from_sym_file(const char *sym_fname,
607                                            class CVmFile *fp);
608 
609     /*
610      *   Set the string capture file.  If this is set, we'll write each
611      *   string token in the compiled text to this file, one string per
612      *   line.
613      */
set_string_capture(osfildef * fp)614     void set_string_capture(osfildef *fp) { string_fp_ = fp; }
615 
616     /*
617      *   Derive the source/symbol/object filenames for a module.  Fills in
618      *   the buffer with the derived name.  If the filenames don't have
619      *   paths explicitly specified, we'll use our default path settings to
620      *   build the full filename.
621      *
622      *   The buffers are assumed to be OSFNMAX characters long, which should
623      *   be large enough for any valid filename.
624      */
625     void get_srcfile(textchar_t *dst, CTcMakeModule *mod);
626     void get_symfile(textchar_t *dst, CTcMakeModule *mod);
627     void get_objfile(textchar_t *dst, CTcMakeModule *mod);
628 
629 private:
630     /* scan all modules for name collisions with other modules */
631     void check_all_module_collisions(class CTcHostIfc *hostifc,
632                                      class CResLoader *res_loader,
633                                      int *err_cnt, int *warn_cnt);
634 
635     /* check the given module for name collisions with other modules */
636     void check_module_collision(CTcMakeModule *mod);
637 
638     /*
639      *   read and compare a configuration string; returns true if the
640      *   string matches what's stored in the file, false if not
641      */
642     int read_and_compare_config_str(CVmFile *fp, const textchar_t *str);
643 
644     /* preprocess a source file */
645     void preprocess_source(class CTcHostIfc *hostifc,
646                            class CResLoader *res_loader,
647                            const textchar_t *src_fname,
648                            CTcMakeModule *src_mod,
649                            int *error_count, int *warning_count);
650 
651     /* build a symbol file */
652     void build_symbol_file(class CTcHostIfc *hostifc,
653                            class CResLoader *res_loader,
654                            const textchar_t *src_fname,
655                            const textchar_t *sym_fname,
656                            CTcMakeModule *src_mod,
657                            int *error_count, int *warning_count);
658 
659     /* build an object file */
660     void build_object_file(class CTcHostIfc *hostifc,
661                            class CResLoader *res_loader,
662                            const textchar_t *src_fname,
663                            const textchar_t *obj_fname,
664                            CTcMakeModule *src_mod,
665                            int *error_count, int *warning_count);
666 
667     /* build the image file */
668     void build_image_file(class CTcHostIfc *hostifc,
669                           class CResLoader *res_loader,
670                           const textchar_t *image_fname,
671                           int *error_count, int *warning_count,
672                           class CVmRuntimeSymbols *runtime_symtab,
673                           const char tool_data[4]);
674 
675     /* symbol enumeration callback: build runtime symbol table */
676     static void build_runtime_symtab_cb(void *ctx, class CTcSymbol *sym);
677 
678     /* set compiler options in the G_tcmain object */
679     void set_compiler_options();
680 
681     /* add a preprocessor symbol definition or undefinition */
682     void add_pp_def(const textchar_t *sym, const textchar_t *expan,
683                     int is_def);
684 
685     /*
686      *   Get the string to report for a filename in a progress report.  If
687      *   we're in test reporting mode, we'll return the root name so that we
688      *   suppress all paths in progress reports; otherwise, we'll just return
689      *   the name as given.  If we're quoting filenames in messages, we'll
690      *   quote the filename.
691      */
692     const char *get_step_fname(char *buf, const char *fname);
693 
694     /* default source file character set */
695     char *source_charset_;
696 
697     /* symbol file directory */
698     CTcMakeStr symdir_;
699 
700     /* object file diretory */
701     CTcMakeStr objdir_;
702 
703     /* assembly listing file */
704     osfildef *assembly_listing_fp_;
705 
706     /* image file name */
707     CTcMakeStr image_fname_;
708 
709     /* head and tail of module list */
710     CTcMakeModule *mod_head_;
711     CTcMakeModule *mod_tail_;
712 
713     /* head and tail of source path list */
714     CTcMakePath *src_head_;
715     CTcMakePath *src_tail_;
716 
717     /*
718      *   tail of regular source path list - this is where we insert regular
719      *   source path entries, which come before all system path entries
720      */
721     CTcMakePath *nonsys_src_tail_;
722 
723     /* head and tail of #include path list */
724     CTcMakePath *inc_head_;
725     CTcMakePath *inc_tail_;
726 
727     /* tail of regular (non-system) include path list */
728     CTcMakePath *nonsys_inc_tail_;
729 
730     /* head and tail of preprocessor symbol list */
731     CTcMakeDef *def_head_;
732     CTcMakeDef *def_tail_;
733 
734     /* string capture file */
735     osfildef *string_fp_;
736 
737     /* true -> show verbose error messages */
738     int verbose_;
739 
740     /* true -> show error numbers with error messages */
741     int show_err_numbers_;
742 
743     /* true -> show warnings, false -> suppress all warnings */
744     int show_warnings_;
745 
746     /* true -> show "pedantic" warning messages */
747     int pedantic_;
748 
749     /* list of warning numbers to suppress */
750     const int *suppress_list_;
751     size_t suppress_cnt_;
752 
753     /* true -> debug mode */
754     int debug_;
755 
756     /* true -> preprocess only */
757     int pp_only_;
758 
759     /* true -> #include list mode */
760     int list_includes_mode_;
761 
762     /* true -> "clean" mode */
763     int clean_mode_;
764 
765     /* true -> do linking after compiling */
766     int do_link_;
767 
768     /* true -> preinit mode */
769     int preinit_;
770 
771     /*
772      *   true -> obey 'preinit_' setting; otherwise, use default based on
773      *   'debug_' setting
774      */
775     int explicit_preinit_;
776 
777     /*
778      *   data pool XOR mask - we'll mask each byte of each constant data
779      *   pool with this byte when writing the image file, to obscure any
780      *   text strings in the constant data
781      */
782     uchar data_xor_mask_;
783 
784     /*
785      *   true -> test reporting mode: suppress all paths from filenames
786      *   displayed in progress reports, in order to make the output
787      *   independent of local path name conventions
788      */
789     int test_report_mode_;
790 
791     /* true -> use quoted filenames in error messages */
792     int quoted_fname_mode_;
793 };
794 
795 #endif /* TCMAKE_H */
796 
797