nkeynes@1104 | 1 | /**
|
nkeynes@1104 | 2 | * $Id$
|
nkeynes@1104 | 3 | *
|
nkeynes@1104 | 4 | * mmio register code generator
|
nkeynes@1104 | 5 | *
|
nkeynes@1104 | 6 | * Copyright (c) 2010 Nathan Keynes.
|
nkeynes@1104 | 7 | *
|
nkeynes@1104 | 8 | * This program is free software; you can redistribute it and/or modify
|
nkeynes@1104 | 9 | * it under the terms of the GNU General Public License as published by
|
nkeynes@1104 | 10 | * the Free Software Foundation; either version 2 of the License, or
|
nkeynes@1104 | 11 | * (at your option) any later version.
|
nkeynes@1104 | 12 | *
|
nkeynes@1104 | 13 | * This program is distributed in the hope that it will be useful,
|
nkeynes@1104 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nkeynes@1104 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nkeynes@1104 | 16 | * GNU General Public License for more details.
|
nkeynes@1104 | 17 | */
|
nkeynes@1104 | 18 |
|
nkeynes@1104 | 19 | #include <stdio.h>
|
nkeynes@1104 | 20 | #include <stdlib.h>
|
nkeynes@1104 | 21 | #include <string.h>
|
nkeynes@1104 | 22 | #include <unistd.h>
|
nkeynes@1104 | 23 | #include <getopt.h>
|
nkeynes@1104 | 24 | #include <ctype.h>
|
nkeynes@1104 | 25 | #include <errno.h>
|
nkeynes@1296 | 26 | #include <glib.h>
|
nkeynes@1104 | 27 | #include "gettext.h"
|
nkeynes@1104 | 28 | #include "genmach.h"
|
nkeynes@1104 | 29 |
|
nkeynes@1104 | 30 | #define LXDREAM_PAGE_SIZE 4096
|
nkeynes@1104 | 31 |
|
nkeynes@1104 | 32 | const char *short_options = "cd:ho:v";
|
nkeynes@1104 | 33 | struct option long_options[] = {
|
nkeynes@1104 | 34 | { "output", required_argument, NULL, 'o' },
|
nkeynes@1104 | 35 | { "header", required_argument, NULL, 'd' },
|
nkeynes@1104 | 36 | { "check-only", no_argument, NULL, 'c' },
|
nkeynes@1104 | 37 | { "help", no_argument, NULL, 'h' },
|
nkeynes@1104 | 38 | { "verbose", no_argument, NULL, 'v' },
|
nkeynes@1104 | 39 | { NULL, 0, 0, 0 } };
|
nkeynes@1104 | 40 |
|
nkeynes@1104 | 41 | static void print_version()
|
nkeynes@1104 | 42 | {
|
nkeynes@1104 | 43 | printf( "genmmio 0.1\n" );
|
nkeynes@1104 | 44 | }
|
nkeynes@1104 | 45 |
|
nkeynes@1104 | 46 | static void print_usage()
|
nkeynes@1104 | 47 | {
|
nkeynes@1104 | 48 | print_version();
|
nkeynes@1104 | 49 | printf( "Usage: genmmio [options] <input-register-files>\n" );
|
nkeynes@1104 | 50 | printf( "Options:\n" );
|
nkeynes@1104 | 51 | printf( " -c, --check-only %s\n", _("Check specification files but don't write any output") );
|
nkeynes@1104 | 52 | printf( " -d, --header=FILE %s\n", _("Specify header output file [corresponding .h for .c file]") );
|
nkeynes@1104 | 53 | printf( " -h, --help %s\n", _("Display this usage information") );
|
nkeynes@1104 | 54 | printf( " -o, --output=FILE %s\n", _("Specify main output file [corresponding .c for input file]") );
|
nkeynes@1104 | 55 | printf( " -v, --verbose %s\n", _("Print verbose output") );
|
nkeynes@1104 | 56 | }
|
nkeynes@1104 | 57 |
|
nkeynes@1104 | 58 | /**
|
nkeynes@1104 | 59 | * Given an input baseName of the form "path/file.blah", return
|
nkeynes@1104 | 60 | * a newly allocated string "file<ext>" where <ext> is the second
|
nkeynes@1104 | 61 | * parameter.
|
nkeynes@1104 | 62 | *
|
nkeynes@1104 | 63 | * @param baseName a non-null filename
|
nkeynes@1104 | 64 | * @param ext a file extension including leading '.'
|
nkeynes@1104 | 65 | */
|
nkeynes@1104 | 66 | char *makeFilename( const char *baseName, const char *ext )
|
nkeynes@1104 | 67 | {
|
nkeynes@1104 | 68 | const char *p = strrchr(baseName, '/');
|
nkeynes@1104 | 69 | if( p == NULL )
|
nkeynes@1104 | 70 | p = baseName;
|
nkeynes@1104 | 71 | const char *q = strchr(p, '.');
|
nkeynes@1104 | 72 | if( q == NULL ) {
|
nkeynes@1104 | 73 | return g_strdup_printf("%s%s", p, ext);
|
nkeynes@1104 | 74 | } else {
|
nkeynes@1298 | 75 | return g_strdup_printf("%.*s%s", (int)(q-p), p, ext );
|
nkeynes@1104 | 76 | }
|
nkeynes@1104 | 77 | }
|
nkeynes@1104 | 78 |
|
nkeynes@1104 | 79 | /**
|
nkeynes@1104 | 80 | * Process all registers after parsing is complete. This does a few things:
|
nkeynes@1104 | 81 | * 1. Ensures that there are no overlapping registers, so that every operation
|
nkeynes@1104 | 82 | * is well-defined.
|
nkeynes@1104 | 83 | * 2. Replaces transitive mirror groups with a set of equivalent direct
|
nkeynes@1104 | 84 | * mirrors so that later processing doesn't need to check for this case.
|
nkeynes@1104 | 85 | * This also checks for cycles in the graph.
|
nkeynes@1104 | 86 | * 3. Organises the memory map(s) into page-size quantities (combining and
|
nkeynes@1104 | 87 | * splitting groups where necessary).
|
nkeynes@1104 | 88 | */
|
nkeynes@1104 | 89 | GList *postprocess_registers( GList *blocks )
|
nkeynes@1104 | 90 | {
|
nkeynes@1104 | 91 | for( GList *ptr = blocks; ptr != NULL; ptr = ptr->next ) {
|
nkeynes@1104 | 92 | regblock_t block = (regblock_t)ptr->data;
|
nkeynes@1104 | 93 | for( unsigned i=0; i<block->numRegs; i++ ) {
|
nkeynes@1104 | 94 | regdef_t reg = block->regs[i];
|
nkeynes@1104 | 95 | if( reg->mode == REG_MIRROR ) {
|
nkeynes@1104 | 96 | }
|
nkeynes@1104 | 97 | }
|
nkeynes@1104 | 98 | }
|
nkeynes@1104 | 99 | return blocks;
|
nkeynes@1104 | 100 | }
|
nkeynes@1104 | 101 |
|
nkeynes@1104 | 102 | /**
|
nkeynes@1104 | 103 | * Check register definition semantics. Primarily this verifies that there
|
nkeynes@1104 | 104 | * are no overlapping definitions.
|
nkeynes@1104 | 105 | * @return number of errors found.
|
nkeynes@1104 | 106 | */
|
nkeynes@1104 | 107 | int check_registers( GList *registers )
|
nkeynes@1104 | 108 | {
|
nkeynes@1104 | 109 | return 0;
|
nkeynes@1104 | 110 | }
|
nkeynes@1104 | 111 |
|
nkeynes@1104 | 112 | /**
|
nkeynes@1104 | 113 | * Dump the high-level register map to the given file.
|
nkeynes@1104 | 114 | */
|
nkeynes@1104 | 115 | void dump_register_blocks( FILE *f, GList *blocks, gboolean detail )
|
nkeynes@1104 | 116 | {
|
nkeynes@1104 | 117 | const char *mode_names[] = { "--", "RW", "RO", "RW" };
|
nkeynes@1104 | 118 | for( GList *ptr = blocks; ptr != NULL; ptr=ptr->next ) {
|
nkeynes@1104 | 119 | regblock_t block = (regblock_t)ptr->data;
|
nkeynes@1104 | 120 | fprintf( f, "%08X: %s - %s\n", block->address,
|
nkeynes@1104 | 121 | block->name,
|
nkeynes@1104 | 122 | (block->description == NULL ? "<no description>" : block->description) );
|
nkeynes@1104 | 123 | if( detail ) {
|
nkeynes@1104 | 124 | for( unsigned i=0; i<block->numRegs; i++ ) {
|
nkeynes@1104 | 125 | regdef_t reg = block->regs[i];
|
nkeynes@1104 | 126 | fprintf( f, " %04X: %s %s", reg->offset,
|
nkeynes@1104 | 127 | mode_names[reg->mode],
|
nkeynes@1104 | 128 | reg->name == NULL ? "<anon>" : reg->name );
|
nkeynes@1104 | 129 | if( reg->numElements > 1 ) {
|
nkeynes@1104 | 130 | fprintf( f, "[%d]", reg->numElements );
|
nkeynes@1104 | 131 | }
|
nkeynes@1104 | 132 | fprintf( f, " - %s\n",
|
nkeynes@1104 | 133 | (reg->description == NULL ? "<no description>" : reg->description) );
|
nkeynes@1104 | 134 | }
|
nkeynes@1104 | 135 | }
|
nkeynes@1104 | 136 | }
|
nkeynes@1104 | 137 | }
|
nkeynes@1104 | 138 |
|
nkeynes@1298 | 139 | unsigned char *build_page_initializer( regblock_t block )
|
nkeynes@1104 | 140 | {
|
nkeynes@1298 | 141 | unsigned char *page = g_malloc(LXDREAM_PAGE_SIZE);
|
nkeynes@1104 | 142 |
|
nkeynes@1104 | 143 | /* First, background fill if any */
|
nkeynes@1104 | 144 | if( block->flags.fillSizeBytes == 0 ) {
|
nkeynes@1104 | 145 | memset(page, 0, LXDREAM_PAGE_SIZE);
|
nkeynes@1104 | 146 | } else {
|
nkeynes@1104 | 147 | for( unsigned i=0; i<LXDREAM_PAGE_SIZE; i++ ) {
|
nkeynes@1104 | 148 | page[i] = block->flags.fillValue.a[i%block->flags.fillSizeBytes];
|
nkeynes@1104 | 149 | }
|
nkeynes@1104 | 150 | }
|
nkeynes@1104 | 151 |
|
nkeynes@1104 | 152 | /* Next, set register initializer (except for wo + mirror regs) */
|
nkeynes@1104 | 153 | for( unsigned i=0; i<block->numRegs; i++ ) {
|
nkeynes@1104 | 154 | regdef_t reg = block->regs[i];
|
nkeynes@1104 | 155 | if( reg->mode != REG_WO && reg->mode != REG_MIRROR ) {
|
nkeynes@1104 | 156 | unsigned offset = reg->offset;
|
nkeynes@1104 | 157 | for( unsigned j=0; j<reg->numElements; j++ ) {
|
nkeynes@1104 | 158 | if( reg->type == REG_STRING ) {
|
nkeynes@1104 | 159 | memcpy( &page[offset], reg->initValue.s, reg->numBytes );
|
nkeynes@1104 | 160 | } else {
|
nkeynes@1104 | 161 | memcpy( &page[offset], reg->initValue.a, reg->numBytes );
|
nkeynes@1104 | 162 | }
|
nkeynes@1104 | 163 | offset += reg->numBytes;
|
nkeynes@1104 | 164 | }
|
nkeynes@1104 | 165 | }
|
nkeynes@1104 | 166 | }
|
nkeynes@1104 | 167 |
|
nkeynes@1104 | 168 | /* Finally clone mirror groups */
|
nkeynes@1104 | 169 | for( unsigned i=0; i<block->numRegs; i++ ) {
|
nkeynes@1104 | 170 | regdef_t reg = block->regs[i];
|
nkeynes@1104 | 171 | if( reg->mode == REG_MIRROR ) {
|
nkeynes@1104 | 172 | unsigned offset = reg->offset;
|
nkeynes@1104 | 173 | unsigned target = reg->initValue.i;
|
nkeynes@1104 | 174 | for( unsigned i=0; i<reg->numElements; i++ ) {
|
nkeynes@1104 | 175 | memcpy( &page[offset], &page[target], reg->numBytes );
|
nkeynes@1104 | 176 | offset += reg->stride;
|
nkeynes@1104 | 177 | }
|
nkeynes@1104 | 178 | }
|
nkeynes@1104 | 179 | }
|
nkeynes@1104 | 180 |
|
nkeynes@1104 | 181 | return page;
|
nkeynes@1104 | 182 | }
|
nkeynes@1104 | 183 |
|
nkeynes@1104 | 184 |
|
nkeynes@1104 | 185 | void fwrite_dump( unsigned char *data, unsigned int length, FILE *f )
|
nkeynes@1104 | 186 | {
|
nkeynes@1104 | 187 | unsigned int i, j;
|
nkeynes@1104 | 188 | int skipped = 0;
|
nkeynes@1104 | 189 | for( i =0; i<length; i+=16 ) {
|
nkeynes@1104 | 190 | if( i >= 16 && i < length-16 && memcmp( &data[i], &data[i-16], 16) == 0 ) {
|
nkeynes@1104 | 191 | skipped++;
|
nkeynes@1104 | 192 | continue;
|
nkeynes@1104 | 193 | }
|
nkeynes@1104 | 194 | if( skipped ) {
|
nkeynes@1104 | 195 | fprintf( f, " ** \n" );
|
nkeynes@1104 | 196 | skipped = 0;
|
nkeynes@1104 | 197 | }
|
nkeynes@1104 | 198 | fprintf( f, "%08X:", i);
|
nkeynes@1104 | 199 | for( j=i; j<i+16; j++ ) {
|
nkeynes@1104 | 200 | if( j != i && (j % 4) == 0 )
|
nkeynes@1104 | 201 | fprintf( f, " " );
|
nkeynes@1104 | 202 | if( j < length )
|
nkeynes@1104 | 203 | fprintf( f, " %02X", (unsigned int)(data[j]) );
|
nkeynes@1104 | 204 | else
|
nkeynes@1104 | 205 | fprintf( f, " " );
|
nkeynes@1104 | 206 | }
|
nkeynes@1104 | 207 | fprintf( f, " " );
|
nkeynes@1104 | 208 | for( j=i; j<i+16 && j<length; j++ ) {
|
nkeynes@1104 | 209 | fprintf( f, "%c", isprint(data[j]) ? data[j] : '.' );
|
nkeynes@1104 | 210 | }
|
nkeynes@1104 | 211 | fprintf( f, "\n" );
|
nkeynes@1104 | 212 | }
|
nkeynes@1104 | 213 | }
|
nkeynes@1104 | 214 |
|
nkeynes@1104 | 215 | static const char *file_top = "/**\n"
|
nkeynes@1104 | 216 | " * This file was automatically generated by genmmio, do not edit\n"
|
nkeynes@1104 | 217 | " */\n";
|
nkeynes@1104 | 218 |
|
nkeynes@1104 | 219 | void write_source( FILE *f, GList *blocks, const char *header_filename )
|
nkeynes@1104 | 220 | {
|
nkeynes@1104 | 221 | fputs( file_top, f );
|
nkeynes@1104 | 222 | fprintf( f, "\n#include \"%s\"\n\n", header_filename );
|
nkeynes@1104 | 223 |
|
nkeynes@1104 | 224 | for( GList *ptr = blocks; ptr != NULL; ptr = ptr->next ) {
|
nkeynes@1104 | 225 | regblock_t block = (regblock_t)ptr->data;
|
nkeynes@1104 | 226 | /* Generate the mmio region struct */
|
nkeynes@1104 | 227 | fprintf( f, "void FASTCALL mmio_region_%s_write(uint32_t, uint32_t);\n", block->name );
|
nkeynes@1104 | 228 | fprintf( f, "void FASTCALL mmio_region_%s_write_word(uint32_t, uint32_t);\n", block->name );
|
nkeynes@1104 | 229 | fprintf( f, "void FASTCALL mmio_region_%s_write_byte(uint32_t, uint32_t);\n", block->name );
|
nkeynes@1104 | 230 | fprintf( f, "void FASTCALL mmio_region_%s_write_burst(uint32_t, unsigned char *);\n", block->name );
|
nkeynes@1104 | 231 | fprintf( f, "int32_t FASTCALL mmio_region_%s_read(uint32_t);\n", block->name );
|
nkeynes@1104 | 232 | fprintf( f, "int32_t FASTCALL mmio_region_%s_read_word(uint32_t);\n", block->name );
|
nkeynes@1104 | 233 | fprintf( f, "int32_t FASTCALL mmio_region_%s_read_byte(uint32_t);\n", block->name );
|
nkeynes@1104 | 234 | fprintf( f, "void FASTCALL mmio_region_%s_read_burst(unsigned char *, uint32_t);\n", block->name );
|
nkeynes@1104 | 235 | fprintf( f, "struct mmio_region mmio_region_%s = {\n", block->name );
|
nkeynes@1104 | 236 | fprintf( f, " \"%s\", \"%s\", %08x, {\n", block->name,
|
nkeynes@1104 | 237 | block->description == NULL ? block->name : block->description,
|
nkeynes@1104 | 238 | block->address );
|
nkeynes@1104 | 239 | fprintf( f, " mmio_region_%s_read, mmio_region_%s_write,\n", block->name, block->name );
|
nkeynes@1104 | 240 | fprintf( f, " mmio_region_%s_read_word, mmio_region_%s_write_word,\n", block->name, block->name );
|
nkeynes@1104 | 241 | fprintf( f, " mmio_region_%s_read_byte, mmio_region_%s_write_byte,\n", block->name, block->name );
|
nkeynes@1104 | 242 | fprintf( f, " mmio_region_%s_read_burst, mmio_region_%s_write_burst,\n", block->name, block->name );
|
nkeynes@1298 | 243 | fprintf( f, " unmapped_prefetch, mmio_region_%s_read_byte },\n", block->name );
|
nkeynes@1104 | 244 | fprintf( f, " NULL, NULL, {\n" );
|
nkeynes@1104 | 245 | for( unsigned i=0; i<block->numRegs; i++ ) {
|
nkeynes@1104 | 246 | regdef_t reg = block->regs[i];
|
nkeynes@1104 | 247 | if( reg->mode != REG_CONST ) {
|
nkeynes@1104 | 248 | char tmp[32];
|
nkeynes@1104 | 249 | const char *regname = reg->name;
|
nkeynes@1104 | 250 | if( regname == NULL ) {
|
nkeynes@1104 | 251 | regname = tmp;
|
nkeynes@1104 | 252 | snprintf( tmp, sizeof(tmp), "%s_%03X", block->name, reg->offset );
|
nkeynes@1104 | 253 | }
|
nkeynes@1104 | 254 |
|
nkeynes@1104 | 255 | fprintf( f, " { \"%s\", \"%s\", %d, 0x%03x, 0x%08x, %s },\n", regname,
|
nkeynes@1104 | 256 | reg->description == NULL ? regname : reg->description,
|
nkeynes@1104 | 257 | reg->numBytes*8, reg->offset, (unsigned)reg->initValue.i,
|
nkeynes@1104 | 258 | (reg->mode == REG_RW ? "PORT_MRW" : (reg->mode == REG_WO ? "PORT_W" : "PORT_R")) );
|
nkeynes@1104 | 259 | }
|
nkeynes@1104 | 260 | }
|
nkeynes@1104 | 261 | fprintf( f, " }, NULL };\n" );
|
nkeynes@1104 | 262 | }
|
nkeynes@1104 | 263 |
|
nkeynes@1104 | 264 | }
|
nkeynes@1104 | 265 |
|
nkeynes@1104 | 266 | void write_header( FILE *f, GList *blocks )
|
nkeynes@1104 | 267 | {
|
nkeynes@1104 | 268 | fputs( file_top, f );
|
nkeynes@1104 | 269 |
|
nkeynes@1104 | 270 | fputs( "\n#include \"mmio.h\"\n\n", f );
|
nkeynes@1104 | 271 |
|
nkeynes@1104 | 272 | for( GList *ptr = blocks; ptr != NULL; ptr = ptr->next ) {
|
nkeynes@1104 | 273 | regblock_t block = (regblock_t)ptr->data;
|
nkeynes@1104 | 274 | fprintf( f, "extern struct mmio_region mmio_region_%s;\n", block->name );
|
nkeynes@1104 | 275 | fprintf( f, "enum mmio_region_%s_port_t {\n", block->name );
|
nkeynes@1104 | 276 | for( unsigned i=0; i<block->numRegs; i++ ) {
|
nkeynes@1104 | 277 | regdef_t reg = block->regs[i];
|
nkeynes@1104 | 278 | if( reg->name != NULL ) {
|
nkeynes@1104 | 279 | fprintf( f, " %s = 0x%03x,\n", reg->name, reg->offset );
|
nkeynes@1104 | 280 | }
|
nkeynes@1104 | 281 | }
|
nkeynes@1104 | 282 | fprintf( f, "};\n" );
|
nkeynes@1104 | 283 | }
|
nkeynes@1104 | 284 | }
|
nkeynes@1104 | 285 |
|
nkeynes@1104 | 286 | void write_test( FILE *f, GList *blocks )
|
nkeynes@1104 | 287 | {
|
nkeynes@1104 | 288 |
|
nkeynes@1104 | 289 |
|
nkeynes@1104 | 290 | }
|
nkeynes@1104 | 291 |
|
nkeynes@1104 | 292 | int main(int argc, char *argv[])
|
nkeynes@1104 | 293 | {
|
nkeynes@1104 | 294 | const char *header = NULL;
|
nkeynes@1104 | 295 | const char *output = NULL;
|
nkeynes@1104 | 296 | gboolean check_only = FALSE;
|
nkeynes@1104 | 297 | int verbose = 0, opt;
|
nkeynes@1104 | 298 | GList *block_list = NULL;
|
nkeynes@1104 | 299 |
|
nkeynes@1104 | 300 | while( (opt = getopt_long( argc, argv, short_options, long_options, NULL )) != -1 ) {
|
nkeynes@1104 | 301 | switch(opt) {
|
nkeynes@1104 | 302 | case 'c':
|
nkeynes@1104 | 303 | check_only = TRUE;
|
nkeynes@1104 | 304 | break;
|
nkeynes@1104 | 305 | case 'd':
|
nkeynes@1104 | 306 | header = optarg;
|
nkeynes@1104 | 307 | break;
|
nkeynes@1104 | 308 | case 'h':
|
nkeynes@1104 | 309 | print_usage();
|
nkeynes@1104 | 310 | exit(0);
|
nkeynes@1104 | 311 | case 'o':
|
nkeynes@1104 | 312 | output = optarg;
|
nkeynes@1104 | 313 | break;
|
nkeynes@1104 | 314 | case 'v':
|
nkeynes@1104 | 315 | verbose++;
|
nkeynes@1104 | 316 | break;
|
nkeynes@1104 | 317 | }
|
nkeynes@1104 | 318 | }
|
nkeynes@1104 | 319 |
|
nkeynes@1104 | 320 | if( optind == argc ) {
|
nkeynes@1104 | 321 | print_usage();
|
nkeynes@1104 | 322 | exit(1);
|
nkeynes@1104 | 323 | }
|
nkeynes@1104 | 324 |
|
nkeynes@1104 | 325 | if( output == NULL ) {
|
nkeynes@1104 | 326 | output = makeFilename(argv[optind],".c");
|
nkeynes@1104 | 327 | }
|
nkeynes@1104 | 328 | if( header == NULL ) {
|
nkeynes@1104 | 329 | header = makeFilename(argv[optind],".h");
|
nkeynes@1104 | 330 | }
|
nkeynes@1104 | 331 |
|
nkeynes@1104 | 332 | for( ; optind < argc; optind++ ) {
|
nkeynes@1104 | 333 | block_list = ioparse(argv[optind], block_list);
|
nkeynes@1104 | 334 | }
|
nkeynes@1104 | 335 |
|
nkeynes@1104 | 336 | if( verbose ) {
|
nkeynes@1104 | 337 | dump_register_blocks(stdout, block_list, verbose>1);
|
nkeynes@1104 | 338 | }
|
nkeynes@1104 | 339 |
|
nkeynes@1104 | 340 | int errors = check_registers(block_list);
|
nkeynes@1104 | 341 | if( errors != 0 ) {
|
nkeynes@1104 | 342 | fprintf( stderr, "Aborting due to validation errors\n" );
|
nkeynes@1104 | 343 | return 2;
|
nkeynes@1104 | 344 | }
|
nkeynes@1104 | 345 |
|
nkeynes@1104 | 346 | if( !check_only ) {
|
nkeynes@1104 | 347 | FILE *f = fopen( output, "wo" );
|
nkeynes@1104 | 348 | if( f == NULL ) {
|
nkeynes@1104 | 349 | fprintf( stderr, "Unable to open output file '%s': %s\n", output, strerror(errno) );
|
nkeynes@1104 | 350 | return 3;
|
nkeynes@1104 | 351 | }
|
nkeynes@1104 | 352 | write_source( f, block_list, header );
|
nkeynes@1104 | 353 | fclose(f);
|
nkeynes@1104 | 354 |
|
nkeynes@1104 | 355 | f = fopen( header, "wo" );
|
nkeynes@1104 | 356 | if( f == NULL ) {
|
nkeynes@1104 | 357 | fprintf( stderr, "Unable to open header file '%s': %s\n", header, strerror(errno) );
|
nkeynes@1104 | 358 | return 4;
|
nkeynes@1104 | 359 | }
|
nkeynes@1104 | 360 | write_header( f, block_list );
|
nkeynes@1104 | 361 | fclose(f);
|
nkeynes@1104 | 362 | }
|
nkeynes@1104 | 363 |
|
nkeynes@1104 | 364 | for( GList *ptr = block_list; ptr != NULL; ptr = ptr->next ) {
|
nkeynes@1298 | 365 | unsigned char *data = build_page_initializer((regblock_t)ptr->data);
|
nkeynes@1104 | 366 | fwrite_dump( data, LXDREAM_PAGE_SIZE, stdout );
|
nkeynes@1104 | 367 | g_free(data);
|
nkeynes@1104 | 368 | }
|
nkeynes@1104 | 369 | return 0;
|
nkeynes@1104 | 370 | }
|
nkeynes@1104 | 371 |
|