Skip to content

Commit

Permalink
The Independent JPEG Group's JPEG software v1
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas G. Lane authored and dcommander committed Jul 29, 2015
0 parents commit 2cbeb8a
Show file tree
Hide file tree
Showing 53 changed files with 13,965 additions and 0 deletions.
391 changes: 391 additions & 0 deletions README

Large diffs are not rendered by default.

477 changes: 477 additions & 0 deletions ansi2knr.c

Large diffs are not rendered by default.

1,106 changes: 1,106 additions & 0 deletions architecture

Large diffs are not rendered by default.

99 changes: 99 additions & 0 deletions codingrules
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@

JPEG SYSTEM CODING RULES 27-SEP-91

Since numerous people will be contributing code and bug fixes, it's important
to establish a common coding style. The goal of using similar coding styles
is much more important than the details of just what that style is.

I suggest we follow the recommendations of "Recommended C Style and Coding
Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and
Brader). I have placed a copy of this document in the jpeg FTP archive (see
jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl).

Unless someone has a real strong objection, let's do block comments thusly:

/*
* Block comments in this style.
*/

and indent statements in K&R style, e.g.,

if (test) {
then-part;
} else {
else-part;
}

I suggest that multi-word names be written in the style multi_word_name
rather than multiWordName, but I am open to argument on this.


I would like to use function prototypes everywhere, and rely on automatic
source code transformation to feed non-ANSI C compilers. The best tool
I have so far found for this is 'ansi2knr.c', which is part of Ghostscript.
ansi2knr is not very bright, so it imposes a format requirement on function
declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions
should be written in the following style:

static int *
function_name (int a, char *b)
{
code...
}

ansi2knr won't help with method declarations (function pointers in structs).
I suggest we use a macro to declare method pointers, something like this:

#ifdef PROTO
#define METHOD(type,methodname,arglist) type (*methodname) arglist
#else
#define METHOD(type,methodname,arglist) type (*methodname) ()
#endif

which is used like this:

struct function_pointers {
METHOD(void, init_entropy_encoder, (functptrs fptrs, jparms *jp));
METHOD(void, term_entropy_encoder, (void));
};

Note the set of parentheses surrounding the parameter list.

A similar solution is used for external function declarations (see the PP
macro in jpegdata.h).

If the code is to work on non-ANSI compilers, you cannot rely on a prototype
declaration to coerce actual parameters into the right types. Therefore, use
explicit casts on actual parameters whenever the actual parameter type is not
identical to the formal parameter. Beware of implicit conversions to "int".

It seems there are some non-ANSI compilers in which the sizeof() operator
is defined to return int, while size_t is defined as long. Needless to say,
this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(),
so that the result is guaranteed to be of type size_t.


We can expect that the JPEG compressor and decompressor will be incorporated
into larger programs. Therefore, the following rules are important:

1. Avoid direct use of any file I/O, "malloc", error report printouts, etc;
pass these through the common routines provided.

2. Assume that the JPEG code may be invoked more than once per program run;
therefore, do not rely on static initialization of variables, and be careful
to release all allocated storage at the end of processing.

3. Minimize global namespace pollution. Functions should be declared static
wherever possible. (Note that our method-based calling conventions help this
a lot: in many modules only the method-selector function will ever need to be
called directly, so only that function need be externally visible.) All
global function names should begin with "j", and should be unique in the first
six characters for portability reasons.
Don't use global variables at all; anything that must be used in another
module should be put into parameters (there'll be some large structs passed
around for this purpose).

4. Source file names should also begin with "j"; remember to keep them to
eight characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers.
Do not put code for both compression and decompression into the same source
file.
276 changes: 276 additions & 0 deletions egetopt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
/*
* egetopt.c -- Extended 'getopt'.
*
* A while back, a public-domain version of getopt() was posted to the
* net. A bit later, a gentleman by the name of Keith Bostic made some
* enhancements and reposted it.
*
* In recent weeks (i.e., early-to-mid 1988) there's been some
* heated discussion in comp.lang.c about the merits and drawbacks
* of getopt(), especially with regard to its handling of '?'.
*
* In light of this, I have taken Mr. Bostic's public-domain getopt()
* and have made some changes that I hope will be considered to be
* improvements. I call this routine 'egetopt' ("Extended getopt").
* The default behavior of this routine is the same as that of getopt(),
* but it has some optional features that make it more useful. These
* options are controlled by the settings of some global variables.
* By not setting any of these extra global variables, you will have
* the same functionality as getopt(), which should satisfy those
* purists who believe getopt() is perfect and can never be improved.
* If, on the other hand, you are someone who isn't satisfied with the
* status quo, egetopt() may very well give you the added capabilities
* you want.
*
* Look at the enclosed README file for a description of egetopt()'s
* new features.
*
* The code was originally posted to the net as getopt.c by ...
*
* Keith Bostic
* ARPA: keith@seismo
* UUCP: seismo!keith
*
* Current version: added enhancements and comments, reformatted code.
*
* Lloyd Zusman
* Master Byte Software
* Los Gatos, California
* Internet: [email protected]
* UUCP: ...!ames!fxgrp!ljz
*
* May, 1988
*/

/*
* If you want, include stdio.h or something where EOF and NULL are defined.
* However, egetopt() is written so as not to need stdio.h, which should
* make it significantly smaller on some systems.
*/

#ifndef EOF
# define EOF (-1)
#endif /* ! EOF */

#ifndef NULL
# define NULL (char *)0
#endif /* ! NULL */

/*
* None of these constants are referenced in the executable portion of
* the code ... their sole purpose is to initialize global variables.
*/
#define BADCH (int)'?'
#define NEEDSEP (int)':'
#define MAYBESEP (int)'\0'
#define ERRFD 2
#define EMSG ""
#define START "-"

/*
* Here are all the pertinent global variables.
*/
int opterr = 1; /* if true, output error message */
int optind = 1; /* index into parent argv vector */
int optopt; /* character checked for validity */
int optbad = BADCH; /* character returned on error */
int optchar = 0; /* character that begins returned option */
int optneed = NEEDSEP; /* flag for mandatory argument */
int optmaybe = MAYBESEP;/* flag for optional argument */
int opterrfd = ERRFD; /* file descriptor for error text */
char *optarg; /* argument associated with option */
char *optstart = START; /* list of characters that start options */


/*
* Macros.
*/

/*
* Conditionally print out an error message and return (depends on the
* setting of 'opterr' and 'opterrfd'). Note that this version of
* TELL() doesn't require the existence of stdio.h.
*/
#define TELL(S) { \
if (opterr && opterrfd >= 0) { \
char option = optopt; \
write(opterrfd, *nargv, strlen(*nargv)); \
write(opterrfd, (S), strlen(S)); \
write(opterrfd, &option, 1); \
write(opterrfd, "\n", 1); \
} \
return (optbad); \
}

/*
* This works similarly to index() and strchr(). I include it so that you
* don't need to be concerned as to which one your system has.
*/
static char *
_sindex(string, ch)
char *string;
int ch;
{
if (string != NULL) {
for (; *string != '\0'; ++string) {
if (*string == (char)ch) {
return (string);
}
}
}

return (NULL);
}

/*
* Here it is:
*/
int
egetopt(nargc, nargv, ostr)
int nargc;
char **nargv;
char *ostr;
{
static char *place = EMSG; /* option letter processing */
register char *oli; /* option letter list index */
register char *osi = NULL; /* option start list index */

if (nargv == (char **)NULL) {
return (EOF);
}

if (nargc <= optind || nargv[optind] == NULL) {
return (EOF);
}

if (place == NULL) {
place = EMSG;
}

/*
* Update scanning pointer.
*/
if (*place == '\0') {
place = nargv[optind];
if (place == NULL) {
return (EOF);
}
osi = _sindex(optstart, *place);
if (osi != NULL) {
optchar = (int)*osi;
}
if (optind >= nargc || osi == NULL || *++place == '\0') {
return (EOF);
}

/*
* Two adjacent, identical flag characters were found.
* This takes care of "--", for example.
*/
if (*place == place[-1]) {
++optind;
return (EOF);
}
}

/*
* If the option is a separator or the option isn't in the list,
* we've got an error.
*/
optopt = (int)*place++;
oli = _sindex(ostr, optopt);
if (optopt == optneed || optopt == optmaybe || oli == NULL) {
/*
* If we're at the end of the current argument, bump the
* argument index.
*/
if (*place == '\0') {
++optind;
}
TELL(": illegal option -- "); /* byebye */
}

/*
* If there is no argument indicator, then we don't even try to
* return an argument.
*/
++oli;
if (*oli == '\0' || (*oli != optneed && *oli != optmaybe)) {
/*
* If we're at the end of the current argument, bump the
* argument index.
*/
if (*place == '\0') {
++optind;
}
optarg = NULL;
}
/*
* If we're here, there's an argument indicator. It's handled
* differently depending on whether it's a mandatory or an
* optional argument.
*/
else {
/*
* If there's no white space, use the rest of the
* string as the argument. In this case, it doesn't
* matter if the argument is mandatory or optional.
*/
if (*place != '\0') {
optarg = place;
}
/*
* If we're here, there's whitespace after the option.
*
* Is it a mandatory argument? If so, return the
* next command-line argument if there is one.
*/
else if (*oli == optneed) {
/*
* If we're at the end of the argument list, there
* isn't an argument and hence we have an error.
* Otherwise, make 'optarg' point to the argument.
*/
if (nargc <= ++optind) {
place = EMSG;
TELL(": option requires an argument -- ");
}
else {
optarg = nargv[optind];
}
}
/*
* If we're here it must have been an optional argument.
*/
else {
if (nargc <= ++optind) {
place = EMSG;
optarg = NULL;
}
else {
optarg = nargv[optind];
if (optarg == NULL) {
place = EMSG;
}
/*
* If the next item begins with a flag
* character, we treat it like a new
* argument. This is accomplished by
* decrementing 'optind' and returning
* a null argument.
*/
else if (_sindex(optstart, *optarg) != NULL) {
--optind;
optarg = NULL;
}
}
}
place = EMSG;
++optind;
}

/*
* Return option letter.
*/
return (optopt);
}
Loading

0 comments on commit 2cbeb8a

Please sign in to comment.