Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-message-builder.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */ 00002 /* dbus-message-builder.c Build messages from text files for testing (internal to D-BUS implementation) 00003 * 00004 * Copyright (C) 2003, 2004 Red Hat, Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 * 00022 */ 00023 #include <config.h> 00024 00025 #ifdef DBUS_BUILD_TESTS 00026 00027 #include "dbus-message-builder.h" 00028 #include "dbus-hash.h" 00029 #include "dbus-internals.h" 00030 #include "dbus-marshal.h" 00031 00046 typedef struct 00047 { 00048 DBusString name; 00049 int start; 00050 int length; 00051 int offset; 00052 int endian; 00053 } SavedLength; 00054 00055 static void 00056 free_saved_length (void *data) 00057 { 00058 SavedLength *sl = data; 00059 00060 if (sl == NULL) 00061 return; /* all hash free functions have to accept NULL */ 00062 00063 _dbus_string_free (&sl->name); 00064 dbus_free (sl); 00065 } 00066 00067 static SavedLength* 00068 ensure_saved_length (DBusHashTable *hash, 00069 const DBusString *name) 00070 { 00071 SavedLength *sl; 00072 const char *s; 00073 00074 s = _dbus_string_get_const_data (name); 00075 00076 sl = _dbus_hash_table_lookup_string (hash, s); 00077 if (sl != NULL) 00078 return sl; 00079 00080 sl = dbus_new0 (SavedLength, 1); 00081 00082 if (!_dbus_string_init (&sl->name)) 00083 { 00084 dbus_free (sl); 00085 return NULL; 00086 } 00087 00088 if (!_dbus_string_copy (name, 0, &sl->name, 0)) 00089 goto failed; 00090 00091 s = _dbus_string_get_const_data (&sl->name); 00092 00093 if (!_dbus_hash_table_insert_string (hash, (char*)s, sl)) 00094 goto failed; 00095 00096 sl->start = -1; 00097 sl->length = -1; 00098 sl->offset = -1; 00099 sl->endian = -1; 00100 00101 return sl; 00102 00103 failed: 00104 free_saved_length (sl); 00105 return NULL; 00106 } 00107 00108 static dbus_bool_t 00109 save_start (DBusHashTable *hash, 00110 const DBusString *name, 00111 int start) 00112 { 00113 SavedLength *sl; 00114 00115 sl = ensure_saved_length (hash, name); 00116 00117 if (sl == NULL) 00118 return FALSE; 00119 else if (sl->start >= 0) 00120 { 00121 _dbus_warn ("Same START_LENGTH given twice\n"); 00122 return FALSE; 00123 } 00124 else 00125 sl->start = start; 00126 00127 return TRUE; 00128 } 00129 00130 static dbus_bool_t 00131 save_length (DBusHashTable *hash, 00132 const DBusString *name, 00133 int length) 00134 { 00135 SavedLength *sl; 00136 00137 sl = ensure_saved_length (hash, name); 00138 00139 if (sl == NULL) 00140 return FALSE; 00141 else if (sl->length >= 0) 00142 { 00143 _dbus_warn ("Same END_LENGTH given twice\n"); 00144 return FALSE; 00145 } 00146 else 00147 sl->length = length; 00148 00149 return TRUE; 00150 } 00151 00152 static dbus_bool_t 00153 save_offset (DBusHashTable *hash, 00154 const DBusString *name, 00155 int offset, 00156 int endian) 00157 { 00158 SavedLength *sl; 00159 00160 sl = ensure_saved_length (hash, name); 00161 00162 if (sl == NULL) 00163 return FALSE; 00164 else if (sl->offset >= 0) 00165 { 00166 _dbus_warn ("Same LENGTH given twice\n"); 00167 return FALSE; 00168 } 00169 else 00170 { 00171 sl->offset = offset; 00172 sl->endian = endian; 00173 } 00174 00175 return TRUE; 00176 } 00177 00179 #define SAVE_FOR_UNALIGN(str, boundary) \ 00180 int align_pad_start = _dbus_string_get_length (str); \ 00181 int align_pad_end = _DBUS_ALIGN_VALUE (align_pad_start, (boundary)) 00182 00184 #define PERFORM_UNALIGN(str) \ 00185 if (unalign) \ 00186 { \ 00187 _dbus_string_delete ((str), align_pad_start, \ 00188 align_pad_end - align_pad_start); \ 00189 unalign = FALSE; \ 00190 } 00191 00192 00193 static dbus_bool_t 00194 append_quoted_string (DBusString *dest, 00195 const DBusString *quoted, 00196 int start_pos, 00197 int *new_pos) 00198 { 00199 dbus_bool_t in_quotes = FALSE; 00200 int i; 00201 00202 /* FIXME: We might want to add escaping in case we want to put ' 00203 * characters in our strings. 00204 */ 00205 00206 i = start_pos; 00207 while (i < _dbus_string_get_length (quoted)) 00208 { 00209 unsigned char b; 00210 00211 b = _dbus_string_get_byte (quoted, i); 00212 00213 if (in_quotes) 00214 { 00215 if (b == '\'') 00216 break; 00217 else 00218 { 00219 if (!_dbus_string_append_byte (dest, b)) 00220 return FALSE; 00221 } 00222 } 00223 else 00224 { 00225 if (b == '\'') 00226 in_quotes = TRUE; 00227 else if (b == ' ' || b == '\n' || b == '\t') 00228 break; /* end on whitespace if not quoted */ 00229 else 00230 { 00231 if (!_dbus_string_append_byte (dest, b)) 00232 return FALSE; 00233 } 00234 } 00235 00236 ++i; 00237 } 00238 00239 if (new_pos) 00240 *new_pos = i; 00241 00242 if (!_dbus_string_append_byte (dest, '\0')) 00243 return FALSE; 00244 return TRUE; 00245 } 00246 00247 static dbus_bool_t 00248 append_saved_length (DBusString *dest, 00249 DBusHashTable *length_hash, 00250 const DBusString *name, 00251 int offset, 00252 int endian) 00253 { 00254 if (!save_offset (length_hash, name, 00255 offset, endian)) 00256 { 00257 _dbus_warn ("failed to save offset to LENGTH\n"); 00258 return FALSE; 00259 } 00260 00261 if (!_dbus_marshal_uint32 (dest, endian, 00262 -1)) 00263 { 00264 _dbus_warn ("failed to append a length\n"); 00265 return FALSE; 00266 } 00267 00268 return TRUE; 00269 } 00270 00271 static int 00272 message_type_from_string (const DBusString *str, 00273 int start) 00274 { 00275 const char *s; 00276 00277 s = _dbus_string_get_const_data_len (str, start, 00278 _dbus_string_get_length (str) - start); 00279 00280 if (strncmp (s, "method_call", strlen ("method_call")) == 0) 00281 return DBUS_MESSAGE_TYPE_METHOD_CALL; 00282 else if (strncmp (s, "method_return", strlen ("method_return")) == 0) 00283 return DBUS_MESSAGE_TYPE_METHOD_RETURN; 00284 else if (strncmp (s, "signal", strlen ("signal")) == 0) 00285 return DBUS_MESSAGE_TYPE_SIGNAL; 00286 else if (strncmp (s, "error", strlen ("error")) == 0) 00287 return DBUS_MESSAGE_TYPE_ERROR; 00288 else if (strncmp (s, "invalid", strlen ("invalid")) == 0) 00289 return DBUS_MESSAGE_TYPE_INVALID; 00290 else 00291 return -1; 00292 } 00293 00294 static dbus_bool_t 00295 append_string_field (DBusString *dest, 00296 int endian, 00297 int field, 00298 int type, 00299 const char *value) 00300 { 00301 int len; 00302 00303 if (!_dbus_string_append_byte (dest, field)) 00304 { 00305 _dbus_warn ("couldn't append field name byte\n"); 00306 return FALSE; 00307 } 00308 00309 if (!_dbus_string_append_byte (dest, type)) 00310 { 00311 _dbus_warn ("could not append typecode byte\n"); 00312 return FALSE; 00313 } 00314 00315 len = strlen (value); 00316 00317 if (!_dbus_marshal_uint32 (dest, endian, len)) 00318 { 00319 _dbus_warn ("couldn't append string length\n"); 00320 return FALSE; 00321 } 00322 00323 if (!_dbus_string_append (dest, value)) 00324 { 00325 _dbus_warn ("couldn't append field value\n"); 00326 return FALSE; 00327 } 00328 00329 if (!_dbus_string_append_byte (dest, 0)) 00330 { 00331 _dbus_warn ("couldn't append string nul term\n"); 00332 return FALSE; 00333 } 00334 00335 return TRUE; 00336 } 00337 00338 static dbus_bool_t 00339 parse_basic_type (DBusString *src, char type, 00340 DBusString *dest, dbus_bool_t *unalign, 00341 int endian) 00342 { 00343 int align; 00344 int align_pad_start, align_pad_end; 00345 unsigned char data[16]; 00346 00347 switch (type) 00348 { 00349 case DBUS_TYPE_BYTE: 00350 case DBUS_TYPE_BOOLEAN: 00351 align = 1; 00352 break; 00353 case DBUS_TYPE_UINT32: 00354 case DBUS_TYPE_INT32: 00355 align = 4; 00356 break; 00357 case DBUS_TYPE_DOUBLE: 00358 align = 8; 00359 break; 00360 default: 00361 _dbus_assert_not_reached ("not a basic type"); 00362 break; 00363 } 00364 00365 align_pad_start = _dbus_string_get_length (dest); 00366 align_pad_end = _DBUS_ALIGN_VALUE (align_pad_start, align); 00367 00368 _dbus_string_delete_first_word (src); 00369 00370 if (!_dbus_string_parse_basic_type (src, type, 0, data, NULL)) 00371 { 00372 _dbus_verbose ("failed to parse type '%c'", type); 00373 return FALSE; 00374 } 00375 00376 if (!_dbus_marshal_basic_type (dest, type, data, endian)) 00377 { 00378 _dbus_verbose ("failed to marshal type '%c'", type); 00379 return FALSE; 00380 } 00381 00382 if (*unalign) 00383 { 00384 _dbus_string_delete (dest, align_pad_start, 00385 align_pad_end - align_pad_start); 00386 *unalign = FALSE; 00387 } 00388 00389 return TRUE; 00390 } 00391 00392 static dbus_bool_t 00393 parse_basic_array (DBusString *src, char type, 00394 DBusString *dest, dbus_bool_t *unalign, 00395 int endian) 00396 { 00397 int array_align, elem_size; 00398 int i, len, allocated; 00399 unsigned char *values, b; 00400 int values_offset; 00401 int align_pad_start, align_pad_end; 00402 dbus_bool_t retval = FALSE; 00403 00404 array_align = 4; /* length */ 00405 switch (type) 00406 { 00407 case DBUS_TYPE_BYTE: 00408 case DBUS_TYPE_BOOLEAN: 00409 elem_size = 1; 00410 break; 00411 case DBUS_TYPE_UINT32: 00412 case DBUS_TYPE_INT32: 00413 elem_size = 4; 00414 break; 00415 case DBUS_TYPE_DOUBLE: 00416 array_align = 8; 00417 elem_size = 8; 00418 break; 00419 default: 00420 _dbus_assert_not_reached ("not a basic type"); 00421 break; 00422 } 00423 00424 align_pad_start = _dbus_string_get_length (dest); 00425 align_pad_end = _DBUS_ALIGN_VALUE (align_pad_start, array_align); 00426 00427 len = 0; 00428 allocated = 2; 00429 values = NULL; 00430 values_offset = 0; 00431 00432 _dbus_string_delete_first_word (src); 00433 _dbus_string_skip_blank (src, 0, &i); 00434 b = _dbus_string_get_byte (src, i++); 00435 00436 if (b != '{') 00437 goto failed; 00438 00439 while (i < _dbus_string_get_length (src)) 00440 { 00441 _dbus_string_skip_blank (src, i, &i); 00442 00443 if (!values || len == allocated - 1) 00444 { 00445 allocated *= 2; 00446 values = dbus_realloc (values, allocated * elem_size); 00447 if (!values) 00448 { 00449 _dbus_warn ("could not allocate memory for '%c' ARRAY\n", type); 00450 goto failed; 00451 } 00452 } 00453 00454 if (!_dbus_string_parse_basic_type (src, type, i, values + values_offset, &i)) 00455 { 00456 _dbus_warn ("could not parse integer element %d of '%c' ARRAY\n", len, type); 00457 goto failed; 00458 } 00459 00460 values_offset += elem_size; 00461 len++; 00462 00463 _dbus_string_skip_blank (src, i, &i); 00464 00465 b = _dbus_string_get_byte (src, i++); 00466 00467 if (b == '}') 00468 break; 00469 else if (b != ',') 00470 goto failed; 00471 } 00472 00473 if (!_dbus_marshal_basic_type_array (dest, type, values, len, endian)) 00474 { 00475 _dbus_warn ("failed to append '%c' ARRAY\n", type); 00476 goto failed; 00477 } 00478 00479 if (*unalign) 00480 { 00481 _dbus_string_delete (dest, align_pad_start, 00482 align_pad_end - align_pad_start); 00483 *unalign = FALSE; 00484 } 00485 00486 retval = TRUE; 00487 00488 failed: 00489 dbus_free (values); 00490 return retval; 00491 } 00492 00493 static char 00494 lookup_basic_type (const DBusString *str, dbus_bool_t *is_array) 00495 { 00496 int i; 00497 char type = DBUS_TYPE_INVALID; 00498 static struct { 00499 const char *name; 00500 char type; 00501 } name_to_type[] = { 00502 { "BYTE", DBUS_TYPE_BYTE }, 00503 { "BOOLEAN", DBUS_TYPE_BOOLEAN }, 00504 { "INT32", DBUS_TYPE_INT32 }, 00505 { "UINT32", DBUS_TYPE_UINT32 }, 00506 { "DOUBLE", DBUS_TYPE_DOUBLE } 00507 }; 00508 00509 for (i = 0; i < _DBUS_N_ELEMENTS(name_to_type); i++) 00510 { 00511 const char *name = name_to_type[i].name; 00512 if (_dbus_string_starts_with_c_str (str, name)) 00513 { 00514 int offset = strlen (name); 00515 type = name_to_type[i].type; 00516 if (is_array) 00517 *is_array = _dbus_string_find (str, offset, "_ARRAY", NULL); 00518 break; 00519 } 00520 } 00521 00522 return type; 00523 } 00524 00576 dbus_bool_t 00577 _dbus_message_data_load (DBusString *dest, 00578 const DBusString *filename) 00579 { 00580 DBusString file; 00581 DBusError error; 00582 DBusString line; 00583 dbus_bool_t retval; 00584 int line_no; 00585 dbus_bool_t unalign; 00586 DBusHashTable *length_hash; 00587 int endian; 00588 DBusHashIter iter; 00589 char type; 00590 dbus_bool_t is_array; 00591 00592 retval = FALSE; 00593 length_hash = NULL; 00594 00595 if (!_dbus_string_init (&file)) 00596 return FALSE; 00597 00598 if (!_dbus_string_init (&line)) 00599 { 00600 _dbus_string_free (&file); 00601 return FALSE; 00602 } 00603 00604 _dbus_verbose ("Loading %s\n", _dbus_string_get_const_data (filename)); 00605 00606 dbus_error_init (&error); 00607 if (!_dbus_file_get_contents (&file, filename, &error)) 00608 { 00609 _dbus_warn ("Getting contents of %s failed: %s\n", 00610 _dbus_string_get_const_data (filename), error.message); 00611 dbus_error_free (&error); 00612 goto out; 00613 } 00614 00615 length_hash = _dbus_hash_table_new (DBUS_HASH_STRING, 00616 NULL, 00617 free_saved_length); 00618 if (length_hash == NULL) 00619 goto out; 00620 00621 endian = DBUS_COMPILER_BYTE_ORDER; 00622 unalign = FALSE; 00623 line_no = 0; 00624 next_iteration: 00625 while (_dbus_string_pop_line (&file, &line)) 00626 { 00627 dbus_bool_t just_set_unalign; 00628 00629 just_set_unalign = FALSE; 00630 line_no += 1; 00631 00632 _dbus_string_delete_leading_blanks (&line); 00633 00634 if (_dbus_string_get_length (&line) == 0) 00635 { 00636 /* empty line */ 00637 goto next_iteration; 00638 } 00639 else if (_dbus_string_starts_with_c_str (&line, 00640 "#")) 00641 { 00642 /* Ignore this comment */ 00643 goto next_iteration; 00644 } 00645 else if (_dbus_string_starts_with_c_str (&line, 00646 "VALID_HEADER")) 00647 { 00648 int i; 00649 DBusString name; 00650 int message_type; 00651 00652 if (_dbus_string_get_length (&line) < (int) strlen ("VALID_HEADER ")) 00653 { 00654 _dbus_warn ("no args to VALID_HEADER\n"); 00655 goto parse_failed; 00656 } 00657 00658 if (!_dbus_string_append_byte (dest, endian)) 00659 { 00660 _dbus_warn ("could not append endianness\n"); 00661 goto parse_failed; 00662 } 00663 00664 message_type = message_type_from_string (&line, 00665 strlen ("VALID_HEADER ")); 00666 if (message_type < 0) 00667 { 00668 _dbus_warn ("VALID_HEADER not followed by space then known message type\n"); 00669 goto parse_failed; 00670 } 00671 00672 if (!_dbus_string_append_byte (dest, message_type)) 00673 { 00674 _dbus_warn ("could not append message type\n"); 00675 goto parse_failed; 00676 } 00677 00678 i = 0; 00679 while (i < 2) 00680 { 00681 if (!_dbus_string_append_byte (dest, '\0')) 00682 { 00683 _dbus_warn ("could not append nul pad\n"); 00684 goto parse_failed; 00685 } 00686 ++i; 00687 } 00688 00689 _dbus_string_init_const (&name, "Header"); 00690 if (!append_saved_length (dest, length_hash, 00691 &name, _dbus_string_get_length (dest), 00692 endian)) 00693 goto parse_failed; 00694 00695 _dbus_string_init_const (&name, "Body"); 00696 if (!append_saved_length (dest, length_hash, 00697 &name, _dbus_string_get_length (dest), 00698 endian)) 00699 goto parse_failed; 00700 00701 /* client serial */ 00702 if (!_dbus_marshal_uint32 (dest, endian, 1)) 00703 { 00704 _dbus_warn ("couldn't append client serial\n"); 00705 goto parse_failed; 00706 } 00707 } 00708 else if (_dbus_string_starts_with_c_str (&line, 00709 "REQUIRED_FIELDS")) 00710 { 00711 if (!append_string_field (dest, endian, 00712 DBUS_HEADER_FIELD_INTERFACE, 00713 DBUS_TYPE_STRING, 00714 "org.freedesktop.BlahBlahInterface")) 00715 goto parse_failed; 00716 if (!append_string_field (dest, endian, 00717 DBUS_HEADER_FIELD_MEMBER, 00718 DBUS_TYPE_STRING, 00719 "BlahBlahMethod")) 00720 goto parse_failed; 00721 if (!append_string_field (dest, endian, 00722 DBUS_HEADER_FIELD_PATH, 00723 DBUS_TYPE_OBJECT_PATH, 00724 "/blah/blah/path")) 00725 goto parse_failed; 00726 00727 /* FIXME later we'll validate this, and then it will break 00728 * and the .message files will have to include the right thing 00729 */ 00730 if (!append_string_field (dest, endian, 00731 DBUS_HEADER_FIELD_SIGNATURE, 00732 DBUS_TYPE_STRING, 00733 "iii")) 00734 goto parse_failed; 00735 } 00736 else if (_dbus_string_starts_with_c_str (&line, 00737 "BIG_ENDIAN")) 00738 { 00739 endian = DBUS_BIG_ENDIAN; 00740 } 00741 else if (_dbus_string_starts_with_c_str (&line, 00742 "LITTLE_ENDIAN")) 00743 { 00744 endian = DBUS_LITTLE_ENDIAN; 00745 } 00746 else if (_dbus_string_starts_with_c_str (&line, 00747 "OPPOSITE_ENDIAN")) 00748 { 00749 if (endian == DBUS_BIG_ENDIAN) 00750 endian = DBUS_LITTLE_ENDIAN; 00751 else 00752 endian = DBUS_BIG_ENDIAN; 00753 } 00754 else if (_dbus_string_starts_with_c_str (&line, 00755 "ALIGN")) 00756 { 00757 long val; 00758 int end; 00759 int orig_len; 00760 00761 _dbus_string_delete_first_word (&line); 00762 00763 if (!_dbus_string_parse_int (&line, 0, &val, &end)) 00764 { 00765 _dbus_warn ("Failed to parse integer\n"); 00766 goto parse_failed; 00767 } 00768 00769 if (val > 8) 00770 { 00771 _dbus_warn ("Aligning to %ld boundary is crack\n", 00772 val); 00773 goto parse_failed; 00774 } 00775 00776 orig_len = _dbus_string_get_length (dest); 00777 00778 if (!_dbus_string_align_length (dest, val)) 00779 goto parse_failed; 00780 00781 if (_dbus_string_parse_int (&line, end, &val, NULL)) 00782 { 00783 /* If there's an optional second int argument, 00784 * fill in align padding with that value 00785 */ 00786 if (val < 0 || val > 255) 00787 { 00788 _dbus_warn ("can't fill align padding with %ld, must be a byte value\n", val); 00789 goto parse_failed; 00790 } 00791 00792 end = orig_len; 00793 while (end < _dbus_string_get_length (dest)) 00794 { 00795 _dbus_string_set_byte (dest, end, val); 00796 ++end; 00797 } 00798 } 00799 } 00800 else if (_dbus_string_starts_with_c_str (&line, "UNALIGN")) 00801 { 00802 unalign = TRUE; 00803 just_set_unalign = TRUE; 00804 } 00805 else if (_dbus_string_starts_with_c_str (&line, "CHOP")) 00806 { 00807 long val; 00808 00809 /* FIXME if you CHOP the offset for a LENGTH 00810 * command, we segfault. 00811 */ 00812 00813 _dbus_string_delete_first_word (&line); 00814 00815 if (!_dbus_string_parse_int (&line, 0, &val, NULL)) 00816 { 00817 _dbus_warn ("Failed to parse integer to chop\n"); 00818 goto parse_failed; 00819 } 00820 00821 if (val > _dbus_string_get_length (dest)) 00822 { 00823 _dbus_warn ("Trying to chop %ld bytes but we only have %d\n", 00824 val, 00825 _dbus_string_get_length (dest)); 00826 goto parse_failed; 00827 } 00828 00829 _dbus_string_shorten (dest, val); 00830 } 00831 else if (_dbus_string_starts_with_c_str (&line, 00832 "START_LENGTH")) 00833 { 00834 _dbus_string_delete_first_word (&line); 00835 00836 if (!save_start (length_hash, &line, 00837 _dbus_string_get_length (dest))) 00838 { 00839 _dbus_warn ("failed to save length start\n"); 00840 goto parse_failed; 00841 } 00842 } 00843 else if (_dbus_string_starts_with_c_str (&line, 00844 "END_LENGTH")) 00845 { 00846 _dbus_string_delete_first_word (&line); 00847 00848 if (!save_length (length_hash, &line, 00849 _dbus_string_get_length (dest))) 00850 { 00851 _dbus_warn ("failed to save length end\n"); 00852 goto parse_failed; 00853 } 00854 } 00855 else if (_dbus_string_starts_with_c_str (&line, 00856 "LENGTH")) 00857 { 00858 SAVE_FOR_UNALIGN (dest, 4); 00859 00860 _dbus_string_delete_first_word (&line); 00861 00862 if (!append_saved_length (dest, length_hash, 00863 &line, 00864 unalign ? align_pad_start : align_pad_end, 00865 endian)) 00866 { 00867 _dbus_warn ("failed to add LENGTH\n"); 00868 goto parse_failed; 00869 } 00870 00871 PERFORM_UNALIGN (dest); 00872 } 00873 else if (_dbus_string_starts_with_c_str (&line, 00874 "HEADER_FIELD")) 00875 { 00876 int field; 00877 00878 _dbus_string_delete_first_word (&line); 00879 00880 if (_dbus_string_starts_with_c_str (&line, "INVALID")) 00881 field = DBUS_HEADER_FIELD_INVALID; 00882 else if (_dbus_string_starts_with_c_str (&line, "PATH")) 00883 field = DBUS_HEADER_FIELD_PATH; 00884 else if (_dbus_string_starts_with_c_str (&line, "INTERFACE")) 00885 field = DBUS_HEADER_FIELD_INTERFACE; 00886 else if (_dbus_string_starts_with_c_str (&line, "MEMBER")) 00887 field = DBUS_HEADER_FIELD_MEMBER; 00888 else if (_dbus_string_starts_with_c_str (&line, "ERROR_NAME")) 00889 field = DBUS_HEADER_FIELD_ERROR_NAME; 00890 else if (_dbus_string_starts_with_c_str (&line, "REPLY_SERIAL")) 00891 field = DBUS_HEADER_FIELD_REPLY_SERIAL; 00892 else if (_dbus_string_starts_with_c_str (&line, "DESTINATION")) 00893 field = DBUS_HEADER_FIELD_DESTINATION; 00894 else if (_dbus_string_starts_with_c_str (&line, "SENDER")) 00895 field = DBUS_HEADER_FIELD_SENDER; 00896 else if (_dbus_string_starts_with_c_str (&line, "SIGNATURE")) 00897 field = DBUS_HEADER_FIELD_SIGNATURE; 00898 else if (_dbus_string_starts_with_c_str (&line, "UNKNOWN")) 00899 field = 22; /* random unknown header field */ 00900 else 00901 { 00902 _dbus_warn ("%s is not a valid header field name\n", 00903 _dbus_string_get_const_data (&line)); 00904 goto parse_failed; 00905 } 00906 00907 if (!_dbus_string_append_byte (dest, field)) 00908 { 00909 _dbus_warn ("could not append header field name byte\n"); 00910 goto parse_failed; 00911 } 00912 } 00913 else if (_dbus_string_starts_with_c_str (&line, 00914 "TYPE")) 00915 { 00916 int code; 00917 00918 _dbus_string_delete_first_word (&line); 00919 00920 if (_dbus_string_starts_with_c_str (&line, "INVALID")) 00921 code = DBUS_TYPE_INVALID; 00922 else if (_dbus_string_starts_with_c_str (&line, "NIL")) 00923 code = DBUS_TYPE_NIL; 00924 else if ((code = lookup_basic_type (&line, NULL)) != DBUS_TYPE_INVALID) 00925 ; 00926 else if (_dbus_string_starts_with_c_str (&line, "STRING")) 00927 code = DBUS_TYPE_STRING; 00928 else if (_dbus_string_starts_with_c_str (&line, "OBJECT_PATH")) 00929 code = DBUS_TYPE_OBJECT_PATH; 00930 else if (_dbus_string_starts_with_c_str (&line, "CUSTOM")) 00931 code = DBUS_TYPE_CUSTOM; 00932 else if (_dbus_string_starts_with_c_str (&line, "ARRAY")) 00933 code = DBUS_TYPE_ARRAY; 00934 else if (_dbus_string_starts_with_c_str (&line, "DICT")) 00935 code = DBUS_TYPE_DICT; 00936 else 00937 { 00938 _dbus_warn ("%s is not a valid type name\n", _dbus_string_get_const_data (&line)); 00939 goto parse_failed; 00940 } 00941 00942 if (!_dbus_string_append_byte (dest, code)) 00943 { 00944 _dbus_warn ("could not append typecode byte\n"); 00945 goto parse_failed; 00946 } 00947 } 00948 else if (_dbus_string_starts_with_c_str (&line, 00949 "STRING_ARRAY")) 00950 { 00951 SAVE_FOR_UNALIGN (dest, 4); 00952 int i, len, allocated; 00953 char **values; 00954 char *val; 00955 DBusString val_str; 00956 unsigned char b; 00957 00958 allocated = 4; 00959 values = dbus_new (char *, allocated); 00960 if (!values) 00961 { 00962 _dbus_warn ("could not allocate memory for STRING_ARRAY\n"); 00963 goto parse_failed; 00964 } 00965 00966 len = 0; 00967 00968 _dbus_string_delete_first_word (&line); 00969 _dbus_string_skip_blank (&line, 0, &i); 00970 b = _dbus_string_get_byte (&line, i++); 00971 00972 if (b != '{') 00973 goto parse_failed; 00974 00975 _dbus_string_init (&val_str); 00976 while (i < _dbus_string_get_length (&line)) 00977 { 00978 _dbus_string_skip_blank (&line, i, &i); 00979 00980 if (!append_quoted_string (&val_str, &line, i, &i)) 00981 { 00982 _dbus_warn ("could not parse quoted string for STRING_ARRAY\n"); 00983 goto parse_failed; 00984 } 00985 i++; 00986 00987 if (!_dbus_string_steal_data (&val_str, &val)) 00988 { 00989 _dbus_warn ("could not allocate memory for STRING_ARRAY string\n"); 00990 goto parse_failed; 00991 } 00992 00993 values[len++] = val; 00994 if (len == allocated) 00995 { 00996 allocated *= 2; 00997 values = dbus_realloc (values, allocated * sizeof (char *)); 00998 if (!values) 00999 { 01000 _dbus_warn ("could not allocate memory for STRING_ARRAY\n"); 01001 goto parse_failed; 01002 } 01003 } 01004 01005 _dbus_string_skip_blank (&line, i, &i); 01006 01007 b = _dbus_string_get_byte (&line, i++); 01008 01009 if (b == '}') 01010 break; 01011 else if (b != ',') 01012 { 01013 _dbus_warn ("missing comma when parsing STRING_ARRAY\n"); 01014 goto parse_failed; 01015 } 01016 } 01017 _dbus_string_free (&val_str); 01018 01019 if (!_dbus_marshal_string_array (dest, endian, (const char **)values, len)) 01020 { 01021 _dbus_warn ("failed to append STRING_ARRAY\n"); 01022 goto parse_failed; 01023 } 01024 01025 values[len] = NULL; 01026 dbus_free_string_array (values); 01027 01028 PERFORM_UNALIGN (dest); 01029 } 01030 else if (_dbus_string_starts_with_c_str (&line, 01031 "STRING")) 01032 { 01033 SAVE_FOR_UNALIGN (dest, 4); 01034 int size_offset; 01035 int old_len; 01036 01037 _dbus_string_delete_first_word (&line); 01038 01039 size_offset = _dbus_string_get_length (dest); 01040 size_offset = _DBUS_ALIGN_VALUE (size_offset, 4); 01041 if (!_dbus_marshal_uint32 (dest, endian, 0)) 01042 { 01043 _dbus_warn ("Failed to append string size\n"); 01044 goto parse_failed; 01045 } 01046 01047 old_len = _dbus_string_get_length (dest); 01048 if (!append_quoted_string (dest, &line, 0, NULL)) 01049 { 01050 _dbus_warn ("Failed to append quoted string\n"); 01051 goto parse_failed; 01052 } 01053 01054 _dbus_marshal_set_uint32 (dest, endian, size_offset, 01055 /* subtract 1 for nul */ 01056 _dbus_string_get_length (dest) - old_len - 1); 01057 01058 PERFORM_UNALIGN (dest); 01059 } 01060 else if ((type = lookup_basic_type (&line, &is_array)) != DBUS_TYPE_INVALID) 01061 { 01062 if (is_array) 01063 { 01064 if (!parse_basic_array (&line, type, dest, &unalign, endian)) 01065 goto parse_failed; 01066 } 01067 else 01068 { 01069 if (!parse_basic_type (&line, type, dest, &unalign, endian)) 01070 goto parse_failed; 01071 } 01072 } 01073 else if (_dbus_string_starts_with_c_str (&line, 01074 "OBJECT_PATH")) 01075 { 01076 SAVE_FOR_UNALIGN (dest, 4); 01077 int size_offset; 01078 int old_len; 01079 01080 _dbus_string_delete_first_word (&line); 01081 01082 size_offset = _dbus_string_get_length (dest); 01083 size_offset = _DBUS_ALIGN_VALUE (size_offset, 4); 01084 if (!_dbus_marshal_uint32 (dest, endian, 0)) 01085 { 01086 _dbus_warn ("Failed to append string size\n"); 01087 goto parse_failed; 01088 } 01089 01090 old_len = _dbus_string_get_length (dest); 01091 if (!append_quoted_string (dest, &line, 0, NULL)) 01092 { 01093 _dbus_warn ("Failed to append quoted string\n"); 01094 goto parse_failed; 01095 } 01096 01097 _dbus_marshal_set_uint32 (dest, endian, size_offset, 01098 /* subtract 1 for nul */ 01099 _dbus_string_get_length (dest) - old_len - 1); 01100 01101 PERFORM_UNALIGN (dest); 01102 } 01103 else 01104 goto parse_failed; 01105 01106 if (!just_set_unalign && unalign) 01107 { 01108 _dbus_warn ("UNALIGN prior to something that isn't aligned\n"); 01109 goto parse_failed; 01110 } 01111 01112 goto next_iteration; /* skip parse_failed */ 01113 01114 parse_failed: 01115 { 01116 _dbus_warn ("couldn't process line %d \"%s\"\n", 01117 line_no, _dbus_string_get_const_data (&line)); 01118 goto out; 01119 } 01120 } 01121 01122 _dbus_hash_iter_init (length_hash, &iter); 01123 while (_dbus_hash_iter_next (&iter)) 01124 { 01125 SavedLength *sl = _dbus_hash_iter_get_value (&iter); 01126 const char *s; 01127 01128 s = _dbus_string_get_const_data (&sl->name); 01129 01130 if (sl->length < 0) 01131 { 01132 _dbus_warn ("Used LENGTH %s but never did END_LENGTH\n", 01133 s); 01134 goto out; 01135 } 01136 else if (sl->offset < 0) 01137 { 01138 _dbus_warn ("Did END_LENGTH %s but never used LENGTH\n", 01139 s); 01140 goto out; 01141 } 01142 else 01143 { 01144 if (sl->start < 0) 01145 sl->start = 0; 01146 01147 _dbus_verbose ("Filling in length %s endian = %d offset = %d start = %d length = %d\n", 01148 s, sl->endian, sl->offset, sl->start, sl->length); 01149 _dbus_marshal_set_int32 (dest, 01150 sl->endian, 01151 sl->offset, 01152 sl->length - sl->start); 01153 } 01154 01155 _dbus_hash_iter_remove_entry (&iter); 01156 } 01157 01158 retval = TRUE; 01159 01160 _dbus_verbose_bytes_of_string (dest, 0, _dbus_string_get_length (dest)); 01161 01162 out: 01163 if (length_hash != NULL) 01164 _dbus_hash_table_unref (length_hash); 01165 01166 _dbus_string_free (&file); 01167 _dbus_string_free (&line); 01168 return retval; 01169 } 01170 01172 #endif /* DBUS_BUILD_TESTS */

Generated on Mon Jun 27 07:48:22 2005 for D-BUS by doxygen 1.3.7