sexpr.c

Go to the documentation of this file.
00001 /*
00002  * Portions Copyright (C) 2004, 2005, 2007, 2014  Internet Systems Consortium, Inc. ("ISC")
00003  * Portions Copyright (C) 2001  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
00010  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
00011  * OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
00012  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00013  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00014  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00015  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00016  *
00017  * Portions Copyright (C) 2001  Nominum, Inc.
00018  *
00019  * Permission to use, copy, modify, and/or distribute this software for any
00020  * purpose with or without fee is hereby granted, provided that the above
00021  * copyright notice and this permission notice appear in all copies.
00022  *
00023  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
00024  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
00025  * OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
00026  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00027  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00028  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00029  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00030  */
00031 
00032 /* $Id: sexpr.c,v 1.9 2007/08/28 07:20:43 tbox Exp $ */
00033 
00034 /*! \file */
00035 
00036 #include <config.h>
00037 
00038 #include <ctype.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 
00042 #include <isc/assertions.h>
00043 #include <isccc/sexpr.h>
00044 #include <isccc/util.h>
00045 
00046 static isccc_sexpr_t sexpr_t = { ISCCC_SEXPRTYPE_T, { NULL } };
00047 
00048 #define CAR(s)                  (s)->value.as_dottedpair.car
00049 #define CDR(s)                  (s)->value.as_dottedpair.cdr
00050 
00051 isccc_sexpr_t *
00052 isccc_sexpr_cons(isccc_sexpr_t *car, isccc_sexpr_t *cdr)
00053 {
00054         isccc_sexpr_t *sexpr;
00055 
00056         sexpr = malloc(sizeof(*sexpr));
00057         if (sexpr == NULL)
00058                 return (NULL);
00059         sexpr->type = ISCCC_SEXPRTYPE_DOTTEDPAIR;
00060         CAR(sexpr) = car;
00061         CDR(sexpr) = cdr;
00062 
00063         return (sexpr);
00064 }
00065 
00066 isccc_sexpr_t *
00067 isccc_sexpr_tconst(void)
00068 {
00069         return (&sexpr_t);
00070 }
00071 
00072 isccc_sexpr_t *
00073 isccc_sexpr_fromstring(const char *str)
00074 {
00075         isccc_sexpr_t *sexpr;
00076 
00077         sexpr = malloc(sizeof(*sexpr));
00078         if (sexpr == NULL)
00079                 return (NULL);
00080         sexpr->type = ISCCC_SEXPRTYPE_STRING;
00081         sexpr->value.as_string = strdup(str);
00082         if (sexpr->value.as_string == NULL) {
00083                 free(sexpr);
00084                 return (NULL);
00085         }
00086 
00087         return (sexpr);
00088 }
00089 
00090 isccc_sexpr_t *
00091 isccc_sexpr_frombinary(const isccc_region_t *region)
00092 {
00093         isccc_sexpr_t *sexpr;
00094         unsigned int region_size;
00095 
00096         sexpr = malloc(sizeof(*sexpr));
00097         if (sexpr == NULL)
00098                 return (NULL);
00099         sexpr->type = ISCCC_SEXPRTYPE_BINARY;
00100         region_size = REGION_SIZE(*region);
00101         /*
00102          * We add an extra byte when we malloc so we can NUL terminate
00103          * the binary data.  This allows the caller to use it as a C
00104          * string.  It's up to the caller to ensure this is safe.  We don't
00105          * add 1 to the length of the binary region, because the NUL is
00106          * not part of the binary data.
00107          */
00108         sexpr->value.as_region.rstart = malloc(region_size + 1);
00109         if (sexpr->value.as_region.rstart == NULL) {
00110                 free(sexpr);
00111                 return (NULL);
00112         }
00113         sexpr->value.as_region.rend = sexpr->value.as_region.rstart +
00114                 region_size;
00115         memmove(sexpr->value.as_region.rstart, region->rstart, region_size);
00116         /*
00117          * NUL terminate.
00118          */
00119         sexpr->value.as_region.rstart[region_size] = '\0';
00120 
00121         return (sexpr);
00122 }
00123 
00124 void
00125 isccc_sexpr_free(isccc_sexpr_t **sexprp)
00126 {
00127         isccc_sexpr_t *sexpr;
00128         isccc_sexpr_t *item;
00129 
00130         sexpr = *sexprp;
00131         if (sexpr == NULL)
00132                 return;
00133         switch (sexpr->type) {
00134         case ISCCC_SEXPRTYPE_STRING:
00135                 free(sexpr->value.as_string);
00136                 break;
00137         case ISCCC_SEXPRTYPE_DOTTEDPAIR:
00138                 item = CAR(sexpr);
00139                 if (item != NULL)
00140                         isccc_sexpr_free(&item);
00141                 item = CDR(sexpr);
00142                 if (item != NULL)
00143                         isccc_sexpr_free(&item);
00144                 break;
00145         case ISCCC_SEXPRTYPE_BINARY:
00146                 free(sexpr->value.as_region.rstart);
00147                 break;
00148         }
00149         free(sexpr);
00150 
00151         *sexprp = NULL;
00152 }
00153 
00154 static isc_boolean_t
00155 printable(isccc_region_t *r)
00156 {
00157         unsigned char *curr;
00158 
00159         curr = r->rstart;
00160         while (curr != r->rend) {
00161                 if (!isprint(*curr))
00162                         return (ISC_FALSE);
00163                 curr++;
00164         }
00165 
00166         return (ISC_TRUE);
00167 }
00168 
00169 void
00170 isccc_sexpr_print(isccc_sexpr_t *sexpr, FILE *stream)
00171 {
00172         isccc_sexpr_t *cdr;
00173         unsigned int size, i;
00174         unsigned char *curr;
00175 
00176         if (sexpr == NULL) {
00177                 fprintf(stream, "nil");
00178                 return;
00179         }
00180 
00181         switch (sexpr->type) {
00182         case ISCCC_SEXPRTYPE_T:
00183                 fprintf(stream, "t");
00184                 break;
00185         case ISCCC_SEXPRTYPE_STRING:
00186                 fprintf(stream, "\"%s\"", sexpr->value.as_string);
00187                 break;
00188         case ISCCC_SEXPRTYPE_DOTTEDPAIR:
00189                 fprintf(stream, "(");
00190                 do {
00191                         isccc_sexpr_print(CAR(sexpr), stream);
00192                         cdr = CDR(sexpr);
00193                         if (cdr != NULL) {
00194                                 fprintf(stream, " ");
00195                                 if (cdr->type != ISCCC_SEXPRTYPE_DOTTEDPAIR) {
00196                                         fprintf(stream, ". ");
00197                                         isccc_sexpr_print(cdr, stream);
00198                                         cdr = NULL;
00199                                 }
00200                         }
00201                         sexpr = cdr;
00202                 } while (sexpr != NULL);
00203                 fprintf(stream, ")");
00204                 break;
00205         case ISCCC_SEXPRTYPE_BINARY:
00206                 size = REGION_SIZE(sexpr->value.as_region);
00207                 curr = sexpr->value.as_region.rstart;
00208                 if (printable(&sexpr->value.as_region)) {
00209                         fprintf(stream, "'%.*s'", (int)size, curr);
00210                 } else {
00211                         fprintf(stream, "0x");
00212                         for (i = 0; i < size; i++)
00213                                 fprintf(stream, "%02x", *curr++);
00214                 }
00215                 break;
00216         default:
00217                 INSIST(0);
00218         }
00219 }
00220 
00221 isccc_sexpr_t *
00222 isccc_sexpr_car(isccc_sexpr_t *list)
00223 {
00224         REQUIRE(list->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
00225 
00226         return (CAR(list));
00227 }
00228 
00229 isccc_sexpr_t *
00230 isccc_sexpr_cdr(isccc_sexpr_t *list)
00231 {
00232         REQUIRE(list->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
00233 
00234         return (CDR(list));
00235 }
00236 
00237 void
00238 isccc_sexpr_setcar(isccc_sexpr_t *pair, isccc_sexpr_t *car)
00239 {
00240         REQUIRE(pair->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
00241 
00242         CAR(pair) = car;
00243 }
00244 
00245 void
00246 isccc_sexpr_setcdr(isccc_sexpr_t *pair, isccc_sexpr_t *cdr)
00247 {
00248         REQUIRE(pair->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
00249 
00250         CDR(pair) = cdr;
00251 }
00252 
00253 isccc_sexpr_t *
00254 isccc_sexpr_addtolist(isccc_sexpr_t **l1p, isccc_sexpr_t *l2)
00255 {
00256         isccc_sexpr_t *last, *elt, *l1;
00257 
00258         REQUIRE(l1p != NULL);
00259         l1 = *l1p;
00260         REQUIRE(l1 == NULL || l1->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
00261 
00262         elt = isccc_sexpr_cons(l2, NULL);
00263         if (elt == NULL)
00264                 return (NULL);
00265         if (l1 == NULL) {
00266                 *l1p = elt;
00267                 return (elt);
00268         }
00269         for (last = l1; CDR(last) != NULL; last = CDR(last))
00270                 /* Nothing */;
00271         CDR(last) = elt;
00272 
00273         return (elt);
00274 }
00275 
00276 isc_boolean_t
00277 isccc_sexpr_listp(isccc_sexpr_t *sexpr)
00278 {
00279         if (sexpr == NULL || sexpr->type == ISCCC_SEXPRTYPE_DOTTEDPAIR)
00280                 return (ISC_TRUE);
00281         return (ISC_FALSE);
00282 }
00283 
00284 isc_boolean_t
00285 isccc_sexpr_emptyp(isccc_sexpr_t *sexpr)
00286 {
00287         if (sexpr == NULL)
00288                 return (ISC_TRUE);
00289         return (ISC_FALSE);
00290 }
00291 
00292 isc_boolean_t
00293 isccc_sexpr_stringp(isccc_sexpr_t *sexpr)
00294 {
00295         if (sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_STRING)
00296                 return (ISC_TRUE);
00297         return (ISC_FALSE);
00298 }
00299 
00300 isc_boolean_t
00301 isccc_sexpr_binaryp(isccc_sexpr_t *sexpr)
00302 {
00303         if (sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_BINARY)
00304                 return (ISC_TRUE);
00305         return (ISC_FALSE);
00306 }
00307 
00308 char *
00309 isccc_sexpr_tostring(isccc_sexpr_t *sexpr)
00310 {
00311         REQUIRE(sexpr != NULL &&
00312                 (sexpr->type == ISCCC_SEXPRTYPE_STRING ||
00313                  sexpr->type == ISCCC_SEXPRTYPE_BINARY));
00314 
00315         if (sexpr->type == ISCCC_SEXPRTYPE_BINARY)
00316                 return ((char *)sexpr->value.as_region.rstart);
00317         return (sexpr->value.as_string);
00318 }
00319 
00320 isccc_region_t *
00321 isccc_sexpr_tobinary(isccc_sexpr_t *sexpr)
00322 {
00323         REQUIRE(sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_BINARY);
00324         return (&sexpr->value.as_region);
00325 }

Generated on Tue Apr 28 17:41:06 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha