A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 751 lines 26 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2013 by Amaury Pouly 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#include "soc_desc_v1.hpp" 22#include <stdio.h> 23#include <stdlib.h> 24#include <algorithm> 25#include <map> 26#include <sstream> 27#include <sys/stat.h> 28#include <sys/types.h> 29#include <getopt.h> 30 31using namespace soc_desc_v1; 32 33#define HEADERGEN_VERSION "2.1.8" 34 35#define error(...) do{ fprintf(stderr, __VA_ARGS__); exit(1); } while(0) 36 37bool g_gen_selector = false; 38 39std::string g_macro_filename; 40 41std::string g_soc_name; 42std::string g_soc_dev; 43std::string g_soc_reg; 44std::string g_soc_field; 45std::string g_soc_dev_regs_base; 46 47namespace { 48std::string tolower(const std::string s) 49{ 50 std::string res = s; 51 std::transform(res.begin(), res.end(), res.begin(), ::tolower); 52 return res; 53} 54 55std::string toupper(const std::string& s) 56{ 57 std::string res = s; 58 std::transform(res.begin(), res.end(), res.begin(), ::toupper); 59 return res; 60} 61} 62 63template< typename T > 64std::string to_str(const T& v) 65{ 66 std::ostringstream oss; 67 oss << v; 68 return oss.str(); 69} 70 71template< typename T > 72std::string to_hex(const T& v) 73{ 74 std::ostringstream oss; 75 oss << std::hex << v; 76 return oss.str(); 77} 78 79typedef std::pair< std::string, std::string > xml_ver_t; 80 81void fprint_copyright(FILE *f, const std::vector< xml_ver_t >& versions, char const *author) 82{ 83 std::ostringstream ver; 84 time_t t = time(NULL); 85 struct tm tm = *localtime(&t); 86 87 for(size_t i = 0; i < versions.size(); i++) 88 ver << " " << versions[i].first << ":" << versions[i].second; 89 90 fprintf(f,"\ 91/***************************************************************************\n\ 92 * __________ __ ___.\n\ 93 * Open \\______ \\ ____ ____ | | _\\_ |__ _______ ___\n\ 94 * Source | _// _ \\_/ ___\\| |/ /| __ \\ / _ \\ \\/ /\n\ 95 * Jukebox | | ( <_> ) \\___| < | \\_\\ ( <_> > < <\n\ 96 * Firmware |____|_ /\\____/ \\___ >__|_ \\|___ /\\____/__/\\_ \\\n\ 97 * \\/ \\/ \\/ \\/ \\/\n\ 98 * This file was automatically generated by headergen, DO NOT EDIT it.\n\ 99 * headergen version: " HEADERGEN_VERSION "\n"); 100 if(versions.size() > 0) 101 fprintf(f, " * XML versions:%s\n", ver.str().c_str()); 102 fprintf(f,"\ 103 *\n\ 104 * Copyright (C) "); 105 fprintf(f, "%d by %s\n", 1900+tm.tm_year, author); 106 fprintf(f,"\ 107 *\n\ 108 * This program is free software; you can redistribute it and/or\n\ 109 * modify it under the terms of the GNU General Public License\n\ 110 * as published by the Free Software Foundation; either version 2\n\ 111 * of the License, or (at your option) any later version.\n\ 112 *\n\ 113 * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY\n\ 114 * KIND, either express or implied.\n\ 115 *\n\ 116 ****************************************************************************/\n"); 117} 118 119void fprint_copyright(FILE *f, const xml_ver_t& version, char const *author) 120{ 121 fprint_copyright(f, std::vector< xml_ver_t >(1, version), author); 122} 123 124void fprint_copyright(FILE *f, char const *author) 125{ 126 fprint_copyright(f, std::vector< xml_ver_t >(), author); 127} 128 129void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name) 130{ 131 if(begin) 132 { 133 fprintf(f, "#ifndef %s\n", name.c_str()); 134 fprintf(f, "#define %s\n", name.c_str()); 135 } 136 else 137 fprintf(f, "#endif /* %s */\n", name.c_str()); 138} 139 140void fprint_include_guard(FILE *f, bool begin) 141{ 142 std::string name = "__HEADERGEN__" + toupper(g_soc_name) + "__" + toupper(g_soc_dev) 143 + "__H__"; 144 fprint_include_guard_ex(f, begin, name); 145} 146 147struct limited_column_context_t 148{ 149 limited_column_context_t(size_t nr_col = 80) 150 :m_nr_col(nr_col), m_prevent_wordcut(true) {} 151 void set_prefix(const std::string& prefix) { m_prefix = prefix; } 152 void add(const std::string& text) 153 { 154 for(size_t i = 0; i < text.size();) 155 { 156 size_t offset = 0; 157 if(m_cur_line.size() == 0) 158 m_cur_line = m_prefix; 159 size_t len = std::min(text.size() - i, m_nr_col - m_cur_line.size()); 160 // prevent word cut 161 if(m_prevent_wordcut && !isspace(text[i + len - 1]) && 162 i + len < text.size() && !isspace(text[i + len])) 163 { 164 size_t pos = text.find_last_of(" \t\n\v\r\f", i + len - 1); 165 if(pos == std::string::npos || pos < i) 166 len = 0; 167 else 168 len = pos - i + 1; 169 } 170 size_t pos = text.find('\n', i); 171 if(pos != std::string::npos && pos <= i + len) 172 { 173 offset = 1; 174 len = pos - i; 175 } 176 m_cur_line += text.substr(i, len); 177 // len == 0 means we need a new line 178 if(m_cur_line.size() == m_nr_col || len == 0) 179 { 180 m_lines.push_back(m_cur_line); 181 m_cur_line = ""; 182 } 183 i += len + offset; 184 } 185 } 186 187 std::string to_string() 188 { 189 std::string str; 190 for(size_t i = 0; i < m_lines.size(); i++) 191 str += m_lines[i] + "\n"; 192 if(m_cur_line.size() != 0) 193 str += m_cur_line + "\n"; 194 return str; 195 } 196 197 void print(FILE *f) 198 { 199 fprintf(f, "%s", to_string().c_str()); 200 } 201 202 std::vector< std::string > m_lines; 203 std::string m_cur_line; 204 std::string m_prefix; 205 size_t m_nr_col; 206 bool m_prevent_wordcut; 207}; 208 209struct define_align_context_t 210{ 211 define_align_context_t():m_max_name(0) {} 212 void add(const std::string& name, const std::string& val) 213 { 214 m_lines.push_back(std::make_pair(name, val)); 215 m_max_name = std::max(m_max_name, name.size()); 216 } 217 218 void add_raw(const std::string& line) 219 { 220 m_lines.push_back(std::make_pair("", line)); 221 } 222 223 void print(FILE *f) 224 { 225 std::string define = "#define "; 226 size_t align = define.size() + m_max_name + 1; 227 align = ((align + 3) / 4) * 4; 228 229 for(size_t i = 0; i < m_lines.size(); i++) 230 { 231 std::string name = m_lines[i].first; 232 // raw entry ? 233 if(name.size() == 0) 234 { 235 fprintf(f, "%s", m_lines[i].second.c_str()); 236 continue; 237 } 238 name.insert(name.end(), align - define.size() - name.size(), ' '); 239 fprintf(f, "%s%s%s\n", define.c_str(), name.c_str(), m_lines[i].second.c_str()); 240 } 241 } 242 243 size_t m_max_name; 244 std::vector< std::pair< std::string, std::string > > m_lines; 245}; 246 247limited_column_context_t print_description(const std::string& desc, const std::string& prefix) 248{ 249 limited_column_context_t ctx; 250 if(desc.size() == 0) 251 return ctx; 252 ctx.set_prefix(prefix); 253 ctx.add(desc); 254 return ctx; 255} 256 257void fprint_description(FILE *f, const std::string& desc, const std::string& prefix) 258{ 259 limited_column_context_t ctx = print_description(desc, prefix); 260 ctx.print(f); 261} 262 263void fprint_description(define_align_context_t& ctx, const std::string& desc, const std::string& prefix) 264{ 265 limited_column_context_t ctx2 = print_description(desc, prefix); 266 ctx.add_raw(ctx2.to_string()); 267} 268 269void gen_soc_field(define_align_context_t& ctx, bool multidev, bool multireg, const soc_reg_field_t& field) 270{ 271 if(field.desc.size() != 0) 272 { 273 ctx.add_raw("/* Field: " + field.name + "\n"); 274 fprint_description(ctx, "Description: " + field.desc + " */\n", " * "); 275 } 276 277 std::string prefix = g_soc_dev + "_" + g_soc_reg + "_" + g_soc_field; 278 ctx.add("BP_" + prefix, to_str(field.first_bit)); 279 ctx.add("BM_" + prefix, "0x" + to_hex(field.bitmask())); 280 281 for(size_t i = 0; i < field.value.size(); i++) 282 ctx.add("BV_" + prefix + "__" + field.value[i].name, "0x" + to_hex(field.value[i].value)); 283 284 ctx.add("BF_" + prefix + "(v)", "(((v) << " + to_str(field.first_bit) + ") & 0x" + to_hex(field.bitmask()) + ")"); 285 286 if(field.value.size() > 0) 287 ctx.add("BF_" + prefix + "_V(v)", "((BV_" + prefix + "__##v" + " << " + to_str(field.first_bit) + ") & 0x" + to_hex(field.bitmask()) + ")"); 288} 289 290void gen_soc_reg(FILE *f, bool multidev, const soc_reg_t& reg, char const *author, char const *hwprefix) 291{ 292 bool multireg = reg.addr.size() > 1; 293 294 static const char *suffix[] = {"", "_SET", "_CLR", "_TOG"}; 295 bool sct = !!(reg.flags & REG_HAS_SCT); 296 297 // comment generator 298 fprintf(f, "/**\n"); 299 fprintf(f, " * Register: %s%s_%s\n", hwprefix, g_soc_dev.c_str(), g_soc_reg.c_str()); 300 fprintf(f, " * Address:"); 301 if(multireg && reg.formula.type == REG_FORMULA_STRING) 302 { 303 fprintf(f, " %s\n", reg.formula.string.c_str()); 304 } 305 else 306 { 307 for(size_t i = 0; i < reg.addr.size(); i++) 308 fprintf(f, " %#x", reg.addr[i].addr); 309 fprintf(f, "\n"); 310 } 311 fprintf(f, " * SCT: %s\n", sct ? "yes" : "no"); 312 if(reg.desc.size() != 0) 313 fprint_description(f, "Description: " + reg.desc, " * "); 314 fprintf(f, " */\n"); 315 316 define_align_context_t ctx; 317 318 if (multireg && reg.formula.type != REG_FORMULA_STRING) 319 { 320 for(int i=0; i < (int)reg.addr.size(); i++) 321 { 322 std::ostringstream name, value; 323 name << hwprefix << g_soc_dev << "_" << reg.addr[i].name; 324 if (multidev) 325 { 326 name << "(d)"; 327 } 328 value << "(*(volatile unsigned long *)(" << g_soc_dev_regs_base; 329 if (multidev) 330 { 331 value << "(d)"; 332 } 333 value << " + 0x" << std::hex << reg.addr[i].addr << "))"; 334 335 ctx.add(name.str(), value.str()); 336 } 337 } 338 else 339 { 340 for(int i = 0; i < (sct ? 4 : 1); i++) 341 { 342 std::ostringstream name; 343 name << hwprefix << g_soc_dev << "_" << g_soc_reg << suffix[i]; 344 if(multidev || multireg) 345 { 346 name << "("; 347 if(multidev) 348 name << "d"; 349 if(multidev && multireg) 350 name << ","; 351 if(multireg) 352 name << "n"; 353 name << ")"; 354 } 355 std::ostringstream value; 356 value << "(*(volatile unsigned long *)(" << g_soc_dev_regs_base; 357 if(multidev) 358 value << "(d)"; 359 value << " + "; 360 if(multireg) 361 { 362 std::string formula = reg.formula.string.c_str(); 363 size_t pos = formula.find("n"); 364 while(pos != std::string::npos) 365 { 366 formula.replace(pos, 1, "(n)"); 367 pos = formula.find("n", pos + 2); 368 } 369 value << formula; 370 } 371 else 372 value << "0x" << std::hex << reg.addr[0].addr; 373 374 if(sct) 375 value << " + 0x" << std::hex << (i * 4); 376 value << "))"; 377 378 ctx.add(name.str(), value.str()); 379 } 380 } 381 382 for(size_t i = 0; i < reg.field.size(); i++) 383 { 384 g_soc_field = reg.field[i].name; 385 gen_soc_field(ctx, multidev, multireg, reg.field[i]); 386 } 387 388 ctx.print(f); 389 390 fprintf(f, "\n"); 391} 392 393void gen_soc_dev_header(const std::string& filename, const xml_ver_t& ver, const soc_dev_t& dev, 394 char const *author, char const *hwprefix) 395{ 396 /* 397 printf("Generate headers for soc %s, dev %s: use file %s\n", g_soc_name.c_str(), 398 g_soc_dev.c_str(), filename.c_str()); 399 */ 400 FILE *f = fopen(filename.c_str(), "w"); 401 if(f == NULL) 402 { 403 printf("Cannot open %s for writing: %m\n", filename.c_str()); 404 return; 405 } 406 fprint_copyright(f, ver, author); 407 fprint_include_guard(f, true); 408 if(g_macro_filename.size() > 0) 409 fprintf(f, "#include \"%s\"\n", g_macro_filename.c_str()); 410 411 /* print base */ 412 fprintf(f, "\n"); 413 g_soc_dev_regs_base = "REGS_" + g_soc_dev + "_BASE"; 414 fprintf(f, "#define %s", g_soc_dev_regs_base.c_str()); 415 416 if(dev.addr.size() > 1) 417 fprintf(f, "(i)"); 418 fprintf(f, " ("); 419 420 for(size_t i = 0; i < dev.addr.size() - 1; i++) 421 fprintf(f, "(i) == %d ? %#x : ", (int)i + 1, dev.addr[i].addr); 422 423 fprintf(f, "%#x)\n", dev.addr[dev.addr.size() - 1].addr); 424 425 fprintf(f, "\n"); 426 427 /* print version */ 428 fprintf(f, "#define REGS_%s_VERSION \"%s\"\n\n", g_soc_dev.c_str(), dev.version.c_str()); 429 430 for(size_t i = 0; i < dev.reg.size(); i++) 431 { 432 g_soc_reg = dev.reg[i].name; 433 gen_soc_reg(f, dev.addr.size() > 1, dev.reg[i], author, hwprefix); 434 } 435 436 fprint_include_guard(f, false); 437 fclose(f); 438} 439 440void gen_soc_headers(const std::string& prefix, const soc_t& soc, char const *author, char const *hwprefix) 441{ 442 printf("Generate headers for soc %s: use directory %s\n", soc.name.c_str(), 443 prefix.c_str()); 444 mkdir(prefix.c_str(), 0770); 445 446 for(size_t i = 0; i < soc.dev.size(); i++) 447 { 448 g_soc_dev = soc.dev[i].name; 449 xml_ver_t ver(soc.name, soc.dev[i].version); 450 gen_soc_dev_header(prefix + "/regs-" + tolower(g_soc_dev.c_str()) + ".h", ver, soc.dev[i], author, hwprefix); 451 } 452} 453 454void gen_headers(const std::string& prefix, const std::vector< soc_t >& socs, char const *author, char const *hwprefix) 455{ 456 for(size_t i = 0; i < socs.size(); i++) 457 { 458 g_soc_name = socs[i].name; 459 std::string dir = prefix; 460 if(g_gen_selector) 461 dir += "/" + socs[i].name; 462 gen_soc_headers(dir, socs[i], author, hwprefix); 463 } 464} 465 466typedef std::map< std::string, std::vector< std::pair< size_t, size_t > > > general_dev_list_t; 467general_dev_list_t build_general_dev_list(const std::vector< soc_t >& socs) 468{ 469 general_dev_list_t map; 470 for(size_t i = 0; i < socs.size(); i++) 471 { 472 for(size_t j = 0; j < socs[i].dev.size(); j++) 473 map[tolower(socs[i].dev[j].name)].push_back(std::make_pair(i,j)); 474 } 475 return map; 476} 477 478void gen_select_header(const std::string& filename, const std::string& dev, 479 const std::vector< std::string >& socs, const std::vector< xml_ver_t >& ver, char const *author) 480{ 481 std::string guard = "__SELECT__" + toupper(dev) + "__H__"; 482 FILE *f = fopen(filename.c_str(), "w"); 483 if(f == NULL) 484 error("Cannot open file %s\n", filename.c_str()); 485 fprint_copyright(f, ver, author); 486 fprint_include_guard_ex(f, true, guard); 487 if(g_macro_filename.size() > 0) 488 fprintf(f, "#include \"%s\"\n", g_macro_filename.c_str()); 489 fprintf(f, "\n"); 490 491 for(size_t i = 0; i < socs.size(); i++) 492 { 493 fprintf(f, "#define %s_INCLUDE \"%s/regs-%s.h\"\n", 494 toupper(socs[i]).c_str(), tolower(socs[i]).c_str(), 495 tolower(dev).c_str()); 496 } 497 fprintf(f, "\n#include \"regs-select.h\"\n\n"); 498 for(size_t i = 0; i < socs.size(); i++) 499 { 500 fprintf(f, "#undef %s_INCLUDE\n", toupper(socs[i]).c_str()); 501 } 502 fprintf(f, "\n"); 503 fprint_include_guard_ex(f, false, guard); 504 fclose(f); 505} 506 507void gen_selectors(const std::string& prefix, const std::vector< soc_t >& socs, char const *author) 508{ 509 printf("Generate select headers: use directory %s\n", prefix.c_str()); 510 general_dev_list_t map = build_general_dev_list(socs); 511 for(general_dev_list_t::iterator it = map.begin(); it != map.end(); ++it) 512 { 513 std::vector< xml_ver_t > ver; 514 std::vector< std::string > names; 515 for(size_t i = 0; i < it->second.size(); i++) 516 { 517 size_t soc_nr = it->second[i].first; 518 size_t dev_in_soc_nr = it->second[i].second; 519 ver.push_back(std::make_pair(socs[soc_nr].name, socs[soc_nr].dev[dev_in_soc_nr].version)); 520 names.push_back(socs[soc_nr].name); 521 } 522 gen_select_header(prefix + "/regs-" + it->first + ".h", it->first, names, ver, author); 523 } 524} 525 526void gen_macro_list(FILE *f, const std::string& prefix, int count, int nr_digits, 527 const std::string& sep, int max_per_line = 1000, const std::string& align = "") 528{ 529 for(int i = 1; i <= count;) 530 { 531 for(int j = i; j <= std::min(count, i + max_per_line - 1); j++) 532 { 533 fprintf(f, "%s%0*d", prefix.c_str(), nr_digits, j); 534 if(j < count) 535 fprintf(f, "%s", sep.c_str()); 536 } 537 i += max_per_line; 538 if(i <= count) 539 fprintf(f, "\\\n%s", align.c_str()); 540 } 541} 542 543void gen_macro(const std::string& filename, bool variadic, char const *author, char const *hwprefix) 544{ 545 printf("Generate %smacro header: use %s\n", variadic ? "": "non-variadic ", 546 filename.c_str()); 547 std::string guard = "__REGS__MACRO__H__"; 548 FILE *f = fopen(filename.c_str(), "w"); 549 if(f == NULL) 550 error("Cannot open file %s\n", filename.c_str()); 551 fprint_copyright(f, author); 552 fprint_include_guard_ex(f, true, guard); 553 fprintf(f, "\n"); 554 555#define REG_WRITE "REG_WRITE" 556 fprintf(f, "#ifndef %s\n", REG_WRITE); 557 fprintf(f, "#define %s(var,value) ((var) = (value))\n", REG_WRITE); 558 fprintf(f, "#endif /* %s */\n", REG_WRITE); 559 fprintf(f, "\n"); 560 561#define REG_READ "REG_READ" 562 fprintf(f, "#ifndef %s\n", REG_READ); 563 fprintf(f, "#define %s(var) (var)\n", REG_READ); 564 fprintf(f, "#endif /* %s */\n", REG_READ); 565 fprintf(f, "\n"); 566 567 const int MAX_NARGS = 32; 568 569 fprintf(f, "\ 570#define BF_SET(reg, field) " REG_WRITE "(%1$s##reg##_SET, BM_##reg##_##field)\n\ 571#define BF_CLR(reg, field) " REG_WRITE "(%1$s##reg##_CLR, BM_##reg##_##field)\n\ 572#define BF_TOG(reg, field) " REG_WRITE "(%1$s##reg##_TOG, BM_##reg##_##field)\n\ 573\n\ 574#define BF_SETV(reg, field, v) " REG_WRITE "(%1$s##reg##_SET, BF_##reg##_##field(v))\n\ 575#define BF_CLRV(reg, field, v) " REG_WRITE "(%1$s##reg##_CLR, BF_##reg##_##field(v))\n\ 576#define BF_TOGV(reg, field, v) " REG_WRITE "(%1$s##reg##_TOG, BF_##reg##_##field(v))\n\ 577\n\ 578#define BF_RDX(val, reg, field) ((" REG_READ "(val) & BM_##reg##_##field) >> BP_##reg##_##field)\n\ 579#define BF_RD(reg, field) BF_RDX(" REG_READ "(%1$s##reg), reg, field)\n\ 580#define BF_WRX(val, reg, field, v) " REG_WRITE "(val, (" REG_READ "(val) & ~BM_##reg##_##field) | (((v) << BP_##reg##_##field) & BM_##reg##_##field))\n\ 581#define BF_WR(reg, field, v) BF_WRX(%1$s##reg, reg, field, v)\n\ 582#define BF_WR_V(reg, field, sy) BF_WR(reg, field, BV_##reg##_##field##__##sy)\n\ 583#define BF_WR_VX(val, reg, field, sy) BF_WRX(val, reg, field, BV_##reg##_##field##__##sy)\n\ 584\n\ 585#define BF_SETn(reg, n, field) " REG_WRITE "(%1$s##reg##_SET(n), BM_##reg##_##field)\n\ 586#define BF_CLRn(reg, n, field) " REG_WRITE "(%1$s##reg##_CLR(n), BM_##reg##_##field)\n\ 587#define BF_TOGn(reg, n, field) " REG_WRITE "(%1$s##reg##_TOG(n), BM_##reg##_##field)\n\ 588\n\ 589#define BF_SETVn(reg, n, field, v) " REG_WRITE "(%1$s##reg##_SET(n), BF_##reg##_##field(v))\n\ 590#define BF_CLRVn(reg, n, field, v) " REG_WRITE "(%1$s##reg##_CLR(n), BF_##reg##_##field(v))\n\ 591#define BF_TOGVn(reg, n, field, v) " REG_WRITE "(%1$s##reg##_TOG(n), BF_##reg##_##field(v))\n\ 592\n\ 593#define BF_RDn(reg, n, field) BF_RDX(%1$s##reg(n), reg, field)\n\ 594#define BF_WRn(reg, n, field, v) BF_WRX(%1$s##reg(n), reg, field, v)\n\ 595#define BF_WRn_V(reg, n, field, sy) BF_WRn(reg, n, field, BV_##reg##_##field##__##sy)\n\ 596\n", hwprefix); 597 598 for(int nargs = 1; nargs <= MAX_NARGS; nargs++) 599 { 600 fprintf(f, "#define BM_OR%d(reg, ", nargs); 601 gen_macro_list(f, "f", nargs, 2, ", ", 10, " "); 602 fprintf(f, ") \\\n ("); 603 gen_macro_list(f, "BM_##reg##_##f", nargs, 2, " | ", 4, " "); 604 fprintf(f, ")\n"); 605 } 606 fprintf(f, "\n"); 607 608 for(int nargs = 1; nargs <= MAX_NARGS; nargs++) 609 { 610 fprintf(f, "#define BF_OR%d(reg, ", nargs); 611 gen_macro_list(f, "f", nargs, 2, ", ", 10, " "); 612 fprintf(f, ") \\\n ("); 613 gen_macro_list(f, "BF_##reg##_##f", nargs, 2, " | ", 4, " "); 614 fprintf(f, ")\n"); 615 } 616 fprintf(f, "\n"); 617 618 if(variadic) 619 { 620 fprintf(f, "#define REG_NARG(...) REG_NARGS_(__VA_ARGS__"); 621 for(int i = MAX_NARGS; i >= 1; i--) 622 fprintf(f, ", %d", i); 623 fprintf(f, ")\n"); 624 fprintf(f, "#define REG_NARGS_("); 625 gen_macro_list(f, "_", MAX_NARGS, 1, ", "); 626 fprintf(f, ", N, ...) N\n\n"); 627 628 fprintf(f, "#define REG_VARIADIC(macro, reg, ...) REG_VARIADIC_(macro, REG_NARG(__VA_ARGS__), reg, __VA_ARGS__)\n"); 629 fprintf(f, "#define REG_VARIADIC_(macro, cnt, reg, ...) REG_VARIADIC__(macro, cnt, reg, __VA_ARGS__)\n"); 630 fprintf(f, "#define REG_VARIADIC__(macro, cnt, reg, ...) REG_VARIADIC___(macro##cnt, reg, __VA_ARGS__)\n"); 631 fprintf(f, "#define REG_VARIADIC___(macro, reg, ...) macro(reg, __VA_ARGS__)\n\n"); 632 633 fprintf(f, "#define BM_OR(reg, ...) REG_VARIADIC(BM_OR, reg, __VA_ARGS__)\n"); 634 fprintf(f, "#define BF_OR(reg, ...) REG_VARIADIC(BF_OR, reg, __VA_ARGS__)\n"); 635 } 636 637 fprint_include_guard_ex(f, false, guard); 638 fclose(f); 639} 640 641void usage() 642{ 643 printf("usage: headergen [options] <desc files...> <output directory>\n"); 644 printf("options:\n"); 645 printf(" -?/--help Dispaly this help\n"); 646 printf(" -s/--selector Always produce selector files\n"); 647 printf(" -m/--no-macro Do not generate a macro file with helpers\n"); 648 printf(" -i/--no-include Do not include the macro file in the headers\n"); 649 printf(" -v/--no-variadic Do not generate variadic macros\n"); 650 printf(" -p/--reg-prefix \"prefix\" Prefix register names\n"); 651 printf(" -a/--author \"Author\" Set author name in preamble\n"); 652 printf("\n"); 653 printf("Default option is to generate a macro file with variadic macros.\n"); 654 printf("Default option is to include the macro file in the headers.\n"); 655 printf("Default option is to generate selector files only for two or more socs.\n"); 656 printf("Default option is to create one subdirectory per soc, except if no\n"); 657 printf("selector files are needed. The subdirectories will be created if necessary.\n"); 658 printf("Default option is to not prefix register names\n"); 659 printf("Default option is \"Unknown Author\" for author in preamble\n"); 660 exit(1); 661} 662 663int main(int argc, char **argv) 664{ 665 bool force_selector = false; 666 bool no_variadic = false; 667 bool no_macro = false; 668 bool no_include = false; 669 char const *author = "Unknown Author"; 670 char const *hwprefix = ""; 671 672 if(argc <= 1) 673 usage(); 674 675 while(1) 676 { 677 static struct option long_options[] = 678 { 679 {"help", no_argument, 0, '?'}, 680 {"selector", no_argument, 0, 's'}, 681 {"no-macro", no_argument, 0, 'm'}, 682 {"no-include", no_argument, 0, 'i'}, 683 {"no-variadic", no_argument, 0, 'v'}, 684 {"reg-prefix", required_argument, 0, 'p'}, 685 {"author", required_argument, 0, 'a'}, 686 {0, 0, 0, 0} 687 }; 688 689 int c = getopt_long(argc, argv, "?smivp:a:", long_options, NULL); 690 if(c == -1) 691 break; 692 switch(c) 693 { 694 case -1: 695 break; 696 case '?': 697 usage(); 698 break; 699 case 's': 700 force_selector = true; 701 break; 702 case 'm': 703 no_macro = true; 704 break; 705 case 'i': 706 no_include = true; 707 break; 708 case 'v': 709 no_variadic = true; 710 break; 711 case 'a' : 712 author = optarg; 713 break; 714 case 'p' : 715 hwprefix = optarg; 716 break; 717 default: 718 abort(); 719 } 720 } 721 722 std::vector< soc_t > socs; 723 for(int i = optind; i < argc - 1; i++) 724 { 725 soc_t s; 726 if(!parse_xml(argv[i], s)) 727 { 728 printf("Cannot parse %s\n", argv[i]); 729 return 1; 730 } 731 socs.push_back(s); 732 } 733 734 g_gen_selector = force_selector || socs.size() > 1; 735 736 if(!no_macro) 737 { 738 g_macro_filename = std::string(argv[argc - 1]) + "/regs-macro.h"; 739 gen_macro(g_macro_filename, !no_variadic, author, hwprefix); 740 g_macro_filename = "regs-macro.h"; 741 if(no_include) 742 g_macro_filename.clear(); 743 } 744 if(g_gen_selector) 745 { 746 gen_selectors(argv[argc - 1], socs, author); 747 g_macro_filename.clear(); 748 } 749 gen_headers(argv[argc - 1], socs, author, hwprefix); 750 return 0; 751}