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 1.2
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 
00043 typedef struct
00044 {
00045   DBusString name;
00046   int start;  
00047   int length; 
00048   int offset; 
00049   int endian; 
00050 } SavedLength;
00051 
00052 static void
00053 free_saved_length (void *data)
00054 {
00055   SavedLength *sl = data;
00056 
00057   if (sl == NULL)
00058     return; /* all hash free functions have to accept NULL */
00059   
00060   _dbus_string_free (&sl->name);
00061   dbus_free (sl);
00062 }
00063 
00064 static SavedLength*
00065 ensure_saved_length (DBusHashTable    *hash,
00066                      const DBusString *name)
00067 {
00068   SavedLength *sl;
00069   const char *s;
00070   
00071   s = _dbus_string_get_const_data (name);
00072 
00073   sl = _dbus_hash_table_lookup_string (hash, s);
00074   if (sl != NULL)
00075     return sl;
00076   
00077   sl = dbus_new0 (SavedLength, 1);
00078 
00079   if (!_dbus_string_init (&sl->name))
00080     {
00081       dbus_free (sl);
00082       return NULL;
00083     }
00084 
00085   if (!_dbus_string_copy (name, 0, &sl->name, 0))
00086     goto failed;
00087 
00088   s = _dbus_string_get_const_data (&sl->name);
00089 
00090   if (!_dbus_hash_table_insert_string (hash, (char*)s, sl))
00091     goto failed;
00092 
00093   sl->start = -1;
00094   sl->length = -1;
00095   sl->offset = -1;
00096   sl->endian = -1;
00097   
00098   return sl;
00099   
00100  failed:
00101   free_saved_length (sl);
00102   return NULL;
00103 }
00104 
00105 static dbus_bool_t
00106 save_start (DBusHashTable    *hash,
00107             const DBusString *name,
00108             int               start)
00109 {
00110   SavedLength *sl;
00111 
00112   sl = ensure_saved_length (hash, name);
00113 
00114   if (sl == NULL)
00115     return FALSE;
00116   else if (sl->start >= 0)
00117     {
00118       _dbus_warn ("Same START_LENGTH given twice\n");
00119       return FALSE;
00120     }
00121   else
00122     sl->start = start;
00123 
00124   return TRUE;
00125 }
00126 
00127 static dbus_bool_t
00128 save_length (DBusHashTable    *hash,
00129              const DBusString *name,
00130              int               length)
00131 {
00132   SavedLength *sl;
00133 
00134   sl = ensure_saved_length (hash, name);
00135 
00136   if (sl == NULL)
00137     return FALSE;
00138   else if (sl->length >= 0)
00139     {
00140       _dbus_warn ("Same END_LENGTH given twice\n");
00141       return FALSE;
00142     }
00143   else
00144     sl->length = length;
00145 
00146   return TRUE;
00147 }
00148 
00149 static dbus_bool_t
00150 save_offset (DBusHashTable    *hash,
00151              const DBusString *name,
00152              int               offset,
00153              int               endian)
00154 {
00155   SavedLength *sl;
00156 
00157   sl = ensure_saved_length (hash, name);
00158 
00159   if (sl == NULL)
00160     return FALSE;
00161   else if (sl->offset >= 0)
00162     {
00163       _dbus_warn ("Same LENGTH given twice\n");
00164       return FALSE;
00165     }
00166   else
00167     {
00168       sl->offset = offset;
00169       sl->endian = endian;
00170     }
00171 
00172   return TRUE;
00173 }
00174 
00176 #define SAVE_FOR_UNALIGN(str, boundary)                                 \
00177   int align_pad_start = _dbus_string_get_length (str);                  \
00178   int align_pad_end = _DBUS_ALIGN_VALUE (align_pad_start, (boundary))
00179 
00181 #define PERFORM_UNALIGN(str)                                    \
00182   if (unalign)                                                  \
00183     {                                                           \
00184       _dbus_string_delete ((str), align_pad_start,              \
00185                            align_pad_end - align_pad_start);    \
00186       unalign = FALSE;                                          \
00187     }
00188 
00189 
00190 static dbus_bool_t
00191 append_quoted_string (DBusString       *dest,
00192                       const DBusString *quoted,
00193                       int               start_pos,
00194                       int              *new_pos)
00195 {
00196   dbus_bool_t in_quotes = FALSE;
00197   int i;
00198 
00199   /* FIXME: We might want to add escaping in case we want to put '
00200    * characters in our strings.
00201    */
00202   
00203   i = start_pos;
00204   while (i < _dbus_string_get_length (quoted))
00205     {
00206       unsigned char b;
00207 
00208       b = _dbus_string_get_byte (quoted, i);
00209       
00210       if (in_quotes)
00211         {
00212           if (b == '\'')
00213             break;
00214           else
00215             {
00216               if (!_dbus_string_append_byte (dest, b))
00217                 return FALSE;
00218             }
00219         }
00220       else
00221         {
00222           if (b == '\'')
00223             in_quotes = TRUE;
00224           else if (b == ' ' || b == '\n' || b == '\t')
00225             break; /* end on whitespace if not quoted */
00226           else
00227             {
00228               if (!_dbus_string_append_byte (dest, b))
00229                 return FALSE;
00230             }
00231         }
00232       
00233       ++i;
00234     }
00235 
00236   if (new_pos)
00237     *new_pos = i;
00238   
00239   if (!_dbus_string_append_byte (dest, '\0'))
00240     return FALSE;
00241   return TRUE;
00242 }
00243 
00244 static dbus_bool_t
00245 append_saved_length (DBusString       *dest,
00246                      DBusHashTable    *length_hash,
00247                      const DBusString *name,
00248                      int               offset,
00249                      int               endian)
00250 {
00251   if (!save_offset (length_hash, name,
00252                     offset, endian))
00253     {
00254       _dbus_warn ("failed to save offset to LENGTH\n");
00255       return FALSE;
00256     }
00257   
00258   if (!_dbus_marshal_uint32 (dest, endian,
00259                              -1))
00260     {
00261       _dbus_warn ("failed to append a length\n");
00262       return FALSE;
00263     }
00264 
00265   return TRUE;
00266 }
00267 
00317 dbus_bool_t
00318 _dbus_message_data_load (DBusString       *dest,
00319                          const DBusString *filename)
00320 {
00321   DBusString file;
00322   DBusError error;
00323   DBusString line;
00324   dbus_bool_t retval;
00325   int line_no;
00326   dbus_bool_t unalign;
00327   DBusHashTable *length_hash;
00328   int endian;
00329   DBusHashIter iter;
00330   
00331   retval = FALSE;
00332   length_hash = NULL;
00333   
00334   if (!_dbus_string_init (&file))
00335     return FALSE;
00336 
00337   if (!_dbus_string_init (&line))
00338     {
00339       _dbus_string_free (&file);
00340       return FALSE;
00341     }
00342 
00343   _dbus_verbose ("Loading %s\n", _dbus_string_get_const_data (filename));
00344 
00345   dbus_error_init (&error);
00346   if (!_dbus_file_get_contents (&file, filename, &error))
00347     {
00348       _dbus_warn ("Getting contents of %s failed: %s\n",
00349                   _dbus_string_get_const_data (filename), error.message);
00350       dbus_error_free (&error);
00351       goto out;
00352     }
00353 
00354   length_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
00355                                       NULL,
00356                                       free_saved_length);
00357   if (length_hash == NULL)
00358     goto out;
00359   
00360   endian = DBUS_COMPILER_BYTE_ORDER;
00361   unalign = FALSE;
00362   line_no = 0;
00363  next_iteration:
00364   while (_dbus_string_pop_line (&file, &line))
00365     {
00366       dbus_bool_t just_set_unalign;
00367 
00368       just_set_unalign = FALSE;
00369       line_no += 1;
00370 
00371       _dbus_string_delete_leading_blanks (&line);
00372 
00373       if (_dbus_string_get_length (&line) == 0)
00374         {
00375           /* empty line */
00376           goto next_iteration;
00377         }
00378       else if (_dbus_string_starts_with_c_str (&line,
00379                                                "#"))
00380         {
00381           /* Ignore this comment */
00382           goto next_iteration;
00383         }
00384       else if (_dbus_string_starts_with_c_str (&line,
00385                                                "VALID_HEADER"))
00386         {
00387           int i;
00388           DBusString name;
00389           
00390           if (!_dbus_string_append_byte (dest, endian))
00391             {
00392               _dbus_warn ("could not append endianness\n");
00393               goto parse_failed;
00394             }
00395 
00396           i = 0;
00397           while (i < 3)
00398             {
00399               if (!_dbus_string_append_byte (dest, '\0'))
00400                 {
00401                   _dbus_warn ("could not append nul pad\n");
00402                   goto parse_failed;
00403                 }
00404               ++i;
00405             }
00406 
00407           _dbus_string_init_const (&name, "Header");
00408           if (!append_saved_length (dest, length_hash,
00409                                     &name, _dbus_string_get_length (dest),
00410                                     endian))
00411             goto parse_failed;
00412 
00413           _dbus_string_init_const (&name, "Body");
00414           if (!append_saved_length (dest, length_hash,
00415                                     &name, _dbus_string_get_length (dest),
00416                                     endian))
00417             goto parse_failed;
00418           
00419           /* client serial */
00420           if (!_dbus_marshal_int32 (dest, endian, 1))
00421             {
00422               _dbus_warn ("couldn't append client serial\n");
00423               goto parse_failed;
00424             }
00425         }
00426       else if (_dbus_string_starts_with_c_str (&line,
00427                                                "BIG_ENDIAN"))
00428         {
00429           endian = DBUS_BIG_ENDIAN;
00430         }
00431       else if (_dbus_string_starts_with_c_str (&line,
00432                                                "LITTLE_ENDIAN"))
00433         {
00434           endian = DBUS_LITTLE_ENDIAN;
00435         }
00436       else if (_dbus_string_starts_with_c_str (&line,
00437                                                "OPPOSITE_ENDIAN"))
00438         {
00439           if (endian == DBUS_BIG_ENDIAN)
00440             endian = DBUS_LITTLE_ENDIAN;
00441           else
00442             endian = DBUS_BIG_ENDIAN;
00443         }
00444       else if (_dbus_string_starts_with_c_str (&line,
00445                                                "ALIGN"))
00446         {
00447           long val;
00448           int end;
00449           int orig_len;
00450           
00451           _dbus_string_delete_first_word (&line);
00452 
00453           if (!_dbus_string_parse_int (&line, 0, &val, &end))
00454             {
00455               _dbus_warn ("Failed to parse integer\n");
00456               goto parse_failed;
00457             }
00458 
00459           if (val > 8)
00460             {
00461               _dbus_warn ("Aligning to %ld boundary is crack\n",
00462                           val);
00463               goto parse_failed;
00464             }
00465 
00466           orig_len = _dbus_string_get_length (dest);
00467           
00468           if (!_dbus_string_align_length (dest, val))
00469             goto parse_failed;
00470 
00471           if (_dbus_string_parse_int (&line, end, &val, NULL))
00472             {
00473               /* If there's an optional second int argument,
00474                * fill in align padding with that value
00475                */
00476               if (val < 0 || val > 255)
00477                 {
00478                   _dbus_warn ("can't fill align padding with %ld, must be a byte value\n", val);
00479                   goto parse_failed;
00480                 }
00481 
00482               end = orig_len;
00483               while (end < _dbus_string_get_length (dest))
00484                 {
00485                   _dbus_string_set_byte (dest, end, val);
00486                   ++end;
00487                 }
00488             }
00489         }
00490       else if (_dbus_string_starts_with_c_str (&line, "UNALIGN"))
00491         {
00492           unalign = TRUE;
00493           just_set_unalign = TRUE;
00494         }
00495       else if (_dbus_string_starts_with_c_str (&line, "CHOP"))
00496         {
00497           long val;
00498 
00499           /* FIXME if you CHOP the offset for a LENGTH
00500            * command, we segfault.
00501            */
00502           
00503           _dbus_string_delete_first_word (&line);
00504 
00505           if (!_dbus_string_parse_int (&line, 0, &val, NULL))
00506             {
00507               _dbus_warn ("Failed to parse integer to chop\n");
00508               goto parse_failed;
00509             }
00510 
00511           if (val > _dbus_string_get_length (dest))
00512             {
00513               _dbus_warn ("Trying to chop %ld bytes but we only have %d\n",
00514                           val,
00515                           _dbus_string_get_length (dest));
00516               goto parse_failed;
00517             }
00518           
00519           _dbus_string_shorten (dest, val);
00520         }
00521       else if (_dbus_string_starts_with_c_str (&line,
00522                                                "START_LENGTH"))
00523         {
00524           _dbus_string_delete_first_word (&line);
00525 
00526           if (!save_start (length_hash, &line,
00527                            _dbus_string_get_length (dest)))
00528             {
00529               _dbus_warn ("failed to save length start\n");
00530               goto parse_failed;
00531             }
00532         }
00533       else if (_dbus_string_starts_with_c_str (&line,
00534                                                "END_LENGTH"))
00535         {
00536           _dbus_string_delete_first_word (&line);
00537 
00538           if (!save_length (length_hash, &line,
00539                             _dbus_string_get_length (dest)))
00540             {
00541               _dbus_warn ("failed to save length end\n");
00542               goto parse_failed;
00543             }
00544         }
00545       else if (_dbus_string_starts_with_c_str (&line,
00546                                                "LENGTH"))
00547         {
00548           SAVE_FOR_UNALIGN (dest, 4);
00549           
00550           _dbus_string_delete_first_word (&line);
00551 
00552           if (!append_saved_length (dest, length_hash,
00553                                     &line,
00554                                     unalign ? align_pad_start : align_pad_end,
00555                                     endian))
00556             {
00557               _dbus_warn ("failed to add LENGTH\n");
00558               goto parse_failed;
00559             }
00560 
00561           PERFORM_UNALIGN (dest);
00562         }
00563       else if (_dbus_string_starts_with_c_str (&line,
00564                                                "FIELD_NAME"))
00565         {
00566           _dbus_string_delete_first_word (&line);
00567 
00568           if (_dbus_string_get_length (&line) != 4)
00569             {
00570               _dbus_warn ("Field name must be four characters not \"%s\"\n",
00571                           _dbus_string_get_const_data (&line));
00572               goto parse_failed;
00573             }
00574 
00575           if (unalign)
00576             unalign = FALSE;
00577           else
00578             _dbus_string_align_length (dest, 4);
00579           
00580           if (!_dbus_string_copy (&line, 0, dest,
00581                                   _dbus_string_get_length (dest)))
00582             goto parse_failed;
00583         }
00584       else if (_dbus_string_starts_with_c_str (&line,
00585                                                "TYPE"))
00586         {
00587           int code;
00588           
00589           _dbus_string_delete_first_word (&line);          
00590 
00591           if (_dbus_string_starts_with_c_str (&line, "INVALID"))
00592             code = DBUS_TYPE_INVALID;
00593           else if (_dbus_string_starts_with_c_str (&line, "NIL"))
00594             code = DBUS_TYPE_NIL;
00595           else if (_dbus_string_starts_with_c_str (&line, "BYTE"))
00596             code = DBUS_TYPE_BYTE;
00597           else if (_dbus_string_starts_with_c_str (&line, "BOOLEAN"))
00598             code = DBUS_TYPE_BOOLEAN;
00599           else if (_dbus_string_starts_with_c_str (&line, "INT32"))
00600             code = DBUS_TYPE_INT32;
00601           else if (_dbus_string_starts_with_c_str (&line, "UINT32"))
00602             code = DBUS_TYPE_UINT32;
00603           else if (_dbus_string_starts_with_c_str (&line, "DOUBLE"))
00604             code = DBUS_TYPE_DOUBLE;
00605           else if (_dbus_string_starts_with_c_str (&line, "STRING"))
00606             code = DBUS_TYPE_STRING;
00607           else if (_dbus_string_starts_with_c_str (&line, "NAMED"))
00608             code = DBUS_TYPE_NAMED;
00609           else if (_dbus_string_starts_with_c_str (&line, "ARRAY"))
00610             code = DBUS_TYPE_ARRAY;
00611           else if (_dbus_string_starts_with_c_str (&line, "DICT"))
00612             code = DBUS_TYPE_DICT;
00613           else
00614             {
00615               _dbus_warn ("%s is not a valid type name\n", _dbus_string_get_const_data (&line));
00616               goto parse_failed;
00617             }
00618 
00619           if (!_dbus_string_append_byte (dest, code))
00620             {
00621               _dbus_warn ("could not append typecode byte\n");
00622               goto parse_failed;
00623             }
00624         }
00625       else if (_dbus_string_starts_with_c_str (&line,
00626                                                "BYTE_ARRAY"))
00627         {
00628           SAVE_FOR_UNALIGN (dest, 4);
00629           int i, len, allocated;
00630           unsigned char *values;
00631           unsigned char b;
00632           long val;
00633 
00634           allocated = 4;
00635           values = dbus_new (unsigned char, allocated);
00636           if (!values)
00637             {
00638               _dbus_warn ("could not allocate memory for BYTE_ARRAY\n");
00639               goto parse_failed;
00640             }
00641 
00642           len = 0;
00643           
00644           _dbus_string_delete_first_word (&line);
00645           _dbus_string_skip_blank (&line, 0, &i);
00646           b = _dbus_string_get_byte (&line, i++);
00647           
00648           if (b != '{')
00649             goto parse_failed;
00650 
00651           while (i < _dbus_string_get_length (&line))
00652             {
00653               _dbus_string_skip_blank (&line, i, &i);         
00654 
00655               if (_dbus_string_get_byte (&line, i) == '\'' &&
00656                   _dbus_string_get_length (&line) >= i + 4 &&
00657                   _dbus_string_get_byte (&line, i + 1) == '\\' &&
00658                   _dbus_string_get_byte (&line, i + 2) == '\'' &&
00659                   _dbus_string_get_byte (&line, i + 3) == '\'')
00660                 {
00661                   val = '\'';
00662                   i += 4;
00663                 }
00664               else if (_dbus_string_get_byte (&line, i) == '\'' &&
00665                        _dbus_string_get_length (&line) >= i + 3 &&
00666                        _dbus_string_get_byte (&line, i + 2) == '\'')
00667                 {
00668                   val = _dbus_string_get_byte (&line, i + 1);
00669                   i += 3;
00670                 }
00671               else
00672                 {
00673                   if (!_dbus_string_parse_int (&line, i, &val, &i))
00674                     {
00675                       _dbus_warn ("Failed to parse integer for BYTE_ARRAY\n");
00676                       goto parse_failed;
00677                     }
00678 
00679                   if (val < 0 || val > 255)
00680                     {
00681                       _dbus_warn ("A byte must be in range 0-255 not %ld\n",
00682                                   val);
00683                       goto parse_failed;
00684                     }
00685                 }
00686 
00687               values[len++] = val;
00688               if (len == allocated)
00689                 {
00690                   allocated *= 2;
00691                   values = dbus_realloc (values, allocated * sizeof (unsigned char));
00692                   if (!values)
00693                     {
00694                       _dbus_warn ("could not allocate memory for BYTE_ARRAY\n");
00695                       goto parse_failed;
00696                     }
00697                 }
00698               
00699               _dbus_string_skip_blank (&line, i, &i);
00700               
00701               b = _dbus_string_get_byte (&line, i++);
00702 
00703               if (b == '}')
00704                 break;
00705               else if (b != ',')
00706                 goto parse_failed;
00707             }
00708 
00709           if (!_dbus_marshal_int32 (dest, endian, len) ||
00710               !_dbus_string_append_len (dest, values, len))
00711             {
00712               _dbus_warn ("failed to append BYTE_ARRAY\n");
00713               goto parse_failed;
00714             }
00715           dbus_free (values);
00716           
00717           PERFORM_UNALIGN (dest);
00718         }
00719       else if (_dbus_string_starts_with_c_str (&line,
00720                                                "BOOLEAN_ARRAY"))
00721         {
00722           SAVE_FOR_UNALIGN (dest, 4);
00723           int i, len, allocated;
00724           unsigned char *values;
00725           unsigned char b, val;
00726 
00727           allocated = 4;
00728           values = dbus_new (unsigned char, allocated);
00729           if (!values)
00730             {
00731               _dbus_warn ("could not allocate memory for BOOLEAN_ARRAY\n");
00732               goto parse_failed;
00733             }
00734 
00735           len = 0;
00736           
00737           _dbus_string_delete_first_word (&line);
00738           _dbus_string_skip_blank (&line, 0, &i);
00739           b = _dbus_string_get_byte (&line, i++);
00740           
00741           if (b != '{')
00742             goto parse_failed;
00743 
00744           while (i < _dbus_string_get_length (&line))
00745             {
00746               _dbus_string_skip_blank (&line, i, &i);         
00747               
00748               if (_dbus_string_find_to (&line, i, i + 5,
00749                                         "false", NULL))
00750                 {
00751                   i += 5;
00752                   val = TRUE;
00753                 }
00754               else if (_dbus_string_find_to (&line, i, i + 4,
00755                                              "true", NULL))
00756                 {
00757                   i += 4;
00758                   val = FALSE;
00759                 }
00760               else
00761                 {
00762                   _dbus_warn ("could not parse BOOLEAN_ARRAY\n");
00763                   goto parse_failed;
00764                 }
00765 
00766               values[len++] = val;
00767               if (len == allocated)
00768                 {
00769                   allocated *= 2;
00770                   values = dbus_realloc (values, allocated * sizeof (unsigned char));
00771                   if (!values)
00772                     {
00773                       _dbus_warn ("could not allocate memory for BOOLEAN_ARRAY\n");
00774                       goto parse_failed;
00775                     }
00776                 }
00777               
00778               _dbus_string_skip_blank (&line, i, &i);
00779               
00780               b = _dbus_string_get_byte (&line, i++);
00781 
00782               if (b == '}')
00783                 break;
00784               else if (b != ',')
00785                 goto parse_failed;
00786             }
00787 
00788           if (!_dbus_marshal_int32 (dest, endian, len) ||
00789               !_dbus_string_append_len (dest, values, len))
00790             {
00791               _dbus_warn ("failed to append BOOLEAN_ARRAY\n");
00792               goto parse_failed;
00793             }
00794           dbus_free (values);
00795           
00796           PERFORM_UNALIGN (dest);
00797         }
00798       else if (_dbus_string_starts_with_c_str (&line,
00799                                                "INT32_ARRAY"))
00800         {
00801           SAVE_FOR_UNALIGN (dest, 4);
00802           int i, len, allocated;
00803           dbus_int32_t *values;
00804           long val;
00805           unsigned char b;
00806 
00807           allocated = 4;
00808           values = dbus_new (dbus_int32_t, allocated);
00809           if (!values)
00810             {
00811               _dbus_warn ("could not allocate memory for INT32_ARRAY\n");
00812               goto parse_failed;
00813             }
00814           
00815           len = 0;
00816           
00817           _dbus_string_delete_first_word (&line);
00818           _dbus_string_skip_blank (&line, 0, &i);
00819           b = _dbus_string_get_byte (&line, i++);
00820 
00821           if (b != '{')
00822             goto parse_failed;
00823 
00824           while (i < _dbus_string_get_length (&line))
00825             {
00826               _dbus_string_skip_blank (&line, i, &i);
00827 
00828               if (!_dbus_string_parse_int (&line, i, &val, &i))
00829                 {
00830                   _dbus_warn ("could not parse integer for INT32_ARRAY\n");
00831                   goto parse_failed;
00832                 }
00833 
00834               values[len++] = val;
00835               if (len == allocated)
00836                 {
00837                   allocated *= 2;
00838                   values = dbus_realloc (values, allocated * sizeof (dbus_int32_t));
00839                   if (!values)
00840                     {
00841                       _dbus_warn ("could not allocate memory for INT32_ARRAY\n");
00842                       goto parse_failed;
00843                     }
00844                 }
00845               
00846               _dbus_string_skip_blank (&line, i, &i);
00847               
00848               b = _dbus_string_get_byte (&line, i++);
00849 
00850               if (b == '}')
00851                 break;
00852               else if (b != ',')
00853                 goto parse_failed;
00854             }
00855 
00856           if (!_dbus_marshal_int32_array (dest, endian, values, len))
00857             {
00858               _dbus_warn ("failed to append INT32_ARRAY\n");
00859               goto parse_failed;
00860             }
00861           dbus_free (values);
00862           
00863           PERFORM_UNALIGN (dest);
00864         }
00865       else if (_dbus_string_starts_with_c_str (&line,
00866                                                "UINT32_ARRAY"))
00867         {
00868           SAVE_FOR_UNALIGN (dest, 4);
00869           int i, len, allocated;
00870           dbus_uint32_t *values;
00871           long val;
00872           unsigned char b;
00873 
00874           allocated = 4;
00875           values = dbus_new (dbus_uint32_t, allocated);
00876           if (!values)
00877             {
00878               _dbus_warn ("could not allocate memory for UINT32_ARRAY\n");
00879               goto parse_failed;
00880             }
00881           
00882           len = 0;
00883           
00884           _dbus_string_delete_first_word (&line);
00885           _dbus_string_skip_blank (&line, 0, &i);
00886           b = _dbus_string_get_byte (&line, i++);
00887 
00888           if (b != '{')
00889             goto parse_failed;
00890 
00891           while (i < _dbus_string_get_length (&line))
00892             {
00893               _dbus_string_skip_blank (&line, i, &i);
00894 
00895               if (!_dbus_string_parse_int (&line, i, &val, &i))
00896                 {
00897                   _dbus_warn ("could not parse integer for UINT32_ARRAY\n");
00898                   goto parse_failed;
00899                 }
00900 
00901               values[len++] = val;
00902               if (len == allocated)
00903                 {
00904                   allocated *= 2;
00905                   values = dbus_realloc (values, allocated * sizeof (dbus_uint32_t));
00906                   if (!values)
00907                     {
00908                       _dbus_warn ("could not allocate memory for UINT32_ARRAY\n");
00909                       goto parse_failed;
00910                     }
00911                 }
00912               
00913               _dbus_string_skip_blank (&line, i, &i);
00914               
00915               b = _dbus_string_get_byte (&line, i++);
00916 
00917               if (b == '}')
00918                 break;
00919               else if (b != ',')
00920                 goto parse_failed;
00921             }
00922 
00923           if (!_dbus_marshal_uint32_array (dest, endian, values, len))
00924             {
00925               _dbus_warn ("failed to append UINT32_ARRAY\n");
00926               goto parse_failed;
00927             }
00928           dbus_free (values);
00929           
00930           PERFORM_UNALIGN (dest);
00931         }
00932       else if (_dbus_string_starts_with_c_str (&line,
00933                                                "DOUBLE_ARRAY"))
00934         {
00935           SAVE_FOR_UNALIGN (dest, 8);
00936           int i, len, allocated;
00937           double *values;
00938           double val;
00939           unsigned char b;
00940 
00941           allocated = 4;
00942           values = dbus_new (double, allocated);
00943           if (!values)
00944             {
00945               _dbus_warn ("could not allocate memory for DOUBLE_ARRAY\n");
00946               goto parse_failed;
00947             }
00948           
00949           len = 0;
00950           
00951           _dbus_string_delete_first_word (&line);
00952           _dbus_string_skip_blank (&line, 0, &i);
00953           b = _dbus_string_get_byte (&line, i++);
00954 
00955           if (b != '{')
00956             goto parse_failed;
00957 
00958           while (i < _dbus_string_get_length (&line))
00959             {
00960               _dbus_string_skip_blank (&line, i, &i);
00961 
00962               if (!_dbus_string_parse_double (&line, i, &val, &i))
00963                 {
00964                   _dbus_warn ("could not parse double for DOUBLE_ARRAY\n");
00965                   goto parse_failed;
00966                 }
00967 
00968               values[len++] = val;
00969               if (len == allocated)
00970                 {
00971                   allocated *= 2;
00972                   values = dbus_realloc (values, allocated * sizeof (double));
00973                   if (!values)
00974                     {
00975                       _dbus_warn ("could not allocate memory for DOUBLE_ARRAY\n");
00976                       goto parse_failed;
00977                     }
00978                 }
00979               
00980               _dbus_string_skip_blank (&line, i, &i);
00981               
00982               b = _dbus_string_get_byte (&line, i++);
00983 
00984               if (b == '}')
00985                 break;
00986               else if (b != ',')
00987                 goto parse_failed;
00988             }
00989 
00990           if (!_dbus_marshal_double_array (dest, endian, values, len))
00991             {
00992               _dbus_warn ("failed to append DOUBLE_ARRAY\n");
00993               goto parse_failed;
00994             }
00995           dbus_free (values);
00996           
00997           PERFORM_UNALIGN (dest);
00998         }
00999       else if (_dbus_string_starts_with_c_str (&line,
01000                                                "STRING_ARRAY"))
01001         {
01002           SAVE_FOR_UNALIGN (dest, 4);
01003           int i, len, allocated;
01004           char **values;
01005           char *val;
01006           DBusString val_str;
01007           unsigned char b;
01008 
01009           allocated = 4;
01010           values = dbus_new (char *, allocated);
01011           if (!values)
01012             {
01013               _dbus_warn ("could not allocate memory for STRING_ARRAY\n");
01014               goto parse_failed;
01015             }
01016           
01017           len = 0;
01018           
01019           _dbus_string_delete_first_word (&line);
01020           _dbus_string_skip_blank (&line, 0, &i);
01021           b = _dbus_string_get_byte (&line, i++);
01022 
01023           if (b != '{')
01024             goto parse_failed;
01025 
01026           _dbus_string_init (&val_str);
01027           while (i < _dbus_string_get_length (&line))
01028             {
01029               _dbus_string_skip_blank (&line, i, &i);
01030 
01031               if (!append_quoted_string (&val_str, &line, i, &i))
01032                 {
01033                   _dbus_warn ("could not parse quoted string for STRING_ARRAY\n");
01034                   goto parse_failed;
01035                 }
01036               i++;
01037 
01038               if (!_dbus_string_steal_data (&val_str, &val))
01039                 {
01040                   _dbus_warn ("could not allocate memory for STRING_ARRAY string\n");
01041                   goto parse_failed;
01042                 }
01043               
01044               values[len++] = val;
01045               if (len == allocated)
01046                 {
01047                   allocated *= 2;
01048                   values = dbus_realloc (values, allocated * sizeof (char *));
01049                   if (!values)
01050                     {
01051                       _dbus_warn ("could not allocate memory for STRING_ARRAY\n");
01052                       goto parse_failed;
01053                     }
01054                 }
01055               
01056               _dbus_string_skip_blank (&line, i, &i);
01057               
01058               b = _dbus_string_get_byte (&line, i++);
01059 
01060               if (b == '}')
01061                 break;
01062               else if (b != ',')
01063                 {
01064                   _dbus_warn ("missing comma when parsing STRING_ARRAY\n");
01065                   goto parse_failed;
01066                 }
01067             }
01068           _dbus_string_free (&val_str);
01069           
01070           if (!_dbus_marshal_string_array (dest, endian, (const char **)values, len))
01071             {
01072               _dbus_warn ("failed to append STRING_ARRAY\n");
01073               goto parse_failed;
01074             }
01075 
01076           values[len] = NULL;
01077           dbus_free_string_array (values);
01078           
01079           PERFORM_UNALIGN (dest);
01080         }
01081       else if (_dbus_string_starts_with_c_str (&line, "BYTE"))
01082         {
01083           unsigned char the_byte;
01084           
01085           _dbus_string_delete_first_word (&line);
01086 
01087           if (_dbus_string_equal_c_str (&line, "'\\''"))
01088             the_byte = '\'';
01089           else if (_dbus_string_get_byte (&line, 0) == '\'' &&
01090                    _dbus_string_get_length (&line) >= 3 &&
01091                    _dbus_string_get_byte (&line, 2) == '\'')
01092             the_byte = _dbus_string_get_byte (&line, 1);
01093           else
01094             {
01095               long val;
01096               if (!_dbus_string_parse_int (&line, 0, &val, NULL))
01097                 {
01098                   _dbus_warn ("Failed to parse integer for BYTE\n");
01099                   goto parse_failed;
01100                 }
01101 
01102               if (val > 255)
01103                 {
01104                   _dbus_warn ("A byte must be in range 0-255 not %ld\n",
01105                                  val);
01106                   goto parse_failed;
01107                 }
01108               the_byte = (unsigned char) val;
01109             }
01110 
01111           _dbus_string_append_byte (dest, the_byte);
01112         }
01113       else if (_dbus_string_starts_with_c_str (&line,
01114                                                "BOOLEAN"))
01115         {
01116           unsigned char val;
01117 
01118           _dbus_string_delete_first_word (&line);
01119 
01120           if (_dbus_string_starts_with_c_str (&line, "true"))
01121             val = TRUE;
01122           else if (_dbus_string_starts_with_c_str (&line, "false"))
01123             val = FALSE;
01124           else
01125             {
01126               _dbus_warn ("could not parse BOOLEAN\n");
01127               goto parse_failed;
01128             }
01129           if (!_dbus_string_append_byte (dest, val))
01130             {
01131               _dbus_warn ("failed to append BOOLEAN\n");
01132               goto parse_failed;
01133             }
01134         }
01135       
01136       else if (_dbus_string_starts_with_c_str (&line,
01137                                                "INT32"))
01138         {
01139           SAVE_FOR_UNALIGN (dest, 4);
01140           long val;
01141           
01142           _dbus_string_delete_first_word (&line);
01143 
01144           if (!_dbus_string_parse_int (&line, 0, &val, NULL))
01145             {
01146               _dbus_warn ("could not parse integer for INT32\n");
01147               goto parse_failed;
01148             }
01149           
01150           if (!_dbus_marshal_int32 (dest, endian,
01151                                     val))
01152             {
01153               _dbus_warn ("failed to append INT32\n");
01154               goto parse_failed;
01155             }
01156 
01157           PERFORM_UNALIGN (dest);
01158         }
01159       else if (_dbus_string_starts_with_c_str (&line,
01160                                                "UINT32"))
01161         {
01162           SAVE_FOR_UNALIGN (dest, 4);
01163           unsigned long val;
01164           
01165           _dbus_string_delete_first_word (&line);
01166 
01167           if (!_dbus_string_parse_uint (&line, 0, &val, NULL))
01168             goto parse_failed;
01169           
01170           if (!_dbus_marshal_uint32 (dest, endian,
01171                                      val))
01172             {
01173               _dbus_warn ("failed to append UINT32\n");
01174               goto parse_failed;
01175             }
01176 
01177           PERFORM_UNALIGN (dest);
01178         }
01179       else if (_dbus_string_starts_with_c_str (&line,
01180                                                "DOUBLE"))
01181         {
01182           SAVE_FOR_UNALIGN (dest, 8);
01183           double val;
01184           
01185           _dbus_string_delete_first_word (&line);
01186 
01187           if (!_dbus_string_parse_double (&line, 0, &val, NULL))
01188             goto parse_failed;
01189           
01190           if (!_dbus_marshal_double (dest, endian,
01191                                      val))
01192             {
01193               _dbus_warn ("failed to append DOUBLE\n");
01194               goto parse_failed;
01195             }
01196 
01197           PERFORM_UNALIGN (dest);
01198         }
01199       else if (_dbus_string_starts_with_c_str (&line,
01200                                                "STRING"))
01201         {
01202           SAVE_FOR_UNALIGN (dest, 4);
01203           int size_offset;
01204           int old_len;
01205           
01206           _dbus_string_delete_first_word (&line);
01207 
01208           size_offset = _dbus_string_get_length (dest);
01209           size_offset = _DBUS_ALIGN_VALUE (size_offset, 4);
01210           if (!_dbus_marshal_uint32 (dest, endian, 0))
01211             {
01212               _dbus_warn ("Failed to append string size\n");
01213               goto parse_failed;
01214             }
01215 
01216           old_len = _dbus_string_get_length (dest);
01217           if (!append_quoted_string (dest, &line, 0, NULL))
01218             {
01219               _dbus_warn ("Failed to append quoted string\n");
01220               goto parse_failed;
01221             }
01222 
01223           _dbus_marshal_set_uint32 (dest, endian, size_offset,
01224                                     /* subtract 1 for nul */
01225                                     _dbus_string_get_length (dest) - old_len - 1);
01226           
01227           PERFORM_UNALIGN (dest);
01228         }
01229       else
01230         goto parse_failed;
01231       
01232       if (!just_set_unalign && unalign)
01233         {
01234           _dbus_warn ("UNALIGN prior to something that isn't aligned\n");
01235           goto parse_failed;
01236         }
01237 
01238       goto next_iteration; /* skip parse_failed */
01239       
01240     parse_failed:
01241       {
01242         _dbus_warn ("couldn't process line %d \"%s\"\n",
01243                     line_no, _dbus_string_get_const_data (&line));
01244         goto out;
01245       }
01246     }
01247 
01248   _dbus_hash_iter_init (length_hash, &iter);
01249   while (_dbus_hash_iter_next (&iter))
01250     {
01251       SavedLength *sl = _dbus_hash_iter_get_value (&iter);
01252       const char *s;
01253 
01254       s = _dbus_string_get_const_data (&sl->name);
01255       
01256       if (sl->length < 0)
01257         {
01258           _dbus_warn ("Used LENGTH %s but never did END_LENGTH\n",
01259                       s);
01260           goto out;
01261         }
01262       else if (sl->offset < 0)
01263         {
01264           _dbus_warn ("Did END_LENGTH %s but never used LENGTH\n",
01265                       s);
01266           goto out;
01267         }
01268       else
01269         {
01270           if (sl->start < 0)
01271             sl->start = 0;
01272           
01273           _dbus_verbose ("Filling in length %s endian = %d offset = %d start = %d length = %d\n",
01274                          s, sl->endian, sl->offset, sl->start, sl->length);
01275           _dbus_marshal_set_int32 (dest,
01276                                    sl->endian,
01277                                    sl->offset,
01278                                    sl->length - sl->start);
01279         }
01280 
01281       _dbus_hash_iter_remove_entry (&iter);
01282     }
01283   
01284   retval = TRUE;
01285 
01286   _dbus_verbose_bytes_of_string (dest, 0, _dbus_string_get_length (dest));
01287   
01288  out:
01289   if (length_hash != NULL)
01290     _dbus_hash_table_unref (length_hash);
01291   
01292   _dbus_string_free (&file);
01293   _dbus_string_free (&line);
01294   return retval;
01295 }
01296 
01298 #endif /* DBUS_BUILD_TESTS */

Generated on Wed Oct 22 14:05:02 2003 for D-BUS by doxygen1.3-rc3