Re: [vox-tech] writing free getopt, ran into a dilemma...

2002-04-01 Thread msimons

Micah,

  I'm going to join the last two posts into one reply to make
things easier.


On Sun, Mar 31, 2002 at 12:47:59AM -0800, Micah Cowan wrote:
 On Sat, 2002-03-30 at 04:45, [EMAIL PROTECTED] wrote:
  On Thu, Mar 28, 2002 at 09:13:19AM -0800, Mark K. Kim wrote:
   The one I tried to link statically on Windows one time said it was GPL,
   but according to Micah it's apparently LGPL with misdocumentation. :P
 
readline is GPL, getopt is LGPL... maybe some maintainer got confused?

 getopt's license would seem to be debatable - the sourcefile itself
 claims to be plain ol' GPL, though the accompanying, seperate license
 file claims LGPL.

  I admit I didn't check the source files the first time, because 
logically it *MUST* have the LGPL if it is linked into *the* libc
that practically every binary on a Linux system uses.  I'm not
much for logic proofs but I think this could be a proof by 
contradiction:
  If getopt used the GPL, then everything linked to it must also 
(meaning the rest of libc), and anything linked to that (including 
dynamically linked) would have to... thus every binary that runs 
on a Linux system is GPL'd.  Time to contact Oracle about their
OCI library...
  Well that was fun, now back to reality.  The above demonstrates
the 'viral license' concept microsoft whines about.


  Since I'm generally bad at proofs a source to backup that idea
that everything linked to a GPL thing must also have a GPL license... 
comes from the preamble of the LGPL where it describes the differences 
between itself and the GPL.

/usr/share/common-licenses/LGPL
#   When a program is linked with a library, whether statically or using
# a shared library, the combination of the two is legally speaking a
# combined work, a derivative of the original library.  The ordinary
# General Public License therefore permits such linking only if the
# entire combination fits its criteria of freedom.  The Lesser General
# Public License permits more lax criteria for linking other code with
# the library.


  So we have another reference problem... what source code tarfile
(or whatever) did you find the GPL attached to getopt.c?

  I checked my copy of source which I got via apt-get source glibc
with timestamps shown [way] below.  Both my header and source files have
references to the 'GNU Lesser General Public License':

glibc-2.2.5/posix/getopt.c
#The GNU C Library is free software; you can redistribute it and/or
#modify it under the terms of the GNU Lesser General Public
#License as published by the Free Software Foundation; either
#version 2.1 of the License, or (at your option) any later version.

  Stallman playing his word games renamed the 'Library General Public
License' to the 'Lesser General Public License' I suspect in an attempt
to make it sound more distasteful... he may have had other reasons,
regardless they are both the 'LGPL' we have been talking about.


[...okay onto the second post]

On Sun, Mar 31, 2002 at 12:40:30AM -0800, Micah Cowan wrote:
   Intermixing options with arguments is a GNU
   extension, and GNU pulls some mildly dirty tricks to get it (such as
   permuting argv, despite the fact that it's elements are declared const).
 
  Here is what I believe the valid declarations to be (these from ANSI C):
int main(void);
int main(int argc, const char **argv);

 No, the second shouldn't have the const.

  POSIX adds the following one additional main:
int main(int argc, const char **argv, const char **envp);

 This is a standard UNIX convention, but is not POSIX (at least, I can't
 find it).

  Okay so I've now stumbled on a copy of the ISO draft standard, 
dated about the middle of January 1999.  Thanks for the link,
I'll keep that in mind if I ever need the 'real thing'.

  I agree 100% const is not part of main in the standard.

However, I found that 
  int main(int argc, char **argv, char **envp);
is listed as a 'common extension' it appears that the ISO rule is
extensions which can not cause a valid ISO C program to break when
compiled in that environment are allowed by the standard.  (In
my opinion since main with envp isn't defined by the standard the 
programs that use that form of main are not ISO C programs even through
every other line may be ISO C ;)

c9x-draft:
#   J.5  Common extensions
#
#   [#1]  The  following  extensions  are  widely  used  in many
#   systems, but are not portable to all  implementations.   The
#   inclusion  of  any  extension  that  may  cause  a  strictly
#   conforming   program   to   become   invalid   rendersan
#   implementation  nonconforming.   Examples of such extensions
[...]
#   J.5.1  Environment arguments
#
#   [#1] In a hosted environment, the main function  receives  a
#   third  argument,  char  *envp[],  that  points  to  a  null-


  POSIX declares:
int getopt(int argc, char * const *argv, const char *optstring);

 More or less.

  However the GNU documentation 

Re: [vox-tech] writing free getopt, ran into a dilemma...

2002-03-31 Thread Micah Cowan

On Sat, 2002-03-30 at 04:45, [EMAIL PROTECTED] wrote:
   I often had find alot of interesting (to me) material while digging 
 around on things like this.  I would be fabulous if someone could
 point me at a online source for the ANSI C or ISO C standards.  It would
 be cool to be able to site a section for or against various theories.

I do this frequently on news:comp.lang.c - Great place to get your
theories/conceptions trounced :)

   (Well the technically official standard is something you have to pay 
 hundreds of dollars for, which is why it's not available everywhere
 and is part of the reason so many opinions about what it actually
 says exist... but some _through_ coverage would be nice).

I have an electronic copy.  You can download it for $26 (it was $18 when
I got it):

http://webstore.ansi.org/ansidocstore/product.asp?sku=ISO%2FIEC+9899%3A1999

 
 
 On Thu, Mar 28, 2002 at 09:13:19AM -0800, Mark K. Kim wrote:
  The one I tried to link statically on Windows one time said it was GPL,
  but according to Micah it's apparently LGPL with misdocumentation. :P
 
   readline is GPL, getopt is LGPL... maybe some maintainer got confused? 

getopt's license would seem to be debatable - the sourcefile itself
claims to be plain ol' GPL, though the accompanying, seperate license
file claims LGPL.

Micah

___
vox-tech mailing list
[EMAIL PROTECTED]
http://lists.lugod.org/mailman/listinfo/vox-tech



Re: [vox-tech] writing free getopt, ran into a dilemma...

2002-03-30 Thread msimons

On Thu, Mar 28, 2002 at 10:12:29AM -0800, Micah Cowan wrote:
 On Thu, 2002-03-28 at 00:35, Mark K. Kim wrote:
  I think I now understand why GNU shuffles argv[].  But I don't need this
  to be fully compatible with BSD's getopt; I just need it to behave in
  reasonable manner.  I'd like to hear some ideas and what you think the
  behavior should be and how it's better than others.

 Well, POSIX says that options should always be supplied before
 arguments, so that's why POSIX-conforming implementations don't need to
 permute the order in argv.  Intermixing options with arguments is a GNU
 extension,

  First off Micah is absolutely correct about POSIX and options.  Strict
POSIX stuff only accepts command options as the first bunch of options to 
a command the first non-option found stops parsing of options.  

  This is why if you type 'ls foo* -ltr' on a Solaris version of ls
you will get a standard ls format and then an error about 
'-ltr: file not found' but if you type the same thing on a Linux
system you get a long listing sorted reversely by time (youngest files
last).


 Intermixing options with arguments is a GNU
 extension, and GNU pulls some mildly dirty tricks to get it (such as
 permuting argv, despite the fact that it's elements are declared const).

Micah,

  I am slightly confused, it's elements are declared const, I've been
having a very hard time finding some site which will state something like
POSIX/ANSI C/ISO C require the following prototypes...


Here is what I believe the valid declarations to be (these from ANSI C):
  int main(void);  
  int main(int argc, const char **argv);

POSIX adds the following one additional main:
  int main(int argc, const char **argv, const char **envp);

POSIX declares:
  int getopt(int argc, char * const *argv, const char *optstring);

However the GNU documentation declares:
  int getopt(int argc, char **argv, const char *optstring);

  /* externs are optional, and *argv[] is interchangeable with **argv */


- If you think the declaration of main or getopt don't match any of the
  above could you give your version and some online reference for that
  version?


  If the declaration of main above is correct there is nothing to 
prevent someone reordering the elements in the main function's argv... 
which is what is passed into getopt by _almost_ every caller.
  It would seem the GNU people could just remove the const from their 
header so if POSIX actually _requires_ the const then people would be 
able to rightly complain it doesn't obey the POSIX standard out of 
the box... but the GNU version gives users at least two ways to get
POSIX compatible getopt at run time (POSIXLY_CORRECT and '+' prefix),
and in theory (not current practice) the coder could request POSIX 
compatibilty at compile time via '#define POSIX_SOURCE'.


  The one valid bug I see is that GNU getopt.h and getopt.c both use 
'char * const *argv' and that conflicts with the documentation 
of 'char **argv'.
___
vox-tech mailing list
[EMAIL PROTECTED]
http://lists.lugod.org/mailman/listinfo/vox-tech



Re: [vox-tech] writing free getopt, ran into a dilemma...

2002-03-30 Thread msimons

  I often had find alot of interesting (to me) material while digging 
around on things like this.  I would be fabulous if someone could
point me at a online source for the ANSI C or ISO C standards.  It would
be cool to be able to site a section for or against various theories.
  (Well the technically official standard is something you have to pay 
hundreds of dollars for, which is why it's not available everywhere
and is part of the reason so many opinions about what it actually
says exist... but some _through_ coverage would be nice).


On Thu, Mar 28, 2002 at 09:13:19AM -0800, Mark K. Kim wrote:
 The one I tried to link statically on Windows one time said it was GPL,
 but according to Micah it's apparently LGPL with misdocumentation. :P

  readline is GPL, getopt is LGPL... maybe some maintainer got confused? 


 The reason I'm writing my own getopt is because I want static linkage.

  ...and don't want to give your users the ability to revise getopt.  :)

 Anyway, some options I'm thinking about:

1. Get rid of optind altogether.
2. Shuffle argv[] like LGPL getopt.
3. Set optind to the beginning of the last set of non-option arguments.
4. Set optind to the beginning of the first non-option argument.

 I really don't want to shuffle argv[] (option #2)

  I personally prefer the reordering of argv, it makes the command line
more flexible and makes working with the non-options a breeze for the
program after the options are moved out of the way (the program just 
loops from optind to argc).

  If you do not intend to permute the array, then I recommend you abort
processing later options like POSIX 'requires' (explained in quote below).
There is also the middle option mentioned below which you might not
have implemented/thought of (this allows the application to be notified
about each non-option as it is encountered).

  Don't drop optind because it is required to tell which argv stopped
processing.  By incrementing optind a true POSIX application can 
force getopt to skip over arguments it doesn't know about.

  Realize both sets of people POSIX and GNU have good ideas, GNU is
just more flexible because they provide the true standard then on
top of that implement something that is more generally useful but
don't prevent either the application author or the application 
user from getting the true standard.  (The user doesn't even need 
to touch any code in already compiled application!  It's really 
amazing they went through the thought - effort involved.) 

http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_514.html#SEC524
# getopt has three ways to deal with options that follow
# non-options argv elements.
[...]
# + The default is to permute the contents of argv while scanning
#   it so that eventually all the non-options are at the end.
#   This allows options to be given in any order, even with
#   programs that were not written to expect this.
# + If the options argument string begins with a hyphen (`-'),
#   this is treated specially. It permits arguments that are not
#   options to be returned as if they were associated with option
#   character `\1'.
# + POSIX demands the following behavior: The first non-option
#   stops option processing. This mode is selected by either
#   setting the environment variable POSIXLY_CORRECT or beginning
#   the options argument string with a plus sign (`+').


 I can see how a non-shuffling getopt could be useful on systems 
 that won't let you shuffle argv[].

  Okay, this stems from the end of my post to Micah.  As far as I
can tell the only reason getopt shouldn't reorder the arguments
is because it's declaration says that the array will not be modified,
and getopt was spec'ed by the POSIX people as const because they
don't reorder.

  Anything that seems official that I have been able to find says
main has 'const char **argv', getopt has 'char * const *argv'

const char **argv --
  is an array of pointers to const strings.  the strings themselves may
  not be modified, however one can change the pointers in the array to
  point at different strings and can reorder the strings.

char * const *argv --
  is a const array of pointers to strings.  the strings themselves may
  be modified, however the array itself may not be changed.


  So if I didn't mess something up there, ANSI C, doesn't place a 
restriction on changing main's argv... getopt's prototype says it
will not but, for what it's worth, casting a const a non-const then 
changing the data there may not actually be a violation of the 
standard... see Dennis Ritchie's full post for the whole details but 
the kernel of that idea is below.

http://www.lysator.liu.se/c/dmr-on-noalias.html
#5. Add a constraint (or discussion or example) to assignment that
#   makes clear the illegality of assigning to an object whose actual
#   type is const-qualified, no matter what 

Re: [vox-tech] writing free getopt, ran into a dilemma...

2002-03-30 Thread Mark K. Kim

I tried using increment_optind() technique as Micah suggested, but I found
some technical limitation.  I couldn't find any way to do it without
allocating memory in heap, and I couldn't free it safely without breaking
compatibility.

After reading Mike's [very detailed] posts :), I decided permuting argv[]
is not a bad idea.  So I implemented getopt() using the permuting
technique.

I'd appreciate it if anybody could check it out and give me a feedback.
You can download the file from:

   http://www.cbreak.org/tmp/

I've implemented *EVERYTHING* :)  The - and the + and the : and the
:: and the POSIXLY_CORRECT, and the --.  At least, I *think* that's
everything.  Please let me know if you find any bugs, incompatibilities,
or anything else.

Thanks!

-Mark

--
Mark K. Kim
http://www.cbreak.org/
PGP key available upon request.


___
vox-tech mailing list
[EMAIL PROTECTED]
http://lists.lugod.org/mailman/listinfo/vox-tech



[vox-tech] writing free getopt, ran into a dilemma...

2002-03-28 Thread Mark K. Kim

Keywords: getopt, license issues, GPL, BSD, optind

Hey guys,

I mentioned some months ago about how I was using GPL's getopt library
in one of my company programs, and I was wondering about the GPL
distribution issues.[1]

Anyway, now I'm writing a software I want to release with BSD license,
but I also want the GNU getopt statically-linked.  Since I can't do that,
I decided to write my own GNU-compatible getopt library.  I know Micah
offered to do this if I wanted it badly enough, but I thought it'd be an
interesting challenge so I decided to try it myself.

The library is interestingly working really well.  I wrote a test program,
and I can't tell the difference between the GNU version and mine! :)  But
I've ran into a dilemma regarding how the library should behave, and I
thought I should get some feedback from this group of geniuses :)

The getopt library has the following parts:

   char* optarg; (the argument to an option)
   int optind;   (argv[optind] will be processed at next getopt() call)
   int opterr;   (if true, getopt() will print error on invalid option)
   int optopt;   (getopt() returns this on invalid option)

   int getopt(int argc, const char* argv[], const char* optstr);
 (the actual getopt() call)

I implemented everything.  optarg, opterr, and optopt work exactly
identical to GNU's getopt.  However, optind is a little different because
my library doesn't reshuffle argv[] like GNU's getopt.  That's okay with
me, but things get hairy if optstr doesn't have '-' as its first
character -- then the programmer is expected to search the remaining
argv[] starting with optind... but due to GNU getopt's flexible nature,
there could be unhandled entries in argv[] not only at the end but in the
middle, too (creating holes of unhandled optarg in argv[]).  So where
should optind point to by the time getopt  finishes processing all the
options and there are holes of unhandled optarg only plain strings
remain?  (That's a little long and confusing; I hope you understand all
that :)

I think I now understand why GNU shuffles argv[].  But I don't need this
to be fully compatible with BSD's getopt; I just need it to behave in
reasonable manner.  I'd like to hear some ideas and what you think the
behavior should be and how it's better than others.

Thanks!

-Mark

[1] - Interesting how that issue came up on Slashdot a couple days ago,
and the answers were pretty much what I got here :)

--
Mark K. Kim
http://www.cbreak.org/
PGP key available upon request.

___
vox-tech mailing list
[EMAIL PROTECTED]
http://lists.lugod.org/mailman/listinfo/vox-tech



Re: [vox-tech] writing free getopt, ran into a dilemma...

2002-03-28 Thread nbs

On Thu, Mar 28, 2002 at 12:35:05AM -0800, Mark K. Kim wrote:
 Keywords: getopt, license issues, GPL, BSD, optind
 
 Hey guys,
 
 I mentioned some months ago about how I was using GPL's getopt library
 in one of my company programs, and I was wondering about the GPL
 distribution issues.[1]

Woah... getopt library is GPL, not LGPL?

-bill!
___
vox-tech mailing list
[EMAIL PROTECTED]
http://lists.lugod.org/mailman/listinfo/vox-tech



Re: [vox-tech] writing free getopt, ran into a dilemma...

2002-03-28 Thread Ryan

The idea behind making libs GPL instead of LGPL is to give GPL programmers an 
advantage over commercial programmers.

I think

On Thursday 28 March 2002 12:51 am, you wrote:
 On Thu, Mar 28, 2002 at 12:35:05AM -0800, Mark K. Kim wrote:
  Keywords: getopt, license issues, GPL, BSD, optind
 
  Hey guys,
 
  I mentioned some months ago about how I was using GPL's getopt library
  in one of my company programs, and I was wondering about the GPL
  distribution issues.[1]

 Woah... getopt library is GPL, not LGPL?

 -bill!
 ___
 vox-tech mailing list
 [EMAIL PROTECTED]
 http://lists.lugod.org/mailman/listinfo/vox-tech
___
vox-tech mailing list
[EMAIL PROTECTED]
http://lists.lugod.org/mailman/listinfo/vox-tech



Re: [vox-tech] writing free getopt, ran into a dilemma...

2002-03-28 Thread Mark K. Kim

The one I tried to link statically on Windows one time said it was GPL,
but according to Micah it's apparently LGPL with misdocumentation. :P

The reason I'm writing my own getopt is because I want static linkage.
Anyway, some options I'm thinking about:

   1. Get rid of optind altogether.
   2. Shuffle argv[] like LGPL getopt.
   3. Set optind to the beginning of the last set of non-option arguments.
   4. Set optind to the beginning of the first non-option argument.

I really don't want to shuffle argv[] (option #2)  because I can see how a
non-shuffling getopt could be useful on systems that won't let you shuffle
argv[].  Options #3 and #4 are direct opposites of each other, and each
can be beneficial at different times.  While #3 seems to make more sense
to me, it's nothing you can't handle by using the - option in optstr.
And while #4 seems to make little sense, it can be useful if you're trying
to determine if there are any non-option arguments and throw an error,
which you can't do any other way that I can think of.

-Mark


On Thu, 28 Mar 2002, nbs wrote:

 On Thu, Mar 28, 2002 at 12:35:05AM -0800, Mark K. Kim wrote:
  Keywords: getopt, license issues, GPL, BSD, optind
 
  Hey guys,
 
  I mentioned some months ago about how I was using GPL's getopt library
  in one of my company programs, and I was wondering about the GPL
  distribution issues.[1]

 Woah... getopt library is GPL, not LGPL?

 -bill!
 ___
 vox-tech mailing list
 [EMAIL PROTECTED]
 http://lists.lugod.org/mailman/listinfo/vox-tech


--
Mark K. Kim
http://www.cbreak.org/
PGP key available upon request.

___
vox-tech mailing list
[EMAIL PROTECTED]
http://lists.lugod.org/mailman/listinfo/vox-tech



Re: [vox-tech] writing free getopt, ran into a dilemma...

2002-03-28 Thread nbs

On Thu, Mar 28, 2002 at 09:13:19AM -0800, Mark K. Kim wrote:
 The one I tried to link statically on Windows one time said it was GPL,
 but according to Micah it's apparently LGPL with misdocumentation. :P
 
 The reason I'm writing my own getopt is because I want static linkage.
 Anyway, some options I'm thinking about:

I don't have the LGPL in front of me, but I believe it says something
to the affect of:

  * if you statically-link, you must also provide a version of the binary
that will dynamically-link, if the user wishes to do so

-bill!
___
vox-tech mailing list
[EMAIL PROTECTED]
http://lists.lugod.org/mailman/listinfo/vox-tech



Re: [vox-tech] writing free getopt, ran into a dilemma...

2002-03-28 Thread Micah Cowan

On Thu, 2002-03-28 at 00:35, Mark K. Kim wrote:
 Keywords: getopt, license issues, GPL, BSD, optind

 I implemented everything.  optarg, opterr, and optopt work exactly
 identical to GNU's getopt.  However, optind is a little different because
 my library doesn't reshuffle argv[] like GNU's getopt.  That's okay with
 me, but things get hairy if optstr doesn't have '-' as its first
 character -- then the programmer is expected to search the remaining
 argv[] starting with optind... but due to GNU getopt's flexible nature,
 there could be unhandled entries in argv[] not only at the end but in the
 middle, too (creating holes of unhandled optarg in argv[]).  So where
 should optind point to by the time getopt  finishes processing all the
 options and there are holes of unhandled optarg only plain strings
 remain?  (That's a little long and confusing; I hope you understand all
 that :)
 
 I think I now understand why GNU shuffles argv[].  But I don't need this
 to be fully compatible with BSD's getopt; I just need it to behave in
 reasonable manner.  I'd like to hear some ideas and what you think the
 behavior should be and how it's better than others.

Well, POSIX says that options should always be supplied before
arguments, so that's why POSIX-conforming implementations don't need to
permute the order in argv.  Intermixing options with arguments is a GNU
extension, and GNU pulls some mildly dirty tricks to get it (such as
permuting argv, despite the fact that it's elements are declared const).

Permuting is probably the easiest way to go; but another alternative
would be to create another function, increment_optind(), instead of
doing ++optind.  This function could then automatically skip options.

Oh, but you mentioned it doesn't currently even handle the middle
options (which is what I thought the point was for your getopt()?).  In
that case, if you hate permuting argv, you could copy it into a
seperate, temporary string, and permute that instead.  You'd still need
increment_optind()---or you could break getopt()'s parameter list by
passing back the allocated string (make sure it gets freed
somewhere...).

If you email me the code, I'd be happy to comment on it (comp.lang.c is
a hobby of mine, though one I haven't gotten around to lately).  I won't
get to it this weekend, though, since I'll be out of town (and away from
email).

Micah

___
vox-tech mailing list
[EMAIL PROTECTED]
http://lists.lugod.org/mailman/listinfo/vox-tech



Re: [vox-tech] writing free getopt, ran into a dilemma...

2002-03-28 Thread Mark K. Kim

On Thu, 28 Mar 2002, nbs wrote:

 I don't have the LGPL in front of me, but I believe it says something
 to the affect of:

   * if you statically-link, you must also provide a version of the binary
 that will dynamically-link, if the user wishes to do so

Really?  What if the software were commercial (used in a commercial
product)?  I thought the whole point of all this LGPL discussion on SDL
list way back when was because you couldn't statically-link at all if you
wanted to keep the source closed...?

-Mark

--
Mark K. Kim
http://www.cbreak.org/
PGP key available upon request.

___
vox-tech mailing list
[EMAIL PROTECTED]
http://lists.lugod.org/mailman/listinfo/vox-tech



Re: [vox-tech] writing free getopt, ran into a dilemma...

2002-03-28 Thread Mark K. Kim

On 28 Mar 2002, Micah Cowan wrote:

 Permuting is probably the easiest way to go; but another alternative
 would be to create another function, increment_optind(), instead of
 doing ++optind.  This function could then automatically skip options.

increment_optind() sounds excellent!  Thanks!

 Oh, but you mentioned it doesn't currently even handle the middle
 options (which is what I thought the point was for your getopt()?).

I'm not sure what you mean by middle options...  It currently behaves
exactly like GNU getopt as far as required arguments (as in o:) and
non-option arguments (as in -) except it doesn't permute[1] argv and
optind doesn't work like GNU getopt.  I don't use optional arguments
(which I believe is a GNU extension) but I'll implement it if I knew how
to use it :)  And... I don't think there's anything else, is there???

Oh, my code does handle -- :)

 You'd still need
 increment_optind()---or you could break getopt()'s parameter list by
 passing back the allocated string (make sure it gets freed
 somewhere...).

My original version of getopt allocated an array that is the same size as
argc+1, but I realized freeing it becomes a problem (don't wanna use
atexit(), and wanna keep compatibility so don't wanna use a cleanup
function call).  I modified the program to not use allocation at all.

 If you email me the code, I'd be happy to comment on it (comp.lang.c is
 a hobby of mine, though one I haven't gotten around to lately).  I won't
 get to it this weekend, though, since I'll be out of town (and away from
 email).

I'm gonna work on the code some more and send you a copy for a review.
Maybe I'll just put up a copy on my website.  Thanks, Micah!

-Mark

[1] - Thank you for bringing up the proper vocabulary :)

--
Mark K. Kim
http://www.cbreak.org/
PGP key available upon request.

___
vox-tech mailing list
[EMAIL PROTECTED]
http://lists.lugod.org/mailman/listinfo/vox-tech