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 Red Hat, Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.0
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 
00389 dbus_bool_t
00390 _dbus_message_data_load (DBusString       *dest,
00391                          const DBusString *filename)
00392 {
00393   DBusString file;
00394   DBusError error;
00395   DBusString line;
00396   dbus_bool_t retval;
00397   int line_no;
00398   dbus_bool_t unalign;
00399   DBusHashTable *length_hash;
00400   int endian;
00401   DBusHashIter iter;
00402   
00403   retval = FALSE;
00404   length_hash = NULL;
00405   
00406   if (!_dbus_string_init (&file))
00407     return FALSE;
00408 
00409   if (!_dbus_string_init (&line))
00410     {
00411       _dbus_string_free (&file);
00412       return FALSE;
00413     }
00414 
00415   _dbus_verbose ("Loading %s\n", _dbus_string_get_const_data (filename));
00416 
00417   dbus_error_init (&error);
00418   if (!_dbus_file_get_contents (&file, filename, &error))
00419     {
00420       _dbus_warn ("Getting contents of %s failed: %s\n",
00421                   _dbus_string_get_const_data (filename), error.message);
00422       dbus_error_free (&error);
00423       goto out;
00424     }
00425 
00426   length_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
00427                                       NULL,
00428                                       free_saved_length);
00429   if (length_hash == NULL)
00430     goto out;
00431   
00432   endian = DBUS_COMPILER_BYTE_ORDER;
00433   unalign = FALSE;
00434   line_no = 0;
00435  next_iteration:
00436   while (_dbus_string_pop_line (&file, &line))
00437     {
00438       dbus_bool_t just_set_unalign;
00439 
00440       just_set_unalign = FALSE;
00441       line_no += 1;
00442 
00443       _dbus_string_delete_leading_blanks (&line);
00444 
00445       if (_dbus_string_get_length (&line) == 0)
00446         {
00447           /* empty line */
00448           goto next_iteration;
00449         }
00450       else if (_dbus_string_starts_with_c_str (&line,
00451                                                "#"))
00452         {
00453           /* Ignore this comment */
00454           goto next_iteration;
00455         }
00456       else if (_dbus_string_starts_with_c_str (&line,
00457                                                "VALID_HEADER"))
00458         {
00459           int i;
00460           DBusString name;
00461           int message_type;
00462 
00463           if (_dbus_string_get_length (&line) < (int) strlen ("VALID_HEADER "))
00464             {
00465               _dbus_warn ("no args to VALID_HEADER\n");
00466               goto parse_failed;
00467             }
00468           
00469           if (!_dbus_string_append_byte (dest, endian))
00470             {
00471               _dbus_warn ("could not append endianness\n");
00472               goto parse_failed;
00473             }
00474 
00475           message_type = message_type_from_string (&line,
00476                                                    strlen ("VALID_HEADER "));
00477           if (message_type < 0)
00478             {
00479               _dbus_warn ("VALID_HEADER not followed by space then known message type\n");
00480               goto parse_failed;
00481             }
00482           
00483           if (!_dbus_string_append_byte (dest, message_type))
00484             {
00485               _dbus_warn ("could not append message type\n");
00486               goto parse_failed;
00487             }
00488           
00489           i = 0;
00490           while (i < 2)
00491             {
00492               if (!_dbus_string_append_byte (dest, '\0'))
00493                 {
00494                   _dbus_warn ("could not append nul pad\n");
00495                   goto parse_failed;
00496                 }
00497               ++i;
00498             }
00499 
00500           _dbus_string_init_const (&name, "Header");
00501           if (!append_saved_length (dest, length_hash,
00502                                     &name, _dbus_string_get_length (dest),
00503                                     endian))
00504             goto parse_failed;
00505 
00506           _dbus_string_init_const (&name, "Body");
00507           if (!append_saved_length (dest, length_hash,
00508                                     &name, _dbus_string_get_length (dest),
00509                                     endian))
00510             goto parse_failed;
00511           
00512           /* client serial */
00513           if (!_dbus_marshal_int32 (dest, endian, 1))
00514             {
00515               _dbus_warn ("couldn't append client serial\n");
00516               goto parse_failed;
00517             }
00518         }
00519       else if (_dbus_string_starts_with_c_str (&line,
00520                                                "REQUIRED_FIELDS"))
00521         {
00522           if (!append_string_field (dest, endian,
00523                                     DBUS_HEADER_FIELD_INTERFACE,
00524                                     DBUS_TYPE_STRING,
00525                                     "org.freedesktop.BlahBlahInterface"))
00526             goto parse_failed;
00527           if (!append_string_field (dest, endian,
00528                                     DBUS_HEADER_FIELD_MEMBER,
00529                                     DBUS_TYPE_STRING,
00530                                     "BlahBlahMethod"))
00531             goto parse_failed;
00532           if (!append_string_field (dest, endian,
00533                                     DBUS_HEADER_FIELD_PATH,
00534                                     DBUS_TYPE_OBJECT_PATH,
00535                                     "/blah/blah/path"))
00536             goto parse_failed;
00537         }
00538       else if (_dbus_string_starts_with_c_str (&line,
00539                                                "BIG_ENDIAN"))
00540         {
00541           endian = DBUS_BIG_ENDIAN;
00542         }
00543       else if (_dbus_string_starts_with_c_str (&line,
00544                                                "LITTLE_ENDIAN"))
00545         {
00546           endian = DBUS_LITTLE_ENDIAN;
00547         }
00548       else if (_dbus_string_starts_with_c_str (&line,
00549                                                "OPPOSITE_ENDIAN"))
00550         {
00551           if (endian == DBUS_BIG_ENDIAN)
00552             endian = DBUS_LITTLE_ENDIAN;
00553           else
00554             endian = DBUS_BIG_ENDIAN;
00555         }
00556       else if (_dbus_string_starts_with_c_str (&line,
00557                                                "ALIGN"))
00558         {
00559           long val;
00560           int end;
00561           int orig_len;
00562           
00563           _dbus_string_delete_first_word (&line);
00564 
00565           if (!_dbus_string_parse_int (&line, 0, &val, &end))
00566             {
00567               _dbus_warn ("Failed to parse integer\n");
00568               goto parse_failed;
00569             }
00570 
00571           if (val > 8)
00572             {
00573               _dbus_warn ("Aligning to %ld boundary is crack\n",
00574                           val);
00575               goto parse_failed;
00576             }
00577 
00578           orig_len = _dbus_string_get_length (dest);
00579           
00580           if (!_dbus_string_align_length (dest, val))
00581             goto parse_failed;
00582 
00583           if (_dbus_string_parse_int (&line, end, &val, NULL))
00584             {
00585               /* If there's an optional second int argument,
00586                * fill in align padding with that value
00587                */
00588               if (val < 0 || val > 255)
00589                 {
00590                   _dbus_warn ("can't fill align padding with %ld, must be a byte value\n", val);
00591                   goto parse_failed;
00592                 }
00593 
00594               end = orig_len;
00595               while (end < _dbus_string_get_length (dest))
00596                 {
00597                   _dbus_string_set_byte (dest, end, val);
00598                   ++end;
00599                 }
00600             }
00601         }
00602       else if (_dbus_string_starts_with_c_str (&line, "UNALIGN"))
00603         {
00604           unalign = TRUE;
00605           just_set_unalign = TRUE;
00606         }
00607       else if (_dbus_string_starts_with_c_str (&line, "CHOP"))
00608         {
00609           long val;
00610 
00611           /* FIXME if you CHOP the offset for a LENGTH
00612            * command, we segfault.
00613            */
00614           
00615           _dbus_string_delete_first_word (&line);
00616 
00617           if (!_dbus_string_parse_int (&line, 0, &val, NULL))
00618             {
00619               _dbus_warn ("Failed to parse integer to chop\n");
00620               goto parse_failed;
00621             }
00622 
00623           if (val > _dbus_string_get_length (dest))
00624             {
00625               _dbus_warn ("Trying to chop %ld bytes but we only have %d\n",
00626                           val,
00627                           _dbus_string_get_length (dest));
00628               goto parse_failed;
00629             }
00630           
00631           _dbus_string_shorten (dest, val);
00632         }
00633       else if (_dbus_string_starts_with_c_str (&line,
00634                                                "START_LENGTH"))
00635         {
00636           _dbus_string_delete_first_word (&line);
00637 
00638           if (!save_start (length_hash, &line,
00639                            _dbus_string_get_length (dest)))
00640             {
00641               _dbus_warn ("failed to save length start\n");
00642               goto parse_failed;
00643             }
00644         }
00645       else if (_dbus_string_starts_with_c_str (&line,
00646                                                "END_LENGTH"))
00647         {
00648           _dbus_string_delete_first_word (&line);
00649 
00650           if (!save_length (length_hash, &line,
00651                             _dbus_string_get_length (dest)))
00652             {
00653               _dbus_warn ("failed to save length end\n");
00654               goto parse_failed;
00655             }
00656         }
00657       else if (_dbus_string_starts_with_c_str (&line,
00658                                                "LENGTH"))
00659         {
00660           SAVE_FOR_UNALIGN (dest, 4);
00661           
00662           _dbus_string_delete_first_word (&line);
00663 
00664           if (!append_saved_length (dest, length_hash,
00665                                     &line,
00666                                     unalign ? align_pad_start : align_pad_end,
00667                                     endian))
00668             {
00669               _dbus_warn ("failed to add LENGTH\n");
00670               goto parse_failed;
00671             }
00672 
00673           PERFORM_UNALIGN (dest);
00674         }
00675       else if (_dbus_string_starts_with_c_str (&line,
00676                                                "HEADER_FIELD"))
00677         {
00678           int field;
00679 
00680           _dbus_string_delete_first_word (&line);
00681 
00682           if (_dbus_string_starts_with_c_str (&line, "INVALID"))
00683             field = DBUS_HEADER_FIELD_INVALID;
00684           else if (_dbus_string_starts_with_c_str (&line, "PATH"))
00685             field = DBUS_HEADER_FIELD_PATH;
00686           else if (_dbus_string_starts_with_c_str (&line, "INTERFACE"))
00687             field = DBUS_HEADER_FIELD_INTERFACE;
00688           else if (_dbus_string_starts_with_c_str (&line, "MEMBER"))
00689             field = DBUS_HEADER_FIELD_MEMBER;
00690           else if (_dbus_string_starts_with_c_str (&line, "ERROR_NAME"))
00691             field = DBUS_HEADER_FIELD_ERROR_NAME;
00692           else if (_dbus_string_starts_with_c_str (&line, "REPLY_SERIAL"))
00693             field = DBUS_HEADER_FIELD_REPLY_SERIAL;
00694           else if (_dbus_string_starts_with_c_str (&line, "SERVICE"))
00695             field = DBUS_HEADER_FIELD_SERVICE;
00696           else if (_dbus_string_starts_with_c_str (&line, "SENDER_SERVICE"))
00697             field = DBUS_HEADER_FIELD_SENDER_SERVICE;
00698           else if (_dbus_string_starts_with_c_str (&line, "UNKNOWN"))
00699             field = 22; /* random unknown header field */
00700           else
00701             {
00702               _dbus_warn ("%s is not a valid header field name\n",
00703                           _dbus_string_get_const_data (&line));
00704               goto parse_failed;
00705             }
00706 
00707           if (!_dbus_string_append_byte (dest, field))
00708             {
00709               _dbus_warn ("could not append header field name byte\n");
00710               goto parse_failed;
00711             }
00712         }
00713       else if (_dbus_string_starts_with_c_str (&line,
00714                                                "TYPE"))
00715         {
00716           int code;
00717           
00718           _dbus_string_delete_first_word (&line);          
00719 
00720           if (_dbus_string_starts_with_c_str (&line, "INVALID"))
00721             code = DBUS_TYPE_INVALID;
00722           else if (_dbus_string_starts_with_c_str (&line, "NIL"))
00723             code = DBUS_TYPE_NIL;
00724           else if (_dbus_string_starts_with_c_str (&line, "BYTE"))
00725             code = DBUS_TYPE_BYTE;
00726           else if (_dbus_string_starts_with_c_str (&line, "BOOLEAN"))
00727             code = DBUS_TYPE_BOOLEAN;
00728           else if (_dbus_string_starts_with_c_str (&line, "INT32"))
00729             code = DBUS_TYPE_INT32;
00730           else if (_dbus_string_starts_with_c_str (&line, "UINT32"))
00731             code = DBUS_TYPE_UINT32;
00732           else if (_dbus_string_starts_with_c_str (&line, "DOUBLE"))
00733             code = DBUS_TYPE_DOUBLE;
00734           else if (_dbus_string_starts_with_c_str (&line, "STRING"))
00735             code = DBUS_TYPE_STRING;
00736           else if (_dbus_string_starts_with_c_str (&line, "OBJECT_PATH"))
00737             code = DBUS_TYPE_OBJECT_PATH;
00738           else if (_dbus_string_starts_with_c_str (&line, "CUSTOM"))
00739             code = DBUS_TYPE_CUSTOM;
00740           else if (_dbus_string_starts_with_c_str (&line, "ARRAY"))
00741             code = DBUS_TYPE_ARRAY;
00742           else if (_dbus_string_starts_with_c_str (&line, "DICT"))
00743             code = DBUS_TYPE_DICT;
00744           else
00745             {
00746               _dbus_warn ("%s is not a valid type name\n", _dbus_string_get_const_data (&line));
00747               goto parse_failed;
00748             }
00749 
00750           if (!_dbus_string_append_byte (dest, code))
00751             {
00752               _dbus_warn ("could not append typecode byte\n");
00753               goto parse_failed;
00754             }
00755         }
00756       else if (_dbus_string_starts_with_c_str (&line,
00757                                                "BYTE_ARRAY"))
00758         {
00759           SAVE_FOR_UNALIGN (dest, 4);
00760           int i, len, allocated;
00761           unsigned char *values;
00762           unsigned char b;
00763           long val;
00764 
00765           allocated = 4;
00766           values = dbus_new (unsigned char, allocated);
00767           if (!values)
00768             {
00769               _dbus_warn ("could not allocate memory for BYTE_ARRAY\n");
00770               goto parse_failed;
00771             }
00772 
00773           len = 0;
00774           
00775           _dbus_string_delete_first_word (&line);
00776           _dbus_string_skip_blank (&line, 0, &i);
00777           b = _dbus_string_get_byte (&line, i++);
00778           
00779           if (b != '{')
00780             goto parse_failed;
00781 
00782           while (i < _dbus_string_get_length (&line))
00783             {
00784               _dbus_string_skip_blank (&line, i, &i);         
00785 
00786               if (_dbus_string_get_byte (&line, i) == '\'' &&
00787                   _dbus_string_get_length (&line) >= i + 4 &&
00788                   _dbus_string_get_byte (&line, i + 1) == '\\' &&
00789                   _dbus_string_get_byte (&line, i + 2) == '\'' &&
00790                   _dbus_string_get_byte (&line, i + 3) == '\'')
00791                 {
00792                   val = '\'';
00793                   i += 4;
00794                 }
00795               else if (_dbus_string_get_byte (&line, i) == '\'' &&
00796                        _dbus_string_get_length (&line) >= i + 3 &&
00797                        _dbus_string_get_byte (&line, i + 2) == '\'')
00798                 {
00799                   val = _dbus_string_get_byte (&line, i + 1);
00800                   i += 3;
00801                 }
00802               else
00803                 {
00804                   if (!_dbus_string_parse_int (&line, i, &val, &i))
00805                     {
00806                       _dbus_warn ("Failed to parse integer for BYTE_ARRAY\n");
00807                       goto parse_failed;
00808                     }
00809 
00810                   if (val < 0 || val > 255)
00811                     {
00812                       _dbus_warn ("A byte must be in range 0-255 not %ld\n",
00813                                   val);
00814                       goto parse_failed;
00815                     }
00816                 }
00817 
00818               values[len++] = val;
00819               if (len == allocated)
00820                 {
00821                   allocated *= 2;
00822                   values = dbus_realloc (values, allocated * sizeof (unsigned char));
00823                   if (!values)
00824                     {
00825                       _dbus_warn ("could not allocate memory for BYTE_ARRAY\n");
00826                       goto parse_failed;
00827                     }
00828                 }
00829               
00830               _dbus_string_skip_blank (&line, i, &i);
00831               
00832               b = _dbus_string_get_byte (&line, i++);
00833 
00834               if (b == '}')
00835                 break;
00836               else if (b != ',')
00837                 goto parse_failed;
00838             }
00839 
00840           if (!_dbus_marshal_int32 (dest, endian, len) ||
00841               !_dbus_string_append_len (dest, values, len))
00842             {
00843               _dbus_warn ("failed to append BYTE_ARRAY\n");
00844               goto parse_failed;
00845             }
00846           dbus_free (values);
00847           
00848           PERFORM_UNALIGN (dest);
00849         }
00850       else if (_dbus_string_starts_with_c_str (&line,
00851                                                "BOOLEAN_ARRAY"))
00852         {
00853           SAVE_FOR_UNALIGN (dest, 4);
00854           int i, len, allocated;
00855           unsigned char *values;
00856           unsigned char b, val;
00857 
00858           allocated = 4;
00859           values = dbus_new (unsigned char, allocated);
00860           if (!values)
00861             {
00862               _dbus_warn ("could not allocate memory for BOOLEAN_ARRAY\n");
00863               goto parse_failed;
00864             }
00865 
00866           len = 0;
00867           
00868           _dbus_string_delete_first_word (&line);
00869           _dbus_string_skip_blank (&line, 0, &i);
00870           b = _dbus_string_get_byte (&line, i++);
00871           
00872           if (b != '{')
00873             goto parse_failed;
00874 
00875           while (i < _dbus_string_get_length (&line))
00876             {
00877               _dbus_string_skip_blank (&line, i, &i);         
00878               
00879               if (_dbus_string_find_to (&line, i, i + 5,
00880                                         "false", NULL))
00881                 {
00882                   i += 5;
00883                   val = TRUE;
00884                 }
00885               else if (_dbus_string_find_to (&line, i, i + 4,
00886                                              "true", NULL))
00887                 {
00888                   i += 4;
00889                   val = FALSE;
00890                 }
00891               else
00892                 {
00893                   _dbus_warn ("could not parse BOOLEAN_ARRAY\n");
00894                   goto parse_failed;
00895                 }
00896 
00897               values[len++] = val;
00898               if (len == allocated)
00899                 {
00900                   allocated *= 2;
00901                   values = dbus_realloc (values, allocated * sizeof (unsigned char));
00902                   if (!values)
00903                     {
00904                       _dbus_warn ("could not allocate memory for BOOLEAN_ARRAY\n");
00905                       goto parse_failed;
00906                     }
00907                 }
00908               
00909               _dbus_string_skip_blank (&line, i, &i);
00910               
00911               b = _dbus_string_get_byte (&line, i++);
00912 
00913               if (b == '}')
00914                 break;
00915               else if (b != ',')
00916                 goto parse_failed;
00917             }
00918 
00919           if (!_dbus_marshal_int32 (dest, endian, len) ||
00920               !_dbus_string_append_len (dest, values, len))
00921             {
00922               _dbus_warn ("failed to append BOOLEAN_ARRAY\n");
00923               goto parse_failed;
00924             }
00925           dbus_free (values);
00926           
00927           PERFORM_UNALIGN (dest);
00928         }
00929       else if (_dbus_string_starts_with_c_str (&line,
00930                                                "INT32_ARRAY"))
00931         {
00932           SAVE_FOR_UNALIGN (dest, 4);
00933           int i, len, allocated;
00934           dbus_int32_t *values;
00935           long val;
00936           unsigned char b;
00937 
00938           allocated = 4;
00939           values = dbus_new (dbus_int32_t, allocated);
00940           if (!values)
00941             {
00942               _dbus_warn ("could not allocate memory for INT32_ARRAY\n");
00943               goto parse_failed;
00944             }
00945           
00946           len = 0;
00947           
00948           _dbus_string_delete_first_word (&line);
00949           _dbus_string_skip_blank (&line, 0, &i);
00950           b = _dbus_string_get_byte (&line, i++);
00951 
00952           if (b != '{')
00953             goto parse_failed;
00954 
00955           while (i < _dbus_string_get_length (&line))
00956             {
00957               _dbus_string_skip_blank (&line, i, &i);
00958 
00959               if (!_dbus_string_parse_int (&line, i, &val, &i))
00960                 {
00961                   _dbus_warn ("could not parse integer for INT32_ARRAY\n");
00962                   goto parse_failed;
00963                 }
00964 
00965               values[len++] = val;
00966               if (len == allocated)
00967                 {
00968                   allocated *= 2;
00969                   values = dbus_realloc (values, allocated * sizeof (dbus_int32_t));
00970                   if (!values)
00971                     {
00972                       _dbus_warn ("could not allocate memory for INT32_ARRAY\n");
00973                       goto parse_failed;
00974                     }
00975                 }
00976               
00977               _dbus_string_skip_blank (&line, i, &i);
00978               
00979               b = _dbus_string_get_byte (&line, i++);
00980 
00981               if (b == '}')
00982                 break;
00983               else if (b != ',')
00984                 goto parse_failed;
00985             }
00986 
00987           if (!_dbus_marshal_int32_array (dest, endian, values, len))
00988             {
00989               _dbus_warn ("failed to append INT32_ARRAY\n");
00990               goto parse_failed;
00991             }
00992           dbus_free (values);
00993           
00994           PERFORM_UNALIGN (dest);
00995         }
00996       else if (_dbus_string_starts_with_c_str (&line,
00997                                                "UINT32_ARRAY"))
00998         {
00999           SAVE_FOR_UNALIGN (dest, 4);
01000           int i, len, allocated;
01001           dbus_uint32_t *values;
01002           long val;
01003           unsigned char b;
01004 
01005           allocated = 4;
01006           values = dbus_new (dbus_uint32_t, allocated);
01007           if (!values)
01008             {
01009               _dbus_warn ("could not allocate memory for UINT32_ARRAY\n");
01010               goto parse_failed;
01011             }
01012           
01013           len = 0;
01014           
01015           _dbus_string_delete_first_word (&line);
01016           _dbus_string_skip_blank (&line, 0, &i);
01017           b = _dbus_string_get_byte (&line, i++);
01018 
01019           if (b != '{')
01020             goto parse_failed;
01021 
01022           while (i < _dbus_string_get_length (&line))
01023             {
01024               _dbus_string_skip_blank (&line, i, &i);
01025 
01026               if (!_dbus_string_parse_int (&line, i, &val, &i))
01027                 {
01028                   _dbus_warn ("could not parse integer for UINT32_ARRAY\n");
01029                   goto parse_failed;
01030                 }
01031 
01032               values[len++] = val;
01033               if (len == allocated)
01034                 {
01035                   allocated *= 2;
01036                   values = dbus_realloc (values, allocated * sizeof (dbus_uint32_t));
01037                   if (!values)
01038                     {
01039                       _dbus_warn ("could not allocate memory for UINT32_ARRAY\n");
01040                       goto parse_failed;
01041                     }
01042                 }
01043               
01044               _dbus_string_skip_blank (&line, i, &i);
01045               
01046               b = _dbus_string_get_byte (&line, i++);
01047 
01048               if (b == '}')
01049                 break;
01050               else if (b != ',')
01051                 goto parse_failed;
01052             }
01053 
01054           if (!_dbus_marshal_uint32_array (dest, endian, values, len))
01055             {
01056               _dbus_warn ("failed to append UINT32_ARRAY\n");
01057               goto parse_failed;
01058             }
01059           dbus_free (values);
01060           
01061           PERFORM_UNALIGN (dest);
01062         }
01063       else if (_dbus_string_starts_with_c_str (&line,
01064                                                "DOUBLE_ARRAY"))
01065         {
01066           SAVE_FOR_UNALIGN (dest, 8);
01067           int i, len, allocated;
01068           double *values;
01069           double val;
01070           unsigned char b;
01071 
01072           allocated = 4;
01073           values = dbus_new (double, allocated);
01074           if (!values)
01075             {
01076               _dbus_warn ("could not allocate memory for DOUBLE_ARRAY\n");
01077               goto parse_failed;
01078             }
01079           
01080           len = 0;
01081           
01082           _dbus_string_delete_first_word (&line);
01083           _dbus_string_skip_blank (&line, 0, &i);
01084           b = _dbus_string_get_byte (&line, i++);
01085 
01086           if (b != '{')
01087             goto parse_failed;
01088 
01089           while (i < _dbus_string_get_length (&line))
01090             {
01091               _dbus_string_skip_blank (&line, i, &i);
01092 
01093               if (!_dbus_string_parse_double (&line, i, &val, &i))
01094                 {
01095                   _dbus_warn ("could not parse double for DOUBLE_ARRAY\n");
01096                   goto parse_failed;
01097                 }
01098 
01099               values[len++] = val;
01100               if (len == allocated)
01101                 {
01102                   allocated *= 2;
01103                   values = dbus_realloc (values, allocated * sizeof (double));
01104                   if (!values)
01105                     {
01106                       _dbus_warn ("could not allocate memory for DOUBLE_ARRAY\n");
01107                       goto parse_failed;
01108                     }
01109                 }
01110               
01111               _dbus_string_skip_blank (&line, i, &i);
01112               
01113               b = _dbus_string_get_byte (&line, i++);
01114 
01115               if (b == '}')
01116                 break;
01117               else if (b != ',')
01118                 goto parse_failed;
01119             }
01120 
01121           if (!_dbus_marshal_double_array (dest, endian, values, len))
01122             {
01123               _dbus_warn ("failed to append DOUBLE_ARRAY\n");
01124               goto parse_failed;
01125             }
01126           dbus_free (values);
01127           
01128           PERFORM_UNALIGN (dest);
01129         }
01130       else if (_dbus_string_starts_with_c_str (&line,
01131                                                "STRING_ARRAY"))
01132         {
01133           SAVE_FOR_UNALIGN (dest, 4);
01134           int i, len, allocated;
01135           char **values;
01136           char *val;
01137           DBusString val_str;
01138           unsigned char b;
01139 
01140           allocated = 4;
01141           values = dbus_new (char *, allocated);
01142           if (!values)
01143             {
01144               _dbus_warn ("could not allocate memory for STRING_ARRAY\n");
01145               goto parse_failed;
01146             }
01147           
01148           len = 0;
01149           
01150           _dbus_string_delete_first_word (&line);
01151           _dbus_string_skip_blank (&line, 0, &i);
01152           b = _dbus_string_get_byte (&line, i++);
01153 
01154           if (b != '{')
01155             goto parse_failed;
01156 
01157           _dbus_string_init (&val_str);
01158           while (i < _dbus_string_get_length (&line))
01159             {
01160               _dbus_string_skip_blank (&line, i, &i);
01161 
01162               if (!append_quoted_string (&val_str, &line, i, &i))
01163                 {
01164                   _dbus_warn ("could not parse quoted string for STRING_ARRAY\n");
01165                   goto parse_failed;
01166                 }
01167               i++;
01168 
01169               if (!_dbus_string_steal_data (&val_str, &val))
01170                 {
01171                   _dbus_warn ("could not allocate memory for STRING_ARRAY string\n");
01172                   goto parse_failed;
01173                 }
01174               
01175               values[len++] = val;
01176               if (len == allocated)
01177                 {
01178                   allocated *= 2;
01179                   values = dbus_realloc (values, allocated * sizeof (char *));
01180                   if (!values)
01181                     {
01182                       _dbus_warn ("could not allocate memory for STRING_ARRAY\n");
01183                       goto parse_failed;
01184                     }
01185                 }
01186               
01187               _dbus_string_skip_blank (&line, i, &i);
01188               
01189               b = _dbus_string_get_byte (&line, i++);
01190 
01191               if (b == '}')
01192                 break;
01193               else if (b != ',')
01194                 {
01195                   _dbus_warn ("missing comma when parsing STRING_ARRAY\n");
01196                   goto parse_failed;
01197                 }
01198             }
01199           _dbus_string_free (&val_str);
01200           
01201           if (!_dbus_marshal_string_array (dest, endian, (const char **)values, len))
01202             {
01203               _dbus_warn ("failed to append STRING_ARRAY\n");
01204               goto parse_failed;
01205             }
01206 
01207           values[len] = NULL;
01208           dbus_free_string_array (values);
01209           
01210           PERFORM_UNALIGN (dest);
01211         }
01212       else if (_dbus_string_starts_with_c_str (&line, "BYTE"))
01213         {
01214           unsigned char the_byte;
01215           
01216           _dbus_string_delete_first_word (&line);
01217 
01218           if (_dbus_string_equal_c_str (&line, "'\\''"))
01219             the_byte = '\'';
01220           else if (_dbus_string_get_byte (&line, 0) == '\'' &&
01221                    _dbus_string_get_length (&line) >= 3 &&
01222                    _dbus_string_get_byte (&line, 2) == '\'')
01223             the_byte = _dbus_string_get_byte (&line, 1);
01224           else
01225             {
01226               long val;
01227               if (!_dbus_string_parse_int (&line, 0, &val, NULL))
01228                 {
01229                   _dbus_warn ("Failed to parse integer for BYTE\n");
01230                   goto parse_failed;
01231                 }
01232 
01233               if (val > 255)
01234                 {
01235                   _dbus_warn ("A byte must be in range 0-255 not %ld\n",
01236                                  val);
01237                   goto parse_failed;
01238                 }
01239               the_byte = (unsigned char) val;
01240             }
01241 
01242           _dbus_string_append_byte (dest, the_byte);
01243         }
01244       else if (_dbus_string_starts_with_c_str (&line,
01245                                                "BOOLEAN"))
01246         {
01247           unsigned char val;
01248 
01249           _dbus_string_delete_first_word (&line);
01250 
01251           if (_dbus_string_starts_with_c_str (&line, "true"))
01252             val = TRUE;
01253           else if (_dbus_string_starts_with_c_str (&line, "false"))
01254             val = FALSE;
01255           else
01256             {
01257               _dbus_warn ("could not parse BOOLEAN\n");
01258               goto parse_failed;
01259             }
01260           if (!_dbus_string_append_byte (dest, val))
01261             {
01262               _dbus_warn ("failed to append BOOLEAN\n");
01263               goto parse_failed;
01264             }
01265         }
01266       
01267       else if (_dbus_string_starts_with_c_str (&line,
01268                                                "INT32"))
01269         {
01270           SAVE_FOR_UNALIGN (dest, 4);
01271           long val;
01272           
01273           _dbus_string_delete_first_word (&line);
01274 
01275           if (!_dbus_string_parse_int (&line, 0, &val, NULL))
01276             {
01277               _dbus_warn ("could not parse integer for INT32\n");
01278               goto parse_failed;
01279             }
01280           
01281           if (!_dbus_marshal_int32 (dest, endian,
01282                                     val))
01283             {
01284               _dbus_warn ("failed to append INT32\n");
01285               goto parse_failed;
01286             }
01287 
01288           PERFORM_UNALIGN (dest);
01289         }
01290       else if (_dbus_string_starts_with_c_str (&line,
01291                                                "UINT32"))
01292         {
01293           SAVE_FOR_UNALIGN (dest, 4);
01294           unsigned long val;
01295           
01296           _dbus_string_delete_first_word (&line);
01297 
01298           if (!_dbus_string_parse_uint (&line, 0, &val, NULL))
01299             goto parse_failed;
01300           
01301           if (!_dbus_marshal_uint32 (dest, endian,
01302                                      val))
01303             {
01304               _dbus_warn ("failed to append UINT32\n");
01305               goto parse_failed;
01306             }
01307 
01308           PERFORM_UNALIGN (dest);
01309         }
01310       else if (_dbus_string_starts_with_c_str (&line,
01311                                                "DOUBLE"))
01312         {
01313           SAVE_FOR_UNALIGN (dest, 8);
01314           double val;
01315           
01316           _dbus_string_delete_first_word (&line);
01317 
01318           if (!_dbus_string_parse_double (&line, 0, &val, NULL))
01319             goto parse_failed;
01320           
01321           if (!_dbus_marshal_double (dest, endian,
01322                                      val))
01323             {
01324               _dbus_warn ("failed to append DOUBLE\n");
01325               goto parse_failed;
01326             }
01327 
01328           PERFORM_UNALIGN (dest);
01329         }
01330       else if (_dbus_string_starts_with_c_str (&line,
01331                                                "STRING"))
01332         {
01333           SAVE_FOR_UNALIGN (dest, 4);
01334           int size_offset;
01335           int old_len;
01336           
01337           _dbus_string_delete_first_word (&line);
01338 
01339           size_offset = _dbus_string_get_length (dest);
01340           size_offset = _DBUS_ALIGN_VALUE (size_offset, 4);
01341           if (!_dbus_marshal_uint32 (dest, endian, 0))
01342             {
01343               _dbus_warn ("Failed to append string size\n");
01344               goto parse_failed;
01345             }
01346 
01347           old_len = _dbus_string_get_length (dest);
01348           if (!append_quoted_string (dest, &line, 0, NULL))
01349             {
01350               _dbus_warn ("Failed to append quoted string\n");
01351               goto parse_failed;
01352             }
01353 
01354           _dbus_marshal_set_uint32 (dest, endian, size_offset,
01355                                     /* subtract 1 for nul */
01356                                     _dbus_string_get_length (dest) - old_len - 1);
01357           
01358           PERFORM_UNALIGN (dest);
01359         }
01360       else if (_dbus_string_starts_with_c_str (&line,
01361                                                "OBJECT_PATH"))
01362         {
01363           SAVE_FOR_UNALIGN (dest, 4);
01364           int size_offset;
01365           int old_len;
01366           
01367           _dbus_string_delete_first_word (&line);
01368           
01369           size_offset = _dbus_string_get_length (dest);
01370           size_offset = _DBUS_ALIGN_VALUE (size_offset, 4);
01371           if (!_dbus_marshal_uint32 (dest, endian, 0))
01372             {
01373               _dbus_warn ("Failed to append string size\n");
01374               goto parse_failed;
01375             }
01376 
01377           old_len = _dbus_string_get_length (dest);
01378           if (!append_quoted_string (dest, &line, 0, NULL))
01379             {
01380               _dbus_warn ("Failed to append quoted string\n");
01381               goto parse_failed;
01382             }
01383 
01384           _dbus_marshal_set_uint32 (dest, endian, size_offset,
01385                                     /* subtract 1 for nul */
01386                                     _dbus_string_get_length (dest) - old_len - 1);
01387           
01388           PERFORM_UNALIGN (dest);
01389         }      
01390       else
01391         goto parse_failed;
01392       
01393       if (!just_set_unalign && unalign)
01394         {
01395           _dbus_warn ("UNALIGN prior to something that isn't aligned\n");
01396           goto parse_failed;
01397         }
01398 
01399       goto next_iteration; /* skip parse_failed */
01400       
01401     parse_failed:
01402       {
01403         _dbus_warn ("couldn't process line %d \"%s\"\n",
01404                     line_no, _dbus_string_get_const_data (&line));
01405         goto out;
01406       }
01407     }
01408 
01409   _dbus_hash_iter_init (length_hash, &iter);
01410   while (_dbus_hash_iter_next (&iter))
01411     {
01412       SavedLength *sl = _dbus_hash_iter_get_value (&iter);
01413       const char *s;
01414 
01415       s = _dbus_string_get_const_data (&sl->name);
01416       
01417       if (sl->length < 0)
01418         {
01419           _dbus_warn ("Used LENGTH %s but never did END_LENGTH\n",
01420                       s);
01421           goto out;
01422         }
01423       else if (sl->offset < 0)
01424         {
01425           _dbus_warn ("Did END_LENGTH %s but never used LENGTH\n",
01426                       s);
01427           goto out;
01428         }
01429       else
01430         {
01431           if (sl->start < 0)
01432             sl->start = 0;
01433           
01434           _dbus_verbose ("Filling in length %s endian = %d offset = %d start = %d length = %d\n",
01435                          s, sl->endian, sl->offset, sl->start, sl->length);
01436           _dbus_marshal_set_int32 (dest,
01437                                    sl->endian,
01438                                    sl->offset,
01439                                    sl->length - sl->start);
01440         }
01441 
01442       _dbus_hash_iter_remove_entry (&iter);
01443     }
01444   
01445   retval = TRUE;
01446 
01447   _dbus_verbose_bytes_of_string (dest, 0, _dbus_string_get_length (dest));
01448   
01449  out:
01450   if (length_hash != NULL)
01451     _dbus_hash_table_unref (length_hash);
01452   
01453   _dbus_string_free (&file);
01454   _dbus_string_free (&line);
01455   return retval;
01456 }
01457 
01459 #endif /* DBUS_BUILD_TESTS */

Generated on Sun Mar 21 03:52:05 2004 for D-BUS by doxygen 1.3.6-20040222