fcaggian@kepler.com (Frank Caggiano) (01/05/91)
The following c routine is something I've wanted to write for a while now. It makes creating formatted string objects easier. Its an sprintf like routine but it returns a string object. The call and arguments are the same as for the [sf]printf c routines. Declare it as external format_obj: STRING language "C" Usage colud then be something like : local s: STRING do s := format_obj("%2d %-5s%6d%8.3f%5d%7d%6d%4d", n, stock_list.item.ticker.to_c, stock_list.item.amount, price / 256.0, ktotal / 1000, stock_list.item.position, stock_list.item.pending, stock_list.item.form ); This was written and tested on a space running 4.0.3. It should be poratable. Please let me know of any problems especially with the varargs stuff. ********* BEGIN INCLUDED CODE /* -- Copyright (c) 1990 Kepler Financial Mgmt. -- -- Permission is granted to anyone to make or distribute -- copies of this software provided that the -- copyright notice and this permission notice are preserved. -- Ownership remains with Kepler Financial Mgmt. */ #ifndef lint static char *sccsid = "@(#)_objformat.c:1.1 1/4/91"; #endif #include <varargs.h> #include <_eiffel.h> #ifndef BUFSIZ #define BUFSIZ 512 #endif BUFSIZ OBJPTR format_obj(fmt, va_alist) char *fmt; va_dcl /* the missing ; IS RIGHT see varargs */ { va_list ap; register int n; register char *cp, c, *buf_end; char buf[BUFSIZ], f[20]; OBJPTR strobj; ROUT_PTR from_c; cp = buf; f[0] = '%'; buf_end = buf+BUFSIZ; va_start (ap); while((c = *fmt++) != '\0' && cp < buf_end) { if(c == '%') { for(c = *fmt++,n = 1; c; n++) { switch(c) { case '%': /* its %% put out the % */ *cp++ = '%'; c = '\0'; break; case 's': /* normal string */ f[n++] = c; f[n] = '\0'; sprintf(cp, f, va_arg(ap,char *)); cp += strlen(cp); c = '\0'; break; case '*': /* variable field width */ { char varwidth[10]; int x = 0; sprintf(varwidth,"%d",va_arg(ap, int)); while((f[n++] = varwidth[x++])) ; } n -= 2; c = *fmt++; break; case 'f': /* floats etc. */ case 'g': case 'e': f[n++] = c; f[n] = '\0'; sprintf(cp, f,va_arg(ap, double)); cp += strlen(cp); c = '\0'; break; case 'd': /* ints and such */ case 'o': case 'c': case 'x': case 'u': f[n++] = c; f[n] = '\0'; sprintf(cp, f,va_arg(ap, int)); cp += strlen(cp); c = '\0'; break; default: /* none of the above */ f[n] = c; c = *fmt++; break; } } } else /* c wasn't '%'; just copy it into buf */ *cp++ = c; } va_end(ap); *cp = '\0'; strobj = (OBJPTR) eif_create("string", 0) from_c = (ROUT_PTR) eif_rout(strobj, "from_c"); (*from_c) (strobj, buf); return (strobj); } By the way has anyone had a chance to tryout the RESOURCE managment stuf I posted some time back? Anyone doing anything with X/GUI's and Eiffel. I would like to hear from anyone doing work along those lines. (if they are free to talk. Those on Double Secret Probation need not apply :-) ). -- Frank Caggiano INTERNET: fcaggian@kepler.com Kepler Financial Management, Ltd. UUCP: ..!uunet!kepler1!fcaggian 100 North Country Rd. fax: (516) 751-8678 Sekauket, NY 11733 voice: (516) 689-6300
marc@eiffel.UUCP (Jean-Marc Nerson) (01/06/91)
In article <457@kepler1.kepler.com>, fcaggian@kepler.com (Frank Caggiano) writes: > The following c routine is something I've wanted to write for > a while now. It makes creating formatted string objects > easier. Your contribution will be very helpful. I slightly updated your C code to include: 1) Recognition of conversion characters E, G, X 2) Use of specific Eiffel run-time routine MakeStr() instead of eif_create() and eif_rout() The diff -c follows. -------------------- CUT HERE ------------------ *** /tmp/,RCSt1a04581 Sat Jan 5 15:30:58 1991 --- _format.c Sat Jan 5 15:28:13 1991 *************** *** 25,34 **** register int n; register char *cp, c, *buf_end; char buf[BUFSIZ], f[20]; - OBJPTR strobj; - ROUT_PTR from_c; - cp = buf; f[0] = '%'; --- 25,32 ---- register int n; register char *cp, c, *buf_end; char buf[BUFSIZ], f[20]; + extern OBJPTR MakeStr(); cp = buf; f[0] = '%'; *************** *** 68,74 **** --- 66,74 ---- case 'f': /* floats etc. */ case 'g': + case 'G': case 'e': + case 'E': f[n++] = c; f[n] = '\0'; sprintf(cp, f,va_arg(ap, double)); *************** *** 80,85 **** --- 80,86 ---- case 'o': case 'c': case 'x': + case 'X': case 'u': f[n++] = c; f[n] = '\0'; *************** *** 102,109 **** *cp = '\0'; ! strobj = (OBJPTR) eif_create("string", 0) ! from_c = (ROUT_PTR) eif_rout(strobj, "from_c"); ! (*from_c) (strobj, buf); ! return (strobj); } --- 103,107 ---- *cp = '\0'; ! return (MakeStr (buf)); } -------------------- CUT HERE ------------------ -- Jean-Marc Nerson marc@eiffel.com
rick@tetrauk.UUCP (Rick Jones) (01/07/91)
In article <457@kepler1.kepler.com> fcaggian@kepler.com (Frank Caggiano) writes: >The following c routine is something I've wanted to write for >a while now. It makes creating formatted string objects >easier. I hate to devalue your work, but if your system has the vprintf() set of functions, you can do this extremely simply. It would look like: #include <varargs.h> #include <_eiffel.h> #ifndef BUFSIZ #define BUFSIZ 512 #endif BUFSIZ OBJPTR format_obj(fmt, va_alist) char *fmt; va_dcl /* the missing ; IS RIGHT see varargs */ { va_list ap; char buf[BUFSIZ]; va_start (ap); if (vsprintf (buf, fmt, ap) >= BUFSIZ) { /* PANIC - buffer overrun, need some program abort code here */ } va_end (ap); return (MakeStr (buf)); } You might want to make BUFSIZ something really big to make the probability of buffer overrun very low. I'm not sure of the extent to which vsprintf() is supported. It's standard in System V, but may not be in BSD. The neatest solution is to use this routine, and then if you haven't got vsprintf() in your library write it using the code Frank posted in his article. The almost identical code was recently posted in comp.lang.c for just this purpose. -- Rick Jones Tetra Ltd. Maidenhead, Was it something important? Maybe not Berks, UK What was it you wanted? Tell me again I forgot rick@tetrauk.uucp -- Bob Dylan
fcaggian@kepler.com (Frank Caggiano) (01/08/91)
In article <475@eiffel.UUCP>, marc@eiffel.UUCP (Jean-Marc Nerson) writes: > Your contribution will be very helpful. > > I slightly updated your C code to include: > 2) Use of specific Eiffel run-time routine MakeStr() > instead of eif_create() and eif_rout() > > The diff -c follows. [ Number of lines deleted ] [from] > ! strobj = (OBJPTR) eif_create("string", 0) > ! from_c = (ROUT_PTR) eif_rout(strobj, "from_c"); > ! (*from_c) (strobj, buf); > ! return (strobj); [to] > ! return (MakeStr (buf)); > } Does this mean that the return from MakeStr() is an Eiffel string object ? It would be legal to do something like: OBJPTR s; ROUT_PTR r; s = MakeStr (buf); r = (ROUT_PTR) (s, "append"); (*r)(s,s); [ Doesn't really do anything, just illustrates my question ] This is good to know as I do a lot of passing of string objects back from C. Thanks for the input. -- Frank Caggiano INTERNET: fcaggian@kepler.com Kepler Financial Management, Ltd. UUCP: ..!uunet!kepler1!fcaggian 100 North Country Rd. fax: (516) 751-8678 Sekauket, NY 11733 voice: (516) 689-6300
fcaggian@kepler.com (Frank Caggiano) (01/12/91)
In article <1071@tetrauk.UUCP>, rick@tetrauk.UUCP (Rick Jones) writes: > In article <457@kepler1.kepler.com> fcaggian@kepler.com (Frank Caggiano) writes: > >The following c routine is something I've wanted to write for > >a while now. It makes creating formatted string objects > >easier. > > I hate to devalue your work, but if your system has the vprintf() set of > functions, you can do this extremely simply. It would look like: [ revised code deleted ] I don't feel that your posting devalues my work in anyway. It's a valid solution to the problem. My code was stripped out of another routine I wrote some years ago which is called eprintf. It acts just like the starndard printf routines but had added % parameter recognition for error reporting. I appreciate it when someone tales the time to look at and comment on code I have written. How else is one to learn in this buisiness? > You might want to make BUFSIZ something really big to make the probability of > buffer overrun very low. The double check in the for loop prevents buffer overrun. If the format string and expanded values are to large the returned string will be incomplete. > I'm not sure of the extent to which vsprintf() is supported. A real problem with the growth of UNIX. Just what is truely portable code these days ? If anyone knows how universial the vsprintf() functions are prehaps they could let us know. By the way according to the man page for varargs on the sun my spliting of the format string from the rest of the varargs isn't right. It should be something like: was: OBJPTR format_obj(fmt,va_alist) char *fmt; should be: OBJPTR format_obj(va_alist) /* removed fmt as arg */ va_dcl /* the missing ; IS RIGHT see varargs */ { va_list ap; register int n; register char *cp, c, *buf_end; char buf[BUFSIZ], f[20], *fmt; /* added fmt as local var */ ^^^^^^^^^^^ OBJPTR strobj; ROUT_PTR from_c; cp = buf; f[0] = '%'; buf_end = buf+BUFSIZ; va_start (ap); /* add */ fmt = va_arg(ap, char *); /* set fmt from var arg list */ while((c = *fmt++) != '\0' && cp < buf_end) { [ THE REST is the same ] The code as I orignally posted it works but may have problems with really long arg lists. > -- > Rick Jones > Tetra Ltd. Maidenhead, Was it something important? Maybe not > Berks, UK What was it you wanted? Tell me again I forgot > rick@tetrauk.uucp -- Bob Dylan I like the Dylan quotes in your signature. How come I've never seen the one: 'You know something is happening but you don't know what it is, do you Mr. ........ ' [ It may be a bit off my Dylan is rusty ] :-) Regards PS. Did you do work for an American Law firm in London about 5 years ago? -- Frank Caggiano INTERNET: fcaggian@kepler.com Kepler Financial Management, Ltd. UUCP: ..!uunet!kepler1!fcaggian 100 North Country Rd. fax: (516) 751-8678 Sekauket, NY 11733 voice: (516) 689-6300