PageRenderTime 75ms CodeModel.GetById 31ms app.highlight 23ms RepoModel.GetById 0ms app.codeStats 1ms

/tags/rel-1-3-26/SWIG/Source/DOH/fio.c

#
C | 555 lines | 421 code | 43 blank | 91 comment | 140 complexity | 19da04ece0a840ff17bd63683f4a714d MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  1/* ----------------------------------------------------------------------------- 
  2 * fio.c
  3 *
  4 *     This file implements a number of standard I/O operations included
  5 *     formatted output, readline, and splitting.
  6 * 
  7 * Author(s) : David Beazley (beazley@cs.uchicago.edu)
  8 *
  9 * Copyright (C) 1999-2000.  The University of Chicago
 10 * See the file LICENSE for information on usage and redistribution.	
 11 * ----------------------------------------------------------------------------- */
 12
 13char cvsroot_fio_c[] = "$Header$";
 14
 15#include "dohint.h"
 16
 17#define OBUFLEN  512
 18
 19static DOH *encodings = 0;              /* Encoding hash */
 20
 21/* -----------------------------------------------------------------------------
 22 * Writen()
 23 *
 24 * Write's N characters of output and retries until all characters are
 25 * written.  This is useful should a write operation encounter a spurious signal.
 26 * ----------------------------------------------------------------------------- */
 27
 28static int Writen(DOH *out, void *buffer, int len) {
 29  int nw = len, ret;
 30  char *cb = (char *) buffer;
 31  while (nw) {
 32    ret = Write(out,cb,nw);
 33    if (ret < 0) return -1;
 34    nw = nw - ret;
 35    cb += ret;
 36  }
 37  return len;
 38}
 39
 40/* -----------------------------------------------------------------------------
 41 * DohEncoding()
 42 *
 43 * Registers a new printf encoding method.  An encoder function should accept
 44 * two file-like objects and operate as a filter.
 45 * ----------------------------------------------------------------------------- */
 46
 47void 
 48DohEncoding(char *name, DOH *(*fn)(DOH *s)) {
 49  if (!encodings) encodings = NewHash();
 50  Setattr(encodings,(void *) name, NewVoid((void *)fn,0));
 51}
 52
 53/* internal function for processing an encoding */
 54static DOH *encode(char *name,  DOH *s) {
 55  DOH *handle, *ns;
 56  DOH *(*fn)(DOH *);
 57  long  pos;
 58  if (!encodings || !(handle = Getattr(encodings,name))) {
 59    return Copy(s);
 60  }
 61  pos = Tell(s);
 62  Seek(s,0,SEEK_SET);
 63  fn = (DOH *(*)(DOH *)) Data(handle);
 64  ns = (*fn)(s);
 65  Seek(s,pos,SEEK_SET);
 66  return ns;
 67}
 68
 69/* -----------------------------------------------------------------------------
 70 * DohvPrintf()
 71 *
 72 * DOH implementation of printf.  Output can be directed to any file-like object
 73 * including bare FILE * objects.  The same formatting codes as printf are
 74 * recognized with two extensions:
 75 *
 76 *       %s          - Prints a "char *" or the string representation of any
 77 *                     DOH object.  This will implicitly result in a call to
 78 *                     Str(obj).
 79 *
 80 *       %(encoder)* - Filters the output through an encoding function registered
 81 *                     with DohEncoder().
 82 *
 83 * Note: This function is not particularly memory efficient with large strings.
 84 * It's better to use Dump() or some other method instead.
 85 * ----------------------------------------------------------------------------- */
 86
 87int
 88DohvPrintf(DOH *so, const char *format, va_list ap)
 89{
 90  static char *fmt_codes = "dioxXucsSfeEgGpn";
 91  int state = 0;
 92  const char *p = format;
 93  char  newformat[256];
 94  char  obuffer[OBUFLEN];
 95  char *fmt = 0;
 96  char  temp[64];
 97  int   widthval = 0;
 98  int   precval = 0;
 99  int   maxwidth;
100  char  *w = 0;
101  int   ivalue;
102  double dvalue;
103  void  *pvalue;
104  char  *stemp;
105  int   nbytes = 0;
106  char  encoder[128], *ec = 0;
107
108  memset (newformat, 0, sizeof (newformat));
109
110  while (*p) {
111    switch(state) {
112    case 0:  /* Ordinary text */
113      if (*p != '%') {
114	Putc(*p,so);
115	nbytes++;
116      } else{
117	fmt = newformat;
118	widthval = 0;
119	precval = 0;
120	*(fmt++) = *p;
121	encoder[0] = 0;
122	state = 10;
123      }
124      break;
125    case 10: /* Look for a width and precision */
126      if (isdigit((int)*p) && (*p != '0')) {
127	w = temp;
128	*(w++) = *p;
129	*(fmt++) = *p;
130	state = 20;
131      } else if (strchr(fmt_codes,*p)) {
132	/* Got one of the formatting codes */
133	p--;
134	state = 100;
135      } else if (*p == '*') {
136	/* Width field is specified in the format list */
137	widthval = va_arg(ap,int);
138	sprintf(temp,"%d",widthval);
139	for (w = temp; *w; w++) {
140	  *(fmt++) = *w;
141	}
142	state = 30;
143      } else if (*p == '%') {
144	Putc(*p,so);
145	fmt = newformat;
146	nbytes++;
147	state = 0;
148      } else if (*p == '(') {
149	ec = encoder;
150	state = 60;
151      } else {
152	*(fmt++) = *p;
153      }
154      break;
155      
156    case 20: /* Hmmm. At the start of a width field */
157      if (isdigit((int)*p)) {
158	*(w++) = *p;
159	*(fmt++) = *p;
160      } else if (strchr(fmt_codes,*p)) {
161	/* Got one of the formatting codes */
162	/* Figure out width */
163	*w = 0;
164	widthval = atoi(temp);
165	p--;
166	state = 100;
167      } else if (*p == '.') {
168	*w = 0;
169	widthval = atoi(temp);
170	w = temp;
171	*(fmt++) = *p;
172	state = 40;
173      } else {
174	/* ??? */
175	*w = 0;
176	widthval = atoi(temp);
177	state = 50;
178      }
179      break;
180
181    case 30:   /* Parsed a width from an argument.  Look for a . */
182      if (*p == '.') {
183	w = temp;
184	*(fmt++) = *p;
185	state = 40;
186      } else if (strchr(fmt_codes,*p)) {
187	/* Got one of the formatting codes */
188	/* Figure out width */
189	p--;
190	state = 100;
191      } else {
192	/* hmmm. Something else. */
193	state = 50;
194      }
195      break;
196
197    case 40:
198      /* Start of precision expected */
199      if (isdigit((int)*p) && (*p != '0')) {
200	*(fmt++) = *p;
201	*(w++) = *p;
202	state = 41;
203      } else if (*p == '*') {
204	/* Precision field is specified in the format list */
205	precval = va_arg(ap,int);
206	sprintf(temp,"%d",precval);
207	for (w = temp; *w; w++) {
208	  *(fmt++) = *w;
209	}
210	state = 50;
211      } else if (strchr(fmt_codes,*p)) {
212	p--;
213	state = 100;
214      } else {
215	*(fmt++) = *p;
216	state = 50;
217      }
218      break;
219    case 41:
220      if (isdigit((int)*p)) {
221	*(fmt++) = *p;
222	*(w++) = *p;
223      } else if (strchr(fmt_codes,*p)) {
224	/* Got one of the formatting codes */
225	/* Figure out width */
226	*w = 0;
227	precval = atoi(temp);
228	p--;
229	state = 100;
230      } else {
231	*w = 0;
232	precval = atoi(temp);
233	*(fmt++) = *p;
234	state = 50;
235      }
236      break;
237      /* Hang out, wait for format specifier */
238    case 50:
239      if (strchr(fmt_codes,*p)) {
240	p--;
241	state = 100;
242      } else {
243	*(fmt++) = *p;
244      }
245      break;
246
247      /* Got an encoding header */
248    case 60:
249      if (*p == ')') {
250	*ec = 0;
251	state = 10;
252      } else {
253	*ec = *p;
254	ec++;
255      }
256      break;
257    case 100:
258      /* Got a formatting code */
259      if (widthval < precval) maxwidth = precval;
260      else maxwidth = widthval;
261      if ((*p == 's') || (*p == 'S')) {       /* Null-Terminated string */
262	DOH    *doh;
263	DOH    *Sval;
264	DOH    *enc = 0;
265	doh = va_arg(ap, DOH *);
266	if (DohCheck(doh)) {
267	  /* Is a DOH object. */
268 	  if (DohIsString(doh)) {
269	    Sval = doh;
270	  } else {
271	    Sval = Str(doh);
272	  }
273	  if (strlen(encoder)) {
274	    enc = encode(encoder,Sval);
275	    maxwidth = maxwidth+strlen(newformat)+Len(enc);
276	  } else {
277	    maxwidth = maxwidth+strlen(newformat)+Len(Sval);
278	  }
279	  *(fmt++) = 's';
280	  *fmt = 0;
281	  if ((maxwidth + 1) < OBUFLEN) {
282	    stemp = obuffer;
283	  } else {
284	    stemp = (char *) DohMalloc(maxwidth+1);
285	  }
286	  if (enc) {
287	    nbytes+=sprintf(stemp,newformat,Data(enc));
288	  } else {
289	    nbytes+=sprintf(stemp,newformat,Data(Sval));
290	  }
291	  if (Writen(so,stemp,strlen(stemp)) < 0) return -1;
292	  if ((DOH *) Sval != doh) {
293	    Delete(Sval);
294	  }
295	  if (enc) Delete(enc);
296	  if (*p == 'S') {
297	    Delete(doh);
298	  }
299	  if (stemp != obuffer) {
300	    DohFree(stemp);
301	  }
302	} else {
303	  if (!doh) doh = (char *)"";
304	  
305	  if (strlen(encoder)) {
306	    DOH *s = NewString(doh);
307	    Seek(s,0, SEEK_SET);
308	    enc = encode(encoder,s);
309	    Delete(s);
310	    doh = Char(enc);
311	  } else {
312	    enc = 0;
313	  }
314	  maxwidth = maxwidth+strlen(newformat)+strlen((char *) doh);
315	  *(fmt++) = 's';
316	  *fmt = 0;
317	  if ((maxwidth+1) < OBUFLEN) {
318	    stemp = obuffer;
319	  } else {
320	    stemp = (char *) DohMalloc(maxwidth + 1);
321	  }
322	  nbytes+=sprintf(stemp,newformat,doh);
323	  if (Writen(so,stemp,strlen(stemp)) < 0) return -1;
324	  if (stemp != obuffer) {
325	    DohFree(stemp);
326	  }
327	  if (enc) Delete(enc);
328	}
329      } else {
330	*(fmt++) = *p;
331	*fmt = 0;
332	maxwidth = maxwidth+strlen(newformat)+64;
333	
334	/* Only allocate a buffer if it is too big to fit.  Shouldn't have to do
335           this very often */
336
337	if (maxwidth < OBUFLEN)
338	  stemp = obuffer;
339	else 
340	  stemp = (char *) DohMalloc(maxwidth+1);
341	switch(*p) {
342	case 'd':
343	case 'i':
344	case 'o':
345	case 'u':
346	case 'x':
347	case 'X':
348	case 'c':
349	  ivalue = va_arg(ap,int);
350	  nbytes+=sprintf(stemp,newformat,ivalue);
351	  break;
352	case 'f':
353	case 'g':
354	case 'e':
355	case 'E':
356	case 'G':
357	  dvalue = va_arg(ap,double);
358	  nbytes+=sprintf(stemp,newformat,dvalue);
359	  break;
360	case 'p':
361	  pvalue = va_arg(ap,void *);
362	  nbytes+=sprintf(stemp,newformat,pvalue);	  
363	  break;
364	default:
365	  break;
366	}
367	if (Writen(so,stemp,strlen(stemp)) < 0) return -1;
368	if (stemp != obuffer) DohFree(stemp);
369      }
370      state = 0;
371      break;
372    }
373    p++;
374  }
375  if (state) {
376    int r;
377    *fmt = 0;
378    r = Writen(so,fmt,strlen(fmt));
379    if (r < 0) return -1;
380    nbytes += r;
381  }
382  return nbytes;
383}
384
385/* -----------------------------------------------------------------------------
386 * DohPrintf()
387 *
388 * Variable length argument entry point to Printf
389 * ----------------------------------------------------------------------------- */
390
391int
392DohPrintf(DOH *obj, const char *format, ...) {
393  va_list ap;
394  int ret;
395  va_start(ap,format);
396  ret = DohvPrintf(obj,format,ap);
397  va_end(ap);
398  return ret;
399}
400
401/* -----------------------------------------------------------------------------
402 * DohPrintv()
403 * 
404 * Print a null-terminated variable length list of DOH objects
405 * ----------------------------------------------------------------------------- */
406
407int DohPrintv(DOHFile *f, ...) {
408  va_list ap;
409  int ret = 0;
410  DOH *obj;
411  va_start(ap,f);
412  while(1) {
413    obj = va_arg(ap,void *);
414    if ((!obj) || (obj == DohNone)) break;
415    if (DohCheck(obj)) {
416      ret += DohDump(obj,f);
417    } else {
418      ret += DohWrite(f,obj,strlen((char *) obj));
419    }
420  }
421  va_end(ap);
422  return ret;
423}
424
425/* ----------------------------------------------------------------------------- 
426 * DohCopyto()
427 *
428 * Copies all of the input from an input stream to an output stream. Returns the
429 * number of bytes copied.
430 * ----------------------------------------------------------------------------- */
431
432int
433DohCopyto(DOH *in, DOH *out) {
434  int nbytes = 0, ret;
435  int nwrite = 0, wret;
436  char *cw;
437  char buffer[16384];
438
439  if ((!in) || (!out)) return 0;
440  while (1) {
441    ret = Read(in,buffer,16384);
442    if (ret > 0) {
443      nwrite = ret;
444      cw = buffer;
445      while (nwrite) {
446	wret = Write(out,cw,nwrite);
447	if (wret < 0) return -1;
448	nwrite = nwrite - wret;
449	cw += wret;
450      }
451      nbytes += ret;
452    } else {
453      return nbytes;
454    }
455  }
456}
457
458
459/* -----------------------------------------------------------------------------
460 * DohSplit()
461 *
462 * Split an input stream into a list of strings delimited by the specified
463 * character.  Optionally accepts a maximum number of splits to perform.
464 * ----------------------------------------------------------------------------- */
465
466DOH *
467DohSplit(DOH *in, char ch, int nsplits) {
468  DOH *list;
469  DOH *str;
470  int c;
471  
472  list = NewList();
473
474  if (DohIsString(in)) {
475    Seek(in,0,SEEK_SET);
476  }
477
478  while (1) {
479    str = NewString("");
480    do {
481      c = Getc(in);
482    } while ((c != EOF) && (c == ch));
483    if (c != EOF) {
484      Putc(c,str);
485      while (1) {
486	c = Getc(in);
487	if ((c == EOF) || ((c == ch) && (nsplits != 0))) break;
488	Putc(c,str);
489      }
490      nsplits--;
491    }
492    Append(list,str);
493    Delete(str);
494    if (c == EOF) break;
495  }
496  return list;
497}
498
499/* -----------------------------------------------------------------------------
500 * DohSplitLines()
501 *
502 * Split an input stream into a list of strings delimited by newline characters.
503 * ----------------------------------------------------------------------------- */
504
505DOH *
506DohSplitLines(DOH *in) {
507  DOH *list;
508  DOH *str;
509  int  c = 0;
510
511  list = NewList();
512
513  if (DohIsString(in)) {
514    Seek(in,0,SEEK_SET);
515  }
516
517  while (c != EOF) {
518    str = NewString("");
519    while ((c = Getc(in)) != '\n' && c != EOF) {
520      Putc(c, str);
521    }
522    Append(list,str);
523    Delete(str);
524  }
525  return list;
526}
527
528
529/* -----------------------------------------------------------------------------
530 * DohReadline()
531 *
532 * Read a single input line and return it as a string.
533 * ----------------------------------------------------------------------------- */
534
535DOH *
536DohReadline(DOH *in) {
537  char c;
538  int n = 0;
539  DOH *s = NewString("");
540  while (1) {
541    if (Read(in,&c,1) < 0) {
542      if (n == 0) {
543	Delete(s);
544	return 0;
545      }
546      return s;
547    }
548    if (c == '\n') return s;
549    if (c == '\r') continue;
550    Putc(c,s);
551    n++;
552  }
553}
554
555