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