5761889 [rkeene@sledge /home/rkeene/devel/old/bc-dos/dc]$ cat -n string.c
  1 /* 
  2  * implement string functions for dc
  3  *
  4  * Copyright (C) 1994, 1997, 1998 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 /* here is the completion of the dc_string type: */
 50 struct dc_string {
 51     char *s_ptr;  /* pointer to base of string */
 52     size_t s_len; /* length of counted string */
 53     int  s_refs;  /* reference count to cut down on memory use by duplicates */
 54 };
 55 
 56 
 57 /* return a duplicate of the string in the passed value */
 58 /* The mismatched data types forces the caller to deal with
 59  * bad dc_type'd dc_data values, and makes it more convenient
 60  * for the caller to not have to do the grunge work of setting
 61  * up a dc_type result.
 62  */
 63 dc_data
 64 dc_dup_str DC_DECLARG((value))
 65     dc_str value DC_DECLEND
 66 {
 67     dc_data result;
 68 
 69     ++value->s_refs;
 70     result.v.string = value;
 71     result.dc_type = DC_STRING;
 72     return result;
 73 }
 74 
 75 /* free an instance of a dc_str value */
 76 void
 77 dc_free_str DC_DECLARG((value))
 78     dc_str *value DC_DECLEND
 79 {
 80     struct dc_string *string = *value;
 81 
 82     if (--string->s_refs < 1){
 83         free(string->s_ptr);
 84         free(string);
 85     }
 86 }
 87 
 88 /* Output a dc_str value.
 89  * Add a trailing newline if "newline" is set.
 90  * Free the value after use if discard_flag is set.
 91  */
 92 void
 93 dc_out_str DC_DECLARG((value, newline, discard_flag))
 94     dc_str value DC_DECLSEP
 95     dc_newline newline DC_DECLSEP
 96     dc_discard discard_flag DC_DECLEND
 97 {
 98     fwrite(value->s_ptr, value->s_len, sizeof *value->s_ptr, stdout);
 99     if (newline == DC_WITHNL)
100         putchar('\n');
101     if (discard_flag == DC_TOSS)
102         dc_free_str(&value);
103 }
104 
105 /* make a copy of a string (base s, length len)
106  * into a dc_str value; return a dc_data result
107  * with this value
108  */
109 dc_data
110 dc_makestring DC_DECLARG((s, len))
111     const char *s DC_DECLSEP
112     size_t len DC_DECLEND
113 {
114     dc_data result;
115     struct dc_string *string;
116 
117     string = dc_malloc(sizeof *string);
118     string->s_ptr = dc_malloc(len+1);
119     memcpy(string->s_ptr, s, len);
120     string->s_ptr[len] = '\0';  /* nul terminated for those who need it */
121     string->s_len = len;
122     string->s_refs = 1;
123     result.v.string = string;
124     result.dc_type = DC_STRING;
125     return result;
126 }
127 
128 /* read a dc_str value from FILE *fp;
129  * if ldelim == rdelim, then read until a ldelim char or EOF is reached;
130  * if ldelim != rdelim, then read until a matching rdelim for the
131  * (already eaten) first ldelim is read.
132  * Return a dc_data result with the dc_str value as its contents.
133  */
134 dc_data
135 dc_readstring DC_DECLARG((fp, ldelim, rdelim))
136     FILE *fp DC_DECLSEP
137     int ldelim DC_DECLSEP
138     int rdelim DC_DECLEND
139 {
140     static char *line_buf = NULL;   /* a buffer to build the string in */ 
141     static size_t buflen = 0;       /* the current size of line_buf */
142     int depth=1;
143     int c;
144     char *p;
145     const char *end;
146 
147     if (!line_buf){
148         /* initial buflen should be large enough to handle most cases */
149         buflen = 2016;
150         line_buf = dc_malloc(buflen);
151     }
152     p = line_buf;
153     end = line_buf + buflen;
154     for (;;){
155         c = getc(fp);
156         if (c == EOF)
157             break;
158         else if (c == rdelim && --depth < 1)
159             break;
160         else if (c == ldelim)
161             ++depth;
162         if (p >= end){
163             ptrdiff_t offset = p - line_buf;
164             /* buflen increment should be big enough
165              * to avoid execessive reallocs:
166              */
167             buflen += 2048;
168             line_buf = realloc(line_buf, buflen);
169             if (!line_buf)
170                 dc_memfail();
171             p = line_buf + offset;
172             end = line_buf + buflen;
173         }
174         *p++ = c;
175     }
176     return dc_makestring(line_buf, (size_t)(p-line_buf));
177 }
178 
179 /* return the base pointer of the dc_str value;
180  * This function is needed because no one else knows what dc_str
181  * looks like.
182  */
183 const char *
184 dc_str2charp DC_DECLARG((value))
185     dc_str value DC_DECLEND
186 {
187     return value->s_ptr;
188 }
189 
190 /* return the length of the dc_str value;
191  * This function is needed because no one else knows what dc_str
192  * looks like, and strlen(dc_str2charp(value)) won't work
193  * if there's an embedded '\0'.
194  */
195 size_t
196 dc_strlen DC_DECLARG((value))
197     dc_str value DC_DECLEND
198 {
199     return value->s_len;
200 }
201 
202 
203 /* initialize the strings subsystem */
204 void
205 dc_string_init DC_DECLVOID()
206 {
207     /* nothing to do for this implementation */
208 }
5761890 [rkeene@sledge /home/rkeene/devel/old/bc-dos/dc]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 1998-03-09 05:21:06