root/branches/mcstas-1.x/cogen.c

Revision 2699, 63.2 KB (checked in by pkwi, 2 years ago)

Added files from mcstas-1.12a

Line 
1/*******************************************************************************
2*
3* McStas, neutron ray-tracing package
4*         Copyright (C) 1997-2006, All rights reserved
5*         Risoe National Laboratory, Roskilde, Denmark
6*         Institut Laue Langevin, Grenoble, France
7*
8* Kernel: cogen.c
9*
10* %Identification
11* Written by: K.N.
12* Date: Aug  20, 1997
13* Origin: Risoe
14* Release: McStas 1.6
15* Version: $Revision: 1.81 $
16*
17* Code generation from instrument definition.
18*
19* $Log: cogen.c,v $
20* Revision 1.81  2008-06-13 09:16:47  pkwi
21* Reverting to next-to-last version of cogen.c
22*
23* Revision 1.79  2008/02/09 22:26:26  farhi
24* Major contrib for clusters/multi-core: OpenMP support
25*       try ./configure --with-cc=gcc4.2 or icc
26* then mcrun --threads ...
27* Also tidy-up configure. Made relevant changes to mcrun/mcgui to enable OpenMP
28* Updated install-doc accordingly
29*
30* Revision 1.78  2007/12/11 14:49:32  farhi
31* WHEN now disabled EXTEND
32* Added IN22 examples
33*
34* Revision 1.77  2007/10/29 18:41:18  farhi
35* Fixed GROUP issue that came in after SPLIT insertion in grammar
36*
37* Revision 1.76  2007/07/30 13:43:07  farhi
38* Instrument parameters may be specified more than once (specially when using %include "instr", e.g. Lambda in all instr). Recurrent parameters are
39* skipped, only the first def is used and a warning is issued.
40*
41* Revision 1.75  2007/06/25 12:37:29  pkwi
42* Split bug corrected!
43*
44* Split_counter is smaller than rep count also if there is no split! - Made
45* previously ABSORB'ed neutrons go to the split position.
46*
47* mcstas-1.11 is now one step closer to release...
48*
49* Revision 1.74  2007/04/03 13:16:58  farhi
50* Fixed potential infinite loop when using SPLIT
51*
52* Revision 1.73  2007/04/02 12:11:31  farhi
53* changed ENHANCE keyword to SPLIT
54*
55* Revision 1.72  2007/03/14 15:33:22  farhi
56* records N,p,p2 for each comp, for profiling in Progress_bar
57*
58* Revision 1.71  2007/03/12 14:12:16  farhi
59* SPLIT COMPONENT grammar: new rule for yacc. Code generation and cleaner GROUP handling.
60*
61* Revision 1.70  2007/03/06 09:39:09  farhi
62* NeXus default output is now "5 zip". Then NEXUS keyword is purely optional.
63*
64* Revision 1.69  2007/03/05 19:02:53  farhi
65* NEXUS support now works as MPI. NEXUS keyword is optional and only -DUSE_NEXUS is required. All instruments may then export in NEXUS if McStas
66* has been installed with --with-nexus
67*
68* Revision 1.68  2007/03/02 14:27:17  farhi
69* NEXUS grammar is now simplified. a single string may follow the keyword.
70* NEXUS "5 ZIP" is recommended.
71*
72* Revision 1.67  2007/02/09 13:19:15  farhi
73* When no NEXUS keyword in instrument and NeXus output requested, displays
74* an error/tip to add keyword after INITIALIZE
75*
76* Revision 1.66  2007/01/26 16:23:22  farhi
77* NeXus final integration (mcplot, mcgui, mcrun).
78* Only mcgui initiate mcstas.nxs as default output file, whereas
79* simulation may use instr_time.nxs
80*
81* Revision 1.65  2007/01/21 15:43:04  farhi
82* NeXus support. Draft version (functional). To be tuned.
83*
84* Revision 1.64  2006/12/19 15:11:56  farhi
85* Restored basic threading support without mutexes. All is now in mcstas-r.c
86*
87* Revision 1.63  2006/08/29 15:57:07  farhi
88* improved threads efficiency by using mutexes
89*
90* Revision 1.62  2006/08/28 10:34:25  pchr
91* In cogen.c - implementation of dashed line for mcdisplay.
92*
93* Added component Pol_simpleBfield handeling magnetic fields and spin precession.
94*
95* Test instruments for different types of usage supplied.
96*
97* Revision 1.61  2006/07/06 08:58:36  pchr
98* 'Added rectangle and box drawing modes.
99*
100* Revision 1.60  2006/04/19 13:06:25  farhi
101* * Updated Release, Version and Origin fields in headers
102* * Improved setversion to update all McStasx.y occurencies into current release
103* * Added 'string' type for DEFINITION parameters to be handled as this type so that auto-quoting occurs in mcgui
104* * Added possibility to save log of the session to a file (appended) in mcgui
105* * Made Scilab use either TCL_EvalStr or TK_EvalStr
106*
107* Revision 1.59  2006/04/06 08:46:20  farhi
108* NEW GRAMMAR: JUMP WHEN ITERATE COPY ...
109* need doc in TeX now...
110*
111* Revision 1.58  2005/11/02 09:18:38  farhi
112* More tolerant about DEFINITION parameter values, enabling table init as for PowderN
113*
114* Revision 1.57  2005/09/15 10:46:10  farhi
115* Added mccompcurtype to be e.g. the component type/class being used.
116* Not used yet, but will be with NeXus support and probably elsewere
117*
118* Revision 1.56  2005/07/27 11:29:41  farhi
119* missing arg in printf
120*
121* Revision 1.55  2005/07/18 14:43:05  farhi
122* Now gives a warning message per component for 'computational absorbs'
123*
124* Revision 1.54  2005/07/06 08:24:43  farhi
125* Moved again SHAREd blocks at the very begining of instrument C code
126* so that no name clash can occur.
127*
128* Revision 1.53  2005/07/05 12:18:00  farhi
129* Moved SHAREs defore definition/setting parameter comp definition
130* to avoid name clash. Was reason for failure of updated read_table-lib
131*
132* Revision 1.52  2005/06/20 13:32:45  farhi
133* Only display mcstas-r.* embed files with --verbose
134*
135* Revision 1.51  2005/06/20 09:16:48  farhi
136* Corrected mcScattered definition (char -> MCNUM)
137*
138* Revision 1.50  2005/06/20 09:02:10  farhi
139* Some more info in mcstas --verbose mode.
140*
141* Revision 1.49  2005/06/20 08:01:58  farhi
142* Install ABSORB counter for run-time PROP macros.
143* Report at end of simulation if needed.
144*
145* Revision 1.48  2005/05/31 13:26:16  farhi
146* Make possible to change setting parameter values in the INITIALIZE section.
147* It is thus easier to auto-configure components in their INIT code, depending
148* on some tests and checks...
149* Other sections use local copies of the setting parameters, e.g. TRACE, EXTEND
150* FINALLY, SAVE, ...
151*
152* Revision 1.47  2005/02/17 15:51:02  farhi
153* Added a neutron event per component, so that amessage is displayed when
154* no neutron reaches the COMP in FINALLY. Requested by R. Cubitt
155*
156* Revision 1.46  2004/11/30 16:09:56  farhi
157* Uses SIG_MESSAGE macro defined as strcpy(mcsigmessage...) when signals are used
158* or ignored when NOSIGNALS
159*
160* Revision 1.45  2004/11/29 14:30:52  farhi
161* Defines a component name as instrument name for usage of mcstas-r functions
162* and macros in FINALLY and SAVE (e.g. DETECTOR_OUT...)
163*
164* Revision 1.44  2004/09/10 15:09:56  farhi
165* Use same macro symbols for mcstas kernel and run-time for code uniformity
166*
167* Revision 1.43  2004/09/03 13:43:29  farhi
168* Removed duplicated Instr:FINALLY code (in SAVE and FINALLY). May cause SEGV.
169*
170* Revision 1.42  2003/10/06 14:59:14  farhi
171* Also insert component index in automatic source comments
172*
173* Revision 1.41  2003/09/05 08:59:05  farhi
174* added INSTRUMENT parameter default value grammar
175* mcinputtable now has also default values
176* mcreadpar now uses default values if parameter not given
177* extended instr_formal parameter struct
178* extended mcinputtable structure type
179*
180* Revision 1.40  2003/08/12 13:32:25  farhi
181* Add generation date/time in C code header
182*
183* Revision 1.39  2003/02/11 12:28:45  farhi
184* Variouxs bug fixes after tests in the lib directory
185* mcstas_r  : disable output with --no-out.. flag. Fix 1D McStas output
186* read_table:corrected MC_SYS_DIR -> MCSTAS define
187* monitor_nd-lib: fix Log(signal) log(coord)
188* HOPG.trm: reduce 4000 points -> 400 which is enough and faster to resample
189* Progress_bar: precent -> percent parameter
190* CS: ----------------------------------------------------------------------
191*
192* Revision 1.24 2002/09/17 10:34:45 ef
193* added comp setting parameter types
194*
195* $Id: cogen.c,v 1.81 2008-06-13 09:16:47 pkwi Exp $
196*
197*******************************************************************************/
198
199#include <stdarg.h>
200#include <string.h>
201#include <stdio.h>
202#include "mcstas.h"
203
204
205/*******************************************************************************
206* Some general comments on code generation.
207*
208* Code is output in the form of strings using the following functions:
209*   cout();                        (one line at a time)
210*   coutf();                       (with printf-style formatting)
211*
212* The type of numbers used in the generated code is given by the macro MCNUM
213* (defined in mcstas-r.h).
214*
215* All generated identifiers are prefixed with the string ID_PRE, to make name
216* clashes less likely to occur. Currently, for simplicity, we output modified
217* names directly, eg.
218*
219*   cout("void " ID_PRE "init(void);");
220*
221* But to make a later transition to a better name generation scheme possible,
222* it is important to use the ID_PRE macro everywhere identifiers are
223* generated.
224*
225* After the ID_PRE prefix a few letters occur in generated names to
226* distinguish different kinds of identifiers (instrument parameters,
227* component definition parameters, internal temporary variables and so on).
228* Care must be takes to choose these letters such that no name clashes will
229* occur with names generated by other parts of the code or generated from
230* user symbols.
231*
232* Finally, names generated from user symbols are generally chosen to match
233* the originals as closely as possible to make the generated code more
234* readable (for debugging purposes).
235*
236* The following is a list of the identifiers generated in the output. The
237* ID_PRE prefix is denoted by ##. The first column gives the identifier as it
238* appears in the generated code, the second explains the origin of the
239* identifier in the instrument definition source (if any).
240*
241* ##ip<PAR>        From instrument parameter <PAR>.
242* ##init           Function containing initialization code.
243* ##inputtable     Table of instrument parameters.
244* ##NUMIPAR        Macro giving the number of instrument parameters.
245* ##numipar        Global variable with the value of ##NUMIPAR.
246* ##c<C>_<P>       From definition or setting parameter <P> in component
247*                  instance <C>.
248* ##posa<COMP>     Absolute position of coordinate system of <COMP>.
249* ##posr<COMP>     Position of <COMP> relative to previous component.
250* ##rota<COMP>     Absolute rotation.
251* ##rotr<COMP>     Relative rotation.
252* ##tc1            Temporary variable used to compute transformations.
253* ##tc2
254* ##tr1
255* ##nx             Neutron state (position, velocity, time, and spin).
256* ##ny
257* ##nz
258* ##nvx
259* ##nvy
260* ##nvz
261* ##nt
262* ##nsx
263* ##nsy
264* ##nsz
265* ##np
266* ##compcurname
267* ##compcurtype
268* ##compcurindex
269* ##absorb          label for ABSORB (goto)
270* ##Scattered       Incremented each time a SCATTER is done
271* ##NCounter        Incremented each time a neutron is entering the component
272* ##AbsorbProp      single counter for removed events in PROP calls
273* ##comp_storein    Positions of neutron entering each comp (loc. coords)
274* ##Group<GROUP>    Flag true when in an active group
275* ##sig_message     Message for the signal handler (debug/trace, sim status)
276* ##JumpCounter     iteration counter for JUMP
277*******************************************************************************/
278
279
280
281/*******************************************************************************
282* Generation of declarations.
283*
284* The following declarations are generated (## denotes the value ID_PRE):
285* 1. Header file #include - "mcstas-r.h" for declarations for the
286*    mcstas runtime.
287* 2. Declarations of global variables to hold the values of the instrument
288*    parameters. For example, for an instrument parameter OMM, the
289*    declaration "MCNUM ##ipOMM;" is generated.
290* 3. Declaration of a table ##inputtable containing the list of instrument
291*    parameters. For each parameter, the name, a pointer to the
292*    corresponding global variable, and the type (double, int,
293*    string) is given. The macro ##NUMIPAR gives the number of
294*    entries in the table and is also found as the value of the
295*    variable ##numipar; in addition, the table is terminated by two
296*    NULLs. This table is used to read the instrument parameters from
297*    the user or from another program such as TASCOM.
298* 4. User declarations copied verbatim from the instrument definition file.
299* 5. Declarations for the component parameters. This uses #define for
300*    definition parameters and global variables for setting parameters.
301* X. User declarations from component definitions.
302* X. Declarations of variables for coordinate system transformations.
303* X. Declaration of variables for neutron state.
304* X. Function prototypes.
305*******************************************************************************/
306
307
308/* Functions for outputting code. */
309
310/* Handle for output file. */
311static FILE *output_handle = NULL;/* Handle for output file. */
312static int num_next_output_line = 1; /* Line number for next output line. */
313static char *quoted_output_file_name = NULL; /* str_quote()'ed name
314                                                of output file. */
315
316/* Convert instrument formal parameter type numbers to their enum name. */
317char *instr_formal_type_names[] =
318  { "instr_type_double", "instr_type_int", "instr_type_string" };
319
320char *instr_formal_type_names_real[] =
321  { "MCNUM", "int", "char*", "char"}; /* the last one is for static char allocation */
322
323/*******************************************************************************
324* Output a line of code
325* Assumes that the output does not contain newlines.
326*******************************************************************************/
327static void
328cout(char *s)
329{
330  fprintf(output_handle, "%s\n", s);
331  num_next_output_line++;
332}
333
334/*******************************************************************************
335* Output a line of code using printf-style format string.
336* Assumes that the output does not contain newlines.
337*******************************************************************************/
338static void
339coutf(char *format, ...)
340{
341  va_list ap;
342
343  va_start(ap, format);
344  vfprintf(output_handle, format, ap);
345  va_end(ap);
346  fprintf(output_handle, "\n");
347  num_next_output_line++;
348}
349
350/*******************************************************************************
351* Output #line directive to handle code coming from a different file.
352* The filename is assumed to be already properly quoted for special chars.
353*******************************************************************************/
354static void
355code_set_source(char *filename, int linenum)
356{
357  if(linenum > 0)
358    coutf("#line %d \"%s\"", linenum, filename);
359}
360
361/*******************************************************************************
362* Output #line directive to reset back to the generated output C file.
363*******************************************************************************/
364static void
365code_reset_source(void)
366{
367  /* Note: the number after #line refers to the line AFTER the directive. */
368  coutf("#line %d \"%s\"", num_next_output_line + 1, quoted_output_file_name);
369}
370
371
372static void
373codeblock_out(struct code_block *code)
374{
375  List_handle liter;                /* For list iteration. */
376  char *line;                        /* Single code line. */
377
378  if(list_len(code->lines) <= 0)
379    return;
380  code_set_source(code->quoted_filename, code->linenum + 1);
381  liter = list_iterate(code->lines);
382  while(line = list_next(liter))
383  {
384    fprintf(output_handle, "%s", line);
385    num_next_output_line++;
386  }
387  list_iterate_end(liter);
388  code_reset_source();
389}
390
391static void
392codeblock_out_brace(struct code_block *code)
393{
394  List_handle liter;                /* For list iteration. */
395  char *line;                        /* Single code line. */
396
397  if(list_len(code->lines) <= 0)
398    return;
399  code_set_source(code->quoted_filename, code->linenum);
400  cout("{");
401  liter = list_iterate(code->lines);
402  while(line = list_next(liter))
403  {
404    fprintf(output_handle, "%s", line);
405    num_next_output_line++;
406  }
407  list_iterate_end(liter);
408  cout("}");
409  code_reset_source();
410}
411
412
413struct code_block *
414codeblock_new(void)
415{
416  struct code_block *cb;
417
418  palloc(cb);
419  cb->filename = NULL;
420  cb->quoted_filename = NULL;
421  cb->linenum  = -1;
422  cb->lines    = list_create();
423  return cb;
424}
425
426/*******************************************************************************
427* Read a file and output it to the generated simulation code. Uses a
428* fixed-size buffer, and will silently and arbitrarily break long lines.
429*******************************************************************************/
430static void
431embed_file(char *name)
432{
433  char buf[4096];
434  FILE *f;
435  int last;
436
437  if (!symtab_lookup(lib_instances, name))
438  {
439    /* First look in the system directory. */
440    f = open_file_search_sys(name);
441    /* If not found, look in the full search path. */
442    if(f == NULL) {
443      f = open_file_search(name);
444      /* If still not found, abort. */
445      if(f == NULL)
446        fatal_error("Could not find file '%s'\n", name);
447      else if (verbose) printf("Embedding file      %s (user path)\n", name);
448    } else if (verbose) printf("Embedding file      %s (%s)\n", name, get_sys_dir());
449
450    cout("");
451    code_set_source(name, 1);
452    /* Now loop, reading lines and outputting them in the code. */
453    while(!feof(f))
454    {
455      if(fgets(buf, 4096, f) == NULL)
456        break;
457      last = strlen(buf) - 1;
458      if(last >= 0 && (buf[last] == '\n' || buf[last] == '\r'))
459        buf[last--] = '\0';
460      if(last >= 0 && (buf[last] == '\n' || buf[last] == '\r'))
461        buf[last--] = '\0';
462      cout(buf);
463    }
464    fclose(f);
465    coutf("/* End of file \"%s\". */", name);
466    cout("");
467    code_reset_source();
468    symtab_add(lib_instances, name, NULL);
469  } /* else file has already been embedded */
470} /* embed_file */
471
472
473/*******************************************************************************
474* The following two functions output #define directives around a given piece
475* of code to set up the right variable names (eg. the proper scope) for
476* instrument and component parameters. The functions are recursive on the
477* parameter lists.
478*
479* The functions first output an appropriate list of #define's, then call the
480* supplied function func with the argument data, and finally outputs a
481* matching list of #undef's.
482*******************************************************************************/
483static void cogen_instrument_scope_rec(List_handle parlist,
484                                       void (*func)(void *), void *data)
485{
486  struct instr_formal *par;
487
488  par = list_next(parlist);
489  if(par != NULL)
490  {
491    if (strlen(par->id)) coutf("#define %s %sip%s", par->id, ID_PRE, par->id);
492    cogen_instrument_scope_rec(parlist, func, data);
493    if (strlen(par->id)) coutf("#undef %s", par->id);
494  }
495  else
496  {
497    (*func)(data);
498  }
499}
500
501static void
502cogen_instrument_scope(struct instr_def *instr,
503                       void (*func)(void *), void *data)
504{
505  List_handle parlist;
506
507  coutf("#define %scompcurname %s", ID_PRE, instr->name);
508  /* This simply starts up the recursion on parameters. */
509  parlist = list_iterate(instr->formals);
510  cogen_instrument_scope_rec(parlist, func, data);
511  list_iterate_end(parlist);
512  coutf("#undef %scompcurname", ID_PRE);
513}
514
515/* Create the bindings for the SETTING parameter scope. Since the types of
516* setting parameters are known, local declarations can be used, avoiding the
517* problems with #define macro definitions.
518* infunc=0: no definition of parameters
519* infunc=1: define local copies of setting/definition parameters
520* infunc=2: same as 1, but for TRACE adds the EXTEND block and handles JUMPs
521*/
522static void
523cogen_comp_scope_setpar(struct comp_inst *comp, List_handle set, int infunc,
524                        void (*func)(void *), void *data)
525{
526  struct comp_iformal *formal;
527
528  /* Get the next setting parameter. */
529  formal = list_next(set);
530  if(formal != NULL)
531  {
532    /* Create local parameter equal to global value. */
533    if(infunc)
534      coutf("%s %s = %sc%s_%s;", instr_formal_type_names_real[formal->type], formal->id, ID_PRE, comp->name, formal->id);
535    else
536      coutf("#define %s %sc%s_%s", formal->id, ID_PRE, comp->name, formal->id);
537    cogen_comp_scope_setpar(comp, set, infunc, func, data);
538
539    if(!infunc)
540      coutf("#undef %s", formal->id);
541  }
542  else
543  {
544    /* adds conditional execution for the TRACE */
545    if (infunc==2 && comp->when) {
546      coutf("/* '%s' component has conditional execution */",comp->name);
547      coutf("if (%s)\n", exp_tostring(comp->when));
548    }
549    (*func)(data);                /* Now do the body. */
550    if(infunc == 2 && list_len(comp->extend->lines) > 0)
551    {
552      coutf("/* '%s' component extend code */",comp->name);
553      coutf("    SIG_MESSAGE(\"%s (Trace:Extend)\");", comp->name); /* signal handler message */
554      if (comp->when)
555        coutf("if (%s)\n", exp_tostring(comp->when));
556      codeblock_out(comp->extend);
557    }
558    if (infunc==2 && list_len(comp->jump) > 0) {
559      List_handle liter2;
560      liter2 = list_iterate(comp->jump);
561      struct jump_struct *this_jump;
562      while(this_jump = list_next(liter2)) {
563        char *exp=exp_tostring(this_jump->condition);
564        if (this_jump->iterate)
565          coutf("if (%sJumpCounter%s_%i < (%s)-1)"
566                "{ %sJumpCounter%s_%i++; goto %sJumpTrace_%s; }",
567            ID_PRE, comp->name, this_jump->index, exp,
568            ID_PRE, comp->name, this_jump->index,
569            ID_PRE, this_jump->target);
570        else
571          coutf("if (%s) goto %sJumpTrace_%s;",
572            exp, ID_PRE, this_jump->target);
573      }
574      list_iterate_end(liter2);
575    }
576  }
577} /* cogen_comp_scope_setpar */
578
579/* Create the #define statements to set up the scope for DEFINITION and OUTPUT
580* parameters.
581*/
582static void
583cogen_comp_scope_rec(struct comp_inst *comp, List_handle def, List set_list,
584                     List_handle out, int infunc,
585                     void (*func)(void *), void *data)
586{
587  char *par;
588  struct comp_iformal *formal;
589
590  /* First get the next DEFINITION or OUTPUT parameter, if any. */
591  if(def != NULL)
592  {
593    formal = list_next(def);
594    if(formal == NULL)
595      def = NULL;                /* Now finished with definition parameters. */
596    else
597      par = formal->id;
598  }
599  if(def == NULL)
600    par = list_next(out);
601  if(par != NULL)
602  {
603    /* Create #define / #undef pair for this parameter around rest of code. */
604    coutf("#define %s %sc%s_%s", par, ID_PRE, comp->name, par);
605    cogen_comp_scope_rec(comp, def, set_list, out, infunc, func, data);
606    coutf("#undef %s", par);
607  }
608  else
609  { /* Now do the SETTING parameters. */
610    List_handle set;
611
612    if(infunc && list_len(set_list) > 0)
613      coutf("{   /* Declarations of SETTING parameters. */");
614    set = list_iterate(set_list);
615    cogen_comp_scope_setpar(comp, set, infunc, func, data);
616    list_iterate_end(set);
617    if(infunc && list_len(set_list) > 0)
618      coutf("}   /* End of SETTING parameter declarations. */");
619  }
620} /* cogen_comp_scope_rec */
621
622static void
623cogen_comp_scope(struct comp_inst *comp, int infunc,
624                 void (*func)(void *), void *data)
625{
626  List_handle def, out;
627
628  coutf("#define %scompcurname  %s", ID_PRE, comp->name);
629  coutf("#define %scompcurtype  %s", ID_PRE, comp->type);
630  coutf("#define %scompcurindex %i", ID_PRE, comp->index);
631  def = list_iterate(comp->def->def_par);
632  out = list_iterate(comp->def->out_par);
633  cogen_comp_scope_rec(comp, def, comp->def->set_par, out,
634                       infunc, func, data);
635  list_iterate_end(out);
636  list_iterate_end(def);
637  coutf("#undef %scompcurname", ID_PRE);
638  coutf("#undef %scompcurtype", ID_PRE);
639  coutf("#undef %scompcurindex", ID_PRE);
640} /* cogen_comp_scope */
641
642
643/*******************************************************************************
644* Generate declarations from users declaration section in component definition.
645*******************************************************************************/
646static void
647cogen_comp_decls_doit(void *arg)
648{
649  struct comp_inst *comp = arg;
650
651  /* Output the user declaration code block. */
652  if (list_len(comp->def->decl_code->lines) > 0)
653    codeblock_out(comp->def->decl_code);
654}
655
656static void
657cogen_comp_decls(struct comp_inst *comp)
658{
659  cogen_comp_scope(comp, 0, cogen_comp_decls_doit, comp);
660}
661
662static void
663cogen_comp_shares(struct comp_inst *comp)
664{
665  /* Output the 'share' declaration code block
666    (once for all same components)*/
667
668  if (comp->def->comp_inst_number < 0)
669  {
670    coutf("/* Shared user declarations for all components '%s'. */", comp->def->name);
671    codeblock_out(comp->def->share_code);
672    comp->def->comp_inst_number *= -1;
673  }
674}
675
676
677/*******************************************************************************
678* Generate declaration part of code.
679*******************************************************************************/
680
681static void
682cogen_decls(struct instr_def *instr)
683{
684  List_handle liter;            /* For list iteration. */
685  struct comp_iformal *c_formal;/* Name of component formal input parameter */
686  struct instr_formal *i_formal;/* Name of instrument formal parameter. */
687  struct comp_inst *comp;       /* Component instance. */
688  int    index = 0;             /* index of comp instance */
689  struct group_inst *group;     /* group instances */
690
691  if (verbose) fprintf(stderr, "Writing instrument and components DECLARE\n");
692
693  /* 1. Function prototypes. */
694  coutf("void %sinit(void);", ID_PRE);
695  coutf("void %sraytrace(void);", ID_PRE);
696  coutf("void %ssave(FILE *);", ID_PRE);
697  coutf("void %sfinally(void);", ID_PRE);
698  coutf("void %sdisplay(void);", ID_PRE);
699  cout("");
700
701  /* 2. Component SHAREs. */
702  liter = list_iterate(instr->complist);
703  while(comp = list_next(liter))
704  {
705    if((list_len(comp->def->share_code->lines) > 0) && (comp->def->comp_inst_number < 0))
706    {
707      cogen_comp_shares(comp);
708      cout("");
709    }
710  }
711  list_iterate_end(liter);
712
713  /* 3. Global variables for instrument parameters. */
714  cout("/* Instrument parameters. */");
715  liter = list_iterate(instr->formals);
716  int numipar=0;
717  while(i_formal = list_next(liter))
718  {
719    if (strlen(i_formal->id)) {
720      coutf("%s " ID_PRE "ip%s;", instr_formal_type_names_real[i_formal->type], i_formal->id);
721      numipar++;
722    }
723  }
724  list_iterate_end(liter);
725  cout("");
726
727  /* 4. Table of instrument parameters. */
728  coutf("#define %sNUMIPAR %d", ID_PRE, numipar);
729  coutf("int %snumipar = %d;", ID_PRE, numipar);
730  coutf("struct %sinputtable_struct %sinputtable[%sNUMIPAR+1] = {",
731        ID_PRE, ID_PRE, ID_PRE);
732  liter = list_iterate(instr->formals);
733  while(i_formal = list_next(liter))
734  {
735    if (strlen(i_formal->id)) {
736      if (i_formal->isoptional && !strcmp(instr_formal_type_names[i_formal->type],"instr_type_string"))
737        coutf(\"%s\", &%sip%s, %s, %s, ", i_formal->id, ID_PRE,
738            i_formal->id, instr_formal_type_names[i_formal->type],
739            exp_tostring(i_formal->default_value));
740      else
741        coutf(\"%s\", &%sip%s, %s, \"%s\", ", i_formal->id, ID_PRE, i_formal->id,
742            instr_formal_type_names[i_formal->type],
743            i_formal->isoptional ? exp_tostring(i_formal->default_value) : "");
744    }
745  }
746  list_iterate_end(liter);
747  coutf("  NULL, NULL, instr_type_double, \"\"");
748  coutf("};");  /* 5. Declaration of component definition and setting parameters. */
749  cout("");
750
751  /* 5. User's declarations from the instrument definition file. */
752  cout("/* User declarations from instrument definition. */");
753  cogen_instrument_scope(instr, (void (*)(void *))codeblock_out, instr->decls);
754  cout("");
755
756  /* 6. Table to store neutron states when entering each component */
757  cout("/* Neutron state table at each component input (local coords) */");
758  cout("/* [x, y, z, vx, vy, vz, t, sx, sy, sz, p] */");
759  coutf("MCNUM %scomp_storein[11*%i];", ID_PRE, list_len(instr->complist)+2);
760
761  /* 7. Table to store position (abs/rel) for each component */
762  cout("/* Components position table (absolute and relative coords) */");
763  coutf("Coords %scomp_posa[%i];", ID_PRE, list_len(instr->complist)+2);
764  coutf("Coords %scomp_posr[%i];", ID_PRE, list_len(instr->complist)+2);
765  cout("/* Counter for each comp to check for inactive ones */");
766  coutf("MCNUM  %sNCounter[%i];", ID_PRE, list_len(instr->complist)+2);
767  coutf("MCNUM  %sPCounter[%i];", ID_PRE, list_len(instr->complist)+2);
768  coutf("MCNUM  %sP2Counter[%i];", ID_PRE, list_len(instr->complist)+2);
769  coutf("#define %sNUMCOMP %d /* number of components */", ID_PRE, list_len(instr->complist)+1);
770  cout("/* Counter for PROP ABSORB */");
771  coutf("MCNUM  %sAbsorbProp[%i];", ID_PRE, list_len(instr->complist)+2);
772
773  /* 8. Declaration of SCATTER flags */
774  cout("/* Flag true when previous component acted on the neutron (SCATTER) */");
775  coutf("MCNUM %sScattered=0;", ID_PRE);
776
777  if (list_len(instr->grouplist) > 0)
778  {
779    cout("/* Component group definitions (flags), equals index of scattering comp */");
780    liter = list_iterate(instr->grouplist);
781    while(group = list_next(liter))
782    {
783      coutf("int %sGroup%s=0;", ID_PRE, group->name);
784    }
785    list_iterate_end(liter);
786  }
787
788  /* 9. Declaration of component definition/setting parameters */
789  cout("/* Declarations of component definition and setting parameters. */");
790  cout("");
791  index = 0;
792
793
794  liter = list_iterate(instr->complist);
795  while(comp = list_next(liter))
796  {
797    List_handle liter2;
798
799    index++;
800    comp->index = index; /* should match the one defined with bison */
801
802    if(list_len(comp->def->def_par) > 0)
803    {                                /* (The if avoids a redundant comment.) */
804      coutf("/* Definition parameters for component '%s' [%i]. */", comp->name, comp->index);
805      liter2 = list_iterate(comp->def->def_par);
806      while(c_formal = list_next(liter2))
807      {
808        struct Symtab_entry *entry = symtab_lookup(comp->defpar, c_formal->id);
809        char *val = exp_tostring(entry->val);
810        coutf("#define %sc%s_%s %s", ID_PRE, comp->name, c_formal->id, val);
811        str_free(val);
812      }
813      list_iterate_end(liter2);
814    }
815    if(list_len(comp->def->set_par) > 0)
816    {
817      coutf("/* Setting parameters for component '%s' [%i]. */", comp->name, comp->index);
818      liter2 = list_iterate(comp->def->set_par);
819      while(c_formal = list_next(liter2))
820      {
821        if (c_formal->type != instr_type_string)
822          coutf("%s %sc%s_%s;", instr_formal_type_names_real[c_formal->type], ID_PRE, comp->name, c_formal->id);
823        else  /* char type for component */
824          coutf("%s %sc%s_%s[1024];", instr_formal_type_names_real[c_formal->type+1], ID_PRE, comp->name, c_formal->id);
825      }
826      list_iterate_end(liter2);
827    }
828    if(list_len(comp->def->def_par) > 0 || list_len(comp->def->set_par) > 0)
829      cout("");
830  }
831  list_iterate_end(liter);
832
833  /* 10. User declarations from component definitions (for each instance). */
834  cout("/* User component declarations. */");
835  cout("");
836  liter = list_iterate(instr->complist);
837  while(comp = list_next(liter))
838  {
839    /* set target names for jumps and define iteration counters */
840    if(list_len(comp->jump) > 0) {
841      struct jump_struct *this_jump;
842      int    jump_index=0;
843      List_handle liter2;
844      liter2 = list_iterate(comp->jump);
845      while(this_jump = list_next(liter2)) {
846        List_handle liter3;
847        char *jump_target_type=NULL;
848        jump_index++;
849        struct comp_inst *comp3;
850        /* check name/type of target */
851        liter3 = list_iterate(instr->complist);
852        while(comp3 = list_next(liter3)) {
853          if ((this_jump->target && !strcmp(this_jump->target, comp3->name))
854           || (!this_jump->target && comp3->index == comp->index+this_jump->target_index) ) {
855            if (!this_jump->target) this_jump->target=comp3->name;
856            jump_target_type =comp3->type;
857            break;
858          }
859        }
860        list_iterate_end(liter3);
861
862        this_jump->index = jump_index;
863        if (!this_jump->target || !jump_target_type) {
864          fatal_error("JUMP %i (relative %i) from component %s "
865                      "is not in the instrument.\n",
866            this_jump->index, this_jump->target_index, comp->name);
867        }
868        /* JUMP are valid only if MYSELF or between Arm's */
869        if (!(!strcmp(this_jump->target, comp->name) ||
870        (!strcmp(jump_target_type, "Arm")) ))
871          fatal_error("JUMPs can only apply on MYSELF or to Arm components.\n"
872                      "  Target %s is a %s (not an Arm).\n",
873            this_jump->target, jump_target_type);
874        /* create counter for iteration */
875        if (this_jump->iterate)
876          coutf("long %sJumpCounter%s_%i;",
877            ID_PRE, comp->name, this_jump->index);
878        fprintf(stderr,"Info:    Defining %s JUMP from %s to %s\n",
879          (this_jump->iterate ? "iterative" : "conditional"),
880          comp->name, this_jump->target);
881      }
882      list_iterate_end(liter2);
883    }
884
885    if((list_len(comp->def->decl_code->lines) > 0) || (comp->def->comp_inst_number < 0))
886    {
887      coutf("/* User declarations for component '%s' [%i]. */", comp->name, comp->index);
888      cogen_comp_decls(comp);
889      cout("");
890    }
891  }
892  list_iterate_end(liter);
893
894  /* 11. Declarations for the position and rotation transformations between
895     coordinate systems of components. */
896  liter = list_iterate(instr->complist);
897  while(comp = list_next(liter))
898  {
899    coutf("Coords %sposa%s, %sposr%s;", ID_PRE, comp->name, ID_PRE, comp->name);
900    coutf("Rotation %srota%s, %srotr%s;", ID_PRE, comp->name, ID_PRE, comp->name);
901  }
902  list_iterate_end(liter);
903  cout("");
904
905  /* 12. Neutron state. */
906  coutf("MCNUM %snx, %sny, %snz, %snvx, %snvy, %snvz, %snt, "
907        "%snsx, %snsy, %snsz, %snp;",
908        ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE,
909        ID_PRE, ID_PRE, ID_PRE, ID_PRE);
910  cout("");
911  cout("/* end declare */");
912  cout("");
913
914} /* cogen_decls */
915
916/*******************************************************************************
917* cogen_init: Generate the INIT section.
918*******************************************************************************/
919static void
920cogen_init(struct instr_def *instr)
921{
922  List_handle liter;
923  struct comp_inst *comp, *last;
924  char *d2r;
925
926  if (verbose) fprintf(stderr, "Writing instrument and components INITIALIZE\n");
927
928  coutf("void %sinit(void) {", ID_PRE);
929
930  /* User initializations from instrument definition. */
931  cogen_instrument_scope(instr, (void (*)(void *))codeblock_out_brace,
932                         instr->inits);
933
934  /* MOD: E. Farhi Sep 20th, 2001 moved transformation block so that */
935  /*                              it can be used in following init block */
936
937  /* Compute the necessary vectors and transformation matrices for coordinate
938     system changes between components. */
939  cout("  /* Computation of coordinate transformations. */");
940  cout("  {");
941  coutf("    Coords %stc1, %stc2;", ID_PRE, ID_PRE);
942  coutf("    Rotation %str1;", ID_PRE);
943  cout("");
944  /* Conversion factor degrees->radians for rotation angles. */
945  d2r = "DEG2RAD";
946
947  liter = list_iterate(instr->complist);
948  last = NULL;
949  coutf("    %sDEBUG_INSTR()", ID_PRE);
950
951  while((comp = list_next(liter)) != NULL)
952  {
953    struct comp_inst *relcomp; /* Component relative to. */
954    char *x, *y, *z;
955
956    coutf("    /* Component %s. */", comp->name);
957    coutf("    SIG_MESSAGE(\"%s (Init:Place/Rotate)\");", comp->name); /* signal handler message */
958
959    /* Absolute rotation. */
960    x = exp_tostring(comp->pos->orientation.x);
961    y = exp_tostring(comp->pos->orientation.y);
962    z = exp_tostring(comp->pos->orientation.z);
963    relcomp = comp->pos->orientation_rel;
964    if(relcomp == NULL)
965    {                                /* Absolute orientation. */
966      coutf("    rot_set_rotation(%srota%s,", ID_PRE, comp->name);
967      code_set_source(instr->quoted_source,
968                      exp_getlineno(comp->pos->orientation.x));
969      coutf("      (%s)*%s,", x, d2r);
970      code_set_source(instr->quoted_source,
971                      exp_getlineno(comp->pos->orientation.y));
972      coutf("      (%s)*%s,", y, d2r);
973      code_set_source(instr->quoted_source,
974                      exp_getlineno(comp->pos->orientation.z));
975      coutf("      (%s)*%s);", z, d2r);
976      code_reset_source();
977    }
978    else
979    {
980      coutf("    rot_set_rotation(%str1,", ID_PRE);
981      code_set_source(instr->quoted_source,
982                      exp_getlineno(comp->pos->orientation.x));
983      coutf("      (%s)*%s,", x, d2r);
984      code_set_source(instr->quoted_source,
985                      exp_getlineno(comp->pos->orientation.y));
986      coutf("      (%s)*%s,", y, d2r);
987      code_set_source(instr->quoted_source,
988                      exp_getlineno(comp->pos->orientation.z));
989      coutf("      (%s)*%s);", z, d2r);
990      code_reset_source();
991      coutf("    rot_mul(%str1, %srota%s, %srota%s);",
992            ID_PRE, ID_PRE, relcomp->name, ID_PRE, comp->name);
993    }
994    str_free(z);
995    str_free(y);
996    str_free(x);
997
998    /* Relative rotation. */
999    if(last == NULL)
1000    {                                /* First component. */
1001      coutf("    rot_copy(%srotr%s, %srota%s);",
1002            ID_PRE, comp->name, ID_PRE, comp->name);
1003    }
1004    else
1005    {
1006      coutf("    rot_transpose(%srota%s, %str1);", ID_PRE, last->name, ID_PRE);
1007      coutf("    rot_mul(%srota%s, %str1, %srotr%s);",
1008            ID_PRE, comp->name, ID_PRE, ID_PRE, comp->name);
1009    }
1010
1011    /* Absolute position. */
1012    x = exp_tostring(comp->pos->place.x);
1013    y = exp_tostring(comp->pos->place.y);
1014    z = exp_tostring(comp->pos->place.z);
1015    relcomp = comp->pos->place_rel;
1016    if(relcomp == NULL)
1017    {
1018      coutf("    %sposa%s = coords_set(", ID_PRE, comp->name);
1019      code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.x));
1020      coutf("      %s,", x);
1021      code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.y));
1022      coutf("      %s,", y);
1023      code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.z));
1024      coutf("      %s);", z);
1025      code_reset_source();
1026    }
1027    else
1028    {
1029      coutf("    %stc1 = coords_set(", ID_PRE);
1030      code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.x));
1031      coutf("      %s,", x);
1032      code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.y));
1033      coutf("      %s,", y);
1034      code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.z));
1035      coutf("      %s);", z);
1036      code_reset_source();
1037      coutf("    rot_transpose(%srota%s, %str1);",
1038            ID_PRE, relcomp->name, ID_PRE);
1039      coutf("    %stc2 = rot_apply(%str1, %stc1);",
1040            ID_PRE, ID_PRE, ID_PRE);
1041      coutf("    %sposa%s = coords_add(%sposa%s, %stc2);",
1042            ID_PRE, comp->name, ID_PRE, relcomp->name, ID_PRE);
1043    }
1044
1045    str_free(z);
1046    str_free(y);
1047    str_free(x);
1048
1049    /* Relative position. */
1050    if(last == NULL)
1051      coutf("    %stc1 = coords_neg(%sposa%s);", ID_PRE, ID_PRE, comp->name);
1052    else
1053      coutf("    %stc1 = coords_sub(%sposa%s, %sposa%s);",
1054            ID_PRE, ID_PRE, last->name, ID_PRE, comp->name);
1055    coutf("    %sposr%s = rot_apply(%srota%s, %stc1);",
1056          ID_PRE, comp->name, ID_PRE, comp->name, ID_PRE);
1057
1058    coutf("    %sDEBUG_COMPONENT(\"%s\", %sposa%s, %srota%s)",
1059          ID_PRE, comp->name, ID_PRE, comp->name, ID_PRE, comp->name);
1060
1061    coutf("    %scomp_posa[%i] = %sposa%s;", ID_PRE, comp->index, ID_PRE, comp->name);
1062    coutf("    %scomp_posr[%i] = %sposr%s;", ID_PRE, comp->index, ID_PRE, comp->name);
1063    coutf("    %sNCounter[%i]  = %sPCounter[%i] = %sP2Counter[%i] = 0;",
1064          ID_PRE, comp->index, ID_PRE, comp->index, ID_PRE, comp->index);
1065    coutf("    %sAbsorbProp[%i]= 0;", ID_PRE, comp->index);
1066
1067    last = comp;
1068  }
1069  list_iterate_end(liter);
1070
1071  /* Initialization of component setting parameters and user initialization
1072     code. */
1073  cout("  /* Component initializations. */");
1074  liter = list_iterate(instr->complist);
1075  while((comp = list_next(liter)) != NULL)
1076  {
1077    List_handle setpar;
1078    struct comp_iformal *par;
1079
1080    coutf("  /* Initializations for component %s. */", comp->name);
1081    coutf("  SIG_MESSAGE(\"%s (Init)\");", comp->name); /* signal handler message */
1082    /* Initialization of the component setting parameters. */
1083    setpar = list_iterate(comp->def->set_par);
1084    while((par = list_next(setpar)) != NULL)
1085    {
1086      char *val;
1087      struct Symtab_entry *entry;
1088
1089      entry = symtab_lookup(comp->setpar, par->id);
1090      val = exp_tostring(entry->val);
1091      code_set_source(instr->quoted_source, exp_getlineno(entry->val));
1092      if (par->type != instr_type_string)
1093      {
1094        coutf("  %sc%s_%s = %s;", ID_PRE, comp->name, par->id, val);
1095      }
1096      else
1097      {
1098        coutf("  if(%s) strncpy(%sc%s_%s,%s, 1024); else %sc%s_%s[0]='\\0';", val, ID_PRE, comp->name, par->id, val, ID_PRE, comp->name, par->id);
1099      }
1100      str_free(val);
1101    }
1102    list_iterate_end(setpar);
1103    if(list_len(comp->def->set_par) > 0)
1104      code_reset_source();
1105    cout("");
1106
1107    /* Users initializations. */
1108    if(list_len(comp->def->init_code->lines) > 0)
1109      cogen_comp_scope(comp, 0, (void (*)(void *))codeblock_out_brace,
1110                            comp->def->init_code);
1111    cout("");
1112  }
1113  list_iterate_end(liter);
1114
1115  /* Output graphics representation of components. */
1116  coutf("    if(%sdotrace) %sdisplay();", ID_PRE, ID_PRE);
1117  coutf("    %sDEBUG_INSTR_END()", ID_PRE);
1118  cout("  }");
1119  cout("");
1120  cout ("/* NeXus support */\n");
1121  cout ("#ifdef USE_NEXUS\n");
1122  coutf("strncmp(%snxversion,\"%s\",128);\n", ID_PRE,
1123    instr->nxinfo->any && instr->nxinfo->hdfversion && strlen(instr->nxinfo->hdfversion) ?
1124      instr->nxinfo->hdfversion : "5 zip");
1125  cout ("#endif\n");
1126
1127  cout("} /* end init */");
1128  cout("");
1129} /* cogen_init */
1130
1131/*******************************************************************************
1132* cogen_trace: Generate the TRACE section.
1133* Extended Grammar: uses goto and labels and installs tests
1134*   WHEN: the trace section of comp is embraced in a: if (when) { ...  }
1135*   GROUP: defines a global Group_<name> flag which gets true when one of the
1136*          comps SCATTER. Rest of GROUP is then skipped, using goto's.
1137*          ABSORB neutrons are sent to label absorbComp at the end of component
1138*          and next comp in GROUP is tested.
1139*   JUMP:  sends neutron to the JumpTrace labels, either with condition
1140*          or condition is (counter < iterations)
1141*   SPLIT: loops from comp/group TRACE to END, incrementing mcrun_num
1142*******************************************************************************/
1143static void
1144cogen_trace(struct instr_def *instr)
1145{
1146  List_handle liter;
1147  struct comp_inst *comp;
1148  struct group_inst *group;
1149
1150  if (verbose) fprintf(stderr, "Writing instrument and components TRACE\n");
1151
1152  /* Output the function header. */
1153  coutf("void %sraytrace(void) {", ID_PRE);
1154  /* Local neutron state. */
1155  cout("  /* Copy neutron state to local variables. */");
1156  coutf("  MCNUM %snlx = %snx;", ID_PRE, ID_PRE);
1157  coutf("  MCNUM %snly = %sny;", ID_PRE, ID_PRE);
1158  coutf("  MCNUM %snlz = %snz;", ID_PRE, ID_PRE);
1159  coutf("  MCNUM %snlvx = %snvx;", ID_PRE, ID_PRE);
1160  coutf("  MCNUM %snlvy = %snvy;", ID_PRE, ID_PRE);
1161  coutf("  MCNUM %snlvz = %snvz;", ID_PRE, ID_PRE);
1162  coutf("  MCNUM %snlt = %snt;", ID_PRE, ID_PRE);
1163  coutf("  MCNUM %snlsx = %snsx;", ID_PRE, ID_PRE);
1164  coutf("  MCNUM %snlsy = %snsy;", ID_PRE, ID_PRE);
1165  coutf("  MCNUM %snlsz = %snsz;", ID_PRE, ID_PRE);
1166  coutf("  MCNUM %snlp = %snp;", ID_PRE, ID_PRE);
1167  cout("");
1168
1169  /* Debugging (initial state). */
1170  coutf("  %sDEBUG_ENTER()", ID_PRE);
1171  coutf("  %sDEBUG_STATE(%snlx, %snly, %snlz, %snlvx, %snlvy, %snlvz,"
1172        "%snlt,%snlsx,%snlsy, %snlp)",
1173        ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE,
1174        ID_PRE, ID_PRE, ID_PRE, ID_PRE);
1175
1176  /* Set group flags */
1177  if (list_len(instr->grouplist) > 0)
1178  {
1179    cout("/* Set Component group definitions (flags) */");
1180    liter = list_iterate(instr->grouplist);
1181    while(group = list_next(liter))
1182    {
1183      coutf("  %sGroup%s=0; /* equals index of scattering comp when in group */", ID_PRE, group->name);
1184    }
1185    list_iterate_end(liter);
1186  }
1187  /* default is the normal ABSORB to end of TRACE */
1188  coutf("#define %sabsorb %sabsorbAll", ID_PRE, ID_PRE);
1189
1190  /* initiate iteration counters for each TRACE */
1191  liter = list_iterate(instr->complist);
1192  while((comp = list_next(liter)) != NULL)
1193  {
1194    if(list_len(comp->jump) > 0) {
1195      struct jump_struct *this_jump;
1196      List_handle liter2;
1197      liter2 = list_iterate(comp->jump);
1198      while(this_jump = list_next(liter2)) {
1199        /* create counter for iteration */
1200        if (this_jump->iterate)
1201          coutf("  %sJumpCounter%s_%i=0;",
1202            ID_PRE, comp->name, this_jump->index);
1203      }
1204      list_iterate_end(liter2);
1205    }
1206    /* if comp is in a split GROUP, install counter only for first comp of GROUP */
1207    if (comp->group && comp->group->split) {
1208      if (!strcmp(comp->name, comp->group->first_comp))
1209        comp->split      = comp->group->split;
1210      else comp->split   = NULL;
1211    }
1212    if (comp->split) {
1213      coutf("  /* SPLIT counter for component %s */", comp->name);
1214      coutf("  int %sSplit_%s=0;", ID_PRE, comp->name);
1215      fprintf(stderr,"Info:    Defining SPLIT from %s to END\n",
1216          comp->name);
1217    }
1218  }
1219  list_iterate_end(liter);
1220
1221  /* Now the trace code for each component. Proper scope is set up for each
1222     component using #define/#undef. */
1223  liter = list_iterate(instr->complist);
1224  while((comp = list_next(liter)) != NULL)
1225  {
1226    char *statepars[10];
1227    static char *statepars_names[10] =
1228      {
1229        "nlx", "nly", "nlz", "nlvx", "nlvy", "nlvz",
1230        "nlt", "nlsx", "nlsy", "nlp"
1231      };
1232    int i;
1233    List_handle statepars_handle;
1234
1235    coutf("  /* TRACE Component %s [%i] */", comp->name, comp->index);
1236
1237    /* Change of coordinates. */
1238    coutf("  %scoordschange(%sposr%s, %srotr%s,", ID_PRE, ID_PRE, comp->name,
1239          ID_PRE, comp->name);
1240    coutf("    &%snlx, &%snly, &%snlz,", ID_PRE, ID_PRE, ID_PRE);
1241    coutf("    &%snlvx, &%snlvy, &%snlvz,", ID_PRE, ID_PRE, ID_PRE);
1242    coutf("    &%snlt, &%snlsx, &%snlsy);", ID_PRE, ID_PRE, ID_PRE);
1243    if(instr->polarised)
1244      coutf("  %scoordschange_polarisation("
1245            "%srotr%s, &%snlsx, &%snlsy, &%snlsz);",
1246            ID_PRE, ID_PRE, comp->name, ID_PRE, ID_PRE, ID_PRE);
1247    /* JUMP RELATIVE comp */
1248    coutf("  /* define label inside component %s (without coords transformations) */", comp->name);
1249    coutf("  %sJumpTrace_%s:", ID_PRE, comp->name);
1250
1251    coutf("  SIG_MESSAGE(\"%s (Trace)\");", comp->name); /* signal handler message */
1252    coutf("  %sDEBUG_COMP(\"%s\")", ID_PRE, comp->name);
1253    /* Debugging (entry into component). */
1254    coutf("  %sDEBUG_STATE(%snlx, %snly, %snlz, %snlvx, %snlvy, %snlvz,"
1255          "%snlt,%snlsx,%snlsy, %snlp)",
1256          ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE,
1257          ID_PRE, ID_PRE, ID_PRE, ID_PRE);
1258
1259    /* Trace code. */
1260    for(i = 0; i < 10; i++)
1261      statepars[i] = NULL;
1262    statepars_handle = list_iterate(comp->def->state_par);
1263    for(i = 0; i < 10; i++)
1264    {
1265      statepars[i] = list_next(statepars_handle);
1266      if(statepars[i] == NULL)
1267        break;
1268    }
1269    list_iterate_end(statepars_handle);
1270    for(i = 0; i < 10; i++)
1271    {
1272      if(statepars[i] != NULL)
1273        coutf("#define %s %s%s", statepars[i], ID_PRE, statepars_names[i]);
1274      else
1275        break;
1276    }
1277    if(comp->def->polarisation_par)
1278    {
1279      coutf("#define %s %s%s", comp->def->polarisation_par[0], ID_PRE, "nlsx");
1280      coutf("#define %s %s%s", comp->def->polarisation_par[1], ID_PRE, "nlsy");
1281      coutf("#define %s %s%s", comp->def->polarisation_par[2], ID_PRE, "nlsz");
1282    }
1283    /* store neutron state in mccomp_storein */
1284    if (!comp->split)
1285    coutf("  STORE_NEUTRON(%i,%snlx, %snly, %snlz, %snlvx,"
1286          "%snlvy,%snlvz,%snlt,%snlsx,%snlsy, %snlsz, %snlp);",
1287          comp->index, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE,
1288          ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE);
1289    else {
1290      /* spliting: store first time, then restore neutron */
1291      coutf("  if (!%sSplit_%s) { /* STORE only the first time */", ID_PRE, comp->name);
1292      coutf("    STORE_NEUTRON(%i,%snlx, %snly, %snlz, %snlvx,"
1293          "%snlvy,%snlvz,%snlt,%snlsx,%snlsy, %snlsz, %snlp);",
1294          comp->index, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE,
1295          ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE);
1296      coutf("  } else {");
1297      coutf("    RESTORE_NEUTRON(%i,%snlx, %snly, %snlz, %snlvx,"
1298          "%snlvy,%snlvz,%snlt,%snlsx,%snlsy, %snlsz, %snlp); }",
1299          comp->index, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE,
1300          ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE);
1301      coutf("  %sSplit_%s++; /* SPLIT number */", ID_PRE, comp->name);
1302    }
1303
1304    coutf("  %sScattered=0;", ID_PRE);
1305    coutf("  %sNCounter[%i]++;", ID_PRE, comp->index);
1306    coutf("  %sPCounter[%i] += p;", ID_PRE, comp->index);
1307    coutf("  %sP2Counter[%i] += p*p;", ID_PRE, comp->index);
1308
1309    if (comp->group)
1310    {
1311      coutf("  if (!%sGroup%s) { /* previous comps of GROUP have not SCATTERED yet */", ID_PRE, comp->group->name);
1312      coutf("#undef %sabsorb", ID_PRE);
1313      cout ("/* if ABSORBed in GROUP/comp, will go to end of component */");
1314      coutf("#define %sabsorb %sabsorbComp%s", ID_PRE, ID_PRE, comp->name);
1315
1316    }
1317
1318    /* write component parameters and trace+extend code */
1319    /* also handles jumps after extend */
1320    cogen_comp_scope(comp, 2, (void (*)(void *))codeblock_out_brace,
1321                     comp->def->trace_code);
1322
1323    if (comp->group) {
1324      coutf("#undef %sabsorb", ID_PRE);
1325      coutf("#define %sabsorb %sabsorbAll", ID_PRE, ID_PRE);
1326      coutf("  } /* end comp %s in GROUP %s */", comp->name, comp->group->name);
1327      coutf("  if (SCATTERED) %sGroup%s=%i;",
1328        ID_PRE, comp->group->name, comp->index);
1329      cout ("  /* Label to skip component instead of ABSORB */");
1330      coutf("  %sabsorbComp%s:", ID_PRE, comp->name);
1331     
1332      if (strcmp(comp->name, comp->group->last_comp)) {
1333        /* not the last comp of GROUP: check if SCATTERED */
1334        coutf("  if (!%sGroup%s) /* restore neutron if was not scattered in GROUP yet */", ID_PRE, comp->group->name);
1335        coutf("    { RESTORE_NEUTRON(%i,%snlx, %snly, %snlz, %snlvx,"
1336          "%snlvy,%snlvz,%snlt,%snlsx,%snlsy, %snlsz, %snlp); }",
1337          comp->index, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE,
1338          ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE);
1339      } else {
1340        /* last comp of GROUP: restore default ABSORB */
1341        coutf("/* end of GROUP %s */", comp->group->name);
1342        coutf("  if (!%sGroup%s) ABSORB; /* absorb neutrons non scattered in GROUP */", ID_PRE, comp->group->name);
1343        if (comp->group->split) {
1344          /* only adapt weight for split neutrons in last comp of GROUP */
1345          char *exp=exp_tostring(comp->group->split); /* number of splits */
1346          coutf("  if (floor(%s) > 1) p /= floor(%s); /* adapt weight for SPLITed neutron in GROUP */",
1347            exp, exp);
1348          str_free(exp);
1349        }
1350      }
1351    } else if (comp->split) { /*  && !comp->group */
1352      /* only split for SCATTERED neutrons in comp */
1353      char *exp=exp_tostring(comp->split); /* number of splits */
1354      coutf("  if (floor(%s) > 1) p /= floor(%s); /* adapt weight for SPLITed neutron */", exp, exp);
1355      str_free(exp);
1356    }
1357
1358    if(comp->def->polarisation_par)
1359    {
1360      coutf("#undef %s", comp->def->polarisation_par[2]);
1361      coutf("#undef %s", comp->def->polarisation_par[1]);
1362      coutf("#undef %s", comp->def->polarisation_par[0]);
1363    }
1364    for(i = 9; i >= 0; i--)
1365    {
1366      if(statepars[i] != NULL)
1367        coutf("#undef %s", statepars[i]);
1368    }
1369    /* Debugging (exit from component). */
1370    coutf("  %sDEBUG_STATE(%snlx, %snly, %snlz, %snlvx, %snlvy, %snlvz,"
1371          "%snlt,%snlsx,%snlsy, %snlp)",
1372          ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE,
1373          ID_PRE, ID_PRE, ID_PRE, ID_PRE);
1374    cout("");
1375  }
1376  list_iterate_end(liter);
1377  /* SPLITing: should loop components if required */
1378  liter = list_iterate(instr->complist);
1379  char *reverse_SplitJumps = str_dup("");
1380  char has_splits=0;
1381  while((comp = list_next(liter)) != NULL)
1382  {
1383    if (comp->split) {
1384      has_splits = 1;
1385      char *exp=exp_tostring(comp->split); /* number of splits */
1386      char line[256];
1387      char cat_line[1024]; strcpy(cat_line, "");
1388      sprintf(line,"  if (%sSplit_%s && %sSplit_%s < (%s)) {\n",
1389        ID_PRE, comp->name, ID_PRE, comp->name, exp);
1390      strcat(cat_line, line);
1391      if (comp->group) {
1392        sprintf(line,"    %sGroup%s=0;\n", ID_PRE, comp->group->name);
1393        strcat(cat_line, line);
1394      }
1395      sprintf(line,"    goto %sJumpTrace_%s;\n  }\n", ID_PRE, comp->name);
1396      strcat(cat_line, line);
1397      sprintf(line,"    else %sSplit_%s=0;\n", ID_PRE, comp->name);
1398      strcat(cat_line, line);
1399      char *tmp=str_cat(cat_line, reverse_SplitJumps, NULL);
1400      str_free(reverse_SplitJumps); reverse_SplitJumps = tmp;
1401      str_free(exp);
1402    }
1403  }
1404  list_iterate_end(liter);
1405
1406  /* Absorbing neutrons - goto this label to skip remaining components. End of TRACE */
1407  coutf("  %sabsorbAll:", ID_PRE);
1408
1409  if (has_splits) coutf("  /* SPLIT loops in reverse order */\n%s", reverse_SplitJumps);
1410
1411  /* Debugging (final state). */
1412  coutf("  %sDEBUG_LEAVE()", ID_PRE);
1413  coutf("  %sDEBUG_STATE(%snlx, %snly, %snlz, %snlvx, %snlvy, %snlvz,"
1414        "%snlt,%snlsx,%snlsy, %snlp)",
1415        ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE,
1416        ID_PRE, ID_PRE, ID_PRE, ID_PRE);
1417
1418
1419  /* Copy back neutron state to global variables. */
1420  /* ToDo: Currently, this will be in the local coordinate system of the last
1421     component - should be transformed back into the global system. */
1422  cout("  /* Copy neutron state to global variables. */");
1423  coutf("  %snx = %snlx;", ID_PRE, ID_PRE);
1424  coutf("  %sny = %snly;", ID_PRE, ID_PRE);
1425  coutf("  %snz = %snlz;", ID_PRE, ID_PRE);
1426  coutf("  %snvx = %snlvx;", ID_PRE, ID_PRE);
1427  coutf("  %snvy = %snlvy;", ID_PRE, ID_PRE);
1428  coutf("  %snvz = %snlvz;", ID_PRE, ID_PRE);
1429  coutf("  %snt = %snlt;", ID_PRE, ID_PRE);
1430  coutf("  %snsx = %snlsx;", ID_PRE, ID_PRE);
1431  coutf("  %snsy = %snlsy;", ID_PRE, ID_PRE);
1432  coutf("  %snsz = %snlsz;", ID_PRE, ID_PRE);
1433  coutf("  %snp = %snlp;", ID_PRE, ID_PRE);
1434
1435  /* Function end. */
1436  cout("} /* end trace */");
1437  cout("");
1438} /* cogen_trace */
1439/*******************************************************************************
1440* cogen_save: Generate the SAVE section.
1441*******************************************************************************/
1442static void
1443cogen_save(struct instr_def *instr)
1444{
1445  List_handle liter;             /* For list iteration. */
1446  struct comp_inst *comp;        /* Component instance. */
1447
1448  if (verbose) fprintf(stderr, "Writing instrument and components SAVE\n");
1449
1450  /* User SAVE code from component definitions (for each instance). */
1451  coutf("void %ssave(FILE *handle) {", ID_PRE);
1452  /* In case the save occurs during simulation (-USR2 not at end), we must close
1453   * current siminfo and re-open it, not to have redundant monitor entries
1454   * saved each time for each monitor. The sim_info is then incomplete, but
1455   * data is saved entirely. It is completed during the last siminfo_close
1456   * of mcraytrace
1457   */
1458  coutf("  if (!handle) %ssiminfo_init(NULL);", ID_PRE);
1459  cout("  /* User component SAVE code. */");
1460  cout("");
1461  liter = list_iterate(instr->complist);
1462  while(comp = list_next(liter))
1463  {
1464    if(list_len(comp->def->save_code->lines) > 0)
1465    {
1466      coutf("  /* User SAVE code for component '%s'. */", comp->name);
1467      coutf("  SIG_MESSAGE(\"%s (Save)\");", comp->name); /* signal handler message */
1468      cogen_comp_scope(comp, 1, (void (*)(void *))codeblock_out_brace,
1469                       comp->def->save_code);
1470      cout("");
1471    }
1472  }
1473  list_iterate_end(liter);
1474
1475  /* User's SAVE code from the instrument definition file. */
1476  if(list_len(instr->saves->lines) > 0)
1477  {
1478    cout("  /* User SAVE code from instrument definition. */");
1479    coutf("  SIG_MESSAGE(\"%s (Save)\");", instr->name);
1480    cogen_instrument_scope(instr, (void (*)(void *))codeblock_out_brace,
1481                           instr->saves);
1482    cout("");
1483  }
1484  coutf("  if (!handle) %ssiminfo_close(); ", ID_PRE);
1485  cout("} /* end save */");
1486} /* cogen_save */
1487
1488/*******************************************************************************
1489* cogen_finally: Generate the FINALLY section.
1490*******************************************************************************/
1491static void
1492cogen_finally(struct instr_def *instr)
1493{
1494  List_handle liter;                /* For list iteration. */
1495  struct comp_inst *comp;           /* Component instance. */
1496
1497  if (verbose) fprintf(stderr, "Writing instrument and components FINALLY\n");
1498
1499  /* User FINALLY code from component definitions (for each instance). */
1500  coutf("void %sfinally(void) {", ID_PRE);
1501  cout("  /* User component FINALLY code. */");
1502  /* first call SAVE code to save any remaining data */
1503  coutf("  %ssiminfo_init(NULL);", ID_PRE);
1504  coutf("  %ssave(%ssiminfo_file); /* save data when simulation ends */", ID_PRE, ID_PRE);
1505  cout("");
1506  liter = list_iterate(instr->complist);
1507  while(comp = list_next(liter))
1508  {
1509    if(list_len(comp->def->finally_code->lines) > 0)
1510    {
1511      coutf("  /* User FINALLY code for component '%s'. */", comp->name);
1512      coutf("  SIG_MESSAGE(\"%s (Finally)\");", comp->name); /* signal handler message */
1513      cogen_comp_scope(comp, 1, (void (*)(void *))codeblock_out_brace,
1514                       comp->def->finally_code);
1515      cout("");
1516    }
1517    coutf("    if (!%sNCounter[%i]) "
1518      "fprintf(stderr, \"Warning: No neutron could reach Component[%i] %s\\n\");",
1519      ID_PRE, comp->index, comp->index, comp->name);
1520    if (comp->split) {
1521      char *exp=exp_tostring(comp->split); /* number of splits */
1522      coutf("    if (%sNCounter[%i] < 1000*(%s)) fprintf(stderr, \n"
1523        "\"Warning: Number of events reaching SPLIT position Component[%i] %s\\n\"\n"
1524        "\"         is probably too low. Increase Ncount.\\n\");\n",
1525          ID_PRE, comp->index, exp, comp->index, comp->name);
1526      str_free(exp);
1527    }
1528    coutf("    if (%sAbsorbProp[%i]) "
1529      "fprintf(stderr, "
1530        "\"Warning: %%g events were removed in Component[%i] %s\\n\""
1531        "\"         (negative time, rounding errors).\\n\""
1532        ", %sAbsorbProp[%i]);"
1533    , ID_PRE, comp->index, comp->index, comp->name, ID_PRE, comp->index);
1534  }
1535  list_iterate_end(liter);
1536
1537  /* User's FINALLY code from the instrument definition file. */
1538  if(list_len(instr->finals->lines) > 0)
1539  {
1540    cout("  /* User FINALLY code from instrument definition. */");
1541    coutf("  SIG_MESSAGE(\"%s (Finally)\");", instr->name); /* signal handler message */
1542    cogen_instrument_scope(instr, (void (*)(void *))codeblock_out_brace,
1543                           instr->finals);
1544    cout("");
1545  }
1546  coutf("  %ssiminfo_close(); ", ID_PRE);
1547  cout("} /* end finally */");
1548} /* cogen_finally */
1549
1550/*******************************************************************************
1551* cogen_mcdisplay: Generate the MCDISPLAY section.
1552*******************************************************************************/
1553static void
1554cogen_mcdisplay(struct instr_def *instr)
1555{
1556  List_handle liter;                /* For list iteration. */
1557  struct comp_inst *comp;          /* Component instance. */
1558
1559  if (verbose) fprintf(stderr, "Writing instrument and components MCDISPLAY\n");
1560
1561  /* User FINALLY code from component definitions (for each instance). */
1562  cout("#define magnify mcdis_magnify");
1563  cout("#define line mcdis_line");
1564  cout("#define dashed_line mcdis_dashed_line");
1565  cout("#define multiline mcdis_multiline");
1566  cout("#define rectangle mcdis_rectangle");
1567  cout("#define box mcdis_box");
1568  cout("#define circle mcdis_circle");
1569  coutf("void %sdisplay(void) {", ID_PRE);
1570  cout("  printf(\"MCDISPLAY: start\\n\");");
1571  cout("  /* Components MCDISPLAY code. */");
1572  cout("");
1573
1574  liter = list_iterate(instr->complist);
1575  while(comp = list_next(liter))
1576  {
1577    if(list_len(comp->def->mcdisplay_code->lines) > 0)
1578    {
1579      char *quoted_name = str_quote(comp->name);
1580      coutf("  /* MCDISPLAY code for component '%s'. */", comp->name);
1581      coutf("  SIG_MESSAGE(\"%s (McDisplay)\");", comp->name); /* signal handler message */
1582      coutf("  printf(\"MCDISPLAY: component %%s\\n\", \"%s\");", quoted_name);
1583
1584      cogen_comp_scope(comp, 1, (void (*)(void *))codeblock_out_brace,
1585                       comp->def->mcdisplay_code);
1586      cout("");
1587      str_free(quoted_name);
1588    }
1589  }
1590  list_iterate_end(liter);
1591
1592  cout("  printf(\"MCDISPLAY: end\\n\");");
1593  cout("} /* end display */");
1594  cout("#undef magnify");
1595  cout("#undef line");
1596  cout("#undef dashed_line");
1597  cout("#undef multiline");
1598  cout("#undef rectangle");
1599  cout("#undef box");
1600  cout("#undef circle");
1601} /* cogen_mcdisplay */
1602
1603
1604/*******************************************************************************
1605* Output code for the mcstas runtime system. Default is to copy the runtime
1606* code into the generated executable, to minimize problems with finding the
1607* right files during compilation and linking, but this may be changed using
1608* the --no-runtime compiler switch.
1609*******************************************************************************/
1610static void
1611cogen_runtime(struct instr_def *instr)
1612{
1613  char *sysdir_orig;
1614  char *sysdir_new;
1615  char  pathsep[3];
1616  int   i,j=0;
1617  /* handles Windows '\' chararcters for embedding sys_dir into source code */
1618  if (MC_PATHSEP_C != '\\') strcpy(pathsep, MC_PATHSEP_S); else strcpy(pathsep, "\\\\");
1619  sysdir_orig = get_sys_dir();
1620  sysdir_new  = (char *)mem(2*strlen(sysdir_orig));
1621  for (i=0; i < strlen(sysdir_orig); i++)
1622  {
1623    if (sysdir_orig[i] == '\\')
1624    { sysdir_new[j] = '\\'; j++; sysdir_new[j] = '\\'; }
1625    else sysdir_new[j] = sysdir_orig[i];
1626    j++;
1627  }
1628  sysdir_new[j] = '\0';
1629  if(instr->use_default_main)
1630    cout("#define MC_USE_DEFAULT_MAIN");
1631  if(instr->enable_trace)
1632    cout("#define MC_TRACE_ENABLED");
1633  if(instr->portable)
1634    cout("#define MC_PORTABLE");
1635  if(instr->include_runtime)
1636  {
1637    cout("#define MC_EMBEDDED_RUNTIME"); /* Some stuff will be static. */
1638    embed_file("mcstas-r.h");
1639    /* NeXus support, only active with -DUSE_NEXUS */
1640    embed_file("nexus-lib.h"); /* will require linking with -DUSE_NEXUS -lNeXus */
1641    embed_file("nexus-lib.c");
1642    if (verbose) printf("Requires library    -DUSE_NEXUS -lNeXus (to enable NeXus support)\n");
1643    embed_file("mcstas-r.c");
1644  }
1645  else
1646  {
1647    coutf("#include \"%s%sshare%smcstas-r.h\"",  sysdir_new, pathsep, pathsep);
1648    coutf("#include \"%s%sshare%snexus-lib.h\"", sysdir_new, pathsep, pathsep);
1649    fprintf(stderr,"Dependency: %s.o\n", "mcstas-r");
1650    fprintf(stderr,"Dependency: %s.o and '-DUSE_NEXUS -lNeXus' to enable NeXus support\n", "nexus-lib");
1651    fprintf(stderr,"To build instrument %s, compile and link with these libraries (in %s%sshare)\n", instrument_definition->quoted_source, sysdir_new, pathsep);
1652  }
1653
1654  coutf("#ifdef MC_TRACE_ENABLED");
1655  coutf("int %straceenabled = 1;", ID_PRE);
1656  coutf("#else");
1657  coutf("int %straceenabled = 0;", ID_PRE);
1658  coutf("#endif");
1659  coutf("#define MCSTAS \"%s%s\"", sysdir_new,pathsep);
1660  coutf("int %sdefaultmain = %d;", ID_PRE, instr->use_default_main);
1661  coutf("char %sinstrument_name[] = \"%s\";", ID_PRE, instr->name);
1662  coutf("char %sinstrument_source[] = \"%s\";", ID_PRE, instr->source);
1663  if(instr->use_default_main)
1664    cout("int main(int argc, char *argv[]){return mcstas_main(argc, argv);}");
1665} /* cogen_runtime */
1666
1667
1668/*******************************************************************************
1669* Generate the output file (in C).
1670*******************************************************************************/
1671void
1672cogen(char *output_name, struct instr_def *instr)
1673{
1674  time_t t;
1675  char date[64];
1676
1677  time(&t);
1678  strncpy(date, ctime(&t), 64);
1679  if (strlen(date)) date[strlen(date)-1] = '\0';
1680
1681  /* Initialize output file. */
1682  if(!output_name || !output_name[0] || !strcmp(output_name, "-"))
1683  {
1684    output_handle = fdopen(1, "w");
1685    quoted_output_file_name = str_quote("<stdout>");
1686  }
1687  else
1688  {
1689    output_handle = fopen(output_name, "w");
1690    quoted_output_file_name = str_quote(output_name);
1691  }
1692  num_next_output_line = 1;
1693  if(output_handle == NULL)
1694    fatal_error("Error opening output file '%s'\n", output_name);
1695
1696  cout("/* Automatically generated file. Do not edit. ");
1697  cout(" * Format:     ANSI C source code");
1698  cout(" * Creator:    McStas <http://neutron.risoe.dk>");
1699  coutf(" * Instrument: %s (%s)", instr->source, instr->name);
1700  coutf(" * Date:       %s", date);
1701  cout(" */\n");
1702  cout("");
1703  coutf("#define MCSTAS_VERSION \"%s\"", MCSTAS_VERSION);
1704  cogen_runtime(instr);
1705  cogen_decls(instr);
1706  cogen_init(instr);
1707  cogen_trace(instr);
1708  cogen_save(instr);
1709  cogen_finally(instr);
1710  cogen_mcdisplay(instr);
1711} /* cogen */
Note: See TracBrowser for help on using the browser.