home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / bc-1.03-base.tgz / bc-1.03-base.tar / fsf / bc / dc-string.c < prev    next >
C/C++ Source or Header  |  1994-08-08  |  5KB  |  210 lines

  1. /* 
  2.  * implement string functions for dc
  3.  *
  4.  * Copyright (C) 1994 Free Software Foundation, Inc.
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, you can either send email to this
  18.  * program's author (see below) or write to: The Free Software Foundation,
  19.  * Inc.; 675 Mass Ave. Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. /* This should be the only module that knows the internals of type dc_string */
  23.  
  24. #include "config.h"
  25.  
  26. #include <stdio.h>
  27. #ifdef HAVE_STDDEF_H
  28. # include <stddef.h>    /* ptrdiff_t */
  29. #else
  30. # define ptrdiff_t    size_t
  31. #endif
  32. #ifdef HAVE_STDLIB_H
  33. # include <stdlib.h>
  34. #endif
  35. #ifdef HAVE_STRING_H
  36. # include <string.h>    /* memcpy */
  37. #else
  38. # ifdef HAVE_MEMORY_H
  39. #  include <memory.h>    /* memcpy, maybe */
  40. # else
  41. #  ifdef HAVE_STRINGS_H
  42. #   include <strings.h>    /* memcpy, maybe */
  43. #  endif
  44. # endif
  45. #endif
  46. #include "dc.h"
  47. #include "dc-proto.h"
  48.  
  49. struct dc_string {
  50.     char *s_ptr;  /* pointer to base of string */
  51.     size_t s_len; /* length of counted string */
  52.     int  s_refs;  /* reference count to cut down on memory use by duplicates */
  53. };
  54.  
  55.  
  56. /* return a duplicate of the string in the passed value */
  57. /* The mismatched data types forces the caller to deal with
  58.  * bad dc_type'd dc_data values, and makes it more convenient
  59.  * for the caller to not have to do the grunge work of setting
  60.  * up a dc_type result.
  61.  */
  62. dc_data
  63. dc_dup_str DC_DECLARG((value))
  64.     dc_str value DC_DECLEND
  65. {
  66.     dc_data result;
  67.  
  68.     ++((struct dc_string *)value)->s_refs;
  69.     result.v.string = value;
  70.     result.dc_type = DC_STRING;
  71.     return result;
  72. }
  73.  
  74. /* free an instance of a dc_str value */
  75. void
  76. dc_free_str DC_DECLARG((value))
  77.     dc_str *value DC_DECLEND
  78. {
  79.     struct dc_string *string = *value;
  80.  
  81.     if (--string->s_refs < 1){
  82.         free(string->s_ptr);
  83.         free(string);
  84.     }
  85. }
  86.  
  87. /* Output a dc_str value.
  88.  * Add a trailing newline if "newline" is set.
  89.  * Free the value after use if discard_flag is set.
  90.  */
  91. void
  92. dc_out_str DC_DECLARG((value, newline, discard_flag))
  93.     dc_str value DC_DECLSEP
  94.     dc_boolean newline DC_DECLSEP
  95.     dc_boolean discard_flag DC_DECLEND
  96. {
  97.     struct dc_string *string = value;
  98.  
  99.     printf("%s", string->s_ptr);
  100.     if (newline == DC_TRUE)
  101.         printf("\n");
  102.     if (discard_flag == DC_TRUE)
  103.         dc_free_str(&value);
  104. }
  105.  
  106. /* make a copy of a string (base s, length len)
  107.  * into a dc_str value; return a dc_data result
  108.  * with this value
  109.  */
  110. dc_data
  111. dc_makestring DC_DECLARG((s, len))
  112.     const char *s DC_DECLSEP
  113.     size_t len DC_DECLEND
  114. {
  115.     dc_data result;
  116.     struct dc_string *string;
  117.  
  118.     string = dc_malloc(sizeof *string);
  119.     string->s_ptr = dc_malloc(len+1);
  120.     memcpy(string->s_ptr, s, len);
  121.     string->s_ptr[len] = '\0';    /* nul terminated for those who need it */
  122.     string->s_len = len;
  123.     string->s_refs = 1;
  124.     result.v.string = string;
  125.     result.dc_type = DC_STRING;
  126.     return result;
  127. }
  128.  
  129. /* read a dc_str value from FILE *fp;
  130.  * if ldelim == rdelim, then read until a ldelim char or EOF is reached;
  131.  * if ldelim != rdelim, then read until a matching rdelim for the
  132.  * (already eaten) first ldelim is read.
  133.  * Return a dc_data result with the dc_str value as its contents.
  134.  */
  135. dc_data
  136. dc_readstring DC_DECLARG((fp, ldelim, rdelim))
  137.     FILE *fp DC_DECLSEP
  138.     int ldelim DC_DECLSEP
  139.     int rdelim DC_DECLEND
  140. {
  141.     static char *line_buf = NULL;    /* a buffer to build the string in */ 
  142.     static size_t buflen = 0;        /* the current size of line_buf */
  143.     int depth=1;
  144.     int c;
  145.     char *p;
  146.     const char *end;
  147.  
  148.     if (!line_buf){
  149.         /* initial buflen should be large enough to handle most cases */
  150.         buflen = 2016;
  151.         line_buf = dc_malloc(buflen);
  152.     }
  153.     p = line_buf;
  154.     end = line_buf + buflen;
  155.     for (;;){
  156.         c = getc(fp);
  157.         if (c == EOF)
  158.             break;
  159.         else if (c == rdelim && --depth < 1)
  160.             break;
  161.         else if (c == ldelim)
  162.             ++depth;
  163.         if (p >= end){
  164.             ptrdiff_t offset = p - line_buf;
  165.             /* buflen increment should be big enough
  166.              * to avoid execessive reallocs:
  167.              */
  168.             buflen += 2048;
  169.             line_buf = realloc(line_buf, buflen);
  170.             if (!line_buf)
  171.                 dc_memfail();
  172.             p = line_buf + offset;
  173.             end = line_buf + buflen;
  174.         }
  175.         *p++ = c;
  176.     }
  177.     return dc_makestring(line_buf, (size_t)(p-line_buf));
  178. }
  179.  
  180. /* return the base pointer of the dc_str value;
  181.  * This function is needed because no one else knows what dc_str
  182.  * looks like.
  183.  */
  184. const char *
  185. dc_str2charp DC_DECLARG((value))
  186.     dc_str value DC_DECLEND
  187. {
  188.     return ((struct dc_string *)value)->s_ptr;
  189. }
  190.  
  191. /* return the length of the dc_str value;
  192.  * This function is needed because no one else knows what dc_str
  193.  * looks like, and strlen(dc_str2charp(value)) won't work
  194.  * if there's an embedded '\0'.
  195.  */
  196. size_t
  197. dc_strlen DC_DECLARG((value))
  198.     dc_str value DC_DECLEND
  199. {
  200.     return ((struct dc_string *)value)->s_len;
  201. }
  202.  
  203.  
  204. /* initialize the strings subsystem */
  205. void
  206. dc_string_init DC_DECLVOID()
  207. {
  208.     /* nothing to do for this implementation */
  209. }
  210.