2013-09-07 19:43:33 +02:00
|
|
|
/*
|
2013-10-25 18:03:05 +02:00
|
|
|
* Copyright (C) 2013 Andrea Mazzoleni
|
2013-09-07 19:43:33 +02:00
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2013-12-27 13:56:56 +01:00
|
|
|
#include <stdint.h>
|
2013-09-07 19:43:33 +02:00
|
|
|
|
2013-10-25 18:03:05 +02:00
|
|
|
/**
|
|
|
|
|
* Multiplication in GF(2^8).
|
|
|
|
|
*/
|
2013-12-27 13:56:56 +01:00
|
|
|
static uint8_t gfmul(uint8_t a, uint8_t b)
|
2013-09-07 19:43:33 +02:00
|
|
|
{
|
2013-12-27 13:56:56 +01:00
|
|
|
uint8_t v;
|
2013-09-07 19:43:33 +02:00
|
|
|
|
|
|
|
|
v = 0;
|
|
|
|
|
while (b) {
|
|
|
|
|
if ((b & 1) != 0)
|
|
|
|
|
v ^= a;
|
|
|
|
|
|
|
|
|
|
if ((a & 0x80) != 0) {
|
|
|
|
|
a <<= 1;
|
|
|
|
|
a ^= 0x1d;
|
|
|
|
|
} else {
|
|
|
|
|
a <<= 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b >>= 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return v;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-25 18:03:05 +02:00
|
|
|
/**
|
|
|
|
|
* Inversion table in GF(2^8).
|
|
|
|
|
*/
|
2013-12-27 13:56:56 +01:00
|
|
|
uint8_t gfinv[256];
|
2013-10-22 23:40:05 +02:00
|
|
|
|
|
|
|
|
/**
|
2013-10-25 18:03:05 +02:00
|
|
|
* Number of parity.
|
|
|
|
|
* This is the number of rows of the generation matrix.
|
2013-10-22 23:40:05 +02:00
|
|
|
*/
|
2013-10-25 18:03:05 +02:00
|
|
|
#define PARITY 6
|
2013-10-22 23:40:05 +02:00
|
|
|
|
2013-10-25 18:03:05 +02:00
|
|
|
/**
|
|
|
|
|
* Number of disks.
|
|
|
|
|
* This is the number of columns of the generation matrix.
|
|
|
|
|
*/
|
|
|
|
|
#define DISK (257-PARITY)
|
2013-10-22 23:40:05 +02:00
|
|
|
|
|
|
|
|
/**
|
2013-11-02 15:55:57 +01:00
|
|
|
* Setup the Cauchy matrix used to generate the parity.
|
2013-10-22 23:40:05 +02:00
|
|
|
*/
|
2013-12-28 12:04:16 +01:00
|
|
|
static void set_cauchy(uint8_t *matrix)
|
2013-10-22 23:40:05 +02:00
|
|
|
{
|
|
|
|
|
int i, j;
|
2013-12-27 13:56:56 +01:00
|
|
|
uint8_t inv_x, y;
|
2013-10-25 18:03:05 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* First row is formed by all 1.
|
|
|
|
|
*
|
|
|
|
|
* This is an Extended Cauchy matrix built from a Cauchy matrix
|
|
|
|
|
* adding the first row of all 1.
|
|
|
|
|
*/
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i)
|
2013-10-25 18:03:05 +02:00
|
|
|
matrix[0*DISK+i] = 1;
|
2013-10-22 23:40:05 +02:00
|
|
|
|
2013-10-25 18:03:05 +02:00
|
|
|
/*
|
|
|
|
|
* Second row is formed by power of 2^i.
|
|
|
|
|
*
|
|
|
|
|
* This is the first row of the Cauchy matrix.
|
|
|
|
|
*
|
|
|
|
|
* Each element of the Cauchy matrix is in the form 1/(xi+yj)
|
|
|
|
|
* where all xi, and yj must be different.
|
|
|
|
|
*
|
|
|
|
|
* Choosing xi = 2^-i and y0 = 0, we obtain for the first row:
|
|
|
|
|
*
|
|
|
|
|
* 1/(xi+y0) = 1/(2^-i + 0) = 2^i
|
|
|
|
|
*
|
|
|
|
|
* with 2^-i != 0 for any i
|
|
|
|
|
*/
|
|
|
|
|
inv_x = 1;
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i) {
|
2013-10-25 18:03:05 +02:00
|
|
|
matrix[1*DISK+i] = inv_x;
|
|
|
|
|
inv_x = gfmul(2, inv_x);
|
2013-10-22 23:40:05 +02:00
|
|
|
}
|
|
|
|
|
|
2013-10-25 18:03:05 +02:00
|
|
|
/*
|
|
|
|
|
* Next rows of the Cauchy matrix.
|
|
|
|
|
*
|
2013-10-29 18:22:05 +01:00
|
|
|
* Continue forming the Cauchy matrix with yj = 2^j obtaining :
|
2013-10-25 18:03:05 +02:00
|
|
|
*
|
|
|
|
|
* 1/(xi+yj) = 1/(2^-i + 2^j)
|
|
|
|
|
*
|
2013-11-20 18:51:33 +01:00
|
|
|
* with xi != yj for any i,j with i>=0,j>=1,i+j<255
|
2013-10-25 18:03:05 +02:00
|
|
|
*/
|
|
|
|
|
y = 2;
|
2013-12-28 12:04:16 +01:00
|
|
|
for (j = 0; j < PARITY-2; ++j) {
|
2013-10-25 18:03:05 +02:00
|
|
|
inv_x = 1;
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i) {
|
2013-12-27 13:56:56 +01:00
|
|
|
uint8_t x = gfinv[inv_x];
|
2013-10-25 18:03:05 +02:00
|
|
|
matrix[(j+2)*DISK+i] = gfinv[y ^ x];
|
|
|
|
|
inv_x = gfmul(2, inv_x);
|
2013-10-22 23:40:05 +02:00
|
|
|
}
|
|
|
|
|
|
2013-10-25 18:03:05 +02:00
|
|
|
y = gfmul(2, y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2013-11-02 15:55:57 +01:00
|
|
|
* Adjusts the matrix multipling each row for
|
2013-10-25 18:03:05 +02:00
|
|
|
* the inverse of the first element in the row.
|
|
|
|
|
*
|
|
|
|
|
* This operation doesn't invalidate the property that all the square
|
|
|
|
|
* submatrices are not singular.
|
|
|
|
|
*/
|
2013-12-28 12:04:16 +01:00
|
|
|
for (j = 0; j < PARITY-2; ++j) {
|
2013-12-27 13:56:56 +01:00
|
|
|
uint8_t f = gfinv[matrix[(j+2)*DISK]];
|
2013-10-25 18:03:05 +02:00
|
|
|
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i)
|
2013-10-25 18:03:05 +02:00
|
|
|
matrix[(j+2)*DISK+i] = gfmul(matrix[(j+2)*DISK+i], f);
|
2013-10-22 23:40:05 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-04 23:47:49 +01:00
|
|
|
/**
|
|
|
|
|
* Setup the Power matrix used to generate the parity.
|
|
|
|
|
*/
|
2013-12-28 12:04:16 +01:00
|
|
|
static void set_power(uint8_t *matrix)
|
2013-11-04 23:47:49 +01:00
|
|
|
{
|
|
|
|
|
unsigned i;
|
2013-12-27 13:56:56 +01:00
|
|
|
uint8_t v;
|
2013-11-04 23:47:49 +01:00
|
|
|
|
|
|
|
|
v = 1;
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i)
|
2013-11-04 23:47:49 +01:00
|
|
|
matrix[0*DISK+i] = v;
|
|
|
|
|
|
|
|
|
|
v = 1;
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i) {
|
2013-11-04 23:47:49 +01:00
|
|
|
matrix[1*DISK+i] = v;
|
|
|
|
|
v = gfmul(2, v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
v = 1;
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i) {
|
2013-11-04 23:47:49 +01:00
|
|
|
matrix[2*DISK+i] = v;
|
2013-11-06 22:07:50 +01:00
|
|
|
v = gfmul(0x8e, v);
|
2013-11-04 23:47:49 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-22 23:40:05 +02:00
|
|
|
/**
|
|
|
|
|
* Next power of 2.
|
|
|
|
|
*/
|
2013-12-27 13:56:56 +01:00
|
|
|
static unsigned np(unsigned v)
|
2013-10-22 23:40:05 +02:00
|
|
|
{
|
|
|
|
|
--v;
|
|
|
|
|
v |= v >> 1;
|
|
|
|
|
v |= v >> 2;
|
|
|
|
|
v |= v >> 4;
|
|
|
|
|
v |= v >> 8;
|
|
|
|
|
v |= v >> 16;
|
|
|
|
|
++v;
|
|
|
|
|
|
|
|
|
|
return v;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-07 19:43:33 +02:00
|
|
|
int main(void)
|
|
|
|
|
{
|
2013-12-27 13:56:56 +01:00
|
|
|
uint8_t v;
|
2013-10-22 23:40:05 +02:00
|
|
|
int i, j, k, p;
|
2013-12-27 13:56:56 +01:00
|
|
|
uint8_t matrix[PARITY * 256];
|
2013-10-22 23:40:05 +02:00
|
|
|
|
|
|
|
|
printf("/*\n");
|
2013-10-25 18:03:05 +02:00
|
|
|
printf(" * Copyright (C) 2013 Andrea Mazzoleni\n");
|
2013-10-22 23:40:05 +02:00
|
|
|
printf(" *\n");
|
|
|
|
|
printf(" * This program is free software: you can redistribute it and/or modify\n");
|
|
|
|
|
printf(" * it under the terms of the GNU General Public License as published by\n");
|
|
|
|
|
printf(" * the Free Software Foundation, either version 2 of the License, or\n");
|
|
|
|
|
printf(" * (at your option) any later version.\n");
|
|
|
|
|
printf(" *\n");
|
|
|
|
|
printf(" * This program is distributed in the hope that it will be useful,\n");
|
|
|
|
|
printf(" * but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
|
|
|
|
|
printf(" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
|
|
|
|
|
printf(" * GNU General Public License for more details.\n");
|
|
|
|
|
printf(" */\n");
|
|
|
|
|
printf("\n");
|
2013-09-07 19:43:33 +02:00
|
|
|
|
2013-12-28 09:10:00 +01:00
|
|
|
printf("#include \"internal.h\"\n");
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
2013-09-07 19:43:33 +02:00
|
|
|
/* a*b */
|
2013-12-28 12:04:16 +01:00
|
|
|
printf("const uint8_t __aligned(256) raid_gfmul[256][256] =\n");
|
2013-09-07 19:43:33 +02:00
|
|
|
printf("{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < 256; ++i) {
|
2013-09-07 19:43:33 +02:00
|
|
|
printf("\t{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (j = 0; j < 256; ++j) {
|
2013-09-07 19:43:33 +02:00
|
|
|
if (j % 8 == 0)
|
|
|
|
|
printf("\t\t");
|
2013-09-09 19:12:33 +02:00
|
|
|
v = gfmul(i, j);
|
|
|
|
|
if (v == 1)
|
|
|
|
|
gfinv[i] = j;
|
|
|
|
|
printf("0x%02x,", (unsigned)v);
|
2013-09-07 19:43:33 +02:00
|
|
|
if (j % 8 == 7)
|
|
|
|
|
printf("\n");
|
|
|
|
|
else
|
|
|
|
|
printf(" ");
|
|
|
|
|
}
|
|
|
|
|
printf("\t},\n");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n\n");
|
|
|
|
|
|
|
|
|
|
/* 2^a */
|
2013-12-28 12:04:16 +01:00
|
|
|
printf("const uint8_t __aligned(256) raid_gfexp[256] =\n");
|
2013-09-07 19:43:33 +02:00
|
|
|
printf("{\n");
|
|
|
|
|
v = 1;
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < 256; ++i) {
|
2013-09-07 19:43:33 +02:00
|
|
|
if (i % 8 == 0)
|
|
|
|
|
printf("\t");
|
|
|
|
|
printf("0x%02x,", v);
|
|
|
|
|
v = gfmul(v, 2);
|
|
|
|
|
if (i % 8 == 7)
|
|
|
|
|
printf("\n");
|
|
|
|
|
else
|
|
|
|
|
printf(" ");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n\n");
|
|
|
|
|
|
|
|
|
|
/* 1/a */
|
2013-12-28 12:04:16 +01:00
|
|
|
printf("const uint8_t __aligned(256) raid_gfinv[256] =\n");
|
2013-09-07 19:43:33 +02:00
|
|
|
printf("{\n");
|
|
|
|
|
printf("\t/* note that the first element is not significative */\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < 256; ++i) {
|
2013-09-07 19:43:33 +02:00
|
|
|
if (i % 8 == 0)
|
|
|
|
|
printf("\t");
|
|
|
|
|
if (i == 0)
|
|
|
|
|
v = 0;
|
|
|
|
|
else
|
2013-09-09 19:12:33 +02:00
|
|
|
v = gfinv[i];
|
2013-09-07 19:43:33 +02:00
|
|
|
printf("0x%02x,", v);
|
|
|
|
|
if (i % 8 == 7)
|
|
|
|
|
printf("\n");
|
|
|
|
|
else
|
|
|
|
|
printf(" ");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n\n");
|
|
|
|
|
|
2013-11-04 23:47:49 +01:00
|
|
|
/* power matrix */
|
|
|
|
|
set_power(matrix);
|
|
|
|
|
|
|
|
|
|
printf("/**\n");
|
|
|
|
|
printf(" * Power matrix used to generate parity.\n");
|
|
|
|
|
printf(" * This matrix is valid for up to %u parity with %u data disks.\n", 3, DISK);
|
|
|
|
|
printf(" *\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (p = 0; p < 3; ++p) {
|
2013-11-04 23:47:49 +01:00
|
|
|
printf(" * ");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i)
|
2013-11-04 23:47:49 +01:00
|
|
|
printf("%02x ", matrix[p*DISK+i]);
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
printf(" */\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
printf("const uint8_t __aligned(256) raid_gfvandermonde[%u][256] =\n", 3);
|
2013-11-04 23:47:49 +01:00
|
|
|
printf("{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (p = 0; p < 3; ++p) {
|
2013-11-04 23:47:49 +01:00
|
|
|
printf("\t{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i) {
|
2013-11-04 23:47:49 +01:00
|
|
|
if (i % 8 == 0)
|
|
|
|
|
printf("\t\t");
|
|
|
|
|
printf("0x%02x,", matrix[p*DISK+i]);
|
|
|
|
|
if (i % 8 == 7)
|
|
|
|
|
printf("\n");
|
|
|
|
|
else
|
|
|
|
|
printf(" ");
|
|
|
|
|
}
|
|
|
|
|
printf("\n\t},\n");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n\n");
|
|
|
|
|
|
2013-10-25 18:03:05 +02:00
|
|
|
/* cauchy matrix */
|
2013-10-22 23:40:05 +02:00
|
|
|
set_cauchy(matrix);
|
|
|
|
|
|
|
|
|
|
printf("/**\n");
|
2013-11-03 10:41:52 +01:00
|
|
|
printf(" * Cauchy matrix used to generate parity.\n");
|
2013-10-25 18:03:05 +02:00
|
|
|
printf(" * This matrix is valid for up to %u parity with %u data disks.\n", PARITY, DISK);
|
2013-10-22 23:40:05 +02:00
|
|
|
printf(" *\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (p = 0; p < PARITY; ++p) {
|
2013-10-22 23:40:05 +02:00
|
|
|
printf(" * ");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i)
|
2013-10-25 18:03:05 +02:00
|
|
|
printf("%02x ", matrix[p*DISK+i]);
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
printf(" */\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
printf("const uint8_t __aligned(256) raid_gfcauchy[%u][256] =\n", PARITY);
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (p = 0; p < PARITY; ++p) {
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("\t{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i) {
|
2013-10-22 23:40:05 +02:00
|
|
|
if (i % 8 == 0)
|
|
|
|
|
printf("\t\t");
|
2013-10-25 18:03:05 +02:00
|
|
|
printf("0x%02x,", matrix[p*DISK+i]);
|
2013-10-22 23:40:05 +02:00
|
|
|
if (i % 8 == 7)
|
|
|
|
|
printf("\n");
|
|
|
|
|
else
|
|
|
|
|
printf(" ");
|
|
|
|
|
}
|
|
|
|
|
printf("\n\t},\n");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n\n");
|
|
|
|
|
|
2013-12-30 21:12:29 +01:00
|
|
|
printf("#ifdef CONFIG_X86\n");
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("/**\n");
|
2013-11-03 10:41:52 +01:00
|
|
|
printf(" * PSHUFB tables for the Cauchy matrix.\n");
|
2013-10-22 23:40:05 +02:00
|
|
|
printf(" *\n");
|
2013-10-25 18:03:05 +02:00
|
|
|
printf(" * Indexes are [DISK][PARITY - 2][LH].\n");
|
|
|
|
|
printf(" * Where DISK is from 0 to %u, PARITY from 2 to %u, LH from 0 to 1.\n", DISK - 1, PARITY - 1);
|
2013-10-22 23:40:05 +02:00
|
|
|
printf(" */\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
printf("const uint8_t __aligned(256) raid_gfcauchypshufb[%u][%u][2][16] =\n", DISK, np(PARITY - 2));
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i) {
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("\t{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (p = 2; p < PARITY; ++p) {
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("\t\t{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (j = 0; j < 2; ++j) {
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("\t\t\t{ ");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (k = 0; k < 16; ++k) {
|
2013-10-25 18:03:05 +02:00
|
|
|
v = gfmul(matrix[p*DISK+i], k);
|
2013-10-22 23:40:05 +02:00
|
|
|
if (j == 1)
|
|
|
|
|
v = gfmul(v, 16);
|
|
|
|
|
printf("0x%02x", (unsigned)v);
|
|
|
|
|
if (k != 15)
|
|
|
|
|
printf(", ");
|
|
|
|
|
}
|
|
|
|
|
printf(" },\n");
|
|
|
|
|
}
|
|
|
|
|
printf("\t\t},\n");
|
|
|
|
|
}
|
|
|
|
|
printf("\t},\n");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n");
|
|
|
|
|
printf("#endif\n\n");
|
|
|
|
|
|
2013-12-30 21:12:29 +01:00
|
|
|
printf("#ifdef CONFIG_X86\n");
|
2013-11-03 17:50:09 +01:00
|
|
|
printf("/**\n");
|
|
|
|
|
printf(" * PSHUFB tables for generic multiplication.\n");
|
|
|
|
|
printf(" *\n");
|
|
|
|
|
printf(" * Indexes are [MULTIPLER][LH].\n");
|
|
|
|
|
printf(" * Where MULTIPLER is from 0 to 255, LH from 0 to 1.\n");
|
|
|
|
|
printf(" */\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
printf("const uint8_t __aligned(256) raid_gfmulpshufb[256][2][16] =\n");
|
2013-11-03 17:50:09 +01:00
|
|
|
printf("{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < 256; ++i) {
|
2013-11-03 17:50:09 +01:00
|
|
|
printf("\t{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (j = 0; j < 2; ++j) {
|
2013-11-03 17:50:09 +01:00
|
|
|
printf("\t\t{ ");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (k = 0; k < 16; ++k) {
|
2013-11-03 17:50:09 +01:00
|
|
|
v = gfmul(i, k);
|
|
|
|
|
if (j == 1)
|
|
|
|
|
v = gfmul(v, 16);
|
|
|
|
|
printf("0x%02x", (unsigned)v);
|
|
|
|
|
if (k != 15)
|
|
|
|
|
printf(", ");
|
|
|
|
|
}
|
|
|
|
|
printf(" },\n");
|
|
|
|
|
}
|
|
|
|
|
printf("\t},\n");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n");
|
|
|
|
|
printf("#endif\n\n");
|
|
|
|
|
|
2013-09-07 19:43:33 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|