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