0) { if (preg_match('/^\\/\\/.*/', $str, $matches)) { $str = substr($str, strlen($matches[0])); } else if (preg_match('/^\\s+/', $str, $matches)) { $str = substr($str, strlen($matches[0])); } else if (preg_match('/^include/', $str, $matches)) { $out[] = array('include', null); $str = substr($str, strlen($matches[0])); } else if (preg_match('/^structure/', $str, $matches)) { $out[] = array('structure', null); $str = substr($str, strlen($matches[0])); } else if (preg_match('/^size/', $str, $matches)) { $out[] = array('size', null); $str = substr($str, strlen($matches[0])); } else if (preg_match('/^align/', $str, $matches)) { $out[] = array('align', null); $str = substr($str, strlen($matches[0])); } else if (preg_match('/^{/', $str, $matches)) { $out[] = array('spar', null); $str = substr($str, strlen($matches[0])); } else if (preg_match('/^}/', $str, $matches)) { $out[] = array('epar', null); $str = substr($str, strlen($matches[0])); } else if (preg_match('/^\(/', $str, $matches)) { $out[] = array('srpar', null); $str = substr($str, strlen($matches[0])); } else if (preg_match('/^\)/', $str, $matches)) { $out[] = array('erpar', null); $str = substr($str, strlen($matches[0])); } else if (preg_match('/^\[/', $str, $matches)) { $out[] = array('sbracket', null); $str = substr($str, strlen($matches[0])); } else if (preg_match('/^\]/', $str, $matches)) { $out[] = array('ebracket', null); $str = substr($str, strlen($matches[0])); } else if (preg_match('/^;/', $str, $matches)) { $out[] = array('semicolon', null); $str = substr($str, strlen($matches[0])); } else if (preg_match('/^,/', $str, $matches)) { $out[] = array('comma', null); $str = substr($str, strlen($matches[0])); } else if (preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*/', $str, $matches)) { $out[] = array('name', $matches[0]); $str = substr($str, strlen($matches[0])); } else if (preg_match('/^"([^"]*)"/', $str, $matches)) { $out[] = array('string', $matches[1]); $str = substr($str, strlen($matches[0])); } else { return FALSE; } } return TRUE; } function fatal_error ($message) { fwrite(STDERR, "Fatal error: $message\n"); ob_get_clean(); exit(1); } function make_size ($entry) { switch ($entry["type"]["type"]) { case "sizealign": return "({$entry["type"]["size"]})"; case "structure": return "o->{$entry["name"]}_params.len"; default: assert(0); } } function make_align ($entry) { switch ($entry["type"]["type"]) { case "sizealign": return "({$entry["type"]["align"]})"; case "structure": return "o->{$entry["name"]}_params.align"; default: assert(0); } } function generate_header ($name, $directives, $structures) { ob_start(); echo << #include EOD; foreach ($directives as $directive) { if ($directive["type"] == "include") { echo <<len = 0; o->align = 1; EOD; // Calculate the alignment of the structure as the maximum of alignments of its entries. // This assumes the alignments are powers of two; in general we would need the least // common multiple of the alignments. $prev = NULL; foreach ($struct["entries"] as $entry) { if ($entry["type"]["type"] == "structure") { if ($entry["type"]["parameters"] == "") { $init_add_parameters = ""; } else { $init_add_parameters = ", {$entry["type"]["parameters"]}"; } echo <<{$entry["name"]}_params{$init_add_parameters}); EOD; } $size = make_size($entry); $align = make_align($entry); echo <<{$entry["name"]}_off = {$off}; o->{$entry["name"]}_size = cur_size; #ifndef NDEBUG o->{$entry["name"]}_count = cur_count; #endif o->len = o->{$entry["name"]}_off + {$len}; o->align = (cur_align > o->align ? cur_align : o->align); EOD; } echo <<{$entry["name"]}_off); } static {$entry["type"]["ctype"]} * {$struct["name"]}_{$entry["name"]}_at ({$struct["name"]}Params *o, {$struct["name"]} *s, int i) { ASSERT(i >= 0) ASSERT(i < o->{$entry["name"]}_count) return ({$entry["type"]["ctype"]} *)((uint8_t *)s + o->{$entry["name"]}_off + i * o->{$entry["name"]}_size); } EOD; } echo <<