From: leichter@lrw.com (Jerry Leichter)
Newsgroups: comp.os.vms
Subject: re: cdd and c
Date: 24 Dec 92 18:29:42 GMT
Distribution: world
Organization: The Internet


	[Ung-Ho Yi asked:]
	|>i am currently trying to include a string field from
	|>cdd to my c program.
	|>the string field in cdd was created for cobol, so when i tried to
	|>include the field to my c program, i am one character short.

	[Paul Winalski answered:]
	You've run into a fundamental problem here with the ways that the two
	languages (COBOL and C) handle strings.  The string manipulation
	functions in C deal with NUL-terminated strings.  COBOL does not.
	There are two ways that you can reconcile this difference:

	1) In your C program, process the string without requiring the NUL
	   terminator. This means avoiding functions such as strlen(),
	   strcpy(), and the %s formatting directive in printf(), all of which
	   assume that a string is NUL-terminated.

	2) Define the field in your CDD record to be one character bigger than
	   it has to be (this is the CDD equivalent of saying char x[7] when
	   you want x to hold a string with 6 characters in it).  Then just
	   ignore the last character position in your COBOL code.

	It depends on your application which of these solutions is easier to
	implement.  For example, if the field represents existing data in,
	say, disk file records, you have no choice--the format is dictated by
	the data on disk and your C code will just have to avoid using the
	functions that depend on a NUL terminator.  On the other hand, if you
	are designing the whole application now, you can make the string field
	one bigger than it has to be, to accomodate C's NUL character.

I agree with most of what Mr. Winalski says, but disagree with his conclu-
sions.  I'd very strong recommend taking his alternative 1 in just about all
cases.

The problem with alternative 2 is that it only solves half to problem:  It
leaves ROOM for a trailing NUL byte, but there is no way you are going to get
COBOL or any other language that uses descriptor-based strings (i.e., any VMS
language other than C!) to insert it for you reliably.  Every time you create
a string constant, you'll have to insert the NUL yourself.  Every time you do
any string operation - concatenate two strings, extract a piece of a string,
calculate the length of a string - you'll have to remove and add those NUL
bytes, since to those other languages they will be perfectly valid parts of
the string.  The maintenance problems will kill you.

The only situation I might consider this would be one in which the C and COBOL
programs never share a file.  Since the CDD field was created for COBOL, even
if that's true today, I'd expect it to become false tomorrow.

You could avoid this problem by fixing up each field as you read the record
into the C program.  That might make sense for a quick hack, but it's really
not the right approach.

There are really only to places where C's assumption of a trailing NUL show
up:

	- In string constants, which are implicitly NUL-terminated by the
		compiler;
	- In the string-related library functions.

You can easily avoid running into problems with either of these with just a
bit of discipline in your programming.  For example, use descriptor-based
"string constants" using the $DESCRIPTOR macro in descrip.h, and use the
counted variants of the string functions.  For example, never use strcpy;
use strncpy.  Even the "%s" printf() specification that Mr. Winalski mentions
can be used:  Always specify it in the %.*s", and give the length of the
string as an argument just before the pointer to the string.  (You can insert
a constant field width where applicable, of course.)

While this requires some discipline, it will produce much more reliable C code
(you won't have strings copied into fields too short to hold them, thus
scribbling over other data).  A few carefully-chosen macros and support
routines can go a long way.

The very low level of support for strings that's present in C to begin with
makes this much more natural - and less painful - than trying to keep track of
NUL's in languages with high-level support for string operations.

							-- Jerry

Newsgroups: comp.os.vms