Re: [DNG] "Common knowledge?"-question

2016-01-26 Thread Rainer Weikusat
Steve Litt  writes:
> Rainer Weikusat  wrote:
>
>> Can the effect of the following C function
>> 
>> static void print_start(char const *name, char const *what)
>> {

[...]

>> }
>> 
>> be considered obvious or should it rather get an explanation?
>
> Hi Rainer,
>
> Others have pointed out potential coding problems, but I'm just going
> to answer your question about need for comments. In my opinion, the
> preceding function is short enough to document itself *if and only if*
> the function gets a much more descriptive name. Descriptive of what it
> does and how it's used.

The naming is indeed poor. Thank you for pointing this out.
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-25 Thread Dr. Nikolaus Klepp
Am Montag, 25. Januar 2016 schrieb Rainer Weikusat:
> "Dr. Nikolaus Klepp"  writes:
> 
> [...]
> 
> > What about making the source smaller and not the executable?
> >
> > static void print_start(char const *name, char const *what) {
> >  if (name[0]) fprintf("%c%s",name[0]&~0x20, name+1);
> >  fprintf(stderr, " %s: ",what);
> > }
> 
> Are you seriously convinced that - in 2016 - there are still people who
> haven't heard of the stdio library introduced with the 7th edition of
> UNIX(*)?

Well ... yes.

Nik


-- 
Please do not email me anything that you are not comfortable also sharing with 
the NSA.
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-25 Thread Didier Kryn

Le 24/01/2016 19:14, KatolaZ a écrit :

Soo, the above is nearly the same as
>
>   char buf[total];
>   p = buf;
>
>Why then use alloca()?
>

Maybe because
  
   char buf[total];


works only in ANSI C11. I still don't see the need for an internal
buffer to print out a formatted string, to be honest:)


The following works in plain old C:

#include 
#include 
static void print_start(char const *name, char const *what)
{
 unsigned name_len, what_len, total;

 name_len = strlen(name);
 what_len = strlen(what);
 total = name_len + what_len + 3;
 {
   char buf[total], *p=buf;
   memcpy(p, name, name_len);
   p += name_len;
   *p++ = ' ';
   memcpy(p, what, what_len);
   p += what_len;
   *p++ = ':';
   *p = ' ';
   *buf &= ~0x20;

   Write(2, buf, total);
 }
}

Embedded subprograms have other use cases. In long programs, they 
allow to declare variables with a limited scope, just near where they 
are used.


Didier

___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-25 Thread KatolaZ
On Mon, Jan 25, 2016 at 09:27:15AM +0100, Didier Kryn wrote:

[cut]

> 
> The following works in plain old C:
> 
> #include 
> #include 
> static void print_start(char const *name, char const *what)
> {
>  unsigned name_len, what_len, total;
> 
>  name_len = strlen(name);
>  what_len = strlen(what);
>  total = name_len + what_len + 3;
>  {
>char buf[total], *p=buf;
>memcpy(p, name, name_len);
>p += name_len;
>*p++ = ' ';
>memcpy(p, what, what_len);
>p += what_len;
>*p++ = ':';
>*p = ' ';
>*buf &= ~0x20;
> 
>Write(2, buf, total);
>  }
> }
> 
> Embedded subprograms have other use cases. In long programs,
> they allow to declare variables with a limited scope, just near
> where they are used.

I would say that having embedded subprograms in a function is not the
best thing one can do in C, but that's maybe a matter of preference :)

HND

KatolaZ

-- 
[ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ]
[ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ]
[ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ]
[ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ]
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-25 Thread Didier Kryn

Le 25/01/2016 11:34, KatolaZ a écrit :

I would say that having embedded subprograms in a function is not the
best thing one can do in C


Every block is a subprogram. The block in a do loop, the 
conditional block in an if or while statement. The subprogram blocks are 
everywhere in C; they're a basic construct of the language. I don't see 
why plain blocks woud be bad, ie neither conditional, nor loop. And I 
also consider a sane practice to restrict the scope of variables as much 
as it makes sense.


It's just that there are two features that most C programmers never 
learn or quickly forget:


1) blocks don't need to be conditional or loop,
2) they can contain declarations.

On the contrary, the ability to declare variables outside of a 
block, in the middle of instructions, like in C++ is a nonsense; it is 
an incitation to loose programming.


I personnally re-discovered this very nice features a few years ago 
after having used the equivalent in Ada.


Didier

___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-25 Thread Dr. Nikolaus Klepp
Am Montag, 25. Januar 2016 schrieb KatolaZ:
> On Mon, Jan 25, 2016 at 09:27:15AM +0100, Didier Kryn wrote:
> 
> [cut]
> 
> > 
> > The following works in plain old C:
> > 
> > #include 
> > #include 
> > static void print_start(char const *name, char const *what)
> > {
> >  unsigned name_len, what_len, total;
> > 
> >  name_len = strlen(name);
> >  what_len = strlen(what);
> >  total = name_len + what_len + 3;
> >  {
> >char buf[total], *p=buf;
> >memcpy(p, name, name_len);
> >p += name_len;
> >*p++ = ' ';
> >memcpy(p, what, what_len);
> >p += what_len;
> >*p++ = ':';
> >*p = ' ';
> >*buf &= ~0x20;
> > 
> >Write(2, buf, total);
> >  }
> > }
> > 
> > Embedded subprograms have other use cases. In long programs,
> > they allow to declare variables with a limited scope, just near
> > where they are used.
> 
> I would say that having embedded subprograms in a function is not the
> best thing one can do in C, but that's maybe a matter of preference :)
> 
> HND
> 
> KatolaZ
> 

What about making the source smaller and not the executable?

static void print_start(char const *name, char const *what) {
 if (name[0]) fprintf("%c%s",name[0]&~0x20, name+1);
 fprintf(stderr, " %s: ",what);
}

I know this is not slim, but as maintenance time rises with 
pow(lines-of-code,something>1.0), it pays quite soon :-)

-- 
Please do not email me anything that you are not comfortable also sharing with 
the NSA.
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-25 Thread KatolaZ
On Mon, Jan 25, 2016 at 12:18:09PM +0100, Dr. Nikolaus Klepp wrote:

[cut]

> 
> What about making the source smaller and not the executable?
> 
> static void print_start(char const *name, char const *what) {
>  if (name[0]) fprintf("%c%s",name[0]&~0x20, name+1);
>  fprintf(stderr, " %s: ",what);
> }
> 
> I know this is not slim, but as maintenance time rises with 
> pow(lines-of-code,something>1.0), it pays quite soon :-)

+1

HND

KatolaZ

-- 
[ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ]
[ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ]
[ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ]
[ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ]
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-25 Thread Rainer Weikusat
Didier Kryn  writes:
> Le 24/01/2016 19:14, KatolaZ a écrit :
>>> Soo, the above is nearly the same as
>>> >
>>> >   char buf[total];
>>> >   p = buf;
>>> >
>>> >Why then use alloca()?
>>> >
>> Maybe because
>>  char buf[total];
>>
>> works only in ANSI C11. I still don't see the need for an internal
>> buffer to print out a formatted string, to be honest:)
>
> The following works in plain old C:
>
> #include 
> #include 
> static void print_start(char const *name, char const *what)
> {
>  unsigned name_len, what_len, total;
>
>  name_len = strlen(name);
>  what_len = strlen(what);
>  total = name_len + what_len + 3;
>  {
>char buf[total], *p=buf;

It works if the compiler supports the VLA (variable-length array)
feature introduced with C99. But besides apparently aesthetically
pleasing to certain people, it doesn't offer anything which alloca
doesn't offer as well and doesn't offer some things the latter does, eg,
allocating structures which will end up being linked together via
pointers.
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-25 Thread Rainer Weikusat
"Dr. Nikolaus Klepp"  writes:

[...]

> What about making the source smaller and not the executable?
>
> static void print_start(char const *name, char const *what) {
>  if (name[0]) fprintf("%c%s",name[0]&~0x20, name+1);
>  fprintf(stderr, " %s: ",what);
> }

Are you seriously convinced that - in 2016 - there are still people who
haven't heard of the stdio library introduced with the 7th edition of
UNIX(*)?
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-24 Thread Rainer Weikusat
Peter Olson  writes:

>> On January 23, 2016 at 1:36 PM Rainer Weikusat
>>  wrote:
>> 
>> Peter Olson  writes:
>> 5>> On January 22, 2016 at 4:34 PM Rainer Weikusat
>>  wrote:
>> 
>> [...]
>> 
>> >> p = buf = alloca(total);
>> 
>> [...]
>> 
>> >   the failure mode of alloca is SIGSEGV or some other malfunction and
>> > there is no way to test for it
>> 
>> It's supposed to allocate memory in the current stack frame which will
>> work unless the stack has already grown to the limit.
>
>>From man7.org/linux/man-pages/man3/alloca.3.html section BUGS:
>There is no error indication if the stack frame cannot be extended.
>(However, after a failed allocation, the program is likely to receive
>a SIGSEGV signal if it attempts to access the unallocated
>space.)

Calling this a bug is technical nonsense: The way stack allocation works
for a single-threaded process on UNIX(*) etc is that the code just uses
whatever it needs and that the kernel's supposed to handle faults
resulting from accessing a not-yet-valid address by making it available.
In this respect, there's no difference between alloca and static stack
allocations. If a program tries to use more stack space than can be
provided, it may end up getting a SIGSEGV. Or it may silently overwrite
memory used for something different. In either case, the code cannot
possibly work in the it was written.

OTOH, space allocated on the stack will be automatically reclaimed after
the corresponding function returned which is the best 'automatic memory
management' one can get in C. It's also good for locality as different
functions called at the same depth will keep using the same memory area.

> I have never been a fan of alloca though it obviously _can_ be used safely 
> with
> a little care.

Do you realize that Linux uses 8K kernel stacks (and can be configured
to use 4K) with no protection against overwriting whatsoever? In
contrast to this, even on the 32 bit system, the userspace stack area is
practically infinite compared to the memory requirements of small
program and this becomes even more true on 64bit systems.

With some amount criminal energy, it's possible to use the stack
'unsafely'.
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-24 Thread Rainer Weikusat
Didier Kryn  writes:
> Le 23/01/2016 19:28, Rainer Weikusat a écrit :
>> Didier Kryn  writes:
>>> Le 23/01/2016 12:16, Didier Kryn a écrit :
  I'm curious of the reason why you specify
 static void print_start(char const *name, char const *what)

[...]

>>>  Sorry, I overlooked the code and read "char const *name" as if it
>>> was "char * const name". Actually the syntax you used is equivalent to
>>> "const char *name".
>> That's a habit based on an observation I made when I started to write
>> code in C: Type qualifiers are left-associative (presumably a misuse of
>> the term) unless there's nothing to the left of them,

[...]

> So, we could express it as the general declaration would be:

[...]

> But another syntax is allowed, where the qualifier[s] can be on
> the left. I'm not sure there's a BNF description of the C syntax.

It's really

declaration:
   declaration-specifiers init-declarator-list[opt] ;
   
declaration-specifiers:
  storage-class-specifier declaration-specifiers[opt]
  type-specifier declaration-specifiers[opt]
  type-qualifier declaration-specifiers[opt]
  function-specifier declaration-specifiers[opt]

Which means a type-qualifier can appear both to the left and to the
right of a type specifier.

Originally (as I wrote) the fact that

const char *

meant 'pointer to constant char' while

char const *

also meant this and 'constant pointer to char' had to be expressed as

char * const

simply annoyed me because of it's irregularity --- but now, after having
had to deal with a somewhat largish Java codebase where absolutely
everything had a final tacked onto it, thereby making it seriously
difficult to spot the acting code among all the pointless declarational
clutter, I'm presumably in the process of stopping to use const
altogether.

>>> It actually protects the string from being overwritten by the
>>> function.
>> Not really. It just asserts that the string won't be modified using this
>> pointer. In theory, this would enable a compiler to optimize such
>> accesses, eg, collapse many of them into one, however, in practice, gcc
>> doesn't do that, and the qualifier is useless.
>
> The most important goal is not to optimise the executable, it is
> to protect against programmer's errors. gcc will warn you if you try
> to modify a constant.

It won't even compile code trying to use a pointer-to-constant-something
to modify something. But this usually just means that the const ought to
be dropped. C is all about managing memory manually and this means
whenever the content of some (set of) memory location(s) is to be
modified, thought must be put into determining where this memory comes
from and which other code might use it in which way.
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-24 Thread Rainer Weikusat
k...@aspodata.se writes:

> Katola2:
> ...
>> void another_print_start(char *name, char *what){
>> 
>>  char c[3] = " :";
>> 
>>  c[2] = name[0] & ~0x20;
>> 
>>  write(2, c+2, 1);
>>  write(2, name+1, strlen(name) -1);
>>  write(2, c, 2);
>>  write(2, what, strlen(what));
>> 
>> }
>
> Why not just use writev(2) and write it one system call ?

The idea behind writev is to avoid userspace block memory copies prior
to doing a system call which will end up copying all the memory contents
into kernel memory. In order to achieve this, a vector of struct iovec
structures each specifiyng the location and size of a single area is
used. A struct iovec is

struct iovec {
void *iov_base;
size_t iov_len;
};

On a 64-bit system, this means that an additional 16 bytes of data need
to be copied by the kernel for every area used by writev. For this to be
worthwhile, the average size of an area should be more than 33 bytes,
otherwise, writev will end up doing more copying than userspace code had
need to create a continuous area before doing the system call. And then,
there's also the userspace code needed to initialize the vector. For the
example above, this would be

iovs->iov_base = c + 2;
iovs->iov_len = 2;
iovs[1].iov_base = name + 1;
iovs[1].iov_len = strlen(name) - 1;
iovs[2].iov_base = c;
iovs[2].iov_len = 2;
iovs[3].iov_base = what;
iovs[3].iov_len = strlen(what);

compared to

name_len = strlen(name);
what_len = strlen(what);
total = name_len + what_len + 3;
p = buf = alloca(total);
memcpy(p, name, name_len);
p += name_len;
*p++ = ' ';
memcpy(p, what, what_len);
p += what_len;
*p++ = ':';
*p = ' ';

that's 3 lines of code less which is "not great". In addition to this,
both write and writev may end up writing less data than requested and
the code for restarting a partially completed writev is more complicated
than the same for write.
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-24 Thread karl
Reiner Weikusat:
> Peter Olson  writes:
> 
> >> On January 23, 2016 at 1:36 PM Rainer Weikusat
> >>  wrote:
> >> 
> >> Peter Olson  writes:
> >> 5>> On January 22, 2016 at 4:34 PM Rainer Weikusat
> >>  wrote:
> >> 
> >> [...]
> >> 
> >> >> p = buf = alloca(total);
> >> 
> >> [...]
> >> 
> >> >   the failure mode of alloca is SIGSEGV or some other malfunction and
> >> > there is no way to test for it

You should be able to cache a SIGSEGV if you are useing sigaltstack().
Never tested it though and don't know it it is useful at all.

...
> In this respect, there's no difference between alloca and static stack
> allocations.
...

Soo, the above is nearly the same as

  char buf[total];
  p = buf;

Why then use alloca()?

Regards,
/Karl Hammar

---
Aspö Data
Lilla Aspö 148
S-742 94 Östhammar
Sweden
+46 173 140 57


___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-24 Thread karl
Rainer Weikusat:
> k...@aspodata.se writes:
> > Katola2:
> > ...
> >> void another_print_start(char *name, char *what){
> >> 
> >>  char c[3] = " :";
> >> 
> >>  c[2] = name[0] & ~0x20;
> >> 
> >>  write(2, c+2, 1);
> >>  write(2, name+1, strlen(name) -1);
> >>  write(2, c, 2);
> >>  write(2, what, strlen(what));
> >> 
> >> }
> >
> > Why not just use writev(2) and write it one system call ?

Since people complained about allocations, I thought you could use this
and have a static struct iovec[4];, then the only allocations done 
would be for simple types.

> The idea behind writev is to avoid userspace block memory copies prior
...
> that's 3 lines of code less which is "not great". In addition to this,
> both write and writev may end up writing less data than requested and
> the code for restarting a partially completed writev is more complicated
> than the same for write.

Both true.

Regards,
/Karl Hammar

---
Aspö Data
Lilla Aspö 148
S-742 94 Östhammar
Sweden
+46 173 140 57


___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-24 Thread KatolaZ
On Sun, Jan 24, 2016 at 05:25:47PM +0100, k...@aspodata.se wrote:

[cut]

> ...
> > In this respect, there's no difference between alloca and static stack
> > allocations.
> ...
> 
> Soo, the above is nearly the same as
> 
>   char buf[total];
>   p = buf;
> 
> Why then use alloca()?
> 

Maybe because 
 
  char buf[total];

works only in ANSI C11. I still don't see the need for an internal
buffer to print out a formatted string, to be honest :)

HND

KatolaZ

-- 
[ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ]
[ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ]
[ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ]
[ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ]
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-24 Thread Rainer Weikusat
"Dr. Nikolaus Klepp"  writes:
> Am Freitag, 22. Januar 2016 schrieb Rainer Weikusat:

[...]

>> name_len = strlen(name);
>> what_len = strlen(what);
>> total = name_len + what_len + 3;
>> 
>> p = buf = alloca(total);
>> memcpy(p, name, name_len);
>> p += name_len;
>> *p++ = ' ';
>> memcpy(p, what, what_len);
>> p += what_len;
>> *p++ = ':';

[...]

> just out of couriosity: why don't you use "strcat"?

Because strcat is A Seriously Bizarre Invention[tm].

Programmers using the strcat or wcscat function (or the
following strncat or wcsncar functions for that matter) can
easily be recognized as lazy and reckless. In almost all
situations the lengths of the participating strings are known
(it better should be since how can one otherwise ensure the
allocated size of the buffer is sufficient?) Or at least, one
could know them if one keeps track of the results of the various
function calls. But then it is very inefficient to use
strcat/wcscat. A lot of time is wasted finding the end of the
destination string so that the actual copying can start.


https://www.gnu.org/software/libc/manual/html_node/Copying-and-Concatenation.html#Copying-and-Concatenation
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-24 Thread Rainer Weikusat
k...@aspodata.se writes:
> Reiner Weikusat:
>> Peter Olson  writes:
>> 
>> >> On January 23, 2016 at 1:36 PM Rainer Weikusat
>> >>  wrote:
>> >> 
>> >> Peter Olson  writes:
>> >> 5>> On January 22, 2016 at 4:34 PM Rainer Weikusat
>> >>  wrote:
>> >> 
>> >> [...]
>> >> 
>> >> >> p = buf = alloca(total);
>> >> 
>> >> [...]
>> >> 
>> >> >   the failure mode of alloca is SIGSEGV or some other malfunction and
>> >> > there is no way to test for it
>
> You should be able to cache a SIGSEGV if you are useing sigaltstack().
> Never tested it though and don't know it it is useful at all.
>
> ...
>> In this respect, there's no difference between alloca and static stack
>> allocations.
> ...
>
> Soo, the above is nearly the same as
>
>   char buf[total];
>   p = buf;
>
> Why then use alloca()?

This obviously cuts both ways: Considering that C99 style variable
arrays share all the (largely hypothetical) drawbacks of alloca but
offer less features, why use them?
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-24 Thread Rainer Weikusat
k...@aspodata.se writes:
> Reiner Weikusat:
>> Peter Olson  writes:
>> 
>> >> On January 23, 2016 at 1:36 PM Rainer Weikusat
>> >>  wrote:
>> >> 
>> >> Peter Olson  writes:
>> >> 5>> On January 22, 2016 at 4:34 PM Rainer Weikusat
>> >>  wrote:
>> >> 
>> >> [...]
>> >> 
>> >> >> p = buf = alloca(total);
>> >> 
>> >> [...]
>> >> 
>> >> >   the failure mode of alloca is SIGSEGV or some other malfunction and
>> >> > there is no way to test for it
>
> You should be able to cache a SIGSEGV if you are useing sigaltstack().
> Never tested it though and don't know it it is useful at all.
>
> ...
>> In this respect, there's no difference between alloca and static stack
>> allocations.
> ...
>
> Soo, the above is nearly the same as
>
>   char buf[total];
>   p = buf;
>
> Why then use alloca()?

This obviously cuts both ways: Considering that C99 style variable
arrays share all the (largely hypothetical) drawbacks of alloca but
offer less features, why use them?


___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-24 Thread Rainer Weikusat
k...@aspodata.se writes:
> Rainer Weikusat:
>> k...@aspodata.se writes:
>> > Katola2:
>> > ...
>> >> void another_print_start(char *name, char *what){
>> >> 
>> >>  char c[3] = " :";
>> >> 
>> >>  c[2] = name[0] & ~0x20;
>> >> 
>> >>  write(2, c+2, 1);
>> >>  write(2, name+1, strlen(name) -1);
>> >>  write(2, c, 2);
>> >>  write(2, what, strlen(what));
>> >> 
>> >> }
>> >
>> > Why not just use writev(2) and write it one system call ?
>
> Since people complained about allocations, I thought you could use this
> and have a static struct iovec[4];, then the only allocations done 
> would be for simple types.
>
>> The idea behind writev is to avoid userspace block memory copies
>> prior

[and unless the average block size is more than 2 times 16, this ends up
doing more copying instead of less]

> ...
>> that's 3 lines of code less which is "not great". In addition to this,
>> both write and writev may end up writing less data than requested and
>> the code for restarting a partially completed writev is more complicated
>> than the same for write.
>
> Both true.

The core of my statement was not about neligible code savings in one
place ending up as code increases in another but about causing
additional copying instead of avoiding it in case of small areas.
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread KatolaZ
On Sat, Jan 23, 2016 at 02:10:46AM -0500, Peter Olson wrote:

[cut]

> 
> I'm unhappy for two reasons:
> 
>   the failure mode of alloca is SIGSEGV or some other malfunction and there is
> no way to test for it
> 
>   the *buf &= ~0x20; breaks for UTF8 strings.
> 
> Nevermind that the function implicitly references stderr except when it 
> doesn't.
> 

On a closer look, the major problem I see here is not that *buf &=
~0x20 breaks UTF8, but instead that alloca(3) allocates space on the
stack frame of the caller, and could potentially cause a
stack-overflow... This would pass unobserved to most eyes.

I have also checked that the implementation of alloca(3) in glibc does
never return a null-pointer upon failure, thus making very possible to
stack-overflow.

Nice example :)

HND

KatolaZ

-- 
[ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ]
[ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ]
[ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ]
[ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ]
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread Didier Kryn

Le 22/01/2016 22:34, Rainer Weikusat a écrit :

Can the effect of the following C function

static void print_start(char const *name, char const *what)
{
 char *buf, *p;
 unsigned name_len, what_len, total;

 name_len = strlen(name);
 what_len = strlen(what);
 total = name_len + what_len + 3;
 
 p = buf = alloca(total);

 memcpy(p, name, name_len);
 p += name_len;
 *p++ = ' ';
 memcpy(p, what, what_len);
 p += what_len;
 *p++ = ':';
 *p = ' ';
 
 *buf &= ~0x20;


 Write(2, buf, total);
}

be considered obvious or should it rather get an explanation?

An ASCII lowercase letter can be turned into the corresponding uppercase
letter by clearing the sixth bit.


toupper() wouild be better unless you can assert the first char is 
a lertter.


I'm curious of the reason why you specify
   static void print_start(char const *name, char const *what)

This means the pointers to the arrays of characters are constant 
(not the characters). The effect of this cannot be to protect the 
pointers in the caller program since they are passed by value -- copied 
into register or stack before passing control to the function. If it is 
for the sanity of the function itself, then congratulations, this is a 
sane thing to do, even if it is easy to check by eye that the pointers 
aren't modified. But, to be consistent, since your function doesn't even 
modify the content of the strings, you should also declare constant the 
characters themself, like in the following:

static void print_start(const char const *name, const char const *what)

Didier



___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread Didier Kryn

Le 23/01/2016 14:48, Hendrik Boom a écrit :

I've always said the C syntax for declarators was confusing.
Even those who understand it read it wrong!

(Yes, In understand the logic behind it.  It is still confusing.)

I fully agree: it's confusing.

Actually, in a single statement one can declare objects of 
different data types, the base type, pointers to it, pointers to 
pointers etc. This allows for many places to put qualifiers such as 
const, volatile, static, register.


The syntax used by Rainer is usefull when declaring in the same 
statement constant and non-constant characters, which I, personnaly, try 
to avoid because it is confusing. Confusing statements simply boost the 
probability for bugs.


Didier

___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread Steve Litt
On Fri, 22 Jan 2016 21:34:28 +
Rainer Weikusat  wrote:

> Can the effect of the following C function
> 
> static void print_start(char const *name, char const *what)
> {
> char *buf, *p;
> unsigned name_len, what_len, total;
> 
> name_len = strlen(name);
> what_len = strlen(what);
> total = name_len + what_len + 3;
> 
> p = buf = alloca(total);
> memcpy(p, name, name_len);
> p += name_len;
> *p++ = ' ';
> memcpy(p, what, what_len);
> p += what_len;
> *p++ = ':';
> *p = ' ';
> 
> *buf &= ~0x20;
> 
> Write(2, buf, total);
> }
> 
> be considered obvious or should it rather get an explanation?

Hi Rainer,

Others have pointed out potential coding problems, but I'm just going
to answer your question about need for comments. In my opinion, the
preceding function is short enough to document itself *if and only if*
the function gets a much more descriptive name. Descriptive of what it
does and how it's used.

print_start() means nothing to me. Is "start" a noun (the start of the
record) or a verb (start the printing). And the print isn't to a
printer, it's to stdout, so a better word would be "output". But even
those aren't sufficient: This thing is concatenating two strings,
adding punctuation, and capitalizing the first character. Why are all
these things necessary? If the function name can address that, perhaps
it can be self documenting.

Otherwise, there's no shame in putting a few lines of comments above
the function, and personally I'd put an inline comment on that *buf &=
~0x20; trick. Or you could make a macro called upcase_first_letter()
that does that. That makes it self-documenting, and yet because it's a
macro it compiles as if it were inline.

SteveT

Steve Litt 
January 2016 featured book: Twenty Eight Tales of Troubleshooting
http://www.troubleshooters.com/28


___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread Hendrik Boom
On Sat, Jan 23, 2016 at 11:45:30AM -0500, Steve Litt wrote:
> On Fri, 22 Jan 2016 21:34:28 +
> Rainer Weikusat  wrote:
> 
> > Can the effect of the following C function
> > 
> > static void print_start(char const *name, char const *what)
> > {
> > char *buf, *p;
> > unsigned name_len, what_len, total;
> > 
> > name_len = strlen(name);
> > what_len = strlen(what);
> > total = name_len + what_len + 3;
> > 
> > p = buf = alloca(total);
> > memcpy(p, name, name_len);
> > p += name_len;
> > *p++ = ' ';
> > memcpy(p, what, what_len);
> > p += what_len;
> > *p++ = ':';
> > *p = ' ';
> > 
> > *buf &= ~0x20;
> > 
> > Write(2, buf, total);
> > }
> > 
> > be considered obvious or should it rather get an explanation?
> 
> Hi Rainer,
> 
> Others have pointed out potential coding problems, but I'm just going
> to answer your question about need for comments. In my opinion, the
> preceding function is short enough to document itself *if and only if*
> the function gets a much more descriptive name. Descriptive of what it
> does and how it's used.
> 
> print_start() means nothing to me. Is "start" a noun (the start of the
> record) or a verb (start the printing). And the print isn't to a
> printer, it's to stdout, so a better word would be "output". But even
> those aren't sufficient: This thing is concatenating two strings,
> adding punctuation, and capitalizing the first character. Why are all
> these things necessary? If the function name can address that, perhaps
> it can be self documenting.
> 
> Otherwise, there's no shame in putting a few lines of comments above
> the function, and personally I'd put an inline comment on that *buf &=
> ~0x20; trick. Or you could make a macro called upcase_first_letter()
> that does that. That makes it self-documenting, and yet because it's a
> macro it compiles as if it were inline.

A good compiler would inline it even if you write it as a funciton, 
because it's not recursive, and its code is probably smaller than that 
of a function call.

The trouble with macros in C is that they do not respect nested scopes.
(This is a criticism of the language, not of coding style.)

-- hendrik
k
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread Rainer Weikusat
Didier Kryn  writes:
> Le 23/01/2016 12:16, Didier Kryn a écrit :
>>
>> I'm curious of the reason why you specify
>>static void print_start(char const *name, char const *what)
>>
>> This means the pointers to the arrays of characters are constant
>> (not the characters).

[...]

> Sorry, I overlooked the code and read "char const *name" as if it
> was "char * const name". Actually the syntax you used is equivalent to
> "const char *name".

That's a habit based on an observation I made when I started to write
code in C: Type qualifiers are left-associative (presumably a misuse of
the term) unless there's nothing to the left of them, eg

const char *s;

declares a pointer to a constant string,

char const *s;

does the same and

char * const s;

declares a constant pointer to a non-constant string. If the qualifier
is aways to the right of the thing it's supposed to qualify, it
uniformly binds to what's left of it.

[...]

> It actually protects the string from being overwritten by the
> function.

Not really. It just asserts that the string won't be modified using this
pointer. In theory, this would enable a compiler to optimize such
accesses, eg, collapse many of them into one, however, in practice, gcc
doesn't do that, and the qualifier is useless.
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread KatolaZ
On Sat, Jan 23, 2016 at 06:59:10PM +0100, Didier Kryn wrote:

[cut]

> 
> The syntax used by Rainer is usefull when declaring in the same
> statement constant and non-constant characters, which I, personnaly,
> try to avoid because it is confusing. Confusing statements simply
> boost the probability for bugs.
> 

Correct, but in that specific case the potential bug is in the use of
alloca, not the declarations... :)

HND

KatolaZ

-- 
[ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ]
[ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ]
[ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ]
[ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ]
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread KatolaZ
On Sat, Jan 23, 2016 at 06:36:46PM +, Rainer Weikusat wrote:
> Peter Olson  writes:
> 5>> On January 22, 2016 at 4:34 PM Rainer Weikusat 
>  wrote:
> 
> [...]
> 
> >> p = buf = alloca(total);
> 
> [...]
> 
> >   the failure mode of alloca is SIGSEGV or some other malfunction and
> > there is no way to test for it
> 
> It's supposed to allocate memory in the current stack frame which will
> work unless the stack has already grown to the limit.

Since the size of alloca is determined by the user, not by the
developer of the function, you should assume that the call to alloca
is a potential source of attacks based on stack overflow, or of
very-hard-to-reproduce SIGSEGVs.

Also, in this specific case there is no need at all to copy the two
input strings in an internal buffer. The following function will do
exactly the same:

void another_print_start(char *name, char *what){

 char c[3] = " :";

 c[2] = name[0] & ~0x20;

 write(2, c+2, 1);
 write(2, name+1, strlen(name) -1);
 write(2, c, 2);
 write(2, what, strlen(what));

}

It's just a little more cryptic (and I admit that reusing the last
byte of c[] is not best-practices), but avoids a call to alloca(3)
(which is anyway deprecated) with minimal space overhead, and the
problem of managing internal buffers otherwise. I assumed that you had
to use write(2) instead of fprintf(3), for whatever reason, even if I
can't see why this should be the case, since if you have alloca(3)
then you should most probably also have fprintf(3), whatever the
implementation of the C library

My2Cents

KatolaZ

-- 
[ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ]
[ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ]
[ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ]
[ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ]
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread Hendrik Boom
On Sat, Jan 23, 2016 at 04:45:05PM +0100, Didier Kryn wrote:
> Le 23/01/2016 12:16, Didier Kryn a écrit :
> >
> >I'm curious of the reason why you specify
> >   static void print_start(char const *name, char const *what)
> >
> >This means the pointers to the arrays of characters are
> >constant (not the characters). The effect of this cannot be to
> >protect the pointers in the caller program since they are passed
> >by value -- copied into register or stack before passing control
> >to the function. If it is for the sanity of the function itself,
> >then congratulations, this is a sane thing to do, even if it is
> >easy to check by eye that the pointers aren't modified. But, to be
> >consistent, since your function doesn't even modify the content of
> >the strings, you should also declare constant the characters
> >themself, like in the following:
> >static void print_start(const char const *name, const char
> >const *what)
> 
> Sorry, I overlooked the code and read "char const *name" as if
> it was "char * const name". Actually the syntax you used is
> equivalent to "const char *name". It actually protects the string
> from being overwritten by the function.

I've always said the C syntax for declarators was confusing.
Even those who understand it read it wrong!

(Yes, In understand the logic behind it.  It is still confusing.)

-- hendrik 

___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread Didier Kryn

Le 23/01/2016 12:16, Didier Kryn a écrit :


I'm curious of the reason why you specify
   static void print_start(char const *name, char const *what)

This means the pointers to the arrays of characters are constant 
(not the characters). The effect of this cannot be to protect the 
pointers in the caller program since they are passed by value -- 
copied into register or stack before passing control to the function. 
If it is for the sanity of the function itself, then congratulations, 
this is a sane thing to do, even if it is easy to check by eye that 
the pointers aren't modified. But, to be consistent, since your 
function doesn't even modify the content of the strings, you should 
also declare constant the characters themself, like in the following:
static void print_start(const char const *name, const char const 
*what)


Sorry, I overlooked the code and read "char const *name" as if it 
was "char * const name". Actually the syntax you used is equivalent to 
"const char *name". It actually protects the string from being 
overwritten by the function.


___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread karl
Katola2:
...
> void another_print_start(char *name, char *what){
> 
>  char c[3] = " :";
> 
>  c[2] = name[0] & ~0x20;
> 
>  write(2, c+2, 1);
>  write(2, name+1, strlen(name) -1);
>  write(2, c, 2);
>  write(2, what, strlen(what));
> 
> }

Why not just use writev(2) and write it one system call ?

Regards,
/Karl Hammar

---
Aspö Data
Lilla Aspö 148
S-742 94 Östhammar
Sweden
+46 173 140 57


___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread Rainer Weikusat
Peter Olson  writes:
5>> On January 22, 2016 at 4:34 PM Rainer Weikusat 
 wrote:

[...]

>> p = buf = alloca(total);

[...]

>   the failure mode of alloca is SIGSEGV or some other malfunction and
> there is no way to test for it

It's supposed to allocate memory in the current stack frame which will
work unless the stack has already grown to the limit.
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread Peter Olson
> On January 23, 2016 at 1:36 PM Rainer Weikusat
>  wrote:
> 
> Peter Olson  writes:
> 5>> On January 22, 2016 at 4:34 PM Rainer Weikusat
>  wrote:
> 
> [...]
> 
> >> p = buf = alloca(total);
> 
> [...]
> 
> >   the failure mode of alloca is SIGSEGV or some other malfunction and
> > there is no way to test for it
> 
> It's supposed to allocate memory in the current stack frame which will
> work unless the stack has already grown to the limit.

From man7.org/linux/man-pages/man3/alloca.3.html section BUGS:
   There is no error indication if the stack frame cannot be extended.
   (However, after a failed allocation, the program is likely to receive
   a SIGSEGV signal if it attempts to access the unallocated space.)

I have never been a fan of alloca though it obviously _can_ be used safely with
a little care.  The hazard of passing a very long string by accident is what
makes it unsafe.  In this case, with short enough strings it is no more
hazardous than a recursion that is too deep.

Peter Olson
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-23 Thread Didier Kryn

Le 23/01/2016 19:28, Rainer Weikusat a écrit :

Didier Kryn  writes:

Le 23/01/2016 12:16, Didier Kryn a écrit :

 I'm curious of the reason why you specify
static void print_start(char const *name, char const *what)

 This means the pointers to the arrays of characters are constant
 (not the characters).

[...]


 Sorry, I overlooked the code and read "char const *name" as if it
was "char * const name". Actually the syntax you used is equivalent to
"const char *name".

That's a habit based on an observation I made when I started to write
code in C: Type qualifiers are left-associative (presumably a misuse of
the term) unless there's nothing to the left of them, eg

const char *s;

declares a pointer to a constant string,

char const *s;

does the same and

char * const s;

declares a constant pointer to a non-constant string. If the qualifier
is aways to the right of the thing it's supposed to qualify, it
uniformly binds to what's left of it.

[...]


So, we could express it as the general declaration would be:

= ;

 = 
   |  , 



= 



 =  

|



To simplify the description, I assume  can be null.

For example:

char x,  * const *p;
where p would be a pointer to a constant pointer to a char.

But another syntax is allowed, where the qualifier[s] can be on the 
left. I'm not sure there's a BNF description of the C syntax.



It actually protects the string from being overwritten by the
function.

Not really. It just asserts that the string won't be modified using this
pointer. In theory, this would enable a compiler to optimize such
accesses, eg, collapse many of them into one, however, in practice, gcc
doesn't do that, and the qualifier is useless.


The most important goal is not to optimise the executable, it is to 
protect against programmer's errors. gcc will warn you if you try to 
modify a constant.


Didier



___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-22 Thread KatolaZ
On Fri, Jan 22, 2016 at 09:34:28PM +, Rainer Weikusat wrote:
> Can the effect of the following C function
> 
> static void print_start(char const *name, char const *what)
> {

[cut]

> be considered obvious or should it rather get an explanation?
> 


katolaZ said:

Well, it will depend on the audience. It's a pretty basic example and
if one has got some expeience of writing C code would get it at the
first read (even without your explanation at the end, I guess). If the
audience is a freshman module in programming, I wouldn't use it as a
first example ;)

KatolaZ said

-- 
[ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ]
[ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ]
[ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ]
[ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ]
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-22 Thread Dr. Nikolaus Klepp
Am Freitag, 22. Januar 2016 schrieb Rainer Weikusat:
> Can the effect of the following C function
> 
> static void print_start(char const *name, char const *what)
> {
> char *buf, *p;
> unsigned name_len, what_len, total;
> 
> name_len = strlen(name);
> what_len = strlen(what);
> total = name_len + what_len + 3;
> 
> p = buf = alloca(total);
> memcpy(p, name, name_len);
> p += name_len;
> *p++ = ' ';
> memcpy(p, what, what_len);
> p += what_len;
> *p++ = ':';
> *p = ' ';
> 
> *buf &= ~0x20;
> 
> Write(2, buf, total);
> }
> 
> be considered obvious or should it rather get an explanation?

just out of couriosity: why don't you use "strcat"?


-- 
Please do not email me anything that you are not comfortable also sharing with 
the NSA.
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-22 Thread Peter Olson
> On January 22, 2016 at 4:34 PM Rainer Weikusat
>  wrote:
> 
> Can the effect of the following C function
> 
> static void print_start(char const *name, char const *what)
> {
> char *buf, *p;
> unsigned name_len, what_len, total;
> 
> name_len = strlen(name);
> what_len = strlen(what);
> total = name_len + what_len + 3;
> 
> p = buf = alloca(total);
> memcpy(p, name, name_len);
> p += name_len;
> *p++ = ' ';
> memcpy(p, what, what_len);
> p += what_len;
> *p++ = ':';
> *p = ' ';
> 
> *buf &= ~0x20;
> 
> Write(2, buf, total);
> }
> 
> be considered obvious or should it rather get an explanation?
> 
> An ASCII lowercase letter can be turned into the corresponding uppercase
> letter by clearing the sixth bit.

I'm unhappy for two reasons:

  the failure mode of alloca is SIGSEGV or some other malfunction and there is
no way to test for it

  the *buf &= ~0x20; breaks for UTF8 strings.

Nevermind that the function implicitly references stderr except when it doesn't.

Peter Olson
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng


Re: [DNG] "Common knowledge?"-question

2016-01-22 Thread Gregory Nowak
On Fri, Jan 22, 2016 at 09:34:28PM +, Rainer Weikusat wrote:
> Can the effect of the following C function
> 
> static void print_start(char const *name, char const *what)
> {
> char *buf, *p;
> unsigned name_len, what_len, total;
> 
> name_len = strlen(name);
> what_len = strlen(what);
> total = name_len + what_len + 3;
> 
> p = buf = alloca(total);
> memcpy(p, name, name_len);
> p += name_len;
> *p++ = ' ';
> memcpy(p, what, what_len);
> p += what_len;
> *p++ = ':';
> *p = ' ';
> 
> *buf &= ~0x20;
> 
> Write(2, buf, total);
> }
> 
> be considered obvious or should it rather get an explanation?
> 
> An ASCII lowercase letter can be turned into the corresponding uppercase
> letter by clearing the sixth bit.
> ___

My answer is that you shouldn't assume someone will understand what
your function does, even if you think a five-year-old should get
it. It's always a good idea to include a comment block at the top of
your function describing what it does, what variables it expects, and
what it does (or in this case) doesn't return. Yes, that means
explicitly state a void function returns no value. If nothing else,
you do someone else the courtesy of saving them time by explaining
what your function does so they don't need to read through it to
figure that out. If they want to read through it anyway, they still
have that option of course. Just my $0.01 worth.

Greg


-- 
web site: http://www.gregn.net
gpg public key: http://www.gregn.net/pubkey.asc
skype: gregn1
(authorization required, add me to your contacts list first)
If we haven't been in touch before, e-mail me before adding me to your contacts.

--
Free domains: http://www.eu.org/ or mail dns-mana...@eu.org
___
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng