[net.lang.c] Additions/modifications to C library

chris@sol.UUCP (Christopher Caldwell) (06/04/86)

*** REPLACE THIS LINE WITH YOUR MESSAGE ***

I have been reading articles from the net on and off for about a year now.
If this kind of thing has been posted before, please flame me via email ...

I am trying to create C programs on a microForce-1A (M68010 System V UNIX box)
to download to one of their cards (CPU-1C).  I am able to download code
that does not use any of their standard libraries by emulating the various
systems calls.  However, their standard libraries do stack checking and
annoying port dependant system calling.  I do not have the source to anything.

Therefore, I think I will end up writing my own equivalent of the C library.

Firstly, is there such think as a public domain C library?  (Why are you
all laughing so hard?)

Secondly, I have committed the ultimate sin of programmers everywhere and
added some improvements to mine.  In particular, I no longer use printf.
Instead, I use "format".  I.e.:

	format("The answer is {i}.\n",an_int_variable);

The braces denote a substitution (Like "%" in printf), but the options are
different.  ('{{' means just print a '{')  A substitution is of the form (EBNF):

	'{' <type-letter> { <modifier-character> [ <modifier-value> ] } '}'

Available type letters so far are:

	s	string (Char *)
	i	int
	l	long
	c	character
	f	float (double)
	S	Another format string (I smell recursion)

Available modifers (and their defaults) are:

	l(0)	Number of columns to take up, value will be left justified
	r(0)	Number of columns to take up, value will be right justified
	c(0)	Number of columns to take up, value will be centered
	m(0)	Maximum number of columns display of data
	.(6)	Number of places to display to the right of the decimal point
	b(10)	Base of number
	p(32)	Ascii value of pad character for l, r or c.
	u(0)	Unsigned status (signed=0, unsigned!=0)
	n(1)	Count of times to repeat string

If a modifer value is followed by a string of digits then that string is
converted to an integer and used as the modifier's value, else the value will
be taken from the next argument to format.

Some ridiculous variable type/modifer combinations exist:
	What is an unsigned string (or character) of base 8 with 4 trailing
	    decimal places? (All three modifiers are ignored)
	Do you really want to see floating point variables in base 3?  (Yes!)
	What does centering a left or right justifed variable look like?
	    (The last justification character is the one used)

Now, an example program:

	main()
	{
	int i;

	format("Left justified integer:  '{il10}'\n",1234);
	format("###{f.1c}###\n",123.4,20);
	format("Octal:  {lb8r11pu1}\n",01234L,'0');
	format("Truncate this:  {sm10}\n", "This is a test" );
	format("Print 5 arfs:  {sn5}\n","arf");
	i = 1;
	format("Do it {i} time{sn}.\n",i,"s",i!=1);
	i = 2;
	format("Do it {i} time{sn}.\n",i,"s",i!=1);
	format("Center this: ###{Sc20p}###\n","Answer={i}",'$',1234);
	exit(0);
	}

and its standard output:

	Left justified integer:  '1234      '
	###        123.4       ###
	Octal:  00000001234
	Truncate this:  This is a 
	Print 5 arfs:  arfarfarfarfarf
	Do it 1 time.
	Do it 2 times.
	Center this: ###$$$$$Answer=1234$$$$###

The following flavors of format are available:

	format( formatstring, args... )		Send to standard out
	fformat( stream, formatstring, args... )Send to specified stream
	i = cformat( formatstring, args... )	Calculate number of chars
	sformat( buf, formatstring, args... )	Send to the character array buf
	ptr = mformat( formatstring, args... )	Malloc enough space for result
						(and trailing 0), put the
						result in malloced space, and
						return pointer to it
			    Also, as a kluge:
	ptr = sformat( NULL, formatstring, args... )

mformat (and sformat with a NULL array), perform the format twice,
once to find out how many characters needed to malloc, and the next
time to fill up the array.

I have been using these routines extensively for downloaded applications, and
am now using them for my UNIX programs as well.  The only disadvantage I can
find with them is that simple formats require more characters to specify
than with printf.  I.e. to print a two character integer with printf requires
three characters (%2d), but with format requires five ({ir4}).

Advantages:
	Easier to understand justification
	Centering available
	More flexible padding (instead of just spaces or zeros)
	Arbitrary base output (2 to 36)
	Complex formats available ("S")
	Arbitrarily lengthed everything (up do what you can malloc)
	And from my point of view, I have the source!

I am also working on a replacement for scanf which uses the same style
of modifiers.  In particular, it will be able to malloc space for strings
it has parsed, and the equivalent of "sscanf" will return some kind
of indication of where it stopped parsing the string.  If this is possible
to do with sscanf, I don't know how.

Comments and opinions are welcome.

If people want the source, I am certainly willing to post it or email it.

Also, what do netlanders think of a tiny revision to C?  Namely, to be able
to specify the base of an integer in the form <base>_<number>.  For instance
to specify 10 (base 10) in base 2, one might type 2_1010.  Yes, once again,
I am opting for full generality.  Also, I must admit, I find 0<number> and
0x<number> confusing.  I much prefer 8_777 to 0777.

Christopher M. Caldwell
...decvax!ittatc!sii!dmcnh!sol!chris
16 Columbia Drive, VIBRAC Corporation, Amherst, NH 03031, (603)882-6777
13B Bobby's Lane, Milford, NH 03055, (603)673-2249