Mercurial > hg > xemacs-beta
annotate lib-src/mmencode.c @ 2367:ecf1ebac70d8
[xemacs-hg @ 2004-11-04 23:05:23 by ben]
commit mega-patch
configure.in: Turn off -Winline and -Wchar-subscripts.
Use the right set of cflags when compiling modules.
Rewrite ldap configuration to separate the inclusion of lber
(needed in recent Cygwin) from the basic checks for the
needed libraries.
add a function for MAKE_JUNK_C; initially code was added to
generate xemacs.def using this, but it will need to be rewritten.
add an rm -f for junk.c to avoid weird Cygwin bug with cp -f onto
an existing file.
Sort list of auto-detected functions and eliminate unused checks for
stpcpy, setlocale and getwd.
Add autodetection of Cygwin scanf problems
BETA: Rewrite section on configure to indicate what flags are important
and what not.
digest-doc.c, make-dump-id.c, profile.c, sorted-doc.c: Add proper decls for main().
make-msgfile.c: Document that this is old junk.
Move proposal to text.c.
make-msgfile.lex: Move proposal to text.c.
make-mswin-unicode.pl: Convert error-generating code so that the entire message will
be seen as a single unrecognized token.
mule/mule-ccl.el: Update docs.
lispref/mule.texi: Update CCL docs.
ldap/eldap.c: Mule-ize.
Use EXTERNAL_LIST_LOOP_2 instead of deleted EXTERNAL_LIST_LOOP.
* XEmacs 21.5.18 "chestnut" is released.
---------------------------------------------------------------
MULE-RELATED WORK:
---------------------------------------------------------------
---------------------------
byte-char conversion
---------------------------
buffer.c, buffer.h, insdel.c, text.c: Port FSF algorithm for byte-char conversion, replacing broken
previous version. Track the char position of the gap. Add
functions to do char-byte conversion downwards as well as upwards.
Move comments about algorithm workings to internals manual.
---------------------------
work on types
---------------------------
alloc.c, console-x-impl.h, dump-data.c, dump-data.h, dumper.c, dialog-msw.c, dired-msw.c, doc.c, editfns.c, esd.c, event-gtk.h, event-msw.c, events.c, file-coding.c, file-coding.h, fns.c, glyphs-eimage.c, glyphs-gtk.c, glyphs-msw.c, glyphs-shared.c, glyphs-x.c, glyphs.c, glyphs.h, gui.c, hpplay.c, imgproc.c, intl-win32.c, lrecord.h, lstream.c, keymap.c, lisp.h, libsst.c, linuxplay.c, miscplay.c, miscplay.h, mule-coding.c, nas.c, nt.c, ntheap.c, ntplay.c, objects-msw.c, objects-tty.c, objects-x.c, print.c, process-nt.c, process.c, redisplay.h, select-common.h, select-gtk.c, select-x.c, sgiplay.c, sound.c, sound.h, sunplay.c, sysfile.h, sysdep.c, syswindows.h, text.c, unexnt.c, win32.c, xgccache.c: Further work on types. This creates a full set of types for all
the basic semantics of `char' that I have so far identified, so that
its semantics can always be identified for the purposes of proper
Mule-safe code, and the raw use of `char' always avoided.
(1) More type renaming, for consistency of naming.
Char_ASCII -> Ascbyte
UChar_ASCII -> UAscbyte
Char_Binary -> CBinbyte
UChar_Binary -> Binbyte
SChar_Binary -> SBinbyte
(2) Introduce Rawbyte, CRawbyte, Boolbyte, Chbyte, UChbyte, and
Bitbyte and use them.
(3) New types Itext, Wexttext and Textcount for separating out
the concepts of bytes and textual units (different under UTF-16
and UTF-32, which are potential internal encodings).
(4) qxestr*_c -> qxestr*_ascii.
lisp.h: New; goes with other qxe() functions. #### Maybe goes in a
different section.
lisp.h: Group generic int-type defs together with EMACS_INT defs.
lisp.h: * lisp.h (WEXTTEXT_IS_WIDE)
New defns.
lisp.h: New type to replace places where int occurs as a boolean.
It's signed because occasionally people may want to use -1 as
an error value, and because unsigned ints are viral -- see comments
in the internals manual against using them.
dynarr.c: int -> Bytecount.
---------------------------
Mule-izing
---------------------------
device-x.c: Partially Mule-ize.
dumper.c, dumper.h: Mule-ize. Use Rawbyte. Use stderr_out not printf. Use wext_*().
sysdep.c, syswindows.h, text.c: New Wexttext API for manipulation of external text that may be
Unicode (e.g. startup code under Windows).
emacs.c: Mule-ize. Properly deal with argv in external encoding.
Use wext_*() and Wexttext. Use Rawbyte.
#if 0 some old junk on SCO that is unlikely to be correct.
Rewrite allocation code in run-temacs.
emacs.c, symsinit.h, win32.c: Rename win32 init function and call it even earlier, to
initialize mswindows_9x_p even earlier, for use in startup code
(XEUNICODE_P).
process.c: Use _wenviron not environ under Windows, to get Unicode environment
variables.
event-Xt.c: Mule-ize drag-n-drop related stuff.
dragdrop.c, dragdrop.h, frame-x.c: Mule-ize.
text.h: Add some more stand-in defines for particular kinds of conversion;
use in Mule-ization work in frame-x.c etc.
---------------------------
Freshening
---------------------------
intl-auto-encap-win32.c, intl-auto-encap-win32.h: Regenerate.
---------------------------
Unicode-work
---------------------------
intl-win32.c, syswindows.h: Factor out common options to MultiByteToWideChar and
WideCharToMultiByte. Add convert_unicode_to_multibyte_malloc()
and convert_unicode_to_multibyte_dynarr() and use. Add stuff for
alloca() conversion of multibyte/unicode.
alloc.c: Use dfc_external_data_len() in case of unicode coding system.
alloc.c, mule-charset.c: Don't zero out and reinit charset Unicode tables. This fucks up
dump-time loading. Anyway, either we load them at dump time or
run time, never both.
unicode.c: Dump the blank tables as well.
---------------------------------------------------------------
DOCUMENTATION, MOSTLY MULE-RELATED:
---------------------------------------------------------------
EmacsFrame.c, emodules.c, event-Xt.c, fileio.c, input-method-xlib.c, mule-wnnfns.c, redisplay-gtk.c, redisplay-tty.c, redisplay-x.c, regex.c, sysdep.c: Add comment about Mule work needed.
text.h: Add more documentation describing why DFC routines were not written
to return their value. Add some other DFC documentation.
console-msw.c, console-msw.h: Add pointer to docs in win32.c.
emacs.c: Add comments on sources of doc info.
text.c, charset.h, unicode.c, intl-win32.c, intl-encap-win32.c, text.h, file-coding.c, mule-coding.c: Collect background comments and related to text matters and
internationalization, and proposals for work to be done, in text.c
or Internals manual, stuff related to specific textual API's in
text.h, and stuff related to internal implementation of Unicode
conversion in unicode.c. Put lots of pointers to the comments to
make them easier to find.
s/mingw32.h, s/win32-common.h, s/win32-native.h, s/windowsnt.h, win32.c: Add bunches of new documentation on the different kinds of
builds and environments under Windows and how they work.
Collect this info in win32.c. Add pointers to these docs in
the relevant s/* files.
emacs.c: Document places with long comments.
Remove comment about exiting, move to internals manual, put
in pointer.
event-stream.c: Move docs about event queues and focus to internals manual, put
in pointer.
events.h: Move docs about event stream callbacks to internals manual, put
in pointer.
profile.c, redisplay.c, signal.c: Move documentation to the Internals manual.
process-nt.c: Add pointer to comment in win32-native.el.
lisp.h: Add comments about some comment conventions.
lisp.h: Add comment about the second argument.
device-msw.c, redisplay-msw.c: @@#### comments are out-of-date.
---------------------------------------------------------------
PDUMP WORK (MOTIVATED BY UNICODE CHANGES)
---------------------------------------------------------------
alloc.c, buffer.c, bytecode.c, console-impl.h, console.c, device.c, dumper.c, lrecord.h, elhash.c, emodules.h, events.c, extents.c, frame.c, glyphs.c, glyphs.h, mule-charset.c, mule-coding.c, objects.c, profile.c, rangetab.c, redisplay.c, specifier.c, specifier.h, window.c, lstream.c, file-coding.h, file-coding.c: PDUMP:
Properly implement dump_add_root_block(), which never worked before,
and is necessary for dumping Unicode tables.
Pdump name changes for accuracy:
XD_STRUCT_PTR -> XD_BLOCK_PTR.
XD_STRUCT_ARRAY -> XD_BLOCK_ARRAY.
XD_C_STRING -> XD_ASCII_STRING.
*_structure_* -> *_block_*.
lrecord.h: some comments added about
dump_add_root_block() vs dump_add_root_block_ptr().
extents.c: remove incorrect comment about pdump problems with gap array.
---------------------------------------------------------------
ALLOCATION
---------------------------------------------------------------
abbrev.c, alloc.c, bytecode.c, casefiddle.c, device-msw.c, device-x.c, dired-msw.c, doc.c, doprnt.c, dragdrop.c, editfns.c, emodules.c, file-coding.c, fileio.c, filelock.c, fns.c, glyphs-eimage.c, glyphs-gtk.c, glyphs-msw.c, glyphs-x.c, gui-msw.c, gui-x.c, imgproc.c, intl-win32.c, lread.c, menubar-gtk.c, menubar.c, nt.c, objects-msw.c, objects-x.c, print.c, process-nt.c, process-unix.c, process.c, realpath.c, redisplay.c, search.c, select-common.c, symbols.c, sysdep.c, syswindows.h, text.c, text.h, ui-byhand.c: New macros {alloca,xnew}_{itext,{i,ext,raw,bin,asc}bytes} for
more convenient allocation of these commonly requested items.
Modify functions to use alloca_ibytes, alloca_array, alloca_extbytes,
xnew_ibytes, etc. also XREALLOC_ARRAY, xnew.
alloc.c: Rewrite the allocation functions to factor out repeated code.
Add assertions for freeing dumped data.
lisp.h: Moved down and consolidated with other allocation stuff.
lisp.h, dynarr.c: New functions for allocation that's very efficient when mostly in
LIFO order.
lisp.h, text.c, text.h: Factor out some stuff for general use by alloca()-conversion funs.
text.h, lisp.h: Fill out convenience routines for allocating various kinds of
bytes and put them in lisp.h. Use them in place of xmalloc(),
ALLOCA().
text.h: Fill out the convenience functions so the _MALLOC() kinds match
the alloca() kinds.
---------------------------------------------------------------
ERROR-CHECKING
---------------------------------------------------------------
text.h: Create ASSERT_ASCTEXT_ASCII() and ASSERT_ASCTEXT_ASCII_LEN()
from similar Eistring checkers and change the Eistring checkers to
use them instead.
---------------------------------------------------------------
MACROS IN LISP.H
---------------------------------------------------------------
lisp.h: Redo GCPRO declarations. Create a "base" set of functions that can
be used to generate any kind of gcpro sets -- regular, ngcpro,
nngcpro, private ones used in GC_EXTERNAL_LIST_LOOP_2.
buffer.c, callint.c, chartab.c, console-msw.c, device-x.c, dialog-msw.c, dired.c, extents.c, ui-gtk.c, rangetab.c, nt.c, mule-coding.c, minibuf.c, menubar-msw.c, menubar.c, menubar-gtk.c, lread.c, lisp.h, gutter.c, glyphs.c, glyphs-widget.c, fns.c, fileio.c, file-coding.c, specifier.c: Eliminate EXTERNAL_LIST_LOOP, which does not check for circularities.
Use EXTERNAL_LIST_LOOP_2 instead or EXTERNAL_LIST_LOOP_3
or EXTERNAL_PROPERTY_LIST_LOOP_3 or GC_EXTERNAL_LIST_LOOP_2
(new macro). Removed/redid comments on EXTERNAL_LIST_LOOP.
---------------------------------------------------------------
SPACING FIXES
---------------------------------------------------------------
callint.c, hftctl.c, number-gmp.c, process-unix.c: Spacing fixes.
---------------------------------------------------------------
FIX FOR GEOMETRY PROBLEM IN FIRST FRAME
---------------------------------------------------------------
unicode.c: Add workaround for newlib bug in sscanf() [should be fixed by
release 1.5.12 of Cygwin].
toolbar.c: bug fix for problem of initial frame being 77 chars wide on Windows.
will be overridden by my other ws.
---------------------------------------------------------------
FIX FOR LEAKING PROCESS HANDLES:
---------------------------------------------------------------
process-nt.c: Fixes for leaking handles. Inspired by work done by Adrian Aichner
<adrian@xemacs.org>.
---------------------------------------------------------------
FIX FOR CYGWIN BUG (Unicode-related):
---------------------------------------------------------------
unicode.c: Add workaround for newlib bug in sscanf() [should be fixed by
release 1.5.12 of Cygwin].
---------------------------------------------------------------
WARNING FIXES:
---------------------------------------------------------------
console-stream.c: `reinit' is unused.
compiler.h, event-msw.c, frame-msw.c, intl-encap-win32.c, text.h: Add stuff to deal with ANSI-aliasing warnings I got.
regex.c: Gather includes together to avoid warning.
---------------------------------------------------------------
CHANGES TO INITIALIZATION ROUTINES:
---------------------------------------------------------------
buffer.c, emacs.c, console.c, debug.c, device-x.c, device.c, dragdrop.c, emodules.c, eval.c, event-Xt.c, event-gtk.c, event-msw.c, event-stream.c, event-tty.c, events.c, extents.c, faces.c, file-coding.c, fileio.c, font-lock.c, frame-msw.c, glyphs-widget.c, glyphs.c, gui-x.c, insdel.c, lread.c, lstream.c, menubar-gtk.c, menubar-x.c, minibuf.c, mule-wnnfns.c, objects-msw.c, objects.c, print.c, scrollbar-x.c, search.c, select-x.c, text.c, undo.c, unicode.c, window.c, symsinit.h: Call reinit_*() functions directly from emacs.c, for clarity.
Factor out some redundant init code. Move disallowed stuff
that had crept into vars_of_glyphs() into complex_vars_of_glyphs().
Call init_eval_semi_early() from eval.c not in the middle of
vars_of_() in emacs.c since there should be no order dependency
in the latter calls.
---------------------------------------------------------------
ARMAGEDDON:
---------------------------------------------------------------
alloc.c, emacs.c, lisp.h, print.c: Rename inhibit_non_essential_printing_operations to
inhibit_non_essential_conversion_operations.
text.c: Assert on !inhibit_non_essential_conversion_operations.
console-msw.c, print.c: Don't do conversion in SetConsoleTitle or FindWindow to avoid
problems during armageddon. Put #errors for NON_ASCII_INTERNAL_FORMAT
in places where problems would arise.
---------------------------------------------------------------
CHANGES TO THE BUILD PROCEDURE:
---------------------------------------------------------------
config.h.in, s/cxux.h, s/usg5-4-2.h, m/powerpc.h: Add comment about correct ordering of this file.
Rearrange everything to follow this -- put all #undefs together
and before the s&m files. Add undefs for HAVE_ALLOCA, C_ALLOCA,
BROKEN_ALLOCA_IN_FUNCTION_CALLS, STACK_DIRECTION. Remove unused
HAVE_STPCPY, HAVE_GETWD, HAVE_SETLOCALE.
m/gec63.h: Deleted; totally broken, not used at all, not in FSF.
m/7300.h, m/acorn.h, m/alliant-2800.h, m/alliant.h, m/altos.h, m/amdahl.h, m/apollo.h, m/att3b.h, m/aviion.h, m/celerity.h, m/clipper.h, m/cnvrgnt.h, m/convex.h, m/cydra5.h, m/delta.h, m/delta88k.h, m/dpx2.h, m/elxsi.h, m/ews4800r.h, m/gould.h, m/hp300bsd.h, m/hp800.h, m/hp9000s300.h, m/i860.h, m/ibmps2-aix.h, m/ibmrs6000.h, m/ibmrt-aix.h, m/ibmrt.h, m/intel386.h, m/iris4d.h, m/iris5d.h, m/iris6d.h, m/irist.h, m/isi-ov.h, m/luna88k.h, m/m68k.h, m/masscomp.h, m/mg1.h, m/mips-nec.h, m/mips-siemens.h, m/mips.h, m/news.h, m/nh3000.h, m/nh4000.h, m/ns32000.h, m/orion105.h, m/pfa50.h, m/plexus.h, m/pmax.h, m/powerpc.h, m/pyrmips.h, m/sequent-ptx.h, m/sequent.h, m/sgi-challenge.h, m/symmetry.h, m/tad68k.h, m/tahoe.h, m/targon31.h, m/tekxd88.h, m/template.h, m/tower32.h, m/tower32v3.h, m/ustation.h, m/vax.h, m/wicat.h, m/xps100.h: Delete C_ALLOCA, HAVE_ALLOCA, STACK_DIRECTION,
BROKEN_ALLOCA_IN_FUNCTION_CALLS. All of this is auto-detected.
When in doubt, I followed recent FSF sources, which also have
these things deleted.
| author | ben |
|---|---|
| date | Thu, 04 Nov 2004 23:08:28 +0000 |
| parents | b39c14581166 |
| children | 49316578f12d |
| rev | line source |
|---|---|
| 428 | 1 /* |
| 2 Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore) | |
| 3 | |
| 4 Permission to use, copy, modify, and distribute this material | |
| 5 for any purpose and without fee is hereby granted, provided | |
| 6 that the above copyright notice and this permission notice | |
| 7 appear in all copies, and that the name of Bellcore not be | |
| 8 used in advertising or publicity pertaining to this | |
| 9 material without the specific, prior written permission | |
| 10 of an authorized representative of Bellcore. BELLCORE | |
| 11 MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY | |
| 12 OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS", | |
| 13 WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. | |
| 14 */ | |
| 15 | |
| 16 #define NEWLINE_CHAR '\n' | |
| 17 #include <stdlib.h> | |
| 18 #include <stdio.h> | |
| 19 #include <ctype.h> | |
| 20 #include <string.h> | |
| 430 | 21 #include <errno.h> |
| 428 | 22 |
| 23 static void | |
| 24 output64chunk(int c1, int c2, int c3, int pads, FILE *outfile); | |
| 25 | |
| 26 static signed char basis_64[] = | |
| 27 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
| 28 | |
| 29 static signed char index_64[128] = { | |
| 30 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | |
| 31 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | |
| 32 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, | |
| 33 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, | |
| 34 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, | |
| 35 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, | |
| 36 -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, | |
| 37 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 | |
| 38 }; | |
| 39 | |
| 40 #define char64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) | |
| 41 | |
| 42 /* | |
| 43 char64(c) | |
| 44 char c; | |
| 45 { | |
| 46 char *s = (char *) strchr(basis_64, c); | |
| 47 if (s) return(s-basis_64); | |
| 48 return(-1); | |
| 49 } | |
| 50 */ | |
| 51 | |
| 52 /* the following gets a character, but fakes it properly into two chars if there's a newline character */ | |
| 53 static int InNewline=0; | |
| 54 | |
| 55 static int | |
| 56 nextcharin (FILE *infile, int PortableNewlines) | |
| 57 { | |
| 58 int c; | |
| 59 | |
| 60 #ifndef NEWLINE_CHAR | |
| 61 return(getc(infile)); | |
| 62 #else | |
| 63 if (!PortableNewlines) return(getc(infile)); | |
| 64 if (InNewline) { | |
| 65 InNewline = 0; | |
| 66 return(10); /* LF */ | |
| 67 } | |
| 68 c = getc(infile); | |
| 69 if (c == NEWLINE_CHAR) { | |
| 70 InNewline = 1; | |
| 71 return(13); /* CR */ | |
| 72 } | |
| 73 return(c); | |
| 74 #endif | |
| 75 } | |
| 76 | |
| 77 static void | |
| 78 to64(FILE *infile, FILE *outfile, int PortableNewlines) | |
| 79 { | |
| 80 int c1, c2, c3, ct=0; | |
| 81 InNewline = 0; /* always reset it */ | |
| 82 while ((c1 = nextcharin(infile, PortableNewlines)) != EOF) { | |
| 83 c2 = nextcharin(infile, PortableNewlines); | |
| 84 if (c2 == EOF) { | |
| 85 output64chunk(c1, 0, 0, 2, outfile); | |
| 86 } else { | |
| 87 c3 = nextcharin(infile, PortableNewlines); | |
| 88 if (c3 == EOF) { | |
| 89 output64chunk(c1, c2, 0, 1, outfile); | |
| 90 } else { | |
| 91 output64chunk(c1, c2, c3, 0, outfile); | |
| 92 } | |
| 93 } | |
| 94 ct += 4; | |
| 95 if (ct > 71) { | |
| 96 putc('\n', outfile); | |
| 97 ct = 0; | |
| 98 } | |
| 99 } | |
| 100 if (ct) putc('\n', outfile); | |
| 101 fflush(outfile); | |
| 102 } | |
| 103 | |
| 104 static void | |
| 105 output64chunk(int c1, int c2, int c3, int pads, FILE *outfile) | |
| 106 { | |
| 107 putc(basis_64[c1>>2], outfile); | |
| 108 putc(basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)], outfile); | |
| 109 if (pads == 2) { | |
| 110 putc('=', outfile); | |
| 111 putc('=', outfile); | |
| 112 } else if (pads) { | |
| 113 putc(basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)], outfile); | |
| 114 putc('=', outfile); | |
| 115 } else { | |
| 116 putc(basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)], outfile); | |
| 117 putc(basis_64[c3 & 0x3F], outfile); | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 static int | |
| 122 PendingBoundary(char *s, char **Boundaries, int *BoundaryCt) | |
| 123 { | |
| 124 int i, len; | |
| 125 | |
| 126 if (s[0] != '-' || s[1] != '-') return(0); | |
| 127 | |
| 128 | |
| 129 for (i=0; i < *BoundaryCt; ++i) { | |
| 130 len = strlen(Boundaries[i]); | |
| 131 if (!strncmp(s, Boundaries[i], len)) { | |
| 132 if (s[len] == '-' && s[len+1] == '-') *BoundaryCt = i; | |
| 133 return(1); | |
| 134 } | |
| 135 } | |
| 136 return(0); | |
| 137 } | |
| 138 | |
| 139 /* If we're in portable newline mode, we have to convert CRLF to the | |
| 140 local newline convention on output */ | |
| 141 | |
| 142 static int CRpending = 0; | |
| 143 | |
| 144 #ifdef NEWLINE_CHAR | |
| 145 static void | |
| 146 almostputc(int c, FILE *outfile, int PortableNewlines) | |
| 147 { | |
| 148 if (CRpending) { | |
| 149 if (c == 10) { | |
| 150 putc(NEWLINE_CHAR, outfile); | |
| 151 CRpending = 0; | |
| 152 } else { | |
| 153 putc(13, outfile); | |
| 154 if (c != 13) { | |
| 155 putc(c, outfile); | |
| 156 CRpending = 0; | |
| 157 } | |
| 158 } | |
| 159 } else { | |
| 160 if (PortableNewlines && c == 13) { | |
| 161 CRpending = 1; | |
| 162 } else { | |
| 163 putc(c, outfile); | |
| 164 } | |
| 165 } | |
| 166 } | |
| 167 #else | |
| 168 static void | |
| 169 almostputc(int c, FILE *outfile, int PortableNewlines) | |
| 170 { | |
| 171 putc(c, outfile); | |
| 172 } | |
| 173 #endif | |
| 174 | |
| 175 static void | |
| 176 from64(FILE *infile, FILE *outfile, | |
| 177 char **boundaries, int *boundaryct, int PortableNewlines) | |
| 178 { | |
| 179 int c1, c2, c3, c4; | |
| 180 int newline = 1, DataDone = 0; | |
| 181 | |
| 182 /* always reinitialize */ | |
| 183 CRpending = 0; | |
| 184 while ((c1 = getc(infile)) != EOF) { | |
| 185 if (isspace(c1)) { | |
| 186 if (c1 == '\n') { | |
| 187 newline = 1; | |
| 188 } else { | |
| 189 newline = 0; | |
| 190 } | |
| 191 continue; | |
| 192 } | |
| 193 if (newline && boundaries && c1 == '-') { | |
| 194 char Buf[200]; | |
| 195 /* a dash is NOT base 64, so all bets are off if NOT a boundary */ | |
| 196 ungetc(c1, infile); | |
| 197 fgets(Buf, sizeof(Buf), infile); | |
| 198 if (boundaries | |
| 199 && (Buf[0] == '-') | |
| 200 && (Buf[1] == '-') | |
| 201 && PendingBoundary(Buf, boundaries, boundaryct)) { | |
| 202 return; | |
| 203 } | |
| 204 fprintf(stderr, "Ignoring unrecognized boundary line: %s\n", Buf); | |
| 205 continue; | |
| 206 } | |
| 207 if (DataDone) continue; | |
| 208 newline = 0; | |
| 209 do { | |
| 210 c2 = getc(infile); | |
| 211 } while (c2 != EOF && isspace(c2)); | |
| 212 do { | |
| 213 c3 = getc(infile); | |
| 214 } while (c3 != EOF && isspace(c3)); | |
| 215 do { | |
| 216 c4 = getc(infile); | |
| 217 } while (c4 != EOF && isspace(c4)); | |
| 218 if (c2 == EOF || c3 == EOF || c4 == EOF) { | |
| 219 fprintf(stderr, "Warning: base64 decoder saw premature EOF!\n"); | |
| 220 return; | |
| 221 } | |
| 222 if (c1 == '=' || c2 == '=') { | |
| 223 DataDone=1; | |
| 224 continue; | |
| 225 } | |
| 226 c1 = char64(c1); | |
| 227 c2 = char64(c2); | |
| 228 almostputc(((c1<<2) | ((c2&0x30)>>4)), outfile, PortableNewlines); | |
| 229 if (c3 == '=') { | |
| 230 DataDone = 1; | |
| 231 } else { | |
| 232 c3 = char64(c3); | |
| 233 almostputc((((c2&0XF) << 4) | ((c3&0x3C) >> 2)), outfile, PortableNewlines); | |
| 234 if (c4 == '=') { | |
| 235 DataDone = 1; | |
| 236 } else { | |
| 237 c4 = char64(c4); | |
| 238 almostputc((((c3&0x03) <<6) | c4), outfile, PortableNewlines); | |
| 239 } | |
| 240 } | |
| 241 } | |
| 242 if (CRpending) putc(13, outfile); /* Don't drop a lone trailing char 13 */ | |
| 243 } | |
| 244 | |
| 245 static signed char basis_hex[] = "0123456789ABCDEF"; | |
| 246 static signed char index_hex[128] = { | |
| 247 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | |
| 248 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | |
| 249 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | |
| 250 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1, | |
| 251 -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, | |
| 252 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | |
| 253 -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, | |
| 254 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1 | |
| 255 }; | |
| 256 | |
| 257 /* The following version generated complaints on Solaris. */ | |
| 258 /* #define hexchar(c) (((c) < 0 || (c) > 127) ? -1 : index_hex[(c)]) */ | |
| 259 /* Since we're no longer ever calling it with anything signed, this should work: */ | |
| 260 #define hexchar(c) (((c) > 127) ? -1 : index_hex[(c)]) | |
| 261 | |
| 262 /* | |
| 263 hexchar(c) | |
| 264 char c; | |
| 265 { | |
| 266 char *s; | |
| 267 if (islower(c)) c = toupper(c); | |
| 268 s = (char *) strchr(basis_hex, c); | |
| 269 if (s) return(s-basis_hex); | |
| 270 return(-1); | |
| 271 } | |
| 272 */ | |
| 273 | |
| 274 static void | |
| 275 toqp(FILE *infile, FILE *outfile) | |
| 276 { | |
| 277 int c, ct=0, prevc=255; | |
| 278 while ((c = getc(infile)) != EOF) { | |
| 279 if ((c < 32 && (c != '\n' && c != '\t')) | |
| 280 || (c == '=') | |
| 281 || (c >= 127) | |
| 282 /* Following line is to avoid single periods alone on lines, | |
| 283 which messes up some dumb smtp implementations, sigh... */ | |
| 284 || (ct == 0 && c == '.')) { | |
| 285 putc('=', outfile); | |
| 286 putc(basis_hex[c>>4], outfile); | |
| 287 putc(basis_hex[c&0xF], outfile); | |
| 288 ct += 3; | |
| 289 prevc = 'A'; /* close enough */ | |
| 290 } else if (c == '\n') { | |
| 291 if (prevc == ' ' || prevc == '\t') { | |
| 292 putc('=', outfile); /* soft & hard lines */ | |
| 293 putc(c, outfile); | |
| 294 } | |
| 295 putc(c, outfile); | |
| 296 ct = 0; | |
| 297 prevc = c; | |
| 298 } else { | |
| 299 if (c == 'F' && prevc == '\n') { | |
| 300 /* HORRIBLE but clever hack suggested by MTR for sendmail-avoidance */ | |
| 301 c = getc(infile); | |
| 302 if (c == 'r') { | |
| 303 c = getc(infile); | |
| 304 if (c == 'o') { | |
| 305 c = getc(infile); | |
| 306 if (c == 'm') { | |
| 307 c = getc(infile); | |
| 308 if (c == ' ') { | |
| 309 /* This is the case we are looking for */ | |
| 310 fputs("=46rom", outfile); | |
| 311 ct += 6; | |
| 312 } else { | |
| 313 fputs("From", outfile); | |
| 314 ct += 4; | |
| 315 } | |
| 316 } else { | |
| 317 fputs("Fro", outfile); | |
| 318 ct += 3; | |
| 319 } | |
| 320 } else { | |
| 321 fputs("Fr", outfile); | |
| 322 ct += 2; | |
| 323 } | |
| 324 } else { | |
| 325 putc('F', outfile); | |
| 326 ++ct; | |
| 327 } | |
| 328 ungetc(c, infile); | |
| 329 prevc = 'x'; /* close enough -- printable */ | |
| 330 } else { /* END horrible hack */ | |
| 331 putc(c, outfile); | |
| 332 ++ct; | |
| 333 prevc = c; | |
| 334 } | |
| 335 } | |
| 336 if (ct > 72) { | |
| 337 putc('=', outfile); | |
| 338 putc('\n', outfile); | |
| 339 ct = 0; | |
| 340 prevc = '\n'; | |
| 341 } | |
| 342 } | |
| 343 if (ct) { | |
| 344 putc('=', outfile); | |
| 345 putc('\n', outfile); | |
| 346 } | |
| 347 } | |
| 348 | |
| 349 static void | |
| 350 fromqp(FILE *infile, FILE *outfile, char **boundaries, int *boundaryct) | |
| 351 { | |
| 647 | 352 int c1, c2; |
| 428 | 353 int sawnewline = 1, neednewline = 0; |
| 354 /* The neednewline hack is necessary because the newline leading into | |
| 355 a multipart boundary is part of the boundary, not the data */ | |
| 356 | |
| 357 while ((c1 = getc(infile)) != EOF) { | |
| 358 if (sawnewline && boundaries && (c1 == '-')) { | |
| 359 char Buf[200]; | |
| 360 unsigned char *s; | |
| 361 | |
| 362 ungetc(c1, infile); | |
| 363 fgets(Buf, sizeof(Buf), infile); | |
| 364 if (boundaries | |
| 365 && (Buf[0] == '-') | |
| 366 && (Buf[1] == '-') | |
| 367 && PendingBoundary(Buf, boundaries, boundaryct)) { | |
| 368 return; | |
| 369 } | |
| 370 /* Not a boundary, now we must treat THIS line as q-p, sigh */ | |
| 371 if (neednewline) { | |
| 372 putc('\n', outfile); | |
| 373 neednewline = 0; | |
| 374 } | |
| 375 for (s=(unsigned char *) Buf; *s; ++s) { | |
| 376 if (*s == '=') { | |
| 377 if (!*++s) break; | |
| 378 if (*s == '\n') { | |
| 379 /* ignore it */ | |
| 380 sawnewline = 1; | |
| 381 } else { | |
| 382 c1 = hexchar(*s); | |
| 383 if (!*++s) break; | |
| 384 c2 = hexchar(*s); | |
| 385 putc(c1<<4 | c2, outfile); | |
| 386 } | |
| 387 } else { | |
| 442 | 388 #ifdef WIN32_NATIVE |
| 428 | 389 if (*s == '\n') |
| 390 putc('\r', outfile); /* insert CR for binary-mode write */ | |
| 391 #endif | |
| 392 putc(*s, outfile); | |
| 393 } | |
| 394 } | |
| 395 } else { | |
| 396 if (neednewline) { | |
| 397 putc('\n', outfile); | |
| 398 neednewline = 0; | |
| 399 } | |
| 400 if (c1 == '=') { | |
| 401 sawnewline = 0; | |
| 402 c1 = getc(infile); | |
| 403 if (c1 == '\n') { | |
| 404 /* ignore it */ | |
| 405 sawnewline = 1; | |
| 406 } else { | |
| 407 c2 = getc(infile); | |
| 408 c1 = hexchar(c1); | |
| 409 c2 = hexchar(c2); | |
| 410 putc(c1<<4 | c2, outfile); | |
| 411 if (c2 == '\n') sawnewline = 1; | |
| 412 } | |
| 413 } else { | |
| 414 if (c1 == '\n') { | |
| 415 sawnewline = 1; | |
| 416 neednewline = 1; | |
| 417 } else { | |
| 418 sawnewline = 0; | |
| 419 putc(c1, outfile); | |
| 420 } | |
| 421 } | |
| 422 } | |
| 423 } | |
| 424 if (neednewline) { | |
| 425 putc('\n', outfile); | |
| 426 neednewline = 0; | |
| 427 } | |
| 428 } | |
| 429 | |
| 430 | |
| 431 /* | |
| 432 Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore) | |
| 433 | |
| 434 Permission to use, copy, modify, and distribute this material | |
| 435 for any purpose and without fee is hereby granted, provided | |
| 436 that the above copyright notice and this permission notice | |
| 437 appear in all copies, and that the name of Bellcore not be | |
| 438 used in advertising or publicity pertaining to this | |
| 439 material without the specific, prior written permission | |
| 440 of an authorized representative of Bellcore. BELLCORE | |
| 441 MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY | |
| 442 OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS", | |
| 443 WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. | |
| 444 */ | |
| 442 | 445 #ifdef WIN32_NATIVE |
| 446 #include <io.h> | |
| 428 | 447 #include <fcntl.h> |
| 448 #endif | |
| 449 | |
| 450 #define BASE64 1 | |
| 451 #define QP 2 /* quoted-printable */ | |
| 452 | |
| 453 int main(int argc, char *argv[]) | |
| 454 { | |
| 455 int encode = 1, which = BASE64, i, portablenewlines = 0; | |
| 456 FILE *fp = stdin; | |
| 457 FILE *fpo = stdout; | |
| 458 | |
| 459 for (i=1; i<argc; ++i) { | |
| 460 if (argv[i][0] == '-') { | |
| 461 switch (argv[i][1]) { | |
| 462 case 'o': | |
| 463 if (++i >= argc) { | |
| 464 fprintf(stderr, "mimencode: -o requires a file name.\n"); | |
| 465 exit(-1); | |
| 466 } | |
| 467 fpo = fopen(argv[i], "w"); | |
| 468 if (!fpo) { | |
| 469 perror(argv[i]); | |
| 470 exit(-1); | |
| 471 } | |
| 472 break; | |
| 473 case 'u': | |
| 474 encode = 0; | |
| 475 break; | |
| 476 case 'q': | |
| 477 which = QP; | |
| 478 break; | |
| 479 case 'p': | |
| 480 portablenewlines = 1; | |
| 481 break; | |
| 482 case 'b': | |
| 483 which = BASE64; | |
| 484 break; | |
| 485 default: | |
| 486 fprintf(stderr, | |
| 487 "Usage: mmencode [-u] [-q] [-b] [-p] [-o outputfile] [file name]\n"); | |
| 488 exit(-1); | |
| 489 } | |
| 490 } else { | |
| 442 | 491 #ifdef WIN32_NATIVE |
| 428 | 492 if (encode) |
| 493 fp = fopen(argv[i], "rb"); | |
| 494 else | |
| 495 { | |
| 496 fp = fopen(argv[i], "rt"); | |
| 497 setmode(fileno(fpo), O_BINARY); | |
| 498 } /* else */ | |
| 499 #else | |
| 500 fp = fopen(argv[i], "r"); | |
| 442 | 501 #endif /* WIN32_NATIVE */ |
| 428 | 502 if (!fp) { |
| 503 perror(argv[i]); | |
| 504 exit(-1); | |
| 505 } | |
| 506 } | |
| 507 } | |
| 442 | 508 #ifdef WIN32_NATIVE |
| 428 | 509 if (fp == stdin) setmode(fileno(fp), O_BINARY); |
| 442 | 510 #endif /* WIN32_NATIVE */ |
| 428 | 511 if (which == BASE64) { |
| 512 if (encode) { | |
| 513 to64(fp, fpo, portablenewlines); | |
| 514 } else { | |
| 515 from64(fp,fpo, (char **) NULL, (int *) 0, portablenewlines); | |
| 516 } | |
| 517 } else { | |
| 518 if (encode) toqp(fp, fpo); else fromqp(fp, fpo, NULL, 0); | |
| 519 } | |
| 520 return(0); | |
| 521 } | |
| 522 |
