1#!/bin/sh
2#
3# aegis - project change supervisor.
4# Copyright (C) 2008, 2011, 2012 Peter Miller
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 3 of the License, or (at
9# your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14# General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18#
19
20TEST_SUBJECT="fmtgen, enum"
21
22# load up standard prelude and test functions
23. test_funcs
24
25cat > fubar.def << 'fubar'
26x = (one, two, three);
27fubar
28if test $? -ne 0 ; then no_result; fi
29
30cat > ok.cc << 'TheEnd'
31//
32// This file is generated by fmtgen.
33//
34#include <fubar.h>
35#include <common/sizeof.h>
36
37static const char *fubar_x_s[] =
38{
39  "one",
40  "two",
41  "three",
42};
43static string_ty *fubar_x_f[SIZEOF(fubar_x_s)];
44#include <common/ac/stdio.h>
45
46const char *
47fubar_x_ename(fubar_x_ty this_thing)
48{
49  static char buffer[20];
50
51  if ((int)this_thing >= 0 && (int)this_thing < 3)
52    return fubar_x_s[this_thing];
53  snprintf(buffer, sizeof(buffer), "%d", (int)this_thing);
54  return buffer;
55}
56
57void
58fubar_x_write(const output::pointer &fp, const char *name, fubar_x_ty this_thing, bool show)
59{
60  if (this_thing == 0)
61  {
62    if (!show || type_enum_option_query())
63      return;
64  }
65  if (name)
66  {
67    fp->fputs(name);
68    fp->fputs(" = ");
69  }
70  fp->fputs(fubar_x_s[this_thing]);
71  if (name)
72    fp->fputs(";\n");
73}
74#include <common/ac/assert.h>
75
76void
77fubar_x_write_xml(const output::pointer &fp, const char *name, fubar_x_ty this_thing, bool show)
78{
79  if (this_thing == 0)
80  {
81    if (!show || type_enum_option_query())
82      return;
83  }
84  assert(name);
85  assert(this_thing < fubar_x_max);
86  fp->fputc('<');
87  fp->fputs(name);
88  fp->fputc('>');
89  fp->fputs(fubar_x_s[this_thing]);
90  fp->fputs("</");
91  fp->fputs(name);
92  fp->fputs(">\n");
93}
94#include <common/str.h>
95
96static bool
97fubar_x_parse(string_ty *name, void *ptr)
98{
99  slow_to_fast(fubar_x_s, fubar_x_f, SIZEOF(fubar_x_s));
100  for (size_t j = 0; j < SIZEOF(fubar_x_f); ++j)
101  {
102    if (str_equal(name, fubar_x_f[j]))
103    {
104      *(fubar_x_ty *)ptr = (fubar_x_ty)j;
105      return true;
106    }
107  }
108  return false;
109}
110#include <libaegis/meta_type.h>
111
112static string_ty *
113fubar_x_fuzzy(string_ty *name)
114{
115  return generic_enum_fuzzy(name, fubar_x_f, SIZEOF(fubar_x_f));
116}
117
118static rpt_value::pointer
119fubar_x_convert(void *this_thing)
120{
121  if (!fubar_x_f[0])
122    slow_to_fast(fubar_x_s, fubar_x_f, SIZEOF(fubar_x_s));
123  return
124    generic_enum_convert
125    (
126      (int)*(fubar_x_ty *)this_thing,
127      fubar_x_f,
128      SIZEOF(fubar_x_f)
129    );
130}
131
132static bool
133fubar_x_is_set(void *this_thing)
134{
135  return (*(fubar_x_ty *)this_thing != 0);
136}
137
138meta_type fubar_x_type =
139{
140  "fubar_x",
141  0, // alloc
142  0, // free
143  fubar_x_parse,
144  0, // list_parse
145  0, // struct_parse
146  fubar_x_fuzzy,
147  fubar_x_convert,
148  fubar_x_is_set,
149};
150
151void
152fubar_x__rpt_init()
153{
154  generic_enum__init(fubar_x_s, SIZEOF(fubar_x_s));
155}
156#include <common/trace.h>
157#include <libaegis/output.h>
158
159void
160fubar_write(const output::pointer &fp, fubar_ty *this_thing)
161{
162  if (!this_thing)
163    return;
164  trace(("fubar_write(this_thing = %p)\n{\n", this_thing));
165  assert(((fubar_ty *)this_thing)->reference_count > 0);
166  trace(("rc = %ld;\n", ((fubar_ty *)this_thing)->reference_count));
167  fubar_x_write(fp, "x", this_thing->x, 1);
168  trace(("}\n"));
169}
170
171void
172fubar_write_xml(const output::pointer &fp, fubar_ty *this_thing)
173{
174  if (!this_thing)
175    return;
176  trace(("fubar_write_xml(this_thing = %p)\n{\n", this_thing));
177  assert(((fubar_ty *)this_thing)->reference_count > 0);
178  trace(("rc = %ld;\n", ((fubar_ty *)this_thing)->reference_count));
179  fp->fputs("<fubar>\n");
180  fubar_x_write_xml(fp, "x", this_thing->x, 0);
181  fp->fputs("</fubar>\n");
182}
183#include <common/mem.h>
184#include <libaegis/meta_lex.h>
185
186static void *
187fubar_alloc(void)
188{
189  fubar_ty *this_thing;
190
191  trace(("fubar_alloc()\n{\n"));
192  this_thing = (fubar_ty *)mem_alloc(sizeof(fubar_ty));
193  this_thing->reference_count = 1;
194  this_thing->mask = 0;
195  this_thing->errpos = str_copy(lex_position());
196  this_thing->x = (fubar_x_ty)0;
197  trace(("return %p;\n", this_thing));
198  trace(("}\n"));
199  return this_thing;
200}
201
202fubar_ty *
203fubar_copy(fubar_ty *this_thing)
204{
205  trace(("fubar_copy()\n{\n"));
206  this_thing->reference_count++;
207  trace(("return %p;\n", this_thing));
208  trace(("}\n"));
209  return this_thing;
210}
211
212fubar_ty *
213fubar_clone(fubar_ty *this_thing)
214{
215  if (!this_thing)
216    return 0;
217  trace(("fubar_clone()\n{\n"));
218  fubar_ty *result = (fubar_ty *)fubar_alloc();
219  result->x = this_thing->x;
220  trace(("return %p;\n", result));
221  trace(("}\n"));
222  return result;
223}
224
225#ifdef DEBUG
226
227void
228fubar_trace_real(const char *name, const fubar_ty *value)
229{
230  if (name && *name)
231  {
232    trace_printf("%s = ", name);
233  }
234  if (!value)
235  {
236    trace_printf("NULL");
237  }
238  else
239  {
240    trace_printf("{\n");
241    trace_printf("x = %s;\n", fubar_x_ename(value->x));
242    trace_printf("}");
243  }
244  trace_printf((name && *name) ? ";\n" : ",\n");
245}
246
247#endif // DEBUG
248
249static void
250fubar_free(void *that)
251{
252  fubar_ty *this_thing;
253
254  this_thing = (fubar_ty *)that;
255  if (!this_thing)
256    return;
257  this_thing->reference_count--;
258  assert(this_thing->reference_count >= 0);
259  if (this_thing->reference_count > 0)
260    return;
261  trace(("fubar_free(this_thing = %p)\n{\n", this_thing));
262  if (this_thing->errpos)
263  {
264    str_free(this_thing->errpos);
265    this_thing->errpos = 0;
266  }
267  mem_free(this_thing);
268  trace(("}\n"));
269}
270
271static type_table_ty fubar_table[] =
272{
273  {
274    "x",
275    offsetof(fubar_ty, x),
276    &fubar_x_type,
277    fubar_x_mask,
278    0, // redefinition not ok
279    0, // fast_name
280  },
281};
282
283static void *
284fubar_parse(void *this_thing, string_ty *name, meta_type **type_pp, unsigned long *mask_p, int *redef_p)
285{
286  void *addr;
287
288  trace(("fubar_parse(this_thing = %p, name = %p, type_pp = %p)\n{\n", this_thing, name, type_pp));
289  assert(((fubar_ty *)this_thing)->reference_count > 0);
290  addr =
291    generic_struct_parse
292    (
293      this_thing,
294      name,
295      type_pp,
296      mask_p,
297      redef_p,
298      fubar_table,
299      SIZEOF(fubar_table)
300    );
301  trace(("return %p;\n}\n", addr));
302  return addr;
303}
304
305static string_ty *
306fubar_fuzzy(string_ty *name)
307{
308  string_ty *result;
309
310  trace(("fubar_fuzzy(name = %p)\n{\n", name));
311  result =
312    generic_struct_fuzzy
313    (
314      name,
315      fubar_table,
316      SIZEOF(fubar_table)
317    );
318  trace(("return %p;\n", result));
319  trace(("}\n"));
320  return result;
321}
322
323static rpt_value::pointer
324fubar_convert(void *this_thing)
325{
326  trace(("fubar_convert(name = %p)\n{\n", this_thing));
327  assert(((fubar_ty *)this_thing)->reference_count > 0);
328  rpt_value::pointer result =
329    generic_struct_convert
330    (
331      this_thing,
332      fubar_table,
333      SIZEOF(fubar_table)
334    );
335  trace(("return %p;\n", result.get()));
336  trace(("}\n"));
337  return result;
338}
339
340meta_type fubar_type =
341{
342  "fubar",
343  fubar_alloc,
344  fubar_free,
345  0, // enum_parse
346  0, // list_parse
347  fubar_parse,
348  fubar_fuzzy,
349  fubar_convert,
350  generic_struct_is_set,
351};
352
353fubar_ty *
354fubar_read_file(const nstring &filename)
355{
356  return fubar_read_file(filename.get_ref());
357}
358#include <libaegis/meta_parse.h>
359#include <libaegis/os.h>
360
361fubar_ty *
362fubar_read_file(string_ty *filename)
363{
364  fubar_ty *result;
365
366  trace(("fubar_read_file(filename = \"%s\")\n{\n", (filename ? filename->str_text : "")));
367  os_become_must_be_active();
368  result = (fubar_ty *)parse(filename, &fubar_type);
369  trace(("return %p;\n", result));
370  trace(("}\n"));
371  return result;
372}
373
374void
375fubar_write_file(const nstring &filename, fubar_ty *value, bool comp)
376{
377  fubar_write_file(filename.get_ref(), value, comp);
378}
379#include <libaegis/io.h>
380#include <libaegis/output/file.h>
381#include <libaegis/output/filter/gzip.h>
382#include <libaegis/output/filter/indent.h>
383
384void
385fubar_write_file(string_ty *filename, fubar_ty *value, int needs_compression)
386{
387  trace(("fubar_write_file(filename = \"%s\", value = %p)\n{\n", (filename ? filename->str_text : ""), value));
388  if (filename)
389    os_become_must_be_active();
390  output::pointer fp;
391  if (needs_compression)
392  {
393    fp = output_file::binary_open(filename);
394    fp = output_filter_gzip::create(fp);
395  }
396  else
397  {
398    fp = output_file::text_open(filename);
399  }
400  fp = output_filter_indent::create(fp);
401  io_comment_emit(fp);
402  fubar_write(fp, value);
403  type_enum_option_clear();
404  trace(("}\n"));
405}
406
407void
408fubar__rpt_init(void)
409{
410  trace(("fubar__rpt_init()\n{\n"));
411  fubar_x__rpt_init();
412  trace(("}\n"));
413}
414TheEnd
415if test $? -ne 0 ; then no_result; fi
416
417cat > ok.h << 'TheEnd'
418//
419// This file is generated by fmtgen.
420//
421
422#ifndef FUBAR_H
423#define FUBAR_H
424#include <libaegis/meta_type.h>
425#include <libaegis/output.h>
426
427#ifndef fubar_x_DEF
428#define fubar_x_DEF
429enum fubar_x_ty
430{
431  fubar_x_one,
432  fubar_x_two,
433  fubar_x_three
434};
435#define fubar_x_max 3
436#endif // fubar_x_DEF
437
438extern meta_type fubar_x_type;
439
440void fubar_x_write(const output::pointer &fp, const char *name, fubar_x_ty value, bool show);
441void fubar_x_write_xml(const output::pointer &fp, const char *name, fubar_x_ty value, bool show);
442const char *fubar_x_ename(fubar_x_ty);
443void fubar_x__rpt_init(void);
444
445#ifndef fubar_DEF
446#define fubar_DEF
447
448#define fubar_x_mask  ((unsigned long)1 << 0)
449
450#include <common/str.h>
451struct fubar_ty
452{
453  long reference_count;
454  unsigned long mask;
455  string_ty *errpos;
456  fubar_x_ty x;
457};
458#endif // fubar_DEF
459
460extern meta_type fubar_type;
461
462void fubar_write(const output::pointer &fp, fubar_ty *value);
463void fubar_write_xml(const output::pointer &fp, fubar_ty *value);
464fubar_ty *fubar_copy(fubar_ty *);
465fubar_ty *fubar_clone(fubar_ty *);
466#include <common/debug.h>
467#ifndef fubar_trace
468#ifdef DEBUG
469void fubar_trace_real(const char *name, const fubar_ty *value);
470#define fubar_trace(x) ((void)(trace_pretest_ && (trace_where_, fubar_trace_real(trace_stringize(x), x), 0)))
471#else
472#define fubar_trace(x)
473#endif
474#endif
475
476/**
477* The fubar_write_file function is used to
478* write fubar meta data to the named file.
479*
480* @param filename
481*     The name of the file to be written.
482* @param value
483*     The value of the meta-data to be written.
484* @param comp
485*     true (non-zero) if data should be compressed.
486* @note
487*      If any errors are encountered, this
488*      function will not return.  All errors
489*      will print a fatal error message, and
490*      exit with an exit status of 1.
491*/
492void fubar_write_file(string_ty *filename, fubar_ty *value, int comp);
493#include <common/nstring.h>
494
495/**
496* The fubar_write_file function is used to
497* write fubar meta data to the named file.
498*
499* @param filnam
500*     The name of the file to be written.
501* @param value
502*     The value of the meta-data to be written.
503* @param comp
504*     true if data should be compressed.
505* @note
506*      If any errors are encountered, this
507*      function will not return.  All errors
508*      will print a fatal error message, and
509*      exit with an exit status of 1.
510*/
511void fubar_write_file(const nstring &filnam, fubar_ty *value, bool comp);
512
513/**
514* The fubar_read_file function is used to
515* read fubar meta data from the named file.
516*
517* @param filename
518*     The name of the file to be read.
519* @returns
520*     a pointer to a dynamically allocated
521*     value read from the file.
522* @note
523*      If any errors are encountered, this
524*      function will not return.  All errors
525*      (including syntax errors) will print a
526*      fatal error message, and exit with an
527*      exit status of 1.
528*/
529fubar_ty *fubar_read_file(string_ty *filename);
530
531/**
532* The fubar_read_file function is used to
533* read fubar meta data from the named file.
534*
535* @param filename
536*     The name of the file to be read.
537* @returns
538*     a pointer to a dynamically allocated
539*     value read from the file.
540* @note
541*      If any errors are encountered, this
542*      function will not return.  All errors
543*      (including syntax errors) will print a
544*      fatal error message, and exit with an
545*      exit status of 1.
546*/
547fubar_ty *fubar_read_file(const nstring &filename);
548void fubar__rpt_init(void);
549
550#endif // FUBAR_H
551TheEnd
552if test $? -ne 0 ; then no_result; fi
553
554#
555# test the functionality
556#
557activity="fmtgen-oc 546"
558fmtgen -tw=2 fubar.def -oc fubar.cc -oi fubar.h
559if test $? -ne 0 ; then fail; fi
560
561diff ok.cc fubar.cc
562if test $? -ne 0 ; then fail; fi
563
564diff ok.h fubar.h
565if test $? -ne 0 ; then fail; fi
566
567#
568# Only definite negatives are possible.
569# The functionality exercised by this test appears to work,
570# no other guarantees are made.
571#
572pass
573
574
575// vim: set ts=8 sw=4 et :
576