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