ARTS  2.0.49
make_auto_md_cc.cc
Go to the documentation of this file.
1 /* Copyright (C) 2000-2008 Stefan Buehler <sbuehler@ltu.se>
2 
3  This program is free software; you can redistribute it and/or modify it
4  under the terms of the GNU General Public License as published by the
5  Free Software Foundation; either version 2, or (at your option) any
6  later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16  USA. */
17 
18 #include "arts.h"
19 #include "array.h"
20 #include "file.h"
21 #include "methods.h"
22 #include "workspace_ng.h"
23 #include "agenda_record.h"
24 
25 /* Adds commas and indentation to parameter lists. */
26 void align(ofstream& ofs, bool& is_first_parameter, const String& indent)
27 {
28  // Add comma and line break, if not first element:
29  if (is_first_parameter)
30  is_first_parameter = false;
31  else
32  {
33  ofs << ",\n";
34  // Make proper indentation:
35  ofs << indent;
36  }
37 }
38 
39 int main()
40 {
41  try
42  {
43  // Make the global data visible:
44  extern Array<MdRecord> md_data;
45  extern const ArrayOfString wsv_group_names;
46  const Array<WsvRecord>& wsv_data = Workspace::wsv_data;
47 
48  // Initialize the wsv group name array:
50 
51  // Initialize wsv data.
53 
54  // Initialize WsvMap.
56 
57  // Initialize method data.
59 
60  // Expand supergeneric methods:
62 
63 
64  const Index n_md = md_data.nelem();
65 
66  // Write auto_md.cc:
67  // -----------
68  ofstream ofs;
69  open_output_file(ofs,"auto_md.cc");
70 
71  ofs << "// This file was generated automatically by make_auto_md_cc.cc.\n";
72  ofs << "// DO NOT EDIT !\n";
73  ofs << "// Generated: "
74  << __DATE__ << ", "
75  << __TIME__ << "\n\n";
76 
77  ofs << "#include \"arts.h\"\n"
78  << "#include \"make_array.h\"\n"
79  << "#include \"auto_md.h\"\n"
80  << "#include \"wsv_aux.h\"\n"
81  << "#include \"mc_interp.h\"\n"
82  << "#include \"m_append.h\"\n"
83  << "#include \"m_delete.h\"\n"
84  << "#include \"m_copy.h\"\n"
85  << "#include \"m_conversion.h\"\n"
86  << "#include \"m_extract.h\"\n"
87  << "#include \"m_general.h\"\n"
88  << "#include \"m_ignore.h\"\n"
89  << "#include \"m_nc.h\"\n"
90  << "#include \"m_select.h\"\n"
91  << "#include \"m_xml.h\"\n"
92  << "#include \"m_basic_types.h\"\n"
93  << "#include \"agenda_record.h\"\n"
94  << "#include \"workspace_ng.h\"\n"
95  << "\n";
96 
97  //ofs << "static Index agendacallcount = 0;\n";
98 
99  // Write all get-away functions:
100  // -----------------------------
101  for (Index i=0; i<n_md; ++i)
102  {
103  const MdRecord& mdd = md_data[i];
104 
105  // This is needed to flag the first function parameter, which
106  // needs no line break before being written:
107  bool is_first_parameter = true;
108  // The String indent is needed to achieve the correct
109  // indentation of the functin parameters:
110  String indent = String(mdd.Name().nelem()+3,' ');;
111  // Flag to pass the workspace to the WSM. Only true if the WSM has
112  // an Agenda as input.
113  bool pass_workspace = false;
114 
115  // There are four lists of parameters that we have to
116  // write.
117  ArrayOfIndex vo=mdd.Out(); // Output
118  const ArrayOfIndex& vi = mdd.InOnly(); // Input
119 #ifndef NDEBUG
120  const ArrayOfIndex& voutonly = mdd.OutOnly(); // Output only
121 #endif
122  ArrayOfIndex vgo=mdd.GOutType(); // Generic Output
123  ArrayOfIndex vgi=mdd.GInType(); // Generic Input
124  // vo and vi contain handles of workspace variables,
125  // vgo and vgi handles of workspace variable groups.
126 
127  // There used to be a similar block here for the generic
128  // input/output variables. However, this was a mistake. For
129  // example, if a method has a vector as generic input and a
130  // vector as generic output, this does not mean that it is
131  // the same vector!
132 
133  {
134 
135  String ws, mr;
136 
137  // Use parameter name only if it is used inside the function
138  // to avoid warnings
139  ws = " ws";
140 // if (!mdd.AgendaMethod() && !mdd.PassWorkspace() && !vo.nelem () && !vi.nelem () && !vgo.nelem () && !vgi.nelem ())
141 // {
142 // ws = "";
143 // }
144 
145  // Find out if the WSM gets an agenda as input. If so, pass
146  // the current workspace to this method
147  for (Index j = 0; !pass_workspace && j < mdd.In().nelem(); j++)
148  {
149  if (wsv_data[mdd.In()[j]].Group() == get_wsv_group_id ("Agenda"))
150  {
151  pass_workspace = true;
152  }
153  }
154 
155  // Find out if the WSM gets an agenda as input. If so, pass
156  // the current workspace to this method
157  for (Index j = 0; !pass_workspace && j < mdd.GInType().nelem(); j++)
158  {
159  if (mdd.GInType()[j] == get_wsv_group_id ("Agenda"))
160  {
161  pass_workspace = true;
162  }
163  }
164 
165  // Use parameter name only if it is used inside the function
166  // to avoid warnings
167  if ( vo.nelem () || vi.nelem () || vgo.nelem () || vgi.nelem ()
168  || mdd.AgendaMethod())
169  {
170  mr = " mr";
171  }
172 
173  if ( mdd.Supergeneric() )
174  {
175  ofs << "void " << mdd.Name()
176  << "_sg_" << mdd.ActualGroups()
177  << "_g(Workspace&" << ws
178  << ", const MRecord&" << mr << ")\n"
179  << "{\n";
180  }
181  else
182  {
183  ofs << "void " << mdd.Name()
184  << "_g(Workspace&" << ws
185  << ", const MRecord&" << mr << ")\n"
186  << "{\n";
187  }
188  }
189 
190  // Erase all Output only variables to uncover if they are
191  // misused as Input variables
192 #ifndef NDEBUG
193 #define DUMMY_ELEMS 0
194 #define DUMMY_COLS DUMMY_ELEMS
195 #define DUMMY_ROWS DUMMY_ELEMS
196 #define DUMMY_PAGES DUMMY_ELEMS
197  for (Index j=0; j < voutonly.nelem(); j++)
198  {
199  ostringstream docstr;
200  docstr << " " << "// " << wsv_data[voutonly[j]].Name() << " is Output only.\n";
201 
202  String gname = wsv_group_names[wsv_data[voutonly[j]].Group()];
203  ostringstream initstr;
204  if (gname == "Numeric")
205  initstr << " = NAN;";
206  else if (gname == "Index")
207  initstr << " = -1;";
208  else if (gname == "Vector")
209  initstr << ".resize(" << DUMMY_ELEMS << ");";
210  else if (gname == "Matrix")
211  initstr << ".resize(" << DUMMY_ROWS << ","
212  << DUMMY_COLS << ");";
213  else if (gname == "Tensor3")
214  initstr << ".resize(" << DUMMY_PAGES << ","
215  << DUMMY_ROWS << ","
216  << DUMMY_COLS << ");";
217 
218 
219  if (initstr.str().length())
220  {
221  ofs << " (*(("
222  << wsv_group_names[wsv_data[voutonly[j]].Group()]
223  << " *)ws[" << voutonly[j]
224  << "]))" << initstr.str();
225  }
226  ofs << docstr.str();
227 
228  }
229 #endif /* NDEBUG */
230 
231  ofs << " " << mdd.Name() << "(";
232 
233  if (pass_workspace || mdd.PassWorkspace() || mdd.AgendaMethod())
234  {
235  ofs << "ws";
236  is_first_parameter = false;
237  }
238 
239  // Write the Output workspace variables:
240  for (Index j=0; j<vo.nelem(); ++j)
241  {
242  // Check by assert whether the group identifier is too
243  // large to correspond to a group. This can easily
244  // happen if somebody puts a variable identifier instead
245  // of a group identifier in the argument of GOUTPUT:
246  assert( wsv_data[vo[j]].Group() < wsv_group_names.nelem() );
247 
248  // Add comma and line break, if not first element:
249  align(ofs,is_first_parameter,indent);
250 
251  ofs << "*(("
252  << wsv_group_names[wsv_data[vo[j]].Group()]
253  << " *)ws[mr.Out()[" << j
254  << "]])";
255  }
256 
257  // Write the Generic output workspace variables:
258  for (Index j=0; j<vgo.nelem(); ++j)
259  {
260  // Check by assert whether the group identifier is too
261  // large to correspond to a group. This can easily
262  // happen if somebody puts a variable identifier instead
263  // of a group identifier in the argument of GOUTPUT:
264  assert( vgo[j] < wsv_group_names.nelem() );
265 
266  // Add comma and line break, if not first element:
267  align(ofs,is_first_parameter,indent);
268 
269  ofs << "*((" << wsv_group_names[vgo[j]]
270  << " *)ws[mr.Out()[" << j+vo.nelem()
271  << "]])";
272  }
273 
274  // Write the Generic output workspace variable names:
275  if (mdd.PassWsvNames())
276  {
277  for (Index j=0; j<vgo.nelem(); ++j)
278  {
279  // Add comma and line break, if not first element:
280  align(ofs,is_first_parameter,indent);
281 
282  ofs << "Workspace::wsv_data[mr.Out()["
283  << j+vo.nelem()
284  << "]].Name()";
285  }
286  }
287 
288  // Write the Input workspace variables:
289  for (Index j=0; j<vi.nelem(); ++j)
290  {
291  // Add comma and line break, if not first element:
292  align(ofs,is_first_parameter,indent);
293 
294  if (wsv_data[vi[j]].Group() == get_wsv_group_id("Agenda"))
295  {
296  ofs << "*(("
297  << wsv_group_names[wsv_data[vi[j]].Group()]
298  << " *)ws[mr.In()[" << j
299  << "]])";
300  }
301  else
302  {
303  ofs << "*(("
304  << wsv_group_names[wsv_data[vi[j]].Group()]
305  << " *)ws[mr.In()[" << j
306  << "]])";
307  }
308  }
309 
310  // Write the control parameters:
311  {
312  if (mdd.SetMethod())
313  {
314  // Add comma and line break, if not first element:
315  align(ofs,is_first_parameter,indent);
316 
317  ofs << "mr.SetValue()";
318  }
319  else
320  {
321  // Write the Generic input workspace variables:
322  for (Index j=0; j<vgi.nelem(); ++j)
323  {
324  // Check by assert whether the group identifier is too
325  // large to correspond to a group. This can easily
326  // happen if somebody puts a variable identifier instead
327  // of a group identifier in the argument of GINPUT:
328  assert( vgi[j] < wsv_group_names.nelem() );
329 
330  // Add comma and line break, if not first element:
331  align(ofs,is_first_parameter,indent);
332 
333  ofs << "*((" << wsv_group_names[vgi[j]]
334  << " *)ws[mr.In()[" << j+vi.nelem()
335  << "]])";
336  }
337 
338  // Write the Generic input workspace variable names:
339  if (mdd.PassWsvNames())
340  {
341  for (Index j=0; j<vgi.nelem(); ++j)
342  {
343  // Add comma and line break, if not first element:
344  align(ofs,is_first_parameter,indent);
345 
346  ofs << "Workspace::wsv_data[mr.In()["
347  << j+vi.nelem()
348  << "]].Name()";
349  }
350  }
351  }
352  }
353 
354  // Write the agenda, if there is one.
355  if ( mdd.AgendaMethod() )
356  {
357  align(ofs,is_first_parameter,indent);
358  ofs << "mr.Tasks()";
359  }
360 
361  // Flag that is set to false if the WSM has verbosity as an input or
362  // output already. Otherwise it's passed as the last parameter.
363  bool pass_verbosity = true;
364 
365  // Find out if the WSM has the verbosity as input.
366  for (Index j = 0; pass_verbosity && j < mdd.In().nelem(); j++)
367  {
368  if (wsv_data[mdd.In()[j]].Name() == "verbosity")
369  {
370  pass_verbosity = false;
371  }
372  }
373 
374  // Find out if the WSM has the verbosity as output.
375  for (Index j = 0; pass_verbosity && j < mdd.Out().nelem(); j++)
376  {
377  if (wsv_data[mdd.Out()[j]].Name() == "verbosity")
378  {
379  pass_verbosity = false;
380  }
381  }
382 
383  if (pass_verbosity)
384  {
385  static Index verbosity_wsv_id = get_wsv_id("verbosity");
386  static Index verbosity_group_id = get_wsv_group_id("Verbosity");
387  align(ofs,is_first_parameter,indent);
388  ofs << "*((" << wsv_group_names[verbosity_group_id]
389  << " *)ws[" << verbosity_wsv_id
390  << "])";
391  }
392 
393  ofs << ");\n";
394  ofs << "}\n\n";
395  }
396 
397  // Add getaways, the array that hold pointers to the getaway functions:
398  {
399  String indent = " ";
400  bool is_first_parameter = true;
401 
402  ofs << "// The array holding the pointers to the getaway functions.\n"
403  << "void (*getaways[])(Workspace&, const MRecord&)\n"
404  << " = {";
405  for (Index i=0; i<n_md; ++i)
406  {
407  const MdRecord& mdd = md_data[i];
408 
409  // Add comma and line break, if not first element:
410  align(ofs,is_first_parameter,indent);
411 
412  if ( mdd.Supergeneric() )
413  {
414  ofs << mdd.Name()
415  << "_sg_" << mdd.ActualGroups()
416  << "_g";
417  }
418  else
419  {
420  ofs << mdd.Name() << "_g";
421  }
422  }
423  ofs << "};\n\n";
424  }
425 
426 
427  // Create implementation of the agenda wrappers
428 
429  // Initialize agenda data.
432 
433  extern const Array<AgRecord> agenda_data;
434  for (Index i = 0; i < agenda_data.nelem (); i++)
435  {
436  const AgRecord& agr = agenda_data[i];
437  const ArrayOfIndex& ago = agr.Out();
438  const ArrayOfIndex& agi = agr.In();
439  ostringstream ain_push_os, ain_pop_os;
440  ostringstream aout_push_os, aout_pop_os;
441 
442  write_agenda_wrapper_header (ofs, agr);
443 
444  ofs << "\n";
445  ofs << "{\n";
446 
447  if (ago.nelem () || agi.nelem ())
448  {
449  ofs << " extern map<String, Index> AgendaMap;\n"
450  << " extern const Array<AgRecord> agenda_data;\n"
451  << "\n"
452  << " const AgRecord& agr =\n"
453  << " agenda_data[AgendaMap.find (input_agenda.name ())->second];\n"
454  << "\n";
455  }
456  if (ago.nelem ())
457  {
458  for (Index j = 0; j < ago.nelem (); j++)
459  {
460  // Mark agenda output-only variables as uninitialized
461  ArrayOfIndex::const_iterator it = agi.begin ();
462  while (it != agi.end () && *it != ago[j]) it++;
463  if (it == agi.end ())
464  {
465  aout_push_os << " ws.push_uninitialized (aout[" << j << "], "
466  << "(void *)&" << wsv_data[ago[j]].Name () << ");\n";
467  }
468  else
469  {
470  aout_push_os << " ws.push (aout[" << j << "], "
471  << "(void *)&" << wsv_data[ago[j]].Name () << ");\n";
472  }
473  aout_pop_os << " ws.pop (aout[" << j << "]);\n";
474  }
475  }
476  if (agi.nelem ())
477  {
478  for (Index j = 0; j < agi.nelem (); j++)
479  {
480  // Ignore Input parameters that are also output
481  ArrayOfIndex::const_iterator it = ago.begin ();
482  while (it != ago.end () && *it != agi[j]) it++;
483  if (it == ago.end ())
484  {
485  ain_push_os << " ws.push (ain[" << j << "], "
486  << "(void *)&" << wsv_data[agi[j]].Name () << ");\n";
487  ain_pop_os << " ws.pop (ain[" << j << "]);\n";
488  }
489  }
490  }
491 
492  if (aout_push_os.str().length())
493  {
494  ofs << " const ArrayOfIndex& aout = agr.Out();\n";
495  ofs << aout_push_os.str () << "\n";
496  }
497  if (ain_push_os.str().length())
498  {
499  ofs << " const ArrayOfIndex& ain = agr.In();\n";
500  ofs << ain_push_os.str () << "\n";
501  }
502 
503  ofs << " const ArrayOfIndex& outputs_to_push = input_agenda.get_output2push();\n"
504  << " const ArrayOfIndex& outputs_to_dup = input_agenda.get_output2dup();\n"
505  << "\n"
506  << " for (ArrayOfIndex::const_iterator it = outputs_to_push.begin ();\n"
507  << " it != outputs_to_push.end (); it++)\n"
508  << " { ws.push (*it, NULL); }\n"
509  << "\n"
510  << " for (ArrayOfIndex::const_iterator it = outputs_to_dup.begin ();\n"
511  << " it != outputs_to_dup.end (); it++)\n"
512  << " { ws.duplicate (*it); }\n"
513  << "\n";
514 
515  ofs << " String agenda_error_msg;\n"
516  << " bool agenda_failed = false;\n\n"
517  << " try {\n"
518  << " input_agenda.execute (ws);\n"
519  << " } catch (runtime_error e) {\n"
520  << " ostringstream os;\n"
521  << " os << \"Run-time error in agenda: \"\n"
522  << " << input_agenda.name() << \'\\n\' << e.what();\n"
523  << " agenda_failed = true;\n"
524  << " agenda_error_msg = os.str();\n"
525  << " }\n";
526 
527  ofs << " for (ArrayOfIndex::const_iterator it = outputs_to_push.begin ();\n"
528  << " it != outputs_to_push.end (); it++)\n"
529  << " { ws.pop_free (*it); }\n"
530  << "\n"
531  << " for (ArrayOfIndex::const_iterator it = outputs_to_dup.begin ();\n"
532  << " it != outputs_to_dup.end (); it++)\n"
533  << " { ws.pop_free (*it); }\n\n";
534 
535  if (aout_pop_os.str().length())
536  {
537  ofs << aout_pop_os.str () << "\n";
538  }
539  if (ain_pop_os.str().length())
540  {
541  ofs << ain_pop_os.str () << "\n";
542  }
543 
544  ofs << " if (agenda_failed) throw runtime_error (agenda_error_msg);\n\n";
545 
546  ofs << "}\n\n";
547  }
548 
549 
550  // Create implementation of the GroupCreate WSMs
551  //
552  for (ArrayOfString::const_iterator it = wsv_group_names.begin();
553  it != wsv_group_names.end(); it++)
554  {
555  if (*it != "Any")
556  {
557  ofs
558  << "/* Workspace method: Doxygen documentation will be auto-generated */\n"
559  << "void " << *it << "Create(" << *it << "& var, const Verbosity&)\n"
560  << "{ ";
561 
562  // Treat atomic types separately.
563  // For objects the default constructor is used.
564  if (*it == "Index")
565  ofs << "var = 0;";
566  else if (*it == "Numeric")
567  ofs << "var = 0.;";
568  else
569  ofs << "var = " << *it << "();";
570 
571  ofs << " }\n\n";
572  }
573  }
574  }
575  catch (runtime_error x)
576  {
577  cout << "Something went wrong. Message text:\n";
578  cout << x.what() << '\n';
579  return 1;
580  }
581 
582  return 0;
583 }
agenda_record.h
Declarations for AgRecord, storing lookup information for one agenda.
main
int main()
Definition: make_auto_md_cc.cc:39
Workspace::wsv_data
static Array< WsvRecord > wsv_data
Definition: workspace_ng.h:59
MdRecord::Supergeneric
bool Supergeneric() const
Definition: methods.h:108
MdRecord::GOutType
const ArrayOfIndex & GOutType() const
Definition: methods.h:94
DUMMY_COLS
#define DUMMY_COLS
define_agenda_data
void define_agenda_data()
Definition: agendas.cc:43
MdRecord::GInType
const ArrayOfIndex & GInType() const
Definition: methods.h:99
MdRecord::PassWsvNames
bool PassWsvNames() const
Definition: methods.h:111
get_wsv_id
Index get_wsv_id(const String &name)
Get index of WSV.
Definition: workspace.cc:4555
MdRecord::SetMethod
bool SetMethod() const
Definition: methods.h:106
align
void align(ofstream &ofs, bool &is_first_parameter, const String &indent)
Definition: make_auto_md_cc.cc:26
array.h
This file contains the definition of Array.
DUMMY_ROWS
#define DUMMY_ROWS
MdRecord::OutOnly
const ArrayOfIndex & OutOnly() const
Definition: methods.h:105
Array
This can be used to make arrays out of anything.
Definition: array.h:103
MdRecord::ActualGroups
const String & ActualGroups() const
Definition: methods.h:112
agenda_data
Array< AgRecord > agenda_data
Definition: agendas.cc:40
write_agenda_wrapper_header
void write_agenda_wrapper_header(ofstream &ofs, const AgRecord &agr)
Write a agenda wrapper header.
Definition: agenda_record.cc:279
AgRecord
Lookup information for one agenda.
Definition: agenda_record.h:44
my_basic_string
The implementation for String, the ARTS string class.
Definition: mystring.h:62
MdRecord::AgendaMethod
bool AgendaMethod() const
Definition: methods.h:107
Workspace::define_wsv_data
static void define_wsv_data()
Definition: workspace.cc:50
wsv_group_names
ArrayOfString wsv_group_names
Definition: groups.cc:40
expand_md_data_raw_to_md_data
void expand_md_data_raw_to_md_data()
Expand supergeneric methods.
Definition: methods_aux.cc:364
DUMMY_ELEMS
#define DUMMY_ELEMS
define_wsv_group_names
void define_wsv_group_names()
Define the array of workspace variable group names.
Definition: groups.cc:80
MdRecord::Name
const String & Name() const
Definition: methods.h:89
MdRecord::In
const ArrayOfIndex & In() const
Definition: methods.h:97
MdRecord::InOnly
const ArrayOfIndex & InOnly() const
Definition: methods.h:103
open_output_file
void open_output_file(ofstream &file, const String &name)
Open a file for writing.
Definition: file.cc:97
my_basic_string::nelem
Index nelem() const
Number of elements.
Definition: mystring.h:242
AgRecord::In
const ArrayOfIndex & In() const
Definition: agenda_record.h:66
md_data
Array< MdRecord > md_data
Lookup information for workspace methods.
Definition: globals_2.cc:62
workspace_ng.h
This file contains the declaration and partly the implementation of the workspace class.
MdRecord
All information for one workspace method.
Definition: methods.h:42
String
my_basic_string< char > String
The String type for ARTS.
Definition: mystring.h:305
DUMMY_PAGES
#define DUMMY_PAGES
file.h
This file contains basic functions to handle ASCII files.
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
MdRecord::Out
const ArrayOfIndex & Out() const
Definition: methods.h:92
Workspace::define_wsv_map
static void define_wsv_map()
Definition: workspace_ng.cc:50
get_wsv_group_id
Index get_wsv_group_id(const String &name)
Definition: groups.cc:192
AgRecord::Out
const ArrayOfIndex & Out() const
Definition: agenda_record.h:65
MdRecord::PassWorkspace
bool PassWorkspace() const
Definition: methods.h:110
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:172
methods.h
Declaration of the class MdRecord.
define_md_data_raw
void define_md_data_raw()
Definition: methods.cc:121
arts.h
The global header file for ARTS.