diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/ChangeLog | 1414 | ||||
| -rw-r--r-- | lib/GNUmakefile | 38 | ||||
| -rw-r--r-- | lib/README | 73 | ||||
| -rw-r--r-- | lib/atou.o | bin | 0 -> 4976 bytes | |||
| -rw-r--r-- | lib/basename.o | bin | 0 -> 4956 bytes | |||
| -rw-r--r-- | lib/bb-list.c | 76 | ||||
| -rw-r--r-- | lib/bb-outline.c | 114 | ||||
| -rw-r--r-- | lib/bitmap.c | 258 | ||||
| -rw-r--r-- | lib/bounding-box.c | 78 | ||||
| -rw-r--r-- | lib/charcode.c | 85 | ||||
| -rw-r--r-- | lib/charspec.c | 63 | ||||
| -rw-r--r-- | lib/cmdline.c | 63 | ||||
| -rw-r--r-- | lib/concat.c | 41 | ||||
| -rw-r--r-- | lib/concat3.c | 40 | ||||
| -rw-r--r-- | lib/concat4.c | 43 | ||||
| -rw-r--r-- | lib/concat5.c | 45 | ||||
| -rw-r--r-- | lib/dlsym.c | 28 | ||||
| -rw-r--r-- | lib/edge.c | 265 | ||||
| -rw-r--r-- | lib/encoding.c | 191 | ||||
| -rw-r--r-- | lib/file-input.c | 158 | ||||
| -rw-r--r-- | lib/file-output.c | 73 | ||||
| -rw-r--r-- | lib/filename.c | 99 | ||||
| -rw-r--r-- | lib/fix-num.c | 43 | ||||
| -rw-r--r-- | lib/float-ok.c | 60 | ||||
| -rw-r--r-- | lib/fmod.c | 145 | ||||
| -rw-r--r-- | lib/font.c | 466 | ||||
| -rw-r--r-- | lib/fontmap.c | 210 | ||||
| -rw-r--r-- | lib/gmalloc.c | 1172 | ||||
| -rw-r--r-- | lib/hexify.c | 46 | ||||
| -rw-r--r-- | lib/identity.c | 38 | ||||
| -rw-r--r-- | lib/integer-ok.c | 44 | ||||
| -rw-r--r-- | lib/libfile.c | 130 | ||||
| -rw-r--r-- | lib/line.c | 63 | ||||
| -rw-r--r-- | lib/list.c | 64 | ||||
| -rw-r--r-- | lib/logreport.c | 36 | ||||
| -rw-r--r-- | lib/make-prefix.c | 41 | ||||
| -rw-r--r-- | lib/math.c | 173 | ||||
| -rw-r--r-- | lib/now.c | 38 | ||||
| -rw-r--r-- | lib/numtoa.c | 50 | ||||
| -rw-r--r-- | lib/pathsrch.c | 509 | ||||
| -rw-r--r-- | lib/rand.c | 70 | ||||
| -rw-r--r-- | lib/report.c | 27 | ||||
| -rw-r--r-- | lib/safe-free.c | 37 | ||||
| -rw-r--r-- | lib/scaled-num.c | 75 | ||||
| -rw-r--r-- | lib/spline.c | 216 | ||||
| -rw-r--r-- | lib/statistics.c | 79 | ||||
| -rw-r--r-- | lib/str-lcase.c | 49 | ||||
| -rw-r--r-- | lib/str-to-bit.c | 111 | ||||
| -rw-r--r-- | lib/strstr.o | bin | 0 -> 5172 bytes | |||
| -rw-r--r-- | lib/substring.c | 50 | ||||
| -rw-r--r-- | lib/varstring.c | 97 | ||||
| -rw-r--r-- | lib/vector.c | 272 | ||||
| -rw-r--r-- | lib/xchdir.c | 29 | ||||
| -rw-r--r-- | lib/xfseek.o | bin | 0 -> 3592 bytes | |||
| -rw-r--r-- | lib/xftell.o | bin | 0 -> 3648 bytes | |||
| -rw-r--r-- | lib/xgetcwd.c | 104 | ||||
| -rw-r--r-- | lib/xmessage.c | 101 | ||||
| -rw-r--r-- | lib/xopendir.c | 47 | ||||
| -rw-r--r-- | lib/xrename.c | 44 | ||||
| -rw-r--r-- | lib/xstrdup.c | 29 |
60 files changed, 8010 insertions, 0 deletions
diff --git a/lib/ChangeLog b/lib/ChangeLog new file mode 100644 index 0000000..0f3ff5d --- /dev/null +++ b/lib/ChangeLog @@ -0,0 +1,1414 @@ +Tue Dec 26 10:16:08 1995 Kathy Hargreaves <kathy@cs.umb.edu> + + * identity.c (get_identity): Added. + +Sun Nov 26 12:47:00 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * bb-outline.c: (find_outline_bbs): Doc fix. + + * edge.c: (next_unmarked_outline_edge): Doc fix. + +Fri Nov 24 05:48:20 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * concat*.c: made arguments const_string's to conform to .h files. + Call assert on the arguments, that they aren't NULL, because it + makes strlen blow up if they are. Set answer to NULL, and only + work on it if all the arguments are non-NULL. + +Thu Nov 23 09:08:00 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * font.c: (get_font): replaced find_tfm_filename with kpse_find_tfm. + +Thu Aug 24 16:00:46 1995 Karl Berry <karl@cs.umb.edu> + + * GNUmakefile (c_only): strstr is now in kpathsea. + +Sat May 27 13:52:19 1995 Karl Berry <karl@cs.umb.edu> + + * GNUmakefile (c_only): atou is in kpathsea. + +Fri Apr 14 15:56:43 1995 Karl Berry <karl@cs.umb.edu> + + * GNUmakefile (c_only): Remove xfseek and xftell. + +Mon Oct 24 19:04:34 1994 Karl Berry <karl@cs.umb.edu> + + * GNUmakefile (c_only): basename is in kpathsea now. + +Sun May 1 15:31:10 1994 Karl Berry (karl@cs.umb.edu) + + * vector.c (Vangle): Declare const. + +Thu Sep 30 10:13:45 1993 Karl Berry (karl@cs.umb.edu) + + * str-to-bit.c (string_to_bitmap): Call close_font. + +Sun Aug 1 09:56:42 1993 Karl Berry (karl@cs.umb.edu) + + * Most *.c: Include files now in kpathsea. + + * GNUmakefile (c_only): Add statistics, remove many things now in + kpathsea. + +Tue Jul 27 09:24:08 1993 Karl Berry (karl@cs.umb.edu) + + * GNUmakefile (c_only): Remove dir-p and find-suffix (now in kpathsea). + +Fri May 21 13:45:30 1993 Karl Berry (karl@cs.umb.edu) + + * gmalloc.c (my_memmove): New routine, since ISC doesn't have a + real memmove. + +Thu May 20 19:11:05 1993 Karl Berry (karl@cs.umb.edu) + + * gmalloc.c: New file from the malloc distribution (plus a few + edits). + * GNUmakefile (malloc): Define to be gmalloc, and toss the old + malloc.c. + +Thu Apr 22 17:03:53 1993 Karl Berry (karl@cs.umb.edu) + + * remove-suffx.c (remove_suffix): If no suffix, return the string, + not NULL. + +Tue Apr 6 19:58:45 1993 Karl Berry (karl@cs.umb.edu) + + * malloc.c (getpagesize.h): Do not include. + (memalign, valloc): Remove, since we don't need them. + + * filename.c (find_tfm_filename): Call extend_filename to get the + `.tfm', instead of just concatenating. Not sure if this is a good + idea, but periods in font names are problematic all over, I think. + +Tue Mar 16 07:47:38 1993 Karl Berry (karl@cs.umb.edu) + + * fontmap.c (map_lookup): Don't extend the filename if there was + no suffix. + +Wed Mar 3 06:20:09 1993 Karl Berry (karl@cs.umb.edu) + + * xftell.c (xftell): Declare as unsigned long. + +Mon Jan 18 15:43:02 1993 Karl Berry (karl@cs.umb.edu) + + * xrealloc.c: Doc fix. + +Sun Jan 3 19:36:39 1993 Karl Berry (karl@cs.umb.edu) + + * pathsrch.c (R_OK): Defined in the config files now. + +Fri Dec 11 15:00:31 1992 Karl Berry (karl@cs.umb.edu) + + * font.c (print_char): Change ctype references to use uppercase macros. + * libfile.c (libfile_line), + * pathsrch.c (absolute_p), + * str-to-bit.c (string_to_bitmap), + * float-ok.c (float_ok), + * integer-ok.c (integer_ok), + * charspec.c (xparse_charspec): Likewise. + +Sun Nov 29 17:05:40 1992 Karl Berry (karl@cs.umb.edu) + + * xmessage.c [X_DISPLAY_MISSING]: Conditionalize whole file. + + * numtoa.c (xdtoa): Rename from `dtoa', to avoid Linux conflict. + (awasthi@cps.msu.edu) + +Tue Nov 17 09:25:58 1992 Karl Berry (karl@cs.umb.edu) + + * hexify.c: Doc fix. + +Mon Nov 16 16:08:39 1992 Karl Berry (karl@cs.umb.edu) + + * malloc.c (calloc): Complain if the malloc fails. + +Tue Oct 27 12:56:15 1992 Karl Berry (karl@cs.umb.edu) + + * Version 0.6. + +Sun Oct 25 06:26:42 1992 Karl Berry (karl@cs.umb.edu) + + * getopt.c: New version. + +Thu Oct 22 17:58:12 1992 Karl Berry (karl@cs.umb.edu) + + * make-suffix.c: Doc fix. + +Tue Oct 20 11:57:57 1992 Karl Berry (karl@cs.umb.edu) + + * filename.c (find_{gf,pk,tfm}_filename): Just concatenate the + suffix onto the main font name, don't replace a suffix. + +Mon Oct 5 10:07:59 1992 Karl Berry (karl@cs.umb.edu) + + * report.c (report_file): New variable. + +Sun Oct 4 09:13:24 1992 Karl Berry (karl@cs.umb.edu) + + * bb-list.c: New file, from bb-outline.c. + * GNUmakefile (c_only): Add it. + * bb-outline.c: Change calls and decls for new improved names. + +Sat Oct 3 16:58:38 1992 Karl Berry (karl@cs.umb.edu) + + * bb-outline.c: Doc fix. + +Tue Sep 22 12:46:49 1992 Karl Berry (karl@cs.umb.edu) + + * malloc.c (realloc): abort if we can't malloc enough memory to do + the realloc. + + * bitmap.c (bb_ensure_bounds): new routine. + (extract_subbitmap): call it. + +Mon Sep 21 12:00:35 1992 Karl Berry (karl@cs.umb.edu) + + * malloc.c: define NO_NEW_HANDLER. + +Thu Sep 3 09:31:06 1992 Karl Berry (karl@hayley) + + * Version 0.5. + +Thu Aug 27 09:06:25 1992 Karl Berry (karl@hayley) + + * getopt.c: update from MIT. + +Mon Aug 24 15:50:03 1992 Karl Berry (karl@hayley) + + * rand.c (k_rand): use Ghostscript's algorithm exactly, to avoid + overflow problems. + + * rand.c (seed_rand): Our simplification was a loser if the + state ever became zero, so set the state to the seed + 1, and + subtract again before output. + +Wed Aug 19 07:10:12 1992 Karl Berry (karl@hayley) + + * charspec.c: doc fix. + +Mon Aug 17 15:43:42 1992 Karl Berry (karl@hayley) + + * encoding.c: doc fix. + +Mon Aug 10 11:11:52 1992 Karl Berry (karl@hayley) + + * rand.c (x): change the default seed to 1. + +Mon Jul 27 15:29:33 1992 Karl Berry (karl@hayley) + + * charspec.c (xparse_charspec): use an `int' while figuring out + the charcode. + +Sat Jul 25 14:38:23 1992 Karl Berry (karl@hayley) + + * getopt.c: new version. + + * pathsrch.c (expand_tilde): cast the result of getpwnam. + +Sat Jul 18 16:35:41 1992 Karl Berry (karl@hayley) + + * edge.c: add ^L's. + +Fri Jul 3 15:26:12 1992 Karl Berry (karl@hayley) + + * charspec.c (xparse_charspec): if arg is one character long, and + undefined in the encoding, use its value in C. + +Fri Jun 26 16:53:39 1992 Karl Berry (karl@hayley) + + * charspec.c: new file. + * GNUmakefile: add it. + +Thu Jun 25 07:04:49 1992 Karl Berry (karl@hayley) + + * pathsrch.c (readable) [ENAMETOOLONG]: conditionalize the test + for doing our own truncating, since it appears not all systems + have ENAMETOOLONG. + +Sun Jun 14 08:11:32 1992 Karl Berry (karl@hayley) + + * font.c (get_font): remove computation of NCHARS (and reading of + all the TFM chars). + + * str-lcase.c (str_to_lower): assert the arg is non-null. + +Sat Jun 13 16:28:08 1992 Karl Berry (karl@hayley) + + * libfile.c (libfile_start): return the FILE * we open. + +Sat Jun 13 13:52:30 1992 Kathy Hargreaves (kathy@hayley) + + * encoding.c (DEFAULT_ENCODING): moved to .h file. + +Sat Jun 13 09:24:12 1992 Karl Berry (karl@hayley) + + * encoding.c: include `str-lcase.h', not `str-casefold.h'. + + * xmessage.c (x_message): cast initializer in `popup_args' to + avoid warning. + + * str-to-bit.c (string_to_bitmap): `TFM_FONT_PARAMETER' is now + `TFM_FONTDIMEN'. + + * pathsrch.c (absolute_p): add parens to stop GCC 2's stupid warning. + + * encoding.c: change for new list fn names. + * font.c: likewise. + + * list.c (new_list): rename to `list_init', and rewrite to use + accessor macros. + (append_element): rename to `list_append', and likewise rewrite. + (list_free): new routine. + +Sun Jun 7 17:25:43 1992 Karl Berry (karl@hayley) + + * encoding.c (coding_scheme_to_filename): rewrite to avoid + sentinel boolean, lowercasing the passed codingscheme more than + once, etc. + + * str-casefold.c (str_to_lower): rewrite to use ? :. + (str_to_upper): remove this. + Rename to str-lcase.c. + * GNUmakefile (c_only): change str-casefold to str-lcase. + +Sun Jun 7 14:39:09 1992 Kathy Hargreaves (kathy@hayley) + + * bb-outline.c (find_outline_bbs): don't calculate edge if it's an + interior pixel. + + * bb-outline.c (find_outline_bbs): deleted avoiding finding a + bounding box which corresponds to a counterform by not looking + inside existing bounding boxes. + Added finding the bounding box for a counterform (i.e., marking + its edges) but not adding it to the list unless find_all is true. + Changed find_all to find_inner. + +Sun Jun 7 08:55:31 1992 Karl Berry (karl@hayley) + + * GNUmakefile (c_only): add `str-to-bit'. + * font.c (string_to_bitmap): extract the interword space out of + the TFM information, instead of expecting it in the main font + structure. Also, move this fn to its own file, `str-to-bit.c'. + + * float-ok.c (float_ok): don't accept the empty string, or just a + sign, or just a sign and a `.', etc. + * integer-ok.c (integer_ok): likewise. + +Thu Jun 4 08:11:36 1992 Karl Berry (karl@hayley) + + * pathsrch.c (absolute_p): `k./' should not be considered + explicitly relative. + +Tue Jun 2 11:40:32 1992 Karl Berry (karl@hayley) + + * encoding.c (encoding_number): don't crash if NAME is NULL. + +Mon Jun 1 15:16:15 1992 Karl Berry (karl@hayley) + + * GNUmakefile (c_only): add `integer-ok' and `float-ok'. + * {integer,float}-ok.c: new files. + + * libfile.c (libfile_start): use extend_filename. + + * encoding.c (read_encoding_file): initialize the return structure + after we know the file exists. + +Fri May 29 08:29:26 1992 Karl Berry (karl@hayley) + + * getopt*.c: new versions. + +Sat May 23 15:51:53 1992 Karl Berry (karl@hayley) + + * charcode.c (parse_charcode): ensure there are no extra + characters at the end of the charcode; change return type to + charcode_type. + (xparse_charcode): change return type. + +Sat May 23 12:33:32 1992 Kathy Hargreaves (kathy@hayley) + + * str-casefold.c (str_to_lower): added variable `length'; put 0 at + end of return string. + +Sat May 23 06:27:28 1992 Karl Berry (karl@hayley) + + * dir-p.c (leaf_dir_p): remove; `expand_subdir' now calls stat + itself, for efficiency. + + * pathsrch.c (expand_subdir): rewrite to always look for subdirs. + (initialize_path_list): check for the dir-ness of `foo' in + `foo//'. This change makes symlinks under `foo' be considered. + + * pathsrch.c (add_directory): don't check for the arg being a + directory. + (initialize_path_list): check here for the directory-ness of a + path element. + (expand_subdir): check here, too. + + * pathsrch.c (expand_subdir): call closedir after we read the + directory contents. + +Thu May 21 11:40:53 1992 Karl Berry (karl@hayley) + + * hexify.c (hexify): take a block of memory and a length, instead + of a varstring. + +Tue May 19 16:43:43 1992 Kathy Hargreaves (kathy@hayley) + + * line.c (read_line): return a string if not at EOF. + +Sat May 16 21:22:57 1992 Kathy Hargreaves (kathy@hayley) + + * varstring.c (vs_concat): added. + +Fri May 15 10:22:27 1992 Karl Berry (karl@hayley) + + * getopt.c: new version. + +Thu May 14 22:05:10 1992 Karl Berry (karl@claude.cs.umb.edu) + + * rand.c (srand): -> seed_rand, to avoid header conflicts. + (rand): -> k_rand, same reason. + +Sun May 10 10:05:36 1992 Karl Berry (karl@hayley) + + * encoding.c (coding_scheme_to_filename): don't xstrdup the return + value. + (DEFAULT_ENCODING): new macro. + +Fri May 8 15:38:38 1992 Karl Berry (karl@hayley) + + * pathshare from dvips. + +Thu May 7 16:44:14 1992 Karl Berry (karl@hayley) + + * GNUmakefile (c_only): add dlsym. + * dlsym.c: new file. + +Wed May 6 10:08:09 1992 Karl Berry (karl@hayley) + + * bitmap.c (bitmap_find_transitions): don't look outside the + current row when it's only one pixel long. + +Tue May 5 08:46:48 1992 Karl Berry (karl@hayley) + + * dir-p.c: doc fix. + +Sat May 2 07:51:53 1992 Karl Berry (karl@hayley) + + * pathsrch.c (add_directory): use ?:. + +Thu Apr 30 08:52:34 1992 Karl Berry (karl@hayley) + + * pathsrch.c (parse_envpath): expand the ~ here; + (add_directory): not here. + + * pathsrch.c (expand_tilde): free space for the login name. + + * dir-p.c (leaf_dir_p): use stat, not xlstat, so we don't bomb + out on missing directories in paths, and so we get info about + the (potential) dir, not the link. + +Tue Apr 21 07:44:52 1992 Karl Berry (karl@hayley) + + * bitmap.c (bitmap_find_transitions): use XTALLOC1. + * font.c (get_char): likewise. + +Mon Apr 20 08:35:23 1992 Karl Berry (karl@hayley) + + * pathsrch.c: doc fix. + + * malloc.c: don't include config.h. + (my_bzero, my_bcopy): new routines to simplify things. + +Sat Apr 18 12:22:29 1992 Kathy Hargreaves (kathy@hayley) + + * str-casefold.c: added. + + * encoding.c (coding_scheme_to_filename): compare case-folded + versions of the coding scheme and the mapped scheme. + +Wed Apr 15 15:23:20 1992 Karl Berry (karl@hayley) + + * make-output.c: rename to `extend-fname.c'; rename the fn to + `extend_filename'. + * GNUmakefile (c_only): analogously. + +Wed Apr 15 13:20:11 1992 Kathy Hargreaves (kathy@hayley) + + * encoding.c (coding_scheme_to_filename): changed some variable + names; added `mapped_coding' and set it to a second call to + strtok with `mapping'. + +Tue Apr 14 13:46:45 1992 Karl Berry (karl@hayley) + + * scaled-num.c (scaled_to_real): as below. + +Sun Apr 12 15:06:58 1992 Karl Berry (karl@hayley) + + * scaled-num.c (real_to_scaled): simplify to just multiply the + real by SCALED_UNITY. + +Fri Apr 10 16:36:33 1992 Karl Berry (karl@hayley) + + * concat.c: put concat[345] in separate files. + * GNUmakefile (c_only): update. + + * filename.c: remove prefix/suffix routines. + ({make-{output,prefix,suffix},remove-suffx,find-suffix}.c): new files. + * GNUmakefile (c_only): update. + + * pathsrch.c (initialize_path_list): remove cwd_first_p. + * filename.c (find_*_filename): change calls. + * libfile.c (libfile_start): change call. + +Mon Apr 6 13:46:36 1992 Kathy Hargreaves (kathy@fosse) + + * encoding.c (encoding_scheme_to_filename): added. + +Fri Apr 3 13:17:22 1992 Karl Berry (karl@hayley) + + * rand.c: new file. + * GNUmakefile (c_only): include it. + +Wed Apr 1 14:14:01 1992 Karl Berry (karl at hayley) + + * (pathshare from web2c) + + * filename.c (make_output_filename): don't duplicate the input + string, just return it. + + * filename.c (remove_suffix): remove. + + * edge.c: new file. + * GNUmakefile (c_only): add it. + * bb-outline.c: remove edge stuff in favor of this new file. + +Tue Mar 31 13:35:51 1992 Karl Berry (karl at hayley) + + * bitmap.c (bitmap_find_transitions): handle a row with a single + black pixel at the end correctly. + +Sun Mar 29 10:58:27 1992 Karl Berry (karl at hayley) + + * xrealloc.c (xrealloc): cast the ptr. + + * file-input.c (get_n_bytes): had args switched to fatal. + + * bb-outline.c (is_outline_edge): remove the assertion that we're + at a valid pixel, since it's half-implied by the types, anyway. + + * GNUmakefile (malloc.o): remove the special rule and vars. + * malloc.c [STDC_HEADERS | USG]: add the former for memset etc. + +Sat Mar 28 07:49:09 1992 Karl Berry (karl at hayley) + + * malloc.c: new version, from libg++ 2.0. + + * GNUmakefile (malloc_stats): don't define this. + + * Version 0.4. + + * Change copyright years to 1992 only. + +Wed Mar 25 08:37:28 1992 Karl Berry (karl at hayley) + + * GNUmakefile (c_only): add fmod. + * fmod.c: new file. + +Thu Mar 19 07:47:30 1992 Karl Berry (karl at hayley) + + * pathsearch.c, libfile.c, filename.c: include paths.h. + + * pathsearch.c: rename to pathsrch.c; new version. + +Wed Mar 11 10:03:12 1992 Karl Berry (karl at hayley) + + * bitmap.c (bitmap_find_transitions): handle the pixel at the end + of the row specially, unfortunately. + +Tue Mar 10 12:17:09 1992 Kathy Hargreaves (kathy at hayley) + + * libfile.c (libfile_start): use find_suffix instead of finding a + dot position. + +Mon Mar 9 16:42:49 1992 Kathy Hargreaves (kathy at hayley) + + * filename.c (make_stem_suffix): remove suffix from name before + adding stem_suffix and putting suffix back on. + + * filename.c (make_stem_suffix): don't add a dot if no suffix. + + * filename.c (make_stem_suffix): added. + +Sun Mar 8 17:08:06 1992 Kathy Hargreaves (kathy at hayley) + + * filename.c (make_output_filename): put dot between NAME and + DEFAULT_SUFFIX. + +Sun Mar 8 08:37:46 1992 Karl Berry (karl at fosse) + + * numtoa.c (dtoa): rename from ftoa. + + * strstr.c: new file. + GNUmakefile (c_only): add strstr. + +Sat Mar 7 17:00:44 1992 Kathy Hargreaves (kathy at hayley) + + * filename.c (sizeless_font_name): removed. + +Sat Mar 7 13:21:33 1992 Karl Berry (karl at fosse) + + * xmessage.c: include xmessage.h. + + * GNUmakefile (c_only): remove statistics; we never use it. + + * pathsearch.c: add prototypes for the subroutines. + + * line.c: include line.h. + + * bb-outline.c (find_outlines_bbs): rename parameters to avoid + shadow warnings. + +Sat Mar 7 09:14:00 1992 Karl Berry (karl at hayley) + + * GNUmakefile (files, headers, sources): replace with `c_and_h', etc. + + * scaled-num.c (print_scaled): use putchar instead of printf where + possible. + +Wed Mar 4 10:40:02 1992 Karl Berry (karl at hayley) + + * filename.c (remove_suffix): don't include the `.' in what we + return. + +Tue Mar 3 16:28:38 1992 Karl Berry (karl at hayley) + + * filename.c (find_suffix): new routine. + (remove_suffix, make_output_filename, make_suffix): write in terms + of it. + +Sun Mar 1 16:33:49 1992 Kathy Hargreaves (kathy at hayley) + + * filename.c (make_output_file): use concat instead of make_suffix. + +Sun Mar 1 15:17:28 1992 Karl Berry (karl at hayley) + + * GNUmakefile (files): add bb-outline. + +Sun Mar 1 14:48:41 1992 Kathy Hargreaves (kathy at hayley) + + * filename.c (make_output_file): added. + +Mon Feb 24 08:38:56 1992 Karl Berry (karl at hayley) + + * pathsearch.c (truncate_pathname): separate this out from `readable'. + + * concat.c dir-p.c file-p.c pathsearch.c xmalloc.c xopendir.c + xrealloc.c xstat.c xstrdup.c: redo with (un)prototype macros. + +Wed Feb 19 10:00:35 1992 Karl Berry (karl at hayley) + + * varstring.c (vs_set_char): set the allocated field after we + allocate more space. + + * hexify.c (hexify): add 'a' to each hex char to make it visible + ASCII; shift the upper nybble down before adding. + +Mon Feb 17 07:38:27 1992 Karl Berry (karl at hayley) + + * filename.c (sizeless_font_name): new routine. + + * line.c (read_line): use vs_append_char, and generally simplify. + + * varstring.c (vs_append_char): don't append a null afterwards. + + * GNUmakefile (files): add it. + * hexify.c: new file. + +Sun Feb 16 10:31:41 1992 Karl Berry (karl at hayley) + + * pathsearch.c (readable): keep track of the component lengths + properly; do the second test on the new name, not the old. + +Sat Feb 15 16:10:30 1992 Karl Berry (karl at hayley) + + * pathsearch.c (READABLE): redo the macro as a function, and + truncate the pathname if necessary. + +Fri Feb 14 07:26:35 1992 Karl Berry (karl at hayley) + + * varstring.c (vs_append_char): use VS_USED instead of strlen. + (vs_init): initialize VS_USED to zero. + (vs_set_char): set VS_USED. + All routines: rename `VS_LENGTH to `VS_ALLOCATED'. + + * varstring.c (vs_free): new routine. + + * math.c (acosd): clear errno before testing it. + +Thu Feb 13 13:32:54 1992 Karl Berry (karl at hayley) + + * pathsearch.c (READABLE): call it readable if the error is + ENAMETOOLONG; include <errno.h> and declare errno if that is + undefined. + +Sun Feb 2 16:08:44 1992 Karl Berry (karl at hayley) + + * filename.c (find_{gf,pk}_filename): allocate enough space for + the null sprintf writes. + +Sat Feb 1 14:53:39 1992 Karl Berry (karl at hayley) + + * filename.c (depath): remove. + + * pathsearch.c (initialize_path_list): subdirectories are now + indicated by // terminating a path element, instead of as + a separate envvar/path. + * filename.c (find*filename): remove subdirectory stuff. + * libfile.c (libfile_start): likewise. + +Mon Jan 20 11:09:10 1992 Kathy Hargreaves (kathy at hayley) + + * filename.c (depath): added this routine to take the path off the + front of a filename. + + * filename.c (make_prefix): added this routine to add a prefix to + a filename which may or may not be the full pathname. + +Wed Jan 15 16:57:36 1992 Kathy Hargreaves (kathy at hayley) + + * libfile.c (libfile_start): when FATAL, report `name', not it + concatenated with the default suffix. + +Wed Jan 15 13:01:30 1992 Karl Berry (karl at hayley) + + * GNUmakefile (c_only): remove xchdir and xgetcwd, as we don't + need them anymore. + * pathsearch.c: changes from TeX. + +Wed Jan 15 11:59:56 1992 Kathy Hargreaves (kathy at hayley) + + * filename.c (find_*_filename): only free `name' if it's not the + same string as `*_name'. + +Tue Jan 14 12:36:15 1992 Kathy Hargreaves (kathy at hayley) + + * bitmap.c (bitmap_find_transitions): make the last transition + always imply a black-to-white transition, even if ROW's last + pixel is black. + + * libfile.c (libfile_start): make FATAL2 report `name', not + `filename' as the library file not found. Also, only add suffix + to the library file name if it doesn't have one already. + +Sun Jan 12 16:29:11 1992 Kathy Hargreaves (kathy at hayley) + + * filename.c (make_suffix): copy suffix into new_s, not s. + +Sun Jan 12 14:57:24 1992 Karl Berry (karl at hayley) + + * pathsearch.c (check_subdir): add every existing subdirectory, + even if it's not a leaf. + +Sun Jan 12 12:47:57 1992 Kathy Hargreaves (kathy at hayley) + + * libfile.c (libfile_start): don't prepend a dot to the suffix. + + * dir-p.c (dir_p): call stat instead of xstat. + +Sat Jan 11 15:01:02 1992 Karl Berry (karl at hayley) + + * filename.c (find_*_filename): set cwd_first_p. + + * pathsearch.c (initialize_path_list): take an additional + argument, saying whether to search `.' first. + +Fri Jan 10 07:40:50 1992 Karl Berry (karl at hayley) + + * xgetcwd.c (xgetcwd) [GETWD_MISSING]: if it's not missing, use + it. + + * filename.c (find_*_filename): only initialize the path lists + once. + + * pathsearch.c (expand_colon): if env_path is null, return the + default path. + + * file-input.c (MOVE_BACK): use xfseek. + + * filename.c (*_suffix): use strrchr instead of rpos. + + * varstring.c: change names to start with `vs'. + + * memory.c: split into various files. + + * math.c (adjacent_points): rename to `points_adjacent_p'. + + * math.c (find_bounds): use MAXDOUBLE and MINDOUBLE instead of + MAXFLOAT and MINFLOAT. + + * filename.c (find_dpi): move to cmdline.c. + (basename): move to basename.c. + +Thu Jan 9 08:57:39 1992 Karl Berry (karl at hayley) + + * convert.c: split into various files. + * GNUmakefile: update. + + * cmdline.c (scan_integer_list): rename to `scan_unsigned_list'. + + * *.c: do not include global.h. + + * arith.c: split into `scaled-num.c' and `fix-num.c'. + * GNUmakefile: update. + +Wed Jan 8 09:14:45 1992 Karl Berry (karl at hayley) + + * update copyright messages. + + * change `allocate to `xmalloc', `reallocate' to `xrealloc', and + `string_copy' to `strdup'. + + * list.c: doc fix. + +Tue Jan 7 17:28:07 1992 Karl Berry (karl at hayley) + + * filename.c (expand_colon): don't put the default value at the + end if we've already put it at the beginning. + +Thu Sep 12 11:06:58 1991 Karl Berry (karl at hayley) + + * malloc.c (malloc_sanity_check): new function. + + * bitmap.c (bitmap_find_transitions): rearrange logic for clarity. + + * malloc.c, getpagesize.h: new files. + * GNUmakefile (c_only): add Doug Lea's malloc. + (malloc_stats, malloc_inline): new variables. + (malloc.o): rule to explicitly use them. + +Tue Jul 30 13:18:12 1991 Karl Berry (karl at ra.cs.umb.edu) + + * Version 0.3. + +Wed Jul 24 06:34:11 1991 Karl Berry (karl at hayley) + + * bitmap.c (concat_bitmaps): remove; it's only used in one program. + + * bitmap.c (new_bitmap): call it. + + * memory.c (xcalloc): new routine. + +Tue Jul 16 08:24:08 1991 Karl Berry (karl at hayley) + + * memory.c (allocate): don't do assignment inside if. + + * bitmap.c (bitmap_find_transitions): we don't need to look at the + first black pixel twice. + +Fri Jun 28 09:09:59 1991 Karl Berry (karl at hayley) + + * font.c (close_font): only close the TFM file if the font is not + bitmap-only. + +Sat Jun 15 09:51:45 1991 Karl Berry (karl at hayley) + + * font.c (get_font): set the new `tfm_font' and `tfm_filename' + members. + + * {dirio,file-misc,file-open,filename,libfile}.c: change + `checked_' to `x'. + +Tue Jun 11 16:46:25 1991 Karl Berry (karl at hayley) + + * font.c (get_char): use XTALLOC. + + * font.c (close_font): close the TFM file here, instead of in + `get_font'. + +Sun Jun 9 13:23:59 1991 Karl Berry (karl at hayley) + + * font.c (string_to_bitmap): use `BITMAP_PIXEL (CHAR_BITMAP'... + instead of `CHAR_BITMAP_PIXEL'. + +Thu Jun 6 07:30:07 1991 Karl Berry (karl at hayley) + + * All files: change to version 2 of the GPL. + +Sat Jun 1 16:00:03 1991 Kathy Hargreaves (kathy at hayley) + + * libfile.c (libfile_start): Don't concat a `.' to suffix if it's + the empty string. + +Thu May 16 07:35:47 1991 Karl Berry (karl at hayley) + + * GNUmakefile (files): include `xmessage' (from xbce). + * xmessage.c: new file. + +Sun Apr 21 17:38:48 1991 Karl Berry (karl at hayley) + + * bitmap.c (bitmap_to_bb): declare the arg as const. + +Sun Apr 14 13:45:29 1991 Karl Berry (karl at hayley) + + * bitmap.c (print_bitmap): use `bitmap_to_bb' instead of + `dimensions_to_bb'. + +Fri Apr 12 15:12:32 1991 Karl Berry (karl at hayley) + + * math.c: doc fix. + + * GNUmakefile (files): add `report' and `logreport'. + * {log,}report.c: new files. + +Wed Apr 10 11:27:49 1991 Karl Berry (karl at hayley) + + * font.c (save_internal_font): omit needless casts. + +Mon Apr 8 07:57:20 1991 Karl Berry (karl at hayley) + + * font.c (ascender_part): move to ospace. + + * encoding.c (parse_encoding_line): make a copy of the character + name, since the line gets freed. + + * encoding.c (read_encoding_file): reinitialize the character + code, so we fill up the right array. + + * libfile.c (libfile_start): prepend the `.' to the suffix. + +Sun Apr 7 14:34:06 1991 Karl Berry (karl at hayley) + + * file-output.c (put_signed_four): declare this as a macro in the + .h file. + +Thu Apr 4 07:03:36 1991 Karl Berry (karl at hayley) + + * font.c (get_char): don't allocate any space unless the character + actually exists in the font. + +Mon Apr 1 07:57:58 1991 Karl Berry (karl at hayley) + + * {encoding,libfile}.c: new files. + GNUmakefile (files): add them to the list. + +Sat Mar 23 16:42:39 1991 Karl Berry (karl at hayley) + + * font.c (delete_internal_font): free the memory for the internal + font, and for the font name. + +Sat Mar 9 17:06:57 1991 Karl Berry (karl at hayley) + + * string.c: declare args to routines as const. + + * string.c (lowercasify): new routine. + +Thu Mar 7 07:33:05 1991 Karl Berry (karl at hayley) + + * Version 0.2. + +Mon Mar 4 15:06:59 1991 Karl Berry (karl at hayley) + + * font.c (delete_internal_font): new routine. + (close_font): call it, thus preventing us from finding a font that + has been closed. + +Mon Feb 25 15:58:21 1991 Karl Berry (karl at hayley) + + * font.c (get_font): use `tfm_...' instead of `..._tfm_...'; use + `pk_...' instead of `..._pk_...'; use `gf_...' instead of + `..._gf_...'. + +Sun Feb 24 15:34:36 1991 Karl Berry (karl at ra.cs.umb.edu) + + * math.c (int_distance): cast the arguments to `double'. + +Sun Feb 17 09:43:06 1991 Karl Berry (karl at hayley) + + * *.c: include config.h. + +Sat Feb 16 16:54:18 1991 Karl Berry (karl at hayley) + + * dirio.c (checked_lstat) [HAVE_SYMBOLIC_LINKS]: change + conditional from being on S_ISLNK and S_IFLNK. + +Tue Jan 22 15:44:43 1991 Karl Berry (karl at hayley) + + * bitmap.c (extract_subbitmap): new routine from imgtogf. + +Fri Jan 18 08:14:23 1991 Karl Berry (karl at hayley) + + * vector.c (all routines): declare args to be const. + + * vector.c (Vabs): new routine. + +Tue Jan 15 15:29:38 1991 Karl Berry (karl at hayley) + + * spline.c (append_spline): use LAST_SPLINE_LIST_ELT. + + * spline.c (new_spline_list_array, free_spline_list_array, + append_spline_list): new routines. + + * spline.c (append_spline_list): rename to concat_spline_lists. + +Sun Jan 13 09:48:56 1991 Karl Berry (karl at hayley) + + * font.c (bitmap_format_type): move to font.h. + + * file-output.c (put_n_bytes): give the arguments to fwrite in the + correct order. + +Sat Jan 12 16:46:44 1991 Karl Berry (karl at hayley) + + * file-output.c (put_n_bytes): use fwrite to do all the bytes at + one shot. + +Mon Jan 7 10:42:22 1991 Karl Berry (karl at hayley) + + * spline.c (evaluate_spline): no compiler bug anymore without + temporaries (as of gcc 1.38). + +Sat Dec 29 17:43:40 1990 Karl Berry (karl at hayley) + + * spline.c (print_spline): make the output lines shorter. + +Wed Dec 26 15:13:26 1990 Karl Berry (karl at hayley) + + * math.c (find_bounds): use MAXFLOAT and MINFLOAT, instead of + MAXDOUBLE and MINDOUBLE, since Sun's atof can't deal with + the latter. + +Sun Dec 9 11:02:20 1990 Karl Berry (karl at hayley) + + * spline.c: doc fix. + + * dirio.c (getwd): close each directory after we read it. + + * filename.c (find_subdir_path_filename): use getwd instead of + getcwd, and use checked_chdir. + + * dirio.c (checked_opendir, is_dir): make arguments be const strings. + + * dirio.c (checked_chdir, checked_stat, checked_lstat, getwd): new + routines. + +Sat Nov 17 11:09:56 1990 Karl Berry (karl at hayley) + + * file-*.c: include the appropriate file-....h file. + + * math.c (distance): put this back; it's too annoying to call + hypot with the x and y arguments. + +Thu Oct 18 15:00:32 1990 Karl Berry (karl at hayley) + + * filename.c (find_subdir_path_filename): initialize the list of + subdirectories to the empty string. + +Wed Oct 17 17:54:40 1990 Karl Berry (karl at aten) + + * filename.c (find_subdir_path_filename): do not do strlen when + the path is empty. + +Tue Oct 9 08:59:43 1990 Karl Berry (karl at hayley) + + * filename.c (find_dpi): don't crash if the argument doesn't have + a `.' at all. + + * cmdline.c: new file. + * GNUmakefile (files): add it. + +Mon Oct 8 09:08:30 1990 Karl Berry (karl at hayley) + + * filename.c (find_dpi): new routine. + +Wed Oct 3 07:33:07 1990 Karl Berry (karl at hayley) + + * filename.c (find_tfm_filename, find_pk_filename, + find_gf_filename): new routines. + +Sat Sep 29 08:34:52 1990 Karl Berry (karl at hayley) + + * bitmap.c (new_bitmap): don't use memset if the bitmap is null. + + * font.c (find_internal_font): use STREQ. + +Fri Sep 28 08:30:04 1990 Karl Berry (karl at hayley) + + * filename.c (next_component): return NULL after we've read all + the directories in the list. + + * filename.c (next_component): omit the path separator from the + returned directory. + +Thu Sep 27 11:45:36 1990 Karl Berry (karl at hayley) + + * font.c (DEFAULT_SUBDIR_PATH): new macro. + (get_bitmap_font): try to open the PK and GF files using + subdirectories if opening without them fails. + (get_font): likewise, for the TFM file. + * filename.c (get_subdir_path_filename): new routine. + (next_component): new routine, replaces `find_components'. + +Fri Sep 21 09:15:28 1990 Karl Berry (karl at hayley) + + * dirio.o (is_dir): use S_ISDIR. + +Thu Sep 13 10:38:32 1990 Karl Berry (karl at hayley) + + * convert.c (parse_char_code): new routine to replace the + PARSE_CHAR_CODE macro; return a status indicator. + (xparse_char_code): like the above, but gives a fatal error. + +Wed Sep 12 18:19:13 1990 Karl Berry (karl at aten) + + * font.c (get_font): set `bitmap_only' to false. + (save_internal_font): overwrite the old value if we're called with + the same key twice. + +Sun Sep 9 07:10:29 1990 Karl Berry (karl at hayley) + + * convert.c: new file for some numeric conversions. + * math.c: move atou to convert.c. + +Mon Sep 3 11:05:19 1990 Karl Berry (karl at hayley) + + * line.c (read_line): doc fix. + +Fri Aug 31 11:04:02 1990 Karl Berry (karl at hayley) + + * font.c (get_bitmap_font): new routine, taken from get_font. + +Thu Aug 30 16:32:25 1990 Karl Berry (karl at hayley) + + * file-misc.c (same_file_p): new function. + +Wed Aug 29 11:37:24 1990 Karl Berry (karl at hayley) + + * fileio.c: split up into several new files: file-open.c, + file-input.c, file-output.c, file-misc.c. + +Thu Aug 23 07:26:58 1990 Karl Berry (karl at hayley) + + * filename.c (remove_suffix): new routine. + (make_suffix): if the `.' is before a `/', it doesn't start the + extension. + +Thu Aug 16 07:10:48 1990 Karl Berry (karl at hayley) + + * memory.c (safe_free): use fprintf instead of FATAL, so the core dump + will happen. + +Thu Jul 26 06:53:33 1990 Karl Berry (karl at hayley) + + * bitmap.c (bitmap_find_transitions): new routine (from imgtogf). + +Wed Jul 25 08:20:12 1990 Karl Berry (karl at hayley) + + * string.c (concat5): new routine. + +Tue Jul 24 10:24:59 1990 Karl Berry (karl at hayley) + + * font.c (get_font): save the design size in points instead of + pixels. + + * filename.c: new file. + * fileio.c (find_path_filename): move there. + * string.c (make_suffix): ditto. + + * font.c (get_char): retrieve the TFM width also. + +Mon Jul 16 07:30:33 1990 Karl Berry (karl at hayley) + + * bitmap.c (bitmap_to_bb): new routine. + +Thu Jul 12 06:01:16 1990 Karl Berry (karl at hayley) + + * bitmap.c (copy_bitmap): don't use `new_bitmap', to avoid setting + all the bits twice. + +Tue Jul 10 06:23:54 1990 Karl Berry (karl at hayley) + + * bitmap.c (concat_bitmaps): new routine. + +Mon Jul 9 08:27:09 1990 Karl Berry (karl at hayley) + + * bitmap.c (get_bitmap_bounding_box): delete this. + (print_bitmap): use dimensions_to_bb. + + * bitmap.c (free_bitmap): don't free the bitmap if it's null. + + * bitmap.c (new_bitmap): use memset. + (copy_bitmap): use memcpy if the bitmap's size is greater than + zero. + +Sat Jul 7 18:22:55 1990 Karl Berry (karl at hayley) + + * memory.c (safe_free): dump core if we are freeing a null item. + +Fri Jul 6 14:21:07 1990 Karl Berry (karl at hayley) + + * bounding-box.c (bb_to_dimensions): ensure that the dimensions + are nonnegative. + +Wed Jul 4 12:06:49 1990 Karl Berry (karl at hayley) + + * memory.c (allocate): dump core if we run out of memory. + (reallocate): ditto. + + * bounding-box.c (dimensions_to_bb): don't subtract one from the + width, so it will work with the GF routines. + (bb_to_dimensions): use BB_WIDTH and BB_HEIGHT, instead of doing + the subtraction out here. + + * bounding-box.c (update_bounding_box): new routine. + +Sun Jul 1 15:11:56 1990 Karl Berry (karl at hayley) + + * font.c (ascender_part): new routine. + +Tue Jun 26 11:27:15 1990 Karl Berry (karl at hayley) + + * spline.c (evaluate_spline): use temporaries in the computation + to avoid a compiler bug. + + * vector.c (Padd, Pmult_scalar): remove definitions, since they + are defined as macros now. + +Sun Jun 24 15:31:34 1990 Karl Berry (karl at claude) + + * font.c (get_font): don't check the checksums if either one is + zero. + +Sat Jun 23 12:11:47 1990 Karl Berry (karl at hayley) + + * font.c (print_char): change precision for printing the row numbers. + +Tue Jun 19 11:50:52 1990 Karl Berry (karl at hayley) + + * fileio.c (move_to_byte): delete this. + + * fileio.c (cur_pos): rename to checked_ftell, and take a filename + argument for perror. + +Mon Jun 18 12:47:17 1990 Karl Berry (karl at hayley) + + * font.c (find_internal_font): return a pointer to an + internal_font_type, instead of a structure, and change callers. + (get_font): if we have already saved the font, return it, instead + of opening the files again. + +Mon Jun 4 16:20:32 1990 Karl Berry (karl at hayley) + + * math.c (find_bounds): use MAXDOUBLE and MINDOUBLE, instead of + MAXFLOAT and MINFLOAT. + + * spline.c (spline_bounding_box): remove this routine. + +Sun Jun 3 10:51:28 1990 Karl Berry (karl at hayley) + + * arith.c, math.c, vector.c: add const declarations. + + * fileio.c (get_two, get_four): don't bother to initialize the + variable before we read it. + + * fileio.c (get_n_bytes): improve the error message if the read + fails. + +Sat Jun 2 07:51:08 1990 Karl Berry (karl at hayley) + + * bounding-box.c (increase_int_bound): remove this. + + * spline.c (print_spline): print different things for lines and + splines. + +Wed May 30 16:02:26 1990 Karl Berry (karl at hayley) + + * bitmap.c (new_bitmap): if the bitmap is going to be zero bits, + don't try to allocate it. + + * font.c (get_font): figure out how many characters are in the + font by testing the `exists' member of the TFM structure. + + * font.c (get_font): don't try to open the GF file if we couldn't + find it. + +Tue May 22 09:51:20 1990 Karl Berry (karl at hayley) + + * fileio.c (find_path_filename): close the directories in the path. + +Sat May 19 10:30:39 1990 Karl Berry (karl at hayley) + + * fileio.c (find_path_filename): return NULL if we can't find the + file, instead of the original name. + * font.c (get_font): rewrite the file-opening code. + +Wed May 16 18:02:54 1990 Karl Berry (karl at aten) + + * font.c (string_to_bitmap): if the character doesn't exist in the + font, don't crash. + + * fileio.c (find_path_filename): don't get a fatal error when a + directory in the path doesn't exist. + +Sun May 13 13:45:12 1990 Karl Berry (karl at hayley) + + * dirio.c (is_dir): new routine. + + * fileio.c (find_path_filename): just return the name we're given + if the path is relative; move the suffix concatenation out of the + loop; search in subdirectories. + +Tue May 8 12:08:57 1990 Karl Berry (karl at hayley) + + * math.c: doc fix. + +Thu May 3 10:45:05 1990 Karl Berry (karl at hayley) + + * line.c (read_line): use VS_CHARS. + +Wed May 2 12:25:08 1990 Karl Berry (karl at claude) + + * font.c (string_to_bitmap): don't close the font when we're done. + +Wed Apr 25 13:16:28 1990 Karl Berry (karl at aten) + + * font.c (string_to_bitmap): don't asked for chars[x] when x is a + character that isn't there. + +Tue Apr 24 18:35:08 1990 Karl Berry (karl at hayley) + + * math.c (real_to_int_coord): new routine. + +Sun Apr 22 06:42:37 1990 Karl Berry (karl at hayley) + + * font.c (string_to_bitmap): initialize char_y properly. + [whoops, I mean test it properly, and initialize y.] + Pass the row and column to BITMAP_PIXEL in the right order. + Give the row and column to the constructor in the right order, + too. Use MAX to find the depth, not MIN. + + * font.c (print_char): print the bitmap here, so we can print out + the Cartesian row number, instead of calling `print_bitmap'. + +Sat Apr 21 09:49:42 1990 Karl Berry (karl at hayley) + + * fileio.c (get_n_bytes): use fread to read the whole block, + instead of getting them one byte at a time. + +Thu Apr 19 16:19:33 1990 Karl Berry (karl at hayley) + + * font.c (get_font): do checksum test before getting the + postamble. + +Tue Apr 17 16:53:31 1990 Karl Berry (karl at hayley) + + * font.c (print_char): new routine to print a text representation + of a character. + +Mon Apr 16 11:12:28 1990 Karl Berry (karl at hayley) + + * font.c (get_font): get the design size from the TFM file, + instead of the bitmap file. + +Sun Apr 15 07:34:19 1990 Karl Berry (karl at hayley) + + * font.c (get_font): do not set the font bounding box. + +Sat Apr 14 15:11:19 1990 Karl Berry (karl at hayley) + + * fileio.c (checked_fseek): make argument type be + seek_direction_type. + + * fileio.c (checked_fclose): new (trivial) routine. + +Thu Apr 12 12:06:17 1990 Karl Berry (karl at hayley) + + * GNUmakefile: do not define USG and USGr3. + + * time.c: include <sys/types.h> and declare time(2) and ctime(3) + using time_t. + + * fileio.c (find_path_filename): use access(2) instead of + fopen(3); pass the default path to find_components. + (find_components): use a default path if the environment variable + doesn't exist. + +Mon Apr 9 08:19:53 1990 Karl Berry (karl at hayley) + + * math.c (distance): remove this, I came across hypot(3). + + * all files: upcase macro names. + +Sun Mar 18 14:58:23 1990 Kathy Hargreaves (kathy at hayley) + + * bounding_box.[hc] (increase_int_bound): added this to increase a + bounding boxes bounds nicely, i.e., if the bound is negative, it + gets decreased, and increased otherwise. + +Tue Feb 27 21:01:24 1990 Kathy Hargreaves (kathy at hayley) + + * fileio.c (get_n_bytes): don't try to read zero bytes. + +Wed Feb 7 17:00:47 1990 Karl Berry (karl at hayley) + + * time.c (now): chop off the trailing space. + +Mon Jan 29 12:46:56 1990 Karl Berry (karl at hayley) + + * bounding-box.c (bb_to_dimensions): new routine. + + * math.c (atou): like atoi but < 0 is a fatal error. + +Sun Jan 21 09:55:14 1990 Karl Berry (karl at hayley) + + * Makefile: rename to GNUmakefile. + + * bounding_box.c (dimensions_to_bounding_box): rename to + dimensions_bb. Remove other conversion routines. And rename to + bounding-box.c. + +Tue Oct 31 07:24:05 1989 Karl Berry (karl at hayley) + + * math.c (int_to_real_coordinate): remove this. + +Mon Oct 30 14:03:57 1989 Karl Berry (karl at hayley) + + * all files: add the copyleft. + + * string.c (concat4): define this. + +Sun Oct 29 18:37:33 1989 Karl Berry (karl at claude) + + * math.c (undefined_real_coordinate): remove this. + +Sat Oct 28 15:55:59 1989 Karl Berry (karl at hayley) + + * arith.c (real_to_scaled, real_to_fix): multiply the integer part + by scaled_one and fix_one, respectively. + + * fileio.c (put_three): define this. + (put_three, put_four): had the mask wrong for the + low-order byte. + (put_two, put_three, put_four): a & b >> c is + a & (b >> c), not (a & b) >> c. + +Fri Oct 27 22:14:05 1989 Karl Berry (karl at hayley) + + * bitmap.c (new_bitmap): use the bitmap_dimensions macro. + +Sun Oct 8 15:41:01 1989 Karl Berry (karl at hayley) + + * math.c (epsilon_equal): new function to test if two values are + within epsilon of each other. + (acosd): changed to call that one. + + * bitmap.c (free_bitmap): new function to deallocate storage + used in a bitmap_type. + + * math.c (acosd): normalize to 1.0 or -1.0 if the argument is + within an epsilon of that anyway. + +Fri Oct 6 22:12:05 1989 Karl Berry (karl at hayley) + + * line.c (read_line): overwrite the newline at the end of the + string with a null. diff --git a/lib/GNUmakefile b/lib/GNUmakefile new file mode 100644 index 0000000..ed258fa --- /dev/null +++ b/lib/GNUmakefile @@ -0,0 +1,38 @@ +# Makefile for the fontutils library. +# +# Copyright (C) 1992, 93 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +library = lib + +# If this gives you trouble, just remove it. The system malloc will +# probably work well enough. +#malloc = gmalloc + +# The headers are in the `include' directory, so don't use `c_and_h'. + +c_only = $(malloc) bb-list bb-outline bitmap bounding-box \ +charcode charspec cmdline concat concat3 concat4 concat5 dlsym edge \ +encoding float-ok fmod file-input file-output filename fix-num font \ +getopt getopt1 hexify identity integer-ok libfile line list logreport \ +make-prefix math now numtoa pathsrch rand report safe-free scaled-num \ +spline statistics str-lcase str-to-bit substring varstring vector \ +xmessage xopendir xrename + +include ../data/defs.make +include ../data/defslib.make + +include M.depend diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..4d0c220 --- /dev/null +++ b/lib/README @@ -0,0 +1,73 @@ +This library contains many miscellanous functions that are used by the +other programs we have written. + +The declarations for the functions are in ../include. config.h must be +included first in a .c file; that includes global.h, which declares a +few of the most commonly used functions here. The rest have their own +include files, e.g., line.h. + +Some functions merely call a C library routine or make a system call, +check the return status, and abort if the function failed. (In the +programs this has been used for, that was all that we ever wanted.) + +Here is a brief description of what's here (aside from the files which +have just one function in them and other ``obvious'' ones): + +bb-outline find the outlines in a bitmap character. + +bitmap operations on bitmaps, with each pixel represented by a + byte in memory. + +bounding-box conversions to and from bounding boxes, both integer + and real. + +cmdline standard things for reading option lists. + +dirio directory operations. + +encoding read a font encoding specification in a .enc file. + +file-input read BigEndian values. + +file-open wrappers for fopen and fclose. + +file-output write BigEndian values. + +filename operations on filenames. + +fix-num conversions for the `fix_word' fixed-point fraction + type, used in TFM files et al. + +font read a bitmap font, or a bitmap font and its metrics. + +hexify convert a sequence of binary data to its hex representation. + +libfile read a `library', i.e., an auxiliary data, file. + +line read an arbitrarily long line from a file, returning a string. + +list generic list operations. It is a tossup as to whether + it is easier to repeat this code for the particular + lists you desire, or to use these, often with an extra + level of pointers. Unfortunately, C does not support + generic types. + +math distance, slope, etc., between two points; operations on + arrays as a collection of numeric data. + +now the current time as in date(1). + +pathsearch look up a filename along a path in an environment variable. + +report online progress reporting. + +scaled-num routines for the `scaled' fixed-point fraction + type, used in GF files et al. + +spline operations on Bezier splines. + +statistics find the mean/standard deviation of an array of numbers. + +varstring variable-length strings. + +vector operations on vectors and point/vector combinations. diff --git a/lib/atou.o b/lib/atou.o Binary files differnew file mode 100644 index 0000000..d15e642 --- /dev/null +++ b/lib/atou.o diff --git a/lib/basename.o b/lib/basename.o Binary files differnew file mode 100644 index 0000000..8242dd6 --- /dev/null +++ b/lib/basename.o diff --git a/lib/bb-list.c b/lib/bb-list.c new file mode 100644 index 0000000..e3df94e --- /dev/null +++ b/lib/bb-list.c @@ -0,0 +1,76 @@ +/* bb-list.c: operations on bounding box lists. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "bb-list.h" + + +/* This routine returns an initialized empty list. */ + +bb_list_type +bb_list_init () +{ + bb_list_type bb_list; + + BB_LIST_LENGTH (bb_list) = 0; + BB_LIST_DATA (bb_list) = NULL; + + return bb_list; +} + +/* Append BB to BB_LIST. */ + +void +bb_list_append (bb_list_type *bb_list, bounding_box_type bb) +{ + BB_LIST_LENGTH (*bb_list)++; + XRETALLOC (BB_LIST_DATA (*bb_list), BB_LIST_LENGTH (*bb_list), + bounding_box_type); + + BB_LIST_ELT (*bb_list, BB_LIST_LENGTH (*bb_list) - 1) = bb; +} + +/* Append the elements in the list B2 onto the end of B1. */ + +void +bb_list_splice (bb_list_type *b1, bb_list_type b2) +{ + unsigned new_length; + unsigned this_bb; + + if (BB_LIST_LENGTH (b2) == 0) + return; + + assert (b1 != NULL); + + new_length = BB_LIST_LENGTH (*b1) + BB_LIST_LENGTH (b2); + XRETALLOC (BB_LIST_DATA (*b1), new_length, bounding_box_type); + + for (this_bb = 0; this_bb < BB_LIST_LENGTH (b2); this_bb++) + BB_LIST_ELT (*b1, BB_LIST_LENGTH (*b1)++) = BB_LIST_ELT (b2, this_bb); +} + +/* Free the memory in a list. */ + +void +bb_list_free (bb_list_type *bb_list) +{ + if (BB_LIST_DATA (*bb_list) != NULL) + safe_free ((address *) &BB_LIST_DATA (*bb_list)); +} diff --git a/lib/bb-outline.c b/lib/bb-outline.c new file mode 100644 index 0000000..1f0e3fa --- /dev/null +++ b/lib/bb-outline.c @@ -0,0 +1,114 @@ +/* bb-outline.c: find the bounding boxes enclosing outlines. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "bb-outline.h" +#include "edge.h" + + +static bounding_box_type find_one_bb + (bitmap_type, edge_type, unsigned, unsigned, bitmap_type *); + +/* A character is made up of a list of one or more outlines. Here, we + go through a character's bitmap marking edges on pixels, top to + bottom, left to right, looking for the next pixel with an unmarked + edge that is also on the character's outline. Each one of these + pixels we find is the starting place for one outline. We then get the + bounding boxes of the outlines, and put them in a list to return. We + don't look at pixels that are at or after the column LEFT_MARK or + before RIGHT_MARK. If FIND_INNER is false, we return only outside + outlines; otherwise, we return both inside and outside. */ + +bb_list_type +find_outline_bbs (bitmap_type b, boolean find_inner, + int left_mark, int right_mark) +{ + unsigned row, col; + bb_list_type bb_list = bb_list_init (); + bitmap_type marked = new_bitmap (BITMAP_DIMENSIONS (b)); + + /* By looking through the bitmap in column-major order, we preserve + the original ordering of the characters in the image. Otherwise, + `b' would be found before `a' (for example), because of the + ascender. */ + for (col = 0; col < BITMAP_WIDTH (b); col++) + if (col < left_mark || col >= right_mark) + for (row = 0; row < BITMAP_HEIGHT (b); row++) + { + edge_type edge; + + if (BITMAP_PIXEL (b, row, col) == WHITE + || BITMAP_INTERIOR_PIXEL (b, row, col)) + continue; + + /* Get the next unmarked edge on this pixel, if there is one. */ + edge = next_unmarked_outline_edge (row, col, START_EDGE, b, marked); + + /* If there is an unmarked outline edge on this pixel... */ + if (edge != no_edge) + { + /* Want to mark edges in inner boxes, too. */ + bounding_box_type bb = find_one_bb (b, edge, row, col, &marked); + + /* If edge != START_EDGE, it's on an inner bounding box. */ + if (find_inner || edge == START_EDGE) + { + /* The numbers in BB, as it comes in, refer to pixels; + we have to change the maximum row so that it refers + to the edge beyond the last pixel. */ + MAX_COL (bb)++; + + bb_list_append (&bb_list, bb); + } + } + } + + free_bitmap (&marked); + return bb_list; +} + +/* Here we find one of a character's outlines. We're passed the + position (ORIGINAL_ROW and ORIGINAL_COL) of a starting pixel and one + of its unmarked edges, ORIGINAL_EDGE. We traverse the adjacent edges + of the outline pixels but keep the bounding box in pixel coordinates. + We keep track of the marked edges in MARKED, which should be + initialized to zeros before we get it. */ + +static bounding_box_type +find_one_bb (bitmap_type b, edge_type original_edge, + unsigned original_row, unsigned original_col, + bitmap_type *marked) +{ + bounding_box_type bb = { INT_MAX, INT_MIN, INT_MAX, INT_MIN }; + unsigned row = original_row, col = original_col; + edge_type edge = original_edge; + + do + { + coordinate_type p = { col, row }; + update_bounding_box (&bb, p); + + mark_edge (edge, row, col, marked); + next_outline_edge (b, &edge, &row, &col); + } + while (!(row == original_row && col == original_col + && edge == original_edge)); + + return bb; +} diff --git a/lib/bitmap.c b/lib/bitmap.c new file mode 100644 index 0000000..9223c66 --- /dev/null +++ b/lib/bitmap.c @@ -0,0 +1,258 @@ +/* bitmap.c: operations on bitmaps. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "bitmap.h" +#include "bounding-box.h" + +static void bb_ensure_bounds (bounding_box_type *, bitmap_type, string); + +/* Make sure the bitmap is entirely white to begin with. */ + +bitmap_type +new_bitmap (dimensions_type d) +{ + bitmap_type answer; + unsigned size = DIMENSIONS_WIDTH (d) * DIMENSIONS_HEIGHT (d); + + BITMAP_DIMENSIONS (answer) = d; + BITMAP_BITS (answer) = size > 0 ? xcalloc (size, 1) : NULL; + + return answer; +} + + +/* Free the storage that is allocated for a bitmap. On the other hand, + the bitmap might not have any storage allocated for it if it is zero + in either dimension; in that case, don't free it. */ + +void +free_bitmap (bitmap_type *b) +{ + if (BITMAP_BITS (*b) != NULL) + safe_free ((address *) &BITMAP_BITS (*b)); +} + + +/* Copy an existing bitmap into new memory. We don't want to use + `new_bitmap' here, since that routine clears the bitmap's bits, and + we are going to set all the bits ourselves, anyway. */ + +bitmap_type +copy_bitmap (bitmap_type bitmap) +{ + bitmap_type answer; + unsigned size = BITMAP_WIDTH (bitmap) * BITMAP_HEIGHT (bitmap); + + BITMAP_DIMENSIONS (answer) = BITMAP_DIMENSIONS (bitmap); + BITMAP_BITS (answer) = size > 0 ? xmalloc (size) : NULL; + + if (size > 0) + memcpy (BITMAP_BITS (answer), BITMAP_BITS (bitmap), size); + + return answer; +} + + +/* Return the part of the bitmap SOURCE enclosed by the bounding box BB. + BB is interpreted in bitmap coordinates, with y increasing downwards; + for example, if MIN_ROW (BB) == 10, the subimage will start in the + tenth row from the top of SOURCE. */ + +bitmap_type +extract_subbitmap (bitmap_type source, bounding_box_type bb) +{ + unsigned this_row; + bitmap_type sub = new_bitmap (bb_to_dimensions (bb)); + + /* Move to the bit at which we want to start copying. */ + BITMAP_BITS (source) += MIN_ROW (bb) * BITMAP_WIDTH (source) + MIN_COL (bb); + + bb_ensure_bounds (&bb, source, "extract_subbitmap"); + + for (this_row = MIN_ROW (bb); this_row <= MAX_ROW (bb); this_row++) + { + one_byte *target = BITMAP_ROW (sub, this_row - MIN_ROW (bb)); + + memcpy (target, BITMAP_BITS (source), BITMAP_WIDTH (sub)); + BITMAP_BITS (source) += BITMAP_WIDTH (source); + } + + return sub; +} + + +/* If any of the elements of BB (taken to be in bitmap coordinates) are + outside the bounds of the bitmap SOURCE, give a warning (using NAME) + and update them. */ + +static void +bb_ensure_bounds (bounding_box_type *bb, bitmap_type source, string name) +{ + if (MIN_COL (*bb) < 0) + { + WARNING2 ("%s: min col=%d outside source image", name, MIN_COL (*bb)); + MIN_COL (*bb) = 0; + } + + if (MIN_ROW (*bb) < 0) + { + WARNING2 ("%s: min row=%d outside source image", name, MIN_ROW (*bb)); + MIN_COL (*bb) = 0; + } + + /* See comments at `get_character_bitmap' in gf_input.c for why the + width and height are treated asymetrically. */ + if (MAX_COL (*bb) > BITMAP_WIDTH (source)) + { + WARNING2 ("%s: max col=%d outside source image", name, MAX_COL (*bb)); + MAX_COL (*bb) = BITMAP_WIDTH (source) - 1; + } + + if (MAX_ROW (*bb) >= BITMAP_HEIGHT (source)) + { + WARNING2 ("%s: max row=%d outside source image", name, MAX_ROW (*bb)); + MAX_COL (*bb) = BITMAP_HEIGHT (source) - 1; + } +} + +/* The bounding boxes that we make in this routine are unlike the + bounding boxes used elsewhere. These are in bitmap coordinates, not + Cartesian, and they refer to pixels, not edges. So we have to adjust + the maximum column by one. */ + +const bounding_box_type +bitmap_to_bb (const bitmap_type b) +{ + bounding_box_type bb = dimensions_to_bb (BITMAP_DIMENSIONS (b)); + if (MAX_COL (bb) != 0) MAX_COL (bb)--; + + return bb; +} + +/* Return the (zero-based) column numbers in which ROW changes from + black to white or white to black. The first element marks a + white-to-black transition, and the last element marks a + black-to-white transition, imagining that ROW is surrounded by white. + (In other words, there is always an even number of transitions.) We + mark the end of the vector with an element WIDTH + 1. */ + +/* We use `length - 2' because we need to save one element at the end + for our sentinel. */ +#define INSERT_TRANSITION(e) \ + do { \ + XRETALLOC (vector, ++length, unsigned); \ + vector[length - 2] = e; \ + } while (0) + +unsigned * +bitmap_find_transitions (const one_byte *row, unsigned width) +{ + unsigned col; + unsigned start; + one_byte color = BLACK; + unsigned length = 1; + + /* We want to make sure we start at a column with some black. */ + char *start_ptr = memchr (row, BLACK, width); + + /* Save the last element for the sentinel. */ + unsigned *vector = XTALLOC1 (unsigned); + + if (start_ptr == NULL) + start = width; /* Don't go through the loop. */ + else + { + INSERT_TRANSITION (start_ptr - (char *) row); + start = vector[0] + 1; /* Don't look at this pixel again. */ + } + + for (col = start; col < width - 1; col++) + { + if (row[col] != color) + { + INSERT_TRANSITION (col); + color = row[col]; + } + } + + /* We have to treat the last pixel in ROW specially. There are + several cases: + 1) if it's white, and the previous pixel is white, or the row is + one pixel long, do nothing; + 2) if it's white, and the previous pixel is black, + insert one element in `vector' (marking the end of a run); + 3) if it's black, and either the previous pixel is black or this was the + first black pixel in the row, insert one element (marking the + end of a run because we're at the end of the row); + 4) if it's black, and the previous pixel is white and there was a + previous black pixel, or the row was one pixel long, insert + two elements (marking the start and end of this one-pixel run). + */ + if (row[width - 1] == WHITE) + { + if (width > 1 && row[width - 2] == BLACK) + INSERT_TRANSITION (width - 1); + } + else + { /* Last pixel is black. If previous pixel was also black, just + finish off the run. */ + if (width > 1 && row[width - 2] == BLACK) + INSERT_TRANSITION (width); + else + { /* Last pixel is black, previous pixel was white. If this was + the only black pixel in the row, we've already inserted the + start of the run via `start' above, so just insert the end of + the run. Otherwise, insert both the start and end of this + one-pixel run. */ + if (start != width) + INSERT_TRANSITION (width - 1); + INSERT_TRANSITION (width); + } + } + + vector[length - 1] = width + 1; /* Sentinel for the end of the vector. */ + return vector; +} + +/* Print a part of the bitmap in human-readable form. */ + +void +print_bounded_bitmap (FILE *f, bitmap_type bitmap, bounding_box_type bb) +{ + unsigned this_row, this_col; + + fprintf (f, "Printing bitmap between (%u,%u) and (%u,%u):\n", + MIN_COL (bb), MIN_ROW (bb), + MAX_COL (bb), MAX_ROW (bb)); + for (this_row = MIN_ROW (bb); this_row <= MAX_ROW (bb); this_row++) + { + for (this_col = MIN_COL (bb); this_col <= MAX_COL (bb); this_col++) + putc (BITMAP_PIXEL (bitmap, this_row, this_col) ? '*' : ' ', f); + + fprintf (f, "%u\n", this_row); + } +} + + +void +print_bitmap (FILE *f, bitmap_type b) +{ + print_bounded_bitmap (f, b, bitmap_to_bb (b)); +} diff --git a/lib/bounding-box.c b/lib/bounding-box.c new file mode 100644 index 0000000..25f0b74 --- /dev/null +++ b/lib/bounding-box.c @@ -0,0 +1,78 @@ +/* bounding-box.c: definitions for bounding box operations. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "bounding-box.h" + + +/* See the comments at `get_character_bitmap' in gf_input.c for why the + width and height are treated asymmetrically. */ + +const bounding_box_type +dimensions_to_bb (dimensions_type dimensions) +{ + bounding_box_type answer; + + MIN_ROW (answer) = 0; + MIN_COL (answer) = 0; + MAX_ROW (answer) = MAX ((int) DIMENSIONS_HEIGHT (dimensions) - 1, 0); + MAX_COL (answer) = MAX (DIMENSIONS_WIDTH (dimensions), 0); + + return answer; +} + + +/* Dimensions can't be negative, even though bounding boxes can, so we + have to check. */ + +const dimensions_type +bb_to_dimensions (bounding_box_type bb) +{ + dimensions_type d; + + DIMENSIONS_WIDTH (d) = MAX (BB_WIDTH (bb), 0); + DIMENSIONS_HEIGHT (d) = MAX (BB_HEIGHT (bb), 0); + + return d; +} + + +/* If the point P lies outside of any of the current bounds in BB, + update BB. */ + +void +update_real_bounding_box (real_bounding_box_type *bb, real_coordinate_type p) +{ + if (p.x < MIN_COL (*bb)) MIN_COL (*bb) = p.x; + if (p.x > MAX_COL (*bb)) MAX_COL (*bb) = p.x; + if (p.y < MIN_ROW (*bb)) MIN_ROW (*bb) = p.y; + if (p.y > MAX_ROW (*bb)) MAX_ROW (*bb) = p.y; + +} + + +void +update_bounding_box (bounding_box_type *bb, coordinate_type p) +{ + if (p.x < MIN_COL (*bb)) MIN_COL (*bb) = p.x; + if (p.x > MAX_COL (*bb)) MAX_COL (*bb) = p.x; + if (p.y < MIN_ROW (*bb)) MIN_ROW (*bb) = p.y; + if (p.y > MAX_ROW (*bb)) MAX_ROW (*bb) = p.y; + +} diff --git a/lib/charcode.c b/lib/charcode.c new file mode 100644 index 0000000..931928f --- /dev/null +++ b/lib/charcode.c @@ -0,0 +1,85 @@ +/* charcode.c: parse character code strings into their values. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + + +/* This routine parses the string CHARCODE as a character code (see the + .h file). If CHARCODE cannot be parsed, *VALID is set to false and + the value returned is unpredictable; otherwise, it is set to true and + the value returned is the character code. */ + +charcode_type +parse_charcode (string charcode, boolean *valid) +{ + int code = 75; /* OK, it's not *really* unpredictable. */ + unsigned length = strlen (charcode); + + if (charcode == NULL || length == 0) + *valid = false; + else + { /* We need this to ensure that there are no extra characters after + the character code. */ + char dummy; + + /* If a single character, return its value. */ + if (length == 1) + { + *valid = true; + code = *charcode; + } + + else if (*charcode == '0') + { /* Either octal or hex. */ + if (*(charcode + 1) == 'x' || *(charcode + 1) == 'X') + /* It seems not all scanf's ignore a leading `0x'. */ + *valid = sscanf (charcode + 2, "%x%c", &code, &dummy) == 1; + else + /* octal */ + *valid = sscanf (charcode, "%o%c", &code, &dummy) == 1; + } + + else + /* decimal */ + *valid = sscanf (charcode, "%d%c", &code, &dummy) == 1; + + /* Since our return type can only hold numbers up to 255 (typically), + we are justified in using the numeric constant here, instead of + `MAX_CHARCODE'. */ + if (*valid) + *valid = 0 <= code && code <= 255; + } + + return code; +} + + +/* This routine calls `parse_charcode', and, if the character code is + invalid, gives a fatal error. */ + +charcode_type +xparse_charcode (string charcode) +{ + boolean valid; + charcode_type code = parse_charcode (charcode, &valid); + + if (!valid) + FATAL1 ("xparse_charcode: Invalid character code `%s'", charcode); + + return code; +} diff --git a/lib/charspec.c b/lib/charspec.c new file mode 100644 index 0000000..cf7c407 --- /dev/null +++ b/lib/charspec.c @@ -0,0 +1,63 @@ +/* charspec.c: parse a character code or name. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include <kpathsea/c-ctype.h> +#include "charspec.h" +#include "encoding.h" + + +charcode_type +xparse_charspec (string spec, encoding_info_type *enc) +{ + int code; + + /* It's an error to call this with SPEC == NULL or the empty string. */ + assert (spec != NULL && *spec); + + if (ISDIGIT (*spec)) + code = xparse_charcode (spec); + + else if (enc == NULL) + { + /* If ENC is null, and SPEC is longer than a single character, we + don't know what to do. */ + if (spec[1] != 0) + FATAL1 ("%s: Unparseable character specification", spec); + else + code = *spec; + } + + else + { + int code = encoding_number (*enc, spec); + + /* If SPEC is not in the encoding, and it's one character long, + just use its value as a C integer. */ + if (code == -1) + { + if (spec[1] == 0) + code = spec[0]; + else + FATAL1 ("%s: Undefined character name", spec); + } + } + + return (charcode_type) code; +} diff --git a/lib/cmdline.c b/lib/cmdline.c new file mode 100644 index 0000000..3552fae --- /dev/null +++ b/lib/cmdline.c @@ -0,0 +1,63 @@ +/* cmdline.c: routines to help in parsing command lines. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "cmdline.h" + + +/* This routine takes a string L consisting of unsigned integers + separated by commas and returns a vector of the integers, as numbers. + A element is appended to the vector. */ + +int * +scan_unsigned_list (string l) +{ + string map; + unsigned length = 1; + int *vector = xmalloc (sizeof (int)); + + for (map = strtok (l, ","); map != NULL; map = strtok (NULL, ",")) + { + length++; + vector = xrealloc (vector, length * sizeof (int)); + vector[length - 2] = atou (map); + if (vector[length - 2] < 0) + WARNING1 ("Unsigned number %u is too large", vector[length - 2]); + } + + vector[length - 1] = -1; + return vector; +} + + +/* Return the <number> substring in `<name>.<number><stuff>', if S has + that form. If it doesn't, return NULL. */ + +string +find_dpi (string s) +{ + unsigned dpi_number; + string extension = strrchr (s, '.'); + + if (extension != NULL) + if (sscanf (extension + 1, "%u", &dpi_number) == 1) + return utoa (dpi_number); + + return NULL; +} diff --git a/lib/concat.c b/lib/concat.c new file mode 100644 index 0000000..946ed19 --- /dev/null +++ b/lib/concat.c @@ -0,0 +1,41 @@ +/* concat.c: dynamic string concatenation. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +/* Return the concatenation of S1 and S2. This would be a prime place + to use varargs. */ + +string +concat P2C(const_string, s1, const_string, s2) +{ + string answer = NULL; + + assert (s1 != NULL); + assert (s2 != NULL); + + if (s1 != NULL && s2 != NULL) + { + answer = (string) xmalloc (strlen (s1) + strlen (s2) + 1); + + strcpy (answer, s1); + strcat (answer, s2); + } + + return answer; +} diff --git a/lib/concat3.c b/lib/concat3.c new file mode 100644 index 0000000..383a54c --- /dev/null +++ b/lib/concat3.c @@ -0,0 +1,40 @@ +/* concat3.c: concatenate three strings. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +string +concat3 P3C(const_string, s1, const_string, s2, const_string, s3) +{ + string answer = NULL; + + assert (s1 != NULL); + assert (s2 != NULL); + assert (s3 != NULL); + + if (s1 != NULL && s2 != NULL && s3 != NULL) + { + answer = (string) xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1); + + strcpy (answer, s1); + strcat (answer, s2); + strcat (answer, s3); + } + + return answer; +} diff --git a/lib/concat4.c b/lib/concat4.c new file mode 100644 index 0000000..f8b3d06 --- /dev/null +++ b/lib/concat4.c @@ -0,0 +1,43 @@ +/* concat4.c: concatenate four strings. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +string +concat4 P4C(const_string, s1, const_string, s2, const_string, s3, + const_string, s4) +{ + string answer = NULL; + + assert (s1 != NULL); + assert (s2 != NULL); + assert (s3 != NULL); + assert (s4 != NULL); + + if (s1 != NULL && s2 != NULL && s3 != NULL && s4 != NULL) + { + answer = (string) xmalloc (strlen (s1) + strlen (s2) + + strlen (s3) + strlen (s4) + 1); + strcpy (answer, s1); + strcat (answer, s2); + strcat (answer, s3); + strcat (answer, s4); + } + + return answer; +} diff --git a/lib/concat5.c b/lib/concat5.c new file mode 100644 index 0000000..fbf9601 --- /dev/null +++ b/lib/concat5.c @@ -0,0 +1,45 @@ +/* concat5.c: concatenate five strings. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +string +concat5 P5C(const_string, s1, const_string, s2, const_string, s3, + const_string, s4, const_string, s5) +{ + string answer = NULL; + + assert (s1 != NULL); + assert (s2 != NULL); + assert (s3 != NULL); + assert (s4 != NULL); + assert (s5 != NULL); + + if (s1 != NULL && s2 != NULL && s3 != NULL && s4 != NULL && s5 != NULL) + { + answer = (string) xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + + strlen (s4) + strlen (s5) + 1); + strcpy (answer, s1); + strcat (answer, s2); + strcat (answer, s3); + strcat (answer, s4); + strcat (answer, s5); + } + + return answer; +} diff --git a/lib/dlsym.c b/lib/dlsym.c new file mode 100644 index 0000000..c14ffdd --- /dev/null +++ b/lib/dlsym.c @@ -0,0 +1,28 @@ +/* + * Stub interface to dynamic linker routines + * that SunOS uses but didn't ship with 4.1. + * + * The C library routine wcstombs in SunOS 4.1 tries to dynamically + * load some routines using the dlsym interface, described in dlsym(3x). + * Unfortunately SunOS 4.1 does not include the necessary library, libdl. + * + * The R5 Xlib uses wcstombs. If you link dynamcally, your program can + * run even with the unresolved reference to dlsym. However, if you + * link statically, you will encounter this bug. One workaround + * is to include these stub routines when you link. + */ + +void *dlopen() +{ + return 0; +} + +void *dlsym() +{ + return 0; +} + +int dlclose() +{ + return -1; +} diff --git a/lib/edge.c b/lib/edge.c new file mode 100644 index 0000000..7bec506 --- /dev/null +++ b/lib/edge.c @@ -0,0 +1,265 @@ +/* edge.c: operations on edges in bitmaps. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "edge.h" + + +/* We can move in any of eight directions as we are traversing + the outline. These numbers are not arbitrary; TRY_PIXEL depends on + them. */ + +typedef enum +{ + north = 0, northwest = 1, west = 2, southwest = 3, south = 4, + southeast = 5, east = 6, northeast = 7 +} direction_type; + + +static boolean is_marked_edge (edge_type, unsigned, unsigned, bitmap_type); +static boolean is_outline_edge (edge_type, bitmap_type, unsigned, unsigned); +static edge_type next_edge (edge_type); + +/* The following macros are used (directly or indirectly) by the + `next_outline_edge' routine. */ + +/* Given the direction DIR of the pixel to test, decide which edge on + that pixel we are supposed to test. Because we've chosen the mapping + from directions to numbers carefully, we don't have to do much. */ + +#define FIND_TEST_EDGE(dir) ((dir) / 2) + + +/* Find how to move in direction DIR on the axis AXIS (either `ROW' or + `COL'). We are in the ``display'' coordinate system, with y + increasing downward and x increasing to the right. Therefore, we are + implementing the following table: + + direction row delta col delta + north -1 0 + south +1 0 + east 0 +1 + west 0 +1 + + with the other four directions (e.g., northwest) being the sum of + their components (e.g., north + west). + + The first macro, `COMPUTE_DELTA', handles splitting up the latter + cases, all of which have been assigned odd numbers. */ + +#define COMPUTE_DELTA(axis, dir) \ + ((dir) % 2 != 0 \ + ? COMPUTE_##axis##_DELTA ((dir) - 1) \ + + COMPUTE_##axis##_DELTA (((dir) + 1) % 8) \ + : COMPUTE_##axis##_DELTA (dir) \ + ) + +/* Now it is trivial to implement the four cardinal directions. */ +#define COMPUTE_ROW_DELTA(dir) \ + ((dir) == north ? -1 : (dir) == south ? +1 : 0) + +#define COMPUTE_COL_DELTA(dir) \ + ((dir) == west ? -1 : (dir) == east ? +1 : 0) + + +/* See if the appropriate edge on the pixel from (row,col) in direction + DIR is on the outline. If so, update `row', `col', and `edge', and + break. We also use the variable `character' as the bitmap in which + to look. */ + +#define TRY_PIXEL(dir) \ + { \ + int delta_r = COMPUTE_DELTA (ROW, dir); \ + int delta_c = COMPUTE_DELTA (COL, dir); \ + int test_row = *row + delta_r; \ + int test_col = *col + delta_c; \ + edge_type test_edge = FIND_TEST_EDGE (dir); \ + \ + if (BITMAP_VALID_PIXEL (character, test_row, test_col) \ + && is_outline_edge (test_edge, character, test_row, test_col)) \ + { \ + *row = test_row; \ + *col = test_col; \ + *edge = test_edge; \ + break; \ + } \ + } + +/* Finally, we are ready to implement the routine that finds the next + edge on the outline. We look first for an adjacent edge that is not + on the current pixel. We want to go around outside outlines + counterclockwise, and inside outlines clockwise (because that is how + both Metafont and Adobe Type 1 format want their curves to be drawn). + + The very first outline (an outside one) on each character starts on a + top edge (STARTING_EDGE in edge.h defines this); so, if we're at a + top edge, we want to go only to the left (on the pixel to the west) + or down (on the same pixel), to begin with. Then, when we're on a + left edge, we want to go to the top edge (on the southwest pixel) or + to the left edge (on the south pixel). + + All well and good. But if you draw a rasterized circle (or whatever), + eventually we have to come back around to the beginning; at that + point, we'll be on a top edge, and we'll have to go to the right edge + on the northwest pixel. Draw pictures. + + The upshot is, if we find an edge on another pixel, we return (in ROW + and COL) the position of the new pixel, and (in EDGE) the kind of + edge it is. If we don't find such an edge, we return (in EDGE) the + next (in a counterclockwise direction) edge on the current pixel. */ + +void +next_outline_edge (bitmap_type character, edge_type *edge, + unsigned *row, unsigned *col) +{ + unsigned original_row = *row; + unsigned original_col = *col; + + switch (*edge) + { + case right: + TRY_PIXEL (north); + TRY_PIXEL (northeast); + break; + + case top: + TRY_PIXEL (west); + TRY_PIXEL (northwest); + break; + + case left: + TRY_PIXEL (south); + TRY_PIXEL (southwest); + break; + + case bottom: + TRY_PIXEL (east); + TRY_PIXEL (southeast); + break; + + default: + FATAL1 ("next_outline_edge: Bad edge value (%d)", *edge); + + } + + /* If we didn't find an adjacent edge on another pixel, return the + next edge on the current pixel. */ + if (*row == original_row && *col == original_col) + *edge = next_edge (*edge); +} + +/* We return the next edge on the pixel at position ROW and COL which is + an unmarked outline edge. By ``next'' we mean either the one sent in + in STARTING_EDGE, if it qualifies, or the next such returned by + `next_edge'. Otherwise, it returns NO_EDGE. */ + +edge_type +next_unmarked_outline_edge (unsigned row, unsigned col, + edge_type starting_edge, bitmap_type character, + bitmap_type marked) +{ + edge_type edge = starting_edge; + + assert (edge != no_edge); + + while (is_marked_edge (edge, row, col, marked) + || !is_outline_edge (edge, character, row, col)) + { + edge = next_edge (edge); + if (edge == starting_edge) + return no_edge; + } + + return edge; +} + + +/* We check to see if the edge EDGE of the pixel at position ROW and COL + is an outline edge; i.e., that it is a black pixel which shares that + edge with a white pixel. The position ROW and COL should be inside + the bitmap CHARACTER. */ + +boolean +is_outline_edge (edge_type edge, bitmap_type character, + unsigned row, unsigned col) +{ + /* If this pixel isn't black, it's not part of the outline. */ + if (BITMAP_PIXEL (character, row, col) == WHITE) + return false; + + switch (edge) + { + case left: + return col == 0 || BITMAP_PIXEL (character, row, col - 1) == WHITE; + + case top: + return row == 0 || BITMAP_PIXEL (character, row - 1, col) == WHITE; + + case right: + return col == BITMAP_WIDTH (character) - 1 + || BITMAP_PIXEL (character, row, col + 1) == WHITE; + + case bottom: + return row == BITMAP_HEIGHT (character) - 1 + || BITMAP_PIXEL (character, row + 1, col) == WHITE; + + case no_edge: + default: + FATAL1 ("is_outline_edge: Bad edge value(%d)", edge); + } + + return 0; /* NOTREACHED */ +} + +/* If EDGE is not already marked, we mark it; otherwise, it's a fatal error. + The position ROW and COL should be inside the bitmap MARKED. EDGE can + be `no_edge'; we just return false. */ + +void +mark_edge (edge_type edge, unsigned row, unsigned col, bitmap_type *marked) +{ + assert (!is_marked_edge (edge, row, col, *marked)); + + if (edge != no_edge) + BITMAP_PIXEL (*marked, row, col) |= 1 << edge; +} + + +/* Test if the edge EDGE at ROW/COL in MARKED is marked. */ + +static boolean +is_marked_edge (edge_type edge, unsigned row, unsigned col, bitmap_type marked) +{ + return + edge == no_edge ? false : BITMAP_PIXEL (marked, row, col) & (1 << edge); +} + + +/* Return the edge which is counterclockwise-adjacent to EDGE. This + code makes use of the ``numericness'' of C enumeration constants; + sorry about that. */ + +#define NUM_EDGES no_edge + +static edge_type +next_edge (edge_type edge) +{ + return edge == no_edge ? edge : (edge + 1) % NUM_EDGES; +} + diff --git a/lib/encoding.c b/lib/encoding.c new file mode 100644 index 0000000..a40d281 --- /dev/null +++ b/lib/encoding.c @@ -0,0 +1,191 @@ +/* encoding.c: read a font encoding (.enc) file. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "encoding.h" +#include "libfile.h" +#include "str-lcase.h" +#include "tfm.h" + + +static encoding_char_type parse_encoding_line (string); +static tfm_ligature_type parse_ligature (void); + +/* Look through INFO for NAME. */ + +int +encoding_number (encoding_info_type info, string name) +{ + unsigned code; + + if (name == NULL) + return -1; + + for (code = 0; code <= MAX_CHARCODE; code++) + if (ENCODING_CHAR_NAME (info, code) != NULL + && STREQ (ENCODING_CHAR_NAME (info, code), name)) + return code; + + return -1; +} + +/* Return the basename for the encoding file in which the encoding + CODING_SCHEME can be found. If we can't find CODING_SCHEME, return + DEFAULT_ENCODING. */ + +string +coding_scheme_to_filename (string coding_scheme) +{ + string mapping_line, enc_name; + string lc_coding_scheme = str_to_lower (coding_scheme); + + libfile_start ("encoding", "map"); + + while ((mapping_line = libfile_line ()) != NULL) + { + string test_coding_scheme, lc_test_coding_scheme; + + enc_name = strtok (mapping_line, " \t"); + test_coding_scheme = strtok (NULL, "\t"); + lc_test_coding_scheme = str_to_lower (test_coding_scheme); + + if (STREQ (lc_coding_scheme, lc_test_coding_scheme)) + break; + + free (lc_test_coding_scheme); + free (mapping_line); + } + + libfile_close (); + + if (mapping_line == NULL) + { + WARNING3 ("%s: unknown encoding `%s'; using default `%s'", + "encoding.map", coding_scheme, DEFAULT_ENCODING); + enc_name = DEFAULT_ENCODING; + } + + free (lc_coding_scheme); + + return enc_name; +} + +/* Parse the encoding file `FILENAME.enc' and return a structure + describing what we read. If the file doesn't exist, give a fatal + error. */ + +encoding_info_type +read_encoding_file (string filename) +{ + encoding_info_type info; + string line; + unsigned code; + + /* Prepare to read from FILENAME. */ + libfile_start (filename, "enc"); + + /* Start with an empty encoding. */ + for (code = 0; code <= MAX_CHARCODE; code++) + ENCODING_CHAR_NAME (info, code) = NULL; + + /* The entire first line is the TFM `CODINGSCHEME'. */ + ENCODING_SCHEME_NAME (info) = libfile_line (); + + /* Each remaining line defines one character. */ + code = 0; + while ((line = libfile_line ()) != NULL) + { + ENCODING_CHAR_ELT (info, code) = parse_encoding_line (line); + code++; + free (line); + } + + return info; +} + +/* Parse one line of the encoding file; this specifies one character. + The BNF is: + + <line> ::= <word> <ligatures> + + <ligatures> ::= <ligature> [<ligature>]? + | <empty> + + <ligature> ::= lig <charcode> =: <charcode> + + Whitespace must be between all elements. + + If the line is malformed, we give a fatal error. */ + +#define WORD_SEPARATOR " \t" +#define GET_WORD() strtok (NULL, WORD_SEPARATOR) + +static encoding_char_type +parse_encoding_line (string line) +{ + encoding_char_type c; + + c.name = xstrdup (strtok (line, WORD_SEPARATOR)); + c.ligature = list_init (); + + do + { + tfm_ligature_type *lig; + string t = GET_WORD (); + + if (t == NULL) /* Do we have more ligature specs? */ + break; + + if (!STREQ (t, "lig")) + LIBFILE_ERROR1 ("Expected `lig', found `%s'", t); + + lig = LIST_TAPPEND (&c.ligature, tfm_ligature_type); + *lig = parse_ligature (); + } + while (true); + + return c; +} + + +/* Parse a single ligature: <charcode> =: <charcode>. */ + +static tfm_ligature_type +parse_ligature () +{ + tfm_ligature_type lig; + boolean valid; + string t = GET_WORD (); + + lig.character = parse_charcode (t, &valid); + + if (!valid) + LIBFILE_ERROR1 ("Invalid right character code `%s'", t); + + t = GET_WORD (); + if (!STREQ (t, "=:")) + LIBFILE_ERROR1 ("Expected `=:', found `%s'", t); + + t = GET_WORD (); + lig.ligature = parse_charcode (t, &valid); + if (!valid) + LIBFILE_ERROR1 ("Invalid ligature character code `%s'", t); + + return lig; +} diff --git a/lib/file-input.c b/lib/file-input.c new file mode 100644 index 0000000..1bc138b --- /dev/null +++ b/lib/file-input.c @@ -0,0 +1,158 @@ +/* file-input.c: file reading routines for binary files in BigEndian + order, 2's complement representation. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "file-input.h" + + +one_byte +get_byte (FILE *f, string filename) +{ + one_byte b; + + if (fread (&b, 1, 1, f) != 1) + FATAL_PERROR (concat3 ("get_byte (", filename, ")")); + + return b; +} + + +two_bytes +get_two (FILE *f, string filename) +{ + two_bytes b; + + b = get_byte (f, filename) << 8; + b |= get_byte (f, filename); + + return b; +} + + +four_bytes +get_four (FILE *f, string filename) +{ + four_bytes b; + + b = get_byte (f, filename) << 24; + b |= get_byte (f, filename) << 16; + b |= get_byte (f, filename) << 8; + b |= get_byte (f, filename); + + return b; +} + + +/* In order to get a signed value, we merely read an unsigned value and + cast it; the value in the file is assumed to be 2's complement. */ + +signed_4_bytes +get_signed_four (FILE *f, string filename) +{ + return (signed_4_bytes) get_four (f, filename); +} + + +/* Return the next N bytes in the file F as an array. */ + +address +get_n_bytes (unsigned n, FILE *f, string filename) +{ + one_byte *b; + + if (n == 0) + FATAL1 ("get_n_bytes (%s): can't get zero bytes", filename); + + b = xmalloc (n); + + if (fread (b, n, 1, f) != 1) + FATAL2 ("get_n_bytes (%s): fread of %u bytes failed", filename, n); + + return b; +} + + + +/* Reading backwards. This macro is shared among all the routines by assuming + the name `f' for the file pointer. */ + +#define MOVE_BACK(size) xfseek (f, (long) -size, SEEK_CUR, filename) + +one_byte +get_previous_byte (FILE *f, string filename) +{ + one_byte b; + + MOVE_BACK (1); + b = get_byte (f, filename); + MOVE_BACK (1); + return b; +} + + +two_bytes +get_previous_two (FILE *f, string filename) +{ + two_bytes b; + + MOVE_BACK (2); + b = get_two (f, filename); + MOVE_BACK (2); + + return b; +} + + + +four_bytes +get_previous_four (FILE *f, string filename) +{ + four_bytes b; + + MOVE_BACK (4); + b = get_four (f, filename); + MOVE_BACK (4); + + return b; +} + + + +/* Looking for specific values in the input. */ + +void +match_byte (one_byte expected, FILE *f, string filename) +{ + one_byte b = get_byte (f, filename); + + if (b != expected) + FATAL3 ("%s: Expected byte value %u, found %u", filename, expected, b); +} + + +void +match_previous_byte (one_byte expected, FILE *f, string filename) +{ + one_byte b = get_previous_byte (f, filename); + + if (b != expected) + FATAL3 ("%s: Expected previous byte value %u, found %u", filename, + expected, b); +} diff --git a/lib/file-output.c b/lib/file-output.c new file mode 100644 index 0000000..94559ec --- /dev/null +++ b/lib/file-output.c @@ -0,0 +1,73 @@ +/* file-output.c: file writing routines for binary files in BigEndian + order, 2's complement representation. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "file-output.h" + + +/* Output in BigEndian order. We could do these more efficiently by + checking if the hardware already uses BigEndian order, but it's not + worth it. These routines are never the bottleneck (in the ways + they've been used so far, anyway). We assume that we write negative + numbers in 2's complement, also. */ + +void +put_byte (one_byte b, FILE *f, string filename) +{ + if (fwrite (&b, 1, 1, f) != 1) + FATAL2 ("%s: Could not write byte %u", filename, b); +} + + +void +put_two (two_bytes b, FILE *f, string filename) +{ + put_byte ((b & 0xff00) >> 8, f, filename); /* High-order byte. */ + put_byte (b & 0x00ff, f, filename); /* And low-order. */ +} + + +void +put_three (four_bytes b, FILE *f, string filename) +{ + put_byte ((b & 0x00ff0000) >> 16, f, filename); + put_byte ((b & 0x0000ff00) >> 8, f, filename); + put_byte (b & 0x000000ff, f, filename); +} + + +void +put_four (four_bytes b, FILE *f, string filename) +{ + put_byte ((b & 0xff000000) >> 24, f, filename); + put_byte ((b & 0x00ff0000) >> 16, f, filename); + put_byte ((b & 0x0000ff00) >> 8, f, filename); + put_byte (b & 0x000000ff, f, filename); +} + + +void +put_n_bytes (unsigned n, address b, FILE *f, string filename) +{ + one_byte *data_b = b; /* We can't dereference a pure `address'. */ + + if (fwrite (data_b, n, 1, f) != 1) + FATAL2 ("%s: Could not write %u-byte block", filename, n); +} diff --git a/lib/filename.c b/lib/filename.c new file mode 100644 index 0000000..b85d095 --- /dev/null +++ b/lib/filename.c @@ -0,0 +1,99 @@ +/* filename.c: routines to manipulate filenames. + +Copyright (C) 1992, 93 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" +#include "paths.h" + +#include "filename.h" +#include "pathsrch.h" + + +/* Try to find the PK font FONT_NAME at resolution DPI, using various + paths (see `filename.h'). The filename must have the resolution as + part of the extension, e.g., `cmr10.300pk', for it to be found. */ + +string +find_pk_filename (string font_name, unsigned dpi) +{ + static string *dirs = NULL; + string pk_var, pk_name, name; + char suffix[MAX_INT_LENGTH + sizeof ".pk"]; + + sprintf (suffix, ".%dpk", dpi); + + pk_var = getenv ("PKFONTS") ? "PKFONTS" + : getenv ("TEXPKS") ? "TEXPKS" : "TEXFONTS"; + + if (dirs == NULL) + dirs = initialize_path_list (pk_var, DEFAULT_PK_PATH); + + name = concat (font_name, suffix); + pk_name = find_path_filename (name, dirs); + + if (name != pk_name) + free (name); + + return pk_name; +} + + +/* Like `find_pk_filename', but search for a font in GF format. */ + +string +find_gf_filename (string font_name, unsigned dpi) +{ + static string *dirs = NULL; + string gf_var, gf_name, name; + char suffix[MAX_INT_LENGTH + sizeof ".pk"]; + + sprintf (suffix, ".%dgf", dpi); + + gf_var = getenv ("GFFONTS") ? "GFFONTS" : "TEXFONTS"; + + if (dirs == NULL) + dirs = initialize_path_list (gf_var, DEFAULT_GF_PATH); + + name = concat (font_name, suffix); + gf_name = find_path_filename (name, dirs); + + if (name != gf_name) + free (name); + + return gf_name; +} + + +/* Like `find_pk_filename', except search for a TFM file. */ + +string +find_tfm_filename (string font_name) +{ + static string *dirs = NULL; + string tfm_name, name; + + if (dirs == NULL) + dirs = initialize_path_list ("TEXFONTS", DEFAULT_TFM_PATH); + + name = extend_filename (font_name, "tfm"); + tfm_name = find_path_filename (name, dirs); + + if (name != tfm_name) + free (name); + + return tfm_name; +} diff --git a/lib/fix-num.c b/lib/fix-num.c new file mode 100644 index 0000000..2827d2c --- /dev/null +++ b/lib/fix-num.c @@ -0,0 +1,43 @@ +/* fix-num.c: conversions on ``fixnums'', which are a 32-bit + word with 20 bits of fraction. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "fix-num.h" + + +#define FIX_UNITY (1 << 20) + + +const real +fix_to_real (fix_word f) +{ + real r = f / FIX_UNITY + ((real) (f % FIX_UNITY) / (real) FIX_UNITY); + + return r; +} + + +const fix_word +real_to_fix (real r) +{ + fix_word f = floor (r) * FIX_UNITY + (r - floor (r)) * FIX_UNITY; + + return f; +} diff --git a/lib/float-ok.c b/lib/float-ok.c new file mode 100644 index 0000000..b3e81d6 --- /dev/null +++ b/lib/float-ok.c @@ -0,0 +1,60 @@ +/* float-ok.c: test if a string is a valid floating-point number. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include <kpathsea/c-ctype.h> + + +/* Actually, we don't worry about a trailing exponent. */ + +boolean +float_ok (string str) +{ + boolean found_digit = false; + + if (str == NULL) + return false; + + /* Allow leading `-' or `+' sign (but digits must follow). */ + if (*str == '-' || *str == '+') + { + str++; + } + + /* Skip decimal digits. */ + while (ISDIGIT (*str)) + { + str++; + found_digit = true; + } + + /* If a `.' follows, can have more digits. */ + if (*str == '.') + { + str++; + while (ISDIGIT (*str)) + { + str++; + found_digit = true; + } + } + + return *str == 0 && found_digit; +} + diff --git a/lib/fmod.c b/lib/fmod.c new file mode 100644 index 0000000..0c78f52 --- /dev/null +++ b/lib/fmod.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that: (1) source distributions retain this entire copyright + * notice and comment, and (2) distributions including binaries display + * the following acknowledgement: ``This product includes software + * developed by the University of California, Berkeley and its contributors'' + * in the documentation or other materials provided with the distribution + * and in all advertising materials mentioning features or use of this + * software. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char sccsid[] = "@(#)fmod.c 5.2 (Berkeley) 6/1/90"; +#endif /* not lint */ + +/* fmod.c + * + * SYNOPSIS + * + * #include <math.h> + * double fmod(double x, double y) + * + * DESCRIPTION + * + * The fmod function computes the floating-point remainder of x/y. + * + * RETURNS + * + * The fmod function returns the value x-i*y, for some integer i + * such that, if y is nonzero, the result has the same sign as x and + * magnitude less than the magnitude of y. + * + * On a VAX or CCI, + * + * fmod(x,0) traps/faults on floating-point divided-by-zero. + * + * On IEEE-754 conforming machines with "isnan()" primitive, + * + * fmod(x,0), fmod(INF,y) are invalid operations and NaN is returned. + * + */ +#include <math.h> /* changed from "mathimpl.h" --karl */ + +#if !defined(vax) && !defined(tahoe) +extern int isnan(),finite(); +#endif /* !defined(vax) && !defined(tahoe) */ +extern double frexp(),ldexp(),fabs(); + +#ifdef TEST_FMOD +static double +_fmod(x,y) +#else /* TEST_FMOD */ +double +fmod(x,y) +#endif /* TEST_FMOD */ +double x,y; +{ + int ir,iy; + double r,w; + + if (y == (double)0 +#if 0 /* removed this --karl */ +#if !defined(vax) && !defined(tahoe) /* per "fmod" manual entry, SunOS 4.0 */ + || isnan(y) || !finite(x) +#endif /* !defined(vax) && !defined(tahoe) */ +#endif + ) + return (x*y)/(x*y); + + r = fabs(x); + y = fabs(y); + (void)frexp(y,&iy); + while (r >= y) { + (void)frexp(r,&ir); + w = ldexp(y,ir-iy); + r -= w <= r ? w : w*(double)0.5; + } + return x >= (double)0 ? r : -r; +} + +#ifdef TEST_FMOD +extern long random(); +extern double fmod(); + +#define NTEST 10000 +#define NCASES 3 + +static int nfail = 0; + +static void +doit(x,y) +double x,y; +{ + double ro = fmod(x,y),rn = _fmod(x,y); + if (ro != rn) { + (void)printf(" x = 0x%08.8x %08.8x (%24.16e)\n",x,x); + (void)printf(" y = 0x%08.8x %08.8x (%24.16e)\n",y,y); + (void)printf(" fmod = 0x%08.8x %08.8x (%24.16e)\n",ro,ro); + (void)printf("_fmod = 0x%08.8x %08.8x (%24.16e)\n",rn,rn); + (void)printf("\n"); + } +} + +main() +{ + register int i,cases; + double x,y; + + srandom(12345); + for (i = 0; i < NTEST; i++) { + x = (double)random(); + y = (double)random(); + for (cases = 0; cases < NCASES; cases++) { + switch (cases) { + case 0: + break; + case 1: + y = (double)1/y; break; + case 2: + x = (double)1/x; break; + default: + abort(); break; + } + doit(x,y); + doit(x,-y); + doit(-x,y); + doit(-x,-y); + } + } + if (nfail) + (void)printf("Number of failures: %d (out of a total of %d)\n", + nfail,NTEST*NCASES*4); + else + (void)printf("No discrepancies were found\n"); + exit(0); +} +#endif /* TEST_FMOD */ diff --git a/lib/font.c b/lib/font.c new file mode 100644 index 0000000..e2b9a71 --- /dev/null +++ b/lib/font.c @@ -0,0 +1,466 @@ +/* font.c: define (more or less) format-independent font operations. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include <kpathsea/tex-file.h> +#include <kpathsea/pathsearch.h> +#include <kpathsea/paths.h> +#include <kpathsea/c-ctype.h> + +#include "filename.h" +#include "font.h" +#include "gf.h" +#include "list.h" +#include "pk.h" +#include "tfm.h" + + +/* We want to allow reading of multiple fonts, so we keep some + information around for each font we read. */ + +typedef struct +{ + bitmap_format_type bitmap_format; + boolean bitmap_only; + font_info_type info; +} internal_font_type; + +/* The format of the bitmap file for this font. */ +#define INTERNAL_BITMAP_FORMAT(i) ((i).bitmap_format) + +/* If the font was opened with `get_bitmap_font', this field is true; + if with `get_font', false. */ +#define INTERNAL_BITMAP_ONLY(i) ((i).bitmap_only) + +/* The filename for the bitmap font. */ +#define INTERNAL_BITMAP_NAME(i) ((i).bitmap_name) + +/* The fontwide information. The parts of this that are found in the + TFM file are garbage if INTERNAL_BITMAP_ONLY (I) is true. */ +#define INTERNAL_FONT_INFO(i) ((i).info) + + +static void delete_internal_font (string filename); +static internal_font_type *find_internal_font (string font_name); +static void save_internal_font (string font_name, internal_font_type); + +/* Starting with FONT_NAME as the base filename, e.g., `cmr10', we try + various extensions to find a PK or GF file at resolution DPI. This + bitmap font defines the shapes of the characters. */ + +bitmap_font_type +get_bitmap_font (string font_name, unsigned dpi) +{ + bitmap_font_type font; + internal_font_type internal_f; + internal_font_type *internal_font_ptr; + string pk_name, gf_name; + boolean found_pk = false, found_gf = false; + + /* If we are passed a null pointer or the empty string, it's got to be + a mistake. */ + assert (font_name && *font_name); + + /* If we already have the font saved, we just return it, thus (1) saving + going out to the file system, and (2) causing multiple calls with + the same FONT_NAME not to open more and more bitmap files. */ + internal_font_ptr = find_internal_font (font_name); + if (internal_font_ptr != NULL) + return FONT_BITMAP_FONT (INTERNAL_FONT_INFO (*internal_font_ptr)); + + pk_name = find_pk_filename (font_name, dpi); + if (pk_name != NULL) + { /* Found the PK file, so unless something strange is happening + (like the file being removed between the `find_path_filename' + call and the `pk_open_input_file' call), we will be able to + open it. */ + found_pk = pk_open_input_file (pk_name); + if (!found_pk) + FATAL_PERROR (pk_name); + } + else if ((gf_name = find_gf_filename (font_name, dpi)) != NULL) + { + found_gf = gf_open_input_file (gf_name); + if (!found_gf) + { + perror (gf_name); + FATAL1 ("(I couldn't find the PK file `%s', either.)", pk_name); + } + } + else + FATAL2 ("%s.%d{gf,pk}: Nowhere in path", font_name, dpi); + + + /* We've opened the files; get the information we need to return. */ + if (found_pk) + { + pk_preamble_type preamble = pk_get_preamble (pk_name); + + BITMAP_FONT_DESIGN_SIZE (font) + = fix_to_real (PK_DESIGN_SIZE (preamble)); + BITMAP_FONT_COMMENT (font) = PK_COMMENT (preamble); + BITMAP_FONT_CHECKSUM (font) = PK_CHECKSUM (preamble); + BITMAP_FONT_FILENAME (font) = pk_name; + + INTERNAL_BITMAP_FORMAT (internal_f) = pk_format; + } + else if (found_gf) + { + gf_postamble_type postamble = gf_get_postamble (); + + BITMAP_FONT_DESIGN_SIZE (font) + = fix_to_real (GF_DESIGN_SIZE (postamble)); + BITMAP_FONT_COMMENT (font) = gf_get_preamble (); + BITMAP_FONT_CHECKSUM (font) = GF_CHECKSUM (postamble); + BITMAP_FONT_FILENAME (font) = gf_name; + + INTERNAL_BITMAP_FORMAT (internal_f) = gf_format; + } + else + FATAL ("No bitmap file found, but I must have found one"); + + FONT_BITMAP_FONT (INTERNAL_FONT_INFO (internal_f)) = font; + INTERNAL_BITMAP_ONLY (internal_f) = true; + + save_internal_font (font_name, internal_f); + + return font; +} + + +/* Look for both a bitmap font named FONT_NAME, and for the TFM file + FONT_NAME.tfm. We call `get_bitmap_font' to find the bitmap font. + For the TFM file, we use the path in the environment variable + TEXFONTS; if TEXFONTS isn't set, we use the default defined above. + + If FONT_NAME was previously opened with `get_bitmap_font', we give a + fatal error. */ + +font_info_type +get_font (string font_name, unsigned dpi) +{ + unsigned bitmap_checksum; + font_info_type font; + internal_font_type internal_f; + internal_font_type *internal_font_ptr; + unsigned tfm_checksum; + string tfm_name; + + /* If we are passed a null pointer or the empty string, it's got to be + a mistake. */ + assert (font_name != NULL && *font_name); + + /* If we already have the font saved, we just return it, thus (1) saving + going out to the file system, and (2) causing multiple calls with + the same FONT_NAME not to open more and more bitmap files. */ + internal_font_ptr = find_internal_font (font_name); + if (internal_font_ptr != NULL) + if (INTERNAL_BITMAP_ONLY (*internal_font_ptr)) + FATAL1 ("get_font: `%s' was opened with get_bitmap_font", font_name); + else + return INTERNAL_FONT_INFO (*internal_font_ptr); + + /* If we don't have the font saved, we have to look for the TFM file. */ + tfm_name = kpse_find_tfm (font_name); + + if (tfm_name == NULL) + FATAL1 ("%s.tfm: Nowhere in path", font_name); + + if (!tfm_open_input_file (tfm_name)) + FATAL_PERROR (tfm_name); + + + /* The TFM file is opened. Save some global information. */ + FONT_TFM_FONT (font) = tfm_get_global_info (); + FONT_TFM_FILENAME (font) = tfm_name; + + /* Read the (we hope) corresponding bitmap file. */ + FONT_BITMAP_FONT (font) = get_bitmap_font (font_name, dpi); + + /* We have found the bitmap font on the filesystem, so it should be in + our internal list now. We will overwrite it below. */ + internal_font_ptr = find_internal_font (font_name); + assert (internal_font_ptr != NULL); + + /* We've opened the files; now get the information we're supposed to + return. */ + + /* Let's check the checksums. */ + tfm_checksum = tfm_get_checksum (); + bitmap_checksum = BITMAP_FONT_CHECKSUM (FONT_BITMAP_FONT (font)); + + if (tfm_checksum != 0 && bitmap_checksum != 0 + && tfm_checksum != bitmap_checksum) + WARNING1 ("%s: TFM and bitmap checksums don't match", font_name); + + INTERNAL_FONT_INFO (internal_f) = font; + INTERNAL_BITMAP_ONLY (internal_f) = false; + INTERNAL_BITMAP_FORMAT (internal_f) + = INTERNAL_BITMAP_FORMAT (*internal_font_ptr); + save_internal_font (font_name, internal_f); + + return font; +} + +/* Close the files we have opened, for tidiness. */ + +void +close_font (string font_name) +{ + internal_font_type *f = find_internal_font (font_name); + + if (f == NULL) + FATAL1 ("close_font: Font `%s' not open", font_name); + + switch (INTERNAL_BITMAP_FORMAT (*f)) + { + case pk_format: + { + string pk_name + = BITMAP_FONT_FILENAME (FONT_BITMAP_FONT (INTERNAL_FONT_INFO (*f))); + pk_close_input_file (pk_name); + } + break; + + case gf_format: + gf_close_input_file (); + break; + + default: + FATAL1 ("Impossible bitmap format (%d)", INTERNAL_BITMAP_FORMAT (*f)); + } + + if (!INTERNAL_BITMAP_ONLY (*f)) + tfm_close_input_file (); + + delete_internal_font (font_name); +} + +/* Look for the character numbered CODE in the font FONT_NAME. If it + doesn't exist, return NULL. Otherwise, fill in a `char_info_type' + structure and return a pointer to it. + + This merely calls the get-a-character routine in the appropriate + library. */ + +char_info_type * +get_char (string font_name, one_byte code) +{ + char_info_type *c; + internal_font_type *f = find_internal_font (font_name); + + if (f == NULL) + FATAL1 ("get_char: Font `%s' not open", font_name); + + switch (INTERNAL_BITMAP_FORMAT (*f)) + { + case pk_format: + { + string pk_name + = BITMAP_FONT_FILENAME (FONT_BITMAP_FONT (INTERNAL_FONT_INFO (*f))); + pk_char_type *pk_char = pk_get_char (code, pk_name); + if (pk_char == NULL) return NULL; + + c = XTALLOC1 (char_info_type); + CHARCODE (*c) = PK_CHARCODE (*pk_char); + CHAR_SET_WIDTH (*c) = PK_H_ESCAPEMENT (*pk_char); + CHAR_TFM_WIDTH (*c) = PK_TFM_WIDTH (*pk_char); + CHAR_BB (*c) = PK_CHAR_BB (*pk_char); + CHAR_BITMAP (*c) = PK_BITMAP (*pk_char); + } + break; + + case gf_format: + { + gf_char_type *gf_char = gf_get_char (code); + if (gf_char == NULL) return NULL; + + c = XTALLOC1 (char_info_type); + CHARCODE (*c) = GF_CHARCODE (*gf_char); + CHAR_SET_WIDTH (*c) = GF_H_ESCAPEMENT (*gf_char); + CHAR_TFM_WIDTH (*c) = GF_TFM_WIDTH (*gf_char); + CHAR_BB (*c) = GF_CHAR_BB (*gf_char); + CHAR_BITMAP (*c) = GF_BITMAP (*gf_char); + } + break; + + default: + FATAL1 ("Impossible bitmap format (%d)", INTERNAL_BITMAP_FORMAT (*f)); + } + + return c; +} + +/* Look for the character numbered CODE in the font FONT_NAME. If it + doesn't exist, return NULL. Otherwise, fill in a `raw_char_type' + structure and return a pointer to it. + + This merely calls the corresponding routine in the appropriate + library. */ + +raw_char_type * +get_raw_char (string font_name, one_byte code) +{ + raw_char_type *c; + internal_font_type *f = find_internal_font (font_name); + + if (f == NULL) + FATAL1 ("get_raw_char: Font `%s' not open", font_name); + + switch (INTERNAL_BITMAP_FORMAT (*f)) + { + case pk_format: + c = NULL; + break; + + case gf_format: + c = gf_get_raw_char (code); + break; + + default: + FATAL1 ("Impossible bitmap format (%d)", INTERNAL_BITMAP_FORMAT (*f)); + } + + if (c != NULL) + RAW_CHAR_BITMAP_FORMAT (*c) = INTERNAL_BITMAP_FORMAT (*f); + return c; +} + + +/* Free the information in the raw character RAW_CHAR, including the + character itself. */ + +void +free_raw_char (raw_char_type *raw_char) +{ + free (RAW_CHAR_BYTES (*raw_char)); + free (raw_char); +} + +/* Print the character C to the file F, using ordinary characters. */ + +void +print_char (FILE *f, char_info_type c) +{ + unsigned this_row, this_col; + bitmap_type b = CHAR_BITMAP (c); + + fprintf (f, "Character 0x%x=%u", CHARCODE (c), CHARCODE (c)); + if (ISPRINT (CHARCODE (c))) + fprintf (f, " (%c)", CHARCODE (c)); + + fprintf (f, ":\n"); + + fprintf (f, " min/max col %d/%d, min/max row %d/%d, set width %d.\n", + CHAR_MIN_COL (c), CHAR_MAX_COL (c), + CHAR_MIN_ROW (c), CHAR_MAX_ROW (c), CHAR_SET_WIDTH (c)); + + /* We don't call `print_bitmap' because we want to print the Cartesian + row number, as well as the bitmap row number. */ + + for (this_row = 0; this_row < BITMAP_HEIGHT (b); this_row++) + { + for (this_col = 0; this_col < BITMAP_WIDTH (b); this_col++) + putc (BITMAP_PIXEL (b, this_row, this_col) ? '*' : ' ', f); + + fprintf (f, "%3d\t%u\n", CHAR_MAX_ROW (c) - this_row, this_row); + } +} + +/* We want to implement a typical key/value setup: here we are given the + key (FONT_NAME) and the value (F). We assign an index number to + FONT_NAME, and store it and F in parallel lists. If we are passed a + FONT_NAME that is already in the list, we overwrite the old value. */ + +static list_type font_name_list, internal_font_list; + +static void +save_internal_font (string font_name, internal_font_type f) +{ + string *new_name; + internal_font_type *new_font; + static boolean first_call = true; + + if (first_call) + { /* Have to construct our lists. */ + font_name_list = list_init (); + internal_font_list = list_init (); + first_call = false; + } + + new_font = find_internal_font (font_name); + if (new_font == NULL) + { + /* Add another pointer to the end of the lists. */ + new_name = LIST_TAPPEND (&font_name_list, string); + new_font = LIST_TAPPEND (&internal_font_list, internal_font_type); + + /* Save the information. */ + *new_name = xstrdup (font_name); + } + + /* Either update the existing font, or save the new one. */ + *new_font = f; +} + + +/* This routine returns the font information previously stored with + FONT_NAME. If FONT_NAME hasn't been saved, we return NULL. */ + +static internal_font_type * +find_internal_font (string font_name) +{ + unsigned e; + + for (e = 0; e < LIST_SIZE (font_name_list); e++) + if (STREQ (*(string *) LIST_ELT (font_name_list, e), font_name)) + return (internal_font_type *) LIST_ELT (internal_font_list, e); + + return NULL; +} + + +/* Remove FILENAME from `font_name_list', by setting the name in + `font_name_list' to the empty string, so that the element is useless. + (We don't have any actual memory to free.) What a kludge. */ + +static void +delete_internal_font (string filename) +{ + unsigned e; + + /* We can't use `find_internal_font', since we need to know the list + element index, not just the internal font information. */ + for (e = 0; e < LIST_SIZE (font_name_list); e++) + if (STREQ (*(string *) LIST_ELT (font_name_list, e), filename)) + { + string *name = LIST_ELT (font_name_list, e); + internal_font_type *i + = (internal_font_type *) LIST_ELT (internal_font_list, e); + + free (*name); + *name = ""; + + free (i); + + return; + } + + FATAL1 ("The font `%s' hasn't been saved", filename); +} diff --git a/lib/fontmap.c b/lib/fontmap.c new file mode 100644 index 0000000..2b4f0b7 --- /dev/null +++ b/lib/fontmap.c @@ -0,0 +1,210 @@ +/* fontmap.c: read a file for additional font names. + +Copyright (C) 1993 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "c-pathmx.h" +#include "fontmap.h" + + + +/* Fontname mapping. We use a straightforward hash table. */ + +#define MAP_SIZE 199 + + +/* The hash function. We go for simplicity here. */ + +static unsigned +map_hash (key) + char *key; +{ + unsigned n = 0; + + /* There are very few font names which are anagrams of each other (I + think), so no point in weighting the characters. */ + while (*key != 0) + n += *key++; + + n %= MAP_SIZE; + + return n; +} + +/* Look up STR in MAP. Return the corresponding `value' or NULL. */ + +static char * +map_lookup_str (map, key) + map_type map; + char *key; +{ + map_element_type *p; + unsigned n = map_hash (key); + + for (p = map[n]; p != NULL; p = p->next) + if (STREQ (key, p->key)) + return p->value; + + return NULL; +} + + +/* Look up KEY in MAP; if it's not found, remove any suffix from KEY and + try again. */ + +char * +map_lookup (map, key) + map_type map; + char *key; +{ + extern string extend_filename (); + string suffix = find_suffix (key); + string ret = map_lookup_str (map, key); + + if (!ret) + { + /* OK, the original KEY didn't work. Let's check for the KEY without + an extension -- perhaps they gave foobar.tfm, but the mapping only + defines `foobar'. */ + if (suffix) + { + string base_key = remove_suffix (key); + + ret = map_lookup_str (map, base_key); + + free (base_key); + } + } + + /* Append the same suffix we took off, if necessary. */ + if (ret && suffix) + ret = extend_filename (ret, suffix); + + return ret; +} + +/* If KEY is not already in MAP, insert it and VALUE. */ + +static void +map_insert (map, key, value) + map_type map; + char *key; + char *value; +{ + unsigned n = map_hash (key); + map_element_type **p = &map[n]; + map_element_type ***trailer = &p; + + while (*p != NULL && !STREQ (key, (*p)->key)) + { + *p = (*p)->next; + trailer = &p; + } + + if (*p == NULL) + { + **trailer = XTALLOC (MAP_SIZE, map_element_type); + (**trailer)->key = xstrdup (key); + (**trailer)->value = xstrdup (value); + (**trailer)->next = NULL; + } +} + +/* Open and read the mapping file FILENAME, putting its entries into + MAP. Comments begin with % and continue to the end of the line. Each + line of the file defines an entry: the first word is the real + filename (e.g., `ptmr'), the second word is the alias (e.g., + `Times-Roman'), and any subsequent words are ignored. .tfm is added + if either the filename or the alias have no extension. This is the + same order as in Dvips' psfonts.map; unfortunately, we can't have TeX + read that same file, since most of the real filenames start with an + `r', because of the virtual fonts Dvips uses. */ + +static void +map_file_parse (map, map_filename) + map_type map; + char *map_filename; +{ + extern FILE *xfopen (); /* In xfopen.c. */ + extern char *read_line (); /* In line.c. */ + char *l; + unsigned map_lineno = 0; + FILE *f = xfopen (map_filename, FOPEN_R_MODE); + + while ((l = read_line (f)) != NULL) + { + string filename; + string comment_loc = strrchr (l, '%'); + + map_lineno++; + + /* Ignore anything after a %. */ + if (comment_loc) + *comment_loc = 0; + + /* If we don't have any filename, that's ok, the line is blank. */ + filename = strtok (l, " \t"); + if (filename) + { + string alias = strtok (NULL, " \t"); + + /* But if we have a filename and no alias, something's wrong. */ + if (alias == NULL || *alias == 0) + fprintf (stderr, "%s:%u: Alias missing for filename `%s'.\n", + map_filename, map_lineno, filename); + else + { + /* We've got everything. Insert the new entry. */ + map_insert (map, alias, filename); + } + } + + free (l); + } + + xfclose (f, map_filename); +} + + +/* Look for the file `texfonts.map' in each of the directories in + DIR_LIST. Entries in earlier files override later files. */ + +map_type +map_create (dir_list) + string *dir_list; +{ + map_type map = (map_type) xcalloc (MAP_SIZE, sizeof (map_element_type *)); + + while (*dir_list) + { + char filename[PATH_MAX]; + + /* We don't bother with the filename truncation that `readable' in + `pathsrch.c' does, since we ourselves are giving the filename, + and I don't think it's worth worrying about too-long + intermediate directory names in the path. */ + strcpy (filename, *dir_list); + strcat (filename, "texfonts.map"); + + if (access (filename, R_OK) == 0) + map_file_parse (map, filename); + + dir_list++; + } + return map; +} diff --git a/lib/gmalloc.c b/lib/gmalloc.c new file mode 100644 index 0000000..bf4c70f --- /dev/null +++ b/lib/gmalloc.c @@ -0,0 +1,1172 @@ +/* DO NOT EDIT THIS FILE -- it is automagically generated. -*- C -*- */ + +#define _MALLOC_INTERNAL + +/* The malloc headers and source files from the C library follow here. */ + +/* Declarations for `malloc' and friends. + Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Written May 1989 by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_H + +#define _MALLOC_H 1 + +#ifdef _MALLOC_INTERNAL + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG) +#include <string.h> +#else +#ifndef memset +#define memset(s, zero, n) bzero ((s), (n)) +#endif +#ifndef memcpy +#define memcpy(d, s, n) bcopy ((s), (d), (n)) +#endif +#ifndef memmove +#define memmove(d, s, n) bcopy ((s), (d), (n)) +#endif +#endif + +#if defined(__GNU_LIBRARY__) || defined(__STDC__) +#include <limits.h> +#else +#define CHAR_BIT 8 +#endif + +#endif /* _MALLOC_INTERNAL. */ + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if defined (__cplusplus) || (defined (__STDC__) && __STDC__) +#undef __P +#define __P(args) args +#undef __ptr_t +#define __ptr_t void * +#else /* Not C++ or ANSI C. */ +#undef __P +#define __P(args) () +#undef const +#define const +#undef __ptr_t +#define __ptr_t char * +#endif /* C++ or ANSI C. */ + +#ifdef __STDC__ +#include <stddef.h> +#else +#undef size_t +#define size_t unsigned int +#undef ptrdiff_t +#define ptrdiff_t int +#endif + +#ifndef NULL +#define NULL 0 +#endif + + +/* Allocate SIZE bytes of memory. */ +extern __ptr_t malloc __P ((size_t __size)); +/* Re-allocate the previously allocated block + in __ptr_t, making the new block SIZE bytes long. */ +extern __ptr_t realloc __P ((__ptr_t __ptr, size_t __size)); +/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ +extern __ptr_t calloc __P ((size_t __nmemb, size_t __size)); +/* Free a block allocated by `malloc', `realloc' or `calloc'. */ +extern void free __P ((__ptr_t __ptr)); + +/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ +extern __ptr_t memalign __P ((size_t __alignment, size_t __size)); + +/* Allocate SIZE bytes on a page boundary. */ +extern __ptr_t valloc __P ((size_t __size)); + + +#ifdef _MALLOC_INTERNAL + +/* The allocator divides the heap into blocks of fixed size; large + requests receive one or more whole blocks, and small requests + receive a fragment of a block. Fragment sizes are powers of two, + and all fragments of a block are the same size. When all the + fragments in a block have been freed, the block itself is freed. */ +#define INT_BIT (CHAR_BIT * sizeof(int)) +#define BLOCKLOG (INT_BIT > 16 ? 12 : 9) +#define BLOCKSIZE (1 << BLOCKLOG) +#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE) + +/* Determine the amount of memory spanned by the initial heap table + (not an absolute limit). */ +#define HEAP (INT_BIT > 16 ? 4194304 : 65536) + +/* Number of contiguous free blocks allowed to build up at the end of + memory before they will be returned to the system. */ +#define FINAL_FREE_BLOCKS 8 + +/* Data structure giving per-block information. */ +typedef union + { + /* Heap information for a busy block. */ + struct + { + /* Zero for a large block, or positive giving the + logarithm to the base two of the fragment size. */ + int type; + union + { + struct + { + size_t nfree; /* Free fragments in a fragmented block. */ + size_t first; /* First free fragment of the block. */ + } frag; + /* Size (in blocks) of a large cluster. */ + size_t size; + } info; + } busy; + /* Heap information for a free block + (that may be the first of a free cluster). */ + struct + { + size_t size; /* Size (in blocks) of a free cluster. */ + size_t next; /* Index of next free cluster. */ + size_t prev; /* Index of previous free cluster. */ + } free; + } malloc_info; + +/* Pointer to first block of the heap. */ +extern char *_heapbase; + +/* Table indexed by block number giving per-block information. */ +extern malloc_info *_heapinfo; + +/* Address to block number and vice versa. */ +#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) +#define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase)) + +/* Current search index for the heap table. */ +extern size_t _heapindex; + +/* Limit of valid info table indices. */ +extern size_t _heaplimit; + +/* Doubly linked lists of free fragments. */ +struct list + { + struct list *next; + struct list *prev; + }; + +/* Free list headers for each fragment size. */ +extern struct list _fraghead[]; + +/* List of blocks allocated with `memalign' (or `valloc'). */ +struct alignlist + { + struct alignlist *next; + __ptr_t aligned; /* The address that memaligned returned. */ + __ptr_t exact; /* The address that malloc returned. */ + }; +extern struct alignlist *_aligned_blocks; + +/* Instrumentation. */ +extern size_t _chunks_used; +extern size_t _bytes_used; +extern size_t _chunks_free; +extern size_t _bytes_free; + +/* Internal version of `free' used in `morecore' (malloc.c). */ +extern void _free_internal __P ((__ptr_t __ptr)); + +#endif /* _MALLOC_INTERNAL. */ + +/* Underlying allocation function; successive calls should + return contiguous pieces of memory. */ +extern __ptr_t (*__morecore) __P ((ptrdiff_t __size)); + +/* Default value of `__morecore'. */ +extern __ptr_t __default_morecore __P ((ptrdiff_t __size)); + +/* If not NULL, this function is called after each time + `__morecore' is called to increase the data size. */ +extern void (*__after_morecore_hook) __P ((void)); + +/* Nonzero if `malloc' has been called and done its initialization. */ +extern int __malloc_initialized; + +/* Hooks for debugging versions. */ +extern void (*__free_hook) __P ((__ptr_t __ptr)); +extern __ptr_t (*__malloc_hook) __P ((size_t __size)); +extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size)); + +/* Activate a standard collection of debugging hooks. */ +extern int mcheck __P ((void (*__func) __P ((void)))); + +/* Activate a standard collection of tracing hooks. */ +extern void mtrace __P ((void)); + +/* Statistics available to the user. */ +struct mstats + { + size_t bytes_total; /* Total size of the heap. */ + size_t chunks_used; /* Chunks allocated by the user. */ + size_t bytes_used; /* Byte total of user-allocated chunks. */ + size_t chunks_free; /* Chunks in the free list. */ + size_t bytes_free; /* Byte total of chunks in the free list. */ + }; + +/* Pick up the current statistics. */ +extern struct mstats mstats __P ((void)); + +/* Call WARNFUN with a warning message when memory usage is high. */ +extern void memory_warnings __P ((__ptr_t __start, + void (*__warnfun) __P ((__const char *)))); + + +/* Relocating allocator. */ + +/* Allocate SIZE bytes, and store the address in *HANDLEPTR. */ +extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, size_t __size)); + +/* Free the storage allocated in HANDLEPTR. */ +extern void r_alloc_free __P ((__ptr_t *__handleptr)); + +/* Adjust the block at HANDLEPTR to be SIZE bytes long. */ +extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, size_t __size)); + + +#ifdef __cplusplus +} +#endif + +#endif /* malloc.h */ +/* Memory allocator `malloc'. + Copyright 1990, 1991, 1992, 1993 Free Software Foundation + Written May 1989 by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +/* How to really get more memory. */ +__ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore; + +/* Debugging hook for `malloc'. */ +__ptr_t (*__malloc_hook) __P ((size_t __size)); + +/* Pointer to the base of the first block. */ +char *_heapbase; + +/* Block information table. Allocated with align/__free (not malloc/free). */ +malloc_info *_heapinfo; + +/* Number of info entries. */ +static size_t heapsize; + +/* Search index in the info table. */ +size_t _heapindex; + +/* Limit of valid info table indices. */ +size_t _heaplimit; + +/* Free lists for each fragment size. */ +struct list _fraghead[BLOCKLOG]; + +/* Instrumentation. */ +size_t _chunks_used; +size_t _bytes_used; +size_t _chunks_free; +size_t _bytes_free; + +/* Are you experienced? */ +int __malloc_initialized; + +void (*__after_morecore_hook) __P ((void)); + +/* Aligned allocation. */ +static __ptr_t align __P ((size_t)); +static __ptr_t +align (size) + size_t size; +{ + __ptr_t result; + unsigned long int adj; + + result = (*__morecore) (size); + adj = (unsigned long int) ((unsigned long int) ((char *) result - + (char *) NULL)) % BLOCKSIZE; + if (adj != 0) + { + adj = BLOCKSIZE - adj; + (void) (*__morecore) (adj); + result = (char *) result + adj; + } + + if (__after_morecore_hook) + (*__after_morecore_hook) (); + + return result; +} + +/* Set everything up and remember that we have. */ +static int initialize __P ((void)); +static int +initialize () +{ + heapsize = HEAP / BLOCKSIZE; + _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info)); + if (_heapinfo == NULL) + return 0; + memset (_heapinfo, 0, heapsize * sizeof (malloc_info)); + _heapinfo[0].free.size = 0; + _heapinfo[0].free.next = _heapinfo[0].free.prev = 0; + _heapindex = 0; + _heapbase = (char *) _heapinfo; + __malloc_initialized = 1; + return 1; +} + +/* Get neatly aligned memory, initializing or + growing the heap info table as necessary. */ +static __ptr_t morecore __P ((size_t)); +static __ptr_t +morecore (size) + size_t size; +{ + __ptr_t result; + malloc_info *newinfo, *oldinfo; + size_t newsize; + + result = align (size); + if (result == NULL) + return NULL; + + /* Check if we need to grow the info table. */ + if ((size_t) BLOCK ((char *) result + size) > heapsize) + { + newsize = heapsize; + while ((size_t) BLOCK ((char *) result + size) > newsize) + newsize *= 2; + newinfo = (malloc_info *) align (newsize * sizeof (malloc_info)); + if (newinfo == NULL) + { + (*__morecore) (-size); + return NULL; + } + memset (newinfo, 0, newsize * sizeof (malloc_info)); + memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info)); + oldinfo = _heapinfo; + newinfo[BLOCK (oldinfo)].busy.type = 0; + newinfo[BLOCK (oldinfo)].busy.info.size + = BLOCKIFY (heapsize * sizeof (malloc_info)); + _heapinfo = newinfo; + _free_internal (oldinfo); + heapsize = newsize; + } + + _heaplimit = BLOCK ((char *) result + size); + return result; +} + +/* Allocate memory from the heap. */ +__ptr_t +malloc (size) + size_t size; +{ + __ptr_t result; + size_t block, blocks, lastblocks, start; + register size_t i; + struct list *next; + + /* ANSI C allows `malloc (0)' to either return NULL, or to return a + valid address you can realloc and free (though not dereference). + + It turns out that some extant code (sunrpc, at least Ultrix's version) + expects `malloc (0)' to return non-NULL and breaks otherwise. + Be compatible. */ + +#if 0 + if (size == 0) + return NULL; +#endif + + if (__malloc_hook != NULL) + return (*__malloc_hook) (size); + + if (!__malloc_initialized) + if (!initialize ()) + return NULL; + + if (size < sizeof (struct list)) + size = sizeof (struct list); + + /* Determine the allocation policy based on the request size. */ + if (size <= BLOCKSIZE / 2) + { + /* Small allocation to receive a fragment of a block. + Determine the logarithm to base two of the fragment size. */ + register size_t log = 1; + --size; + while ((size /= 2) != 0) + ++log; + + /* Look in the fragment lists for a + free fragment of the desired size. */ + next = _fraghead[log].next; + if (next != NULL) + { + /* There are free fragments of this size. + Pop a fragment out of the fragment list and return it. + Update the block's nfree and first counters. */ + result = (__ptr_t) next; + next->prev->next = next->next; + if (next->next != NULL) + next->next->prev = next->prev; + block = BLOCK (result); + if (--_heapinfo[block].busy.info.frag.nfree != 0) + _heapinfo[block].busy.info.frag.first = (unsigned long int) + ((unsigned long int) ((char *) next->next - (char *) NULL) + % BLOCKSIZE) >> log; + + /* Update the statistics. */ + ++_chunks_used; + _bytes_used += 1 << log; + --_chunks_free; + _bytes_free -= 1 << log; + } + else + { + /* No free fragments of the desired size, so get a new block + and break it into fragments, returning the first. */ + result = malloc (BLOCKSIZE); + if (result == NULL) + return NULL; + + /* Link all fragments but the first into the free list. */ + for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i) + { + next = (struct list *) ((char *) result + (i << log)); + next->next = _fraghead[log].next; + next->prev = &_fraghead[log]; + next->prev->next = next; + if (next->next != NULL) + next->next->prev = next; + } + + /* Initialize the nfree and first counters for this block. */ + block = BLOCK (result); + _heapinfo[block].busy.type = log; + _heapinfo[block].busy.info.frag.nfree = i - 1; + _heapinfo[block].busy.info.frag.first = i - 1; + + _chunks_free += (BLOCKSIZE >> log) - 1; + _bytes_free += BLOCKSIZE - (1 << log); + _bytes_used -= BLOCKSIZE - (1 << log); + } + } + else + { + /* Large allocation to receive one or more blocks. + Search the free list in a circle starting at the last place visited. + If we loop completely around without finding a large enough + space we will have to get more memory from the system. */ + blocks = BLOCKIFY (size); + start = block = _heapindex; + while (_heapinfo[block].free.size < blocks) + { + block = _heapinfo[block].free.next; + if (block == start) + { + /* Need to get more from the system. Check to see if + the new core will be contiguous with the final free + block; if so we don't need to get as much. */ + block = _heapinfo[0].free.prev; + lastblocks = _heapinfo[block].free.size; + if (_heaplimit != 0 && block + lastblocks == _heaplimit && + (*__morecore) (0) == ADDRESS (block + lastblocks) && + (morecore ((blocks - lastblocks) * BLOCKSIZE)) != NULL) + { + _heapinfo[block].free.size = blocks; + _bytes_free += (blocks - lastblocks) * BLOCKSIZE; + continue; + } + result = morecore (blocks * BLOCKSIZE); + if (result == NULL) + return NULL; + block = BLOCK (result); + _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.info.size = blocks; + ++_chunks_used; + _bytes_used += blocks * BLOCKSIZE; + return result; + } + } + + /* At this point we have found a suitable free list entry. + Figure out how to remove what we need from the list. */ + result = ADDRESS (block); + if (_heapinfo[block].free.size > blocks) + { + /* The block we found has a bit left over, + so relink the tail end back into the free list. */ + _heapinfo[block + blocks].free.size + = _heapinfo[block].free.size - blocks; + _heapinfo[block + blocks].free.next + = _heapinfo[block].free.next; + _heapinfo[block + blocks].free.prev + = _heapinfo[block].free.prev; + _heapinfo[_heapinfo[block].free.prev].free.next + = _heapinfo[_heapinfo[block].free.next].free.prev + = _heapindex = block + blocks; + } + else + { + /* The block exactly matches our requirements, + so just remove it from the list. */ + _heapinfo[_heapinfo[block].free.next].free.prev + = _heapinfo[block].free.prev; + _heapinfo[_heapinfo[block].free.prev].free.next + = _heapindex = _heapinfo[block].free.next; + --_chunks_free; + } + + _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.info.size = blocks; + ++_chunks_used; + _bytes_used += blocks * BLOCKSIZE; + _bytes_free -= blocks * BLOCKSIZE; + } + + return result; +} +/* Free a block of memory allocated by `malloc'. + Copyright 1990, 1991, 1992 Free Software Foundation + Written May 1989 by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +/* Debugging hook for free. */ +void (*__free_hook) __P ((__ptr_t __ptr)); + +/* List of blocks allocated by memalign. */ +struct alignlist *_aligned_blocks = NULL; + +/* Return memory to the heap. + Like `free' but don't call a __free_hook if there is one. */ +void +_free_internal (ptr) + __ptr_t ptr; +{ + int type; + size_t block, blocks; + register size_t i; + struct list *prev, *next; + + block = BLOCK (ptr); + + type = _heapinfo[block].busy.type; + switch (type) + { + case 0: + /* Get as many statistics as early as we can. */ + --_chunks_used; + _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE; + _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE; + + /* Find the free cluster previous to this one in the free list. + Start searching at the last block referenced; this may benefit + programs with locality of allocation. */ + i = _heapindex; + if (i > block) + while (i > block) + i = _heapinfo[i].free.prev; + else + { + do + i = _heapinfo[i].free.next; + while (i > 0 && i < block); + i = _heapinfo[i].free.prev; + } + + /* Determine how to link this block into the free list. */ + if (block == i + _heapinfo[i].free.size) + { + /* Coalesce this block with its predecessor. */ + _heapinfo[i].free.size += _heapinfo[block].busy.info.size; + block = i; + } + else + { + /* Really link this block back into the free list. */ + _heapinfo[block].free.size = _heapinfo[block].busy.info.size; + _heapinfo[block].free.next = _heapinfo[i].free.next; + _heapinfo[block].free.prev = i; + _heapinfo[i].free.next = block; + _heapinfo[_heapinfo[block].free.next].free.prev = block; + ++_chunks_free; + } + + /* Now that the block is linked in, see if we can coalesce it + with its successor (by deleting its successor from the list + and adding in its size). */ + if (block + _heapinfo[block].free.size == _heapinfo[block].free.next) + { + _heapinfo[block].free.size + += _heapinfo[_heapinfo[block].free.next].free.size; + _heapinfo[block].free.next + = _heapinfo[_heapinfo[block].free.next].free.next; + _heapinfo[_heapinfo[block].free.next].free.prev = block; + --_chunks_free; + } + + /* Now see if we can return stuff to the system. */ + blocks = _heapinfo[block].free.size; + if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit + && (*__morecore) (0) == ADDRESS (block + blocks)) + { + register size_t bytes = blocks * BLOCKSIZE; + _heaplimit -= blocks; + (*__morecore) (-bytes); + _heapinfo[_heapinfo[block].free.prev].free.next + = _heapinfo[block].free.next; + _heapinfo[_heapinfo[block].free.next].free.prev + = _heapinfo[block].free.prev; + block = _heapinfo[block].free.prev; + --_chunks_free; + _bytes_free -= bytes; + } + + /* Set the next search to begin at this block. */ + _heapindex = block; + break; + + default: + /* Do some of the statistics. */ + --_chunks_used; + _bytes_used -= 1 << type; + ++_chunks_free; + _bytes_free += 1 << type; + + /* Get the address of the first free fragment in this block. */ + prev = (struct list *) ((char *) ADDRESS (block) + + (_heapinfo[block].busy.info.frag.first << type)); + + if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1) + { + /* If all fragments of this block are free, remove them + from the fragment list and free the whole block. */ + next = prev; + for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i) + next = next->next; + prev->prev->next = next; + if (next != NULL) + next->prev = prev->prev; + _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.info.size = 1; + + /* Keep the statistics accurate. */ + ++_chunks_used; + _bytes_used += BLOCKSIZE; + _chunks_free -= BLOCKSIZE >> type; + _bytes_free -= BLOCKSIZE; + + free (ADDRESS (block)); + } + else if (_heapinfo[block].busy.info.frag.nfree != 0) + { + /* If some fragments of this block are free, link this + fragment into the fragment list after the first free + fragment of this block. */ + next = (struct list *) ptr; + next->next = prev->next; + next->prev = prev; + prev->next = next; + if (next->next != NULL) + next->next->prev = next; + ++_heapinfo[block].busy.info.frag.nfree; + } + else + { + /* No fragments of this block are free, so link this + fragment into the fragment list and announce that + it is the first free fragment of this block. */ + prev = (struct list *) ptr; + _heapinfo[block].busy.info.frag.nfree = 1; + _heapinfo[block].busy.info.frag.first = (unsigned long int) + ((unsigned long int) ((char *) ptr - (char *) NULL) + % BLOCKSIZE >> type); + prev->next = _fraghead[type].next; + prev->prev = &_fraghead[type]; + prev->prev->next = prev; + if (prev->next != NULL) + prev->next->prev = prev; + } + break; + } +} + +/* Return memory to the heap. */ +void +free (ptr) + __ptr_t ptr; +{ + register struct alignlist *l; + + if (ptr == NULL) + return; + + for (l = _aligned_blocks; l != NULL; l = l->next) + if (l->aligned == ptr) + { + l->aligned = NULL; /* Mark the slot in the list as free. */ + ptr = l->exact; + break; + } + + if (__free_hook != NULL) + (*__free_hook) (ptr); + else + _free_internal (ptr); +} +/* Copyright (C) 1991, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +#undef cfree + +#ifdef _LIBC + +#include <ansidecl.h> +#include <gnu-stabs.h> + +function_alias(cfree, free, void, (ptr), + DEFUN(cfree, (ptr), PTR ptr)) + +#else + +void +cfree (ptr) + __ptr_t ptr; +{ + free (ptr); +} + +#endif +/* Change the size of a block allocated by `malloc'. + Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Written May 1989 by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +#define min(A, B) ((A) < (B) ? (A) : (B)) + +/* Debugging hook for realloc. */ +__ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size)); + +/* Resize the given region to the new size, returning a pointer + to the (possibly moved) region. This is optimized for speed; + some benchmarks seem to indicate that greater compactness is + achieved by unconditionally allocating and copying to a + new region. This module has incestuous knowledge of the + internals of both free and malloc. */ +__ptr_t +realloc (ptr, size) + __ptr_t ptr; + size_t size; +{ + __ptr_t result; + int type; + size_t block, blocks, oldlimit; + + if (size == 0) + { + free (ptr); + return malloc (0); + } + else if (ptr == NULL) + return malloc (size); + + if (__realloc_hook != NULL) + return (*__realloc_hook) (ptr, size); + + block = BLOCK (ptr); + + type = _heapinfo[block].busy.type; + switch (type) + { + case 0: + /* Maybe reallocate a large block to a small fragment. */ + if (size <= BLOCKSIZE / 2) + { + result = malloc (size); + if (result != NULL) + { + memcpy (result, ptr, size); + free (ptr); + return result; + } + } + + /* The new size is a large allocation as well; + see if we can hold it in place. */ + blocks = BLOCKIFY (size); + if (blocks < _heapinfo[block].busy.info.size) + { + /* The new size is smaller; return + excess memory to the free list. */ + _heapinfo[block + blocks].busy.type = 0; + _heapinfo[block + blocks].busy.info.size + = _heapinfo[block].busy.info.size - blocks; + _heapinfo[block].busy.info.size = blocks; + free (ADDRESS (block + blocks)); + result = ptr; + } + else if (blocks == _heapinfo[block].busy.info.size) + /* No size change necessary. */ + result = ptr; + else + { + /* Won't fit, so allocate a new region that will. + Free the old region first in case there is sufficient + adjacent free space to grow without moving. */ + blocks = _heapinfo[block].busy.info.size; + /* Prevent free from actually returning memory to the system. */ + oldlimit = _heaplimit; + _heaplimit = 0; + free (ptr); + _heaplimit = oldlimit; + result = malloc (size); + if (result == NULL) + { + /* Now we're really in trouble. We have to unfree + the thing we just freed. Unfortunately it might + have been coalesced with its neighbors. */ + if (_heapindex == block) + (void) malloc (blocks * BLOCKSIZE); + else + { + __ptr_t previous = malloc ((block - _heapindex) * BLOCKSIZE); + (void) malloc (blocks * BLOCKSIZE); + free (previous); + } + return NULL; + } + if (ptr != result) + memmove (result, ptr, blocks * BLOCKSIZE); + } + break; + + default: + /* Old size is a fragment; type is logarithm + to base two of the fragment size. */ + if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type)) + /* The new size is the same kind of fragment. */ + result = ptr; + else + { + /* The new size is different; allocate a new space, + and copy the lesser of the new size and the old. */ + result = malloc (size); + if (result == NULL) + return NULL; + memcpy (result, ptr, min (size, (size_t) 1 << type)); + free (ptr); + } + break; + } + + return result; +} +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +/* Allocate an array of NMEMB elements each SIZE bytes long. + The entire array is initialized to zeros. */ +__ptr_t +calloc (nmemb, size) + register size_t nmemb; + register size_t size; +{ + register __ptr_t result = malloc (nmemb * size); + + if (result != NULL) + (void) memset (result, 0, nmemb * size); + + return result; +} +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the GNU C Library; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +#ifndef __GNU_LIBRARY__ +#define __sbrk sbrk +#endif + +extern __ptr_t __sbrk __P ((int increment)); + +#ifndef NULL +#define NULL 0 +#endif + +/* Allocate INCREMENT more bytes of data space, + and return the start of data space, or NULL on errors. + If INCREMENT is negative, shrink data space. */ +__ptr_t +__default_morecore (increment) + ptrdiff_t increment; +{ + __ptr_t result = __sbrk ((int) increment); + if (result == (__ptr_t) -1) + return NULL; + return result; +} +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +__ptr_t +memalign (alignment, size) + size_t alignment; + size_t size; +{ + __ptr_t result; + unsigned long int adj; + + size = ((size + alignment - 1) / alignment) * alignment; + + result = malloc (size); + if (result == NULL) + return NULL; + adj = (unsigned long int) ((unsigned long int) ((char *) result - + (char *) NULL)) % alignment; + if (adj != 0) + { + struct alignlist *l; + for (l = _aligned_blocks; l != NULL; l = l->next) + if (l->aligned == NULL) + /* This slot is free. Use it. */ + break; + if (l == NULL) + { + l = (struct alignlist *) malloc (sizeof (struct alignlist)); + if (l == NULL) + { + free (result); + return NULL; + } + } + l->exact = result; + result = l->aligned = (char *) result + alignment - adj; + l->next = _aligned_blocks; + _aligned_blocks = l; + } + + return result; +} +/* Allocate memory on a page boundary. + Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +#ifdef __GNU_LIBRARY__ +extern size_t __getpagesize __P ((void)); +#else +#include "getpagesize.h" +#define __getpagesize() getpagesize() +#endif + +static size_t pagesize; + +__ptr_t +valloc (size) + size_t size; +{ + if (pagesize == 0) + pagesize = __getpagesize (); + + return memalign (pagesize, size); +} diff --git a/lib/hexify.c b/lib/hexify.c new file mode 100644 index 0000000..e3941b2 --- /dev/null +++ b/lib/hexify.c @@ -0,0 +1,46 @@ +/* hexify.c: change a binary string to ASCII hex characters. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "hexify.h" + + +/* Convert the number N (assumed to be small enough) to a lowercase hex + character. */ +#define HEX_DIGIT(n) ((n) < 10 ? (n) + '0' : (n) - 10 + 'a') + +string +hexify (one_byte *data, unsigned length) +{ + unsigned i; + /* Each byte in S turns into two hex chars, plus the terminating null. */ + string h = xmalloc (length * 2 + 1); + + for (i = 0; i < length; i++) + { + unsigned char n = (data[i] & 0xf0) >> 4; + h[i * 2] = HEX_DIGIT (n); + + n = data[i] & 0x0f; + h[i * 2 + 1] = HEX_DIGIT (n); + } + h[i * 2] = 0; + + return h; +} diff --git a/lib/identity.c b/lib/identity.c new file mode 100644 index 0000000..ffe0e1d --- /dev/null +++ b/lib/identity.c @@ -0,0 +1,38 @@ +/* identity.c. + +Copyright (C) 1995 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <stdio.h> +#include <kpathsea/c-proto.h> +#include <kpathsea/lib.h> +#include <kpathsea/progname.h> + +/* Return `hostname:pid' as a string. */ + +string +get_identity () +{ + char s[1024]; + int i; + + i = XmuGetHostname (s, sizeof (s)); + if (i == 0) + FATAL ("limn: Could not get hostname"); + + sprintf (&s[i], ":%d", getpid ()); + return (string)xstrdup (s); +} diff --git a/lib/integer-ok.c b/lib/integer-ok.c new file mode 100644 index 0000000..5af9214 --- /dev/null +++ b/lib/integer-ok.c @@ -0,0 +1,44 @@ +/* integer-ok.c: test if a string is a valid integer. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include <kpathsea/c-ctype.h> + + +boolean +integer_ok (string str) +{ + boolean found_digit = false; + + if (str == NULL) + return false; + + /* Allow leading `-' or `+' sign. */ + if (*str == '-' || *str == '+') + str++; + + /* Skip decimal digits. */ + while (ISDIGIT (*str)) + { + str++; + found_digit = true; + } + + return *str == 0 && found_digit; +} diff --git a/lib/libfile.c b/lib/libfile.c new file mode 100644 index 0000000..7ce3633 --- /dev/null +++ b/lib/libfile.c @@ -0,0 +1,130 @@ +/* libfile.c: open and read a single auxiliary data file. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" +#include "paths.h" + +#include <kpathsea/c-ctype.h> +#include <kpathsea/line.h> +#include "libfile.h" +#include "pathsrch.h" + + +/* Private variables to hold the auxiliary file we're reading from, and + its name. */ +static FILE *lib_file = NULL; +static string lib_filename; +static unsigned lib_file_line_number; + + +/* Prepare to read the ``library file'' FILENAME.DEFAULT_SUFFIX (if + FILENAME has no suffix), or just FILENAME (if it has). Give a fatal + error if it cannot be opened. Return the resulting FILE * (although + usually this will just be ignored by the caller). */ + +FILE * +libfile_start (string filename, string default_suffix) +{ + string *lib_dirs = initialize_path_list (LIB_ENVVAR, DEFAULT_LIB_PATH); + string name = extend_filename (filename, default_suffix); + + lib_filename = find_path_filename (name, lib_dirs); + + if (lib_filename == NULL) + FATAL1 ("%s: Cannot find library file in path", name); + + lib_file = xfopen (lib_filename, "r"); + lib_file_line_number = 1; + + return lib_file; +} + + +/* Close our current open file. If we don't have any file open, give a + fatal error. */ + +void +libfile_close () +{ + assert (lib_file != NULL); + + fclose (lib_file); + lib_file = NULL; +} + +/* Return the name of the currently open file, or NULL if none. */ + +string +libfilename () +{ + return lib_file == NULL ? NULL : lib_filename; +} + + +/* Analogously, for the current line number. */ + +unsigned +libfile_linenumber () +{ + return lib_file == NULL ? 0 : lib_file_line_number; +} + +/* Return the next nonblank non-comment line from `lib_file', or NULL if + we are at EOF. Also remove any trailing comment on the line. */ + +string +libfile_line () +{ + string s; + string line; + boolean skip = true; + + assert (lib_file != NULL); + + do + { + line = read_line (lib_file); + lib_file_line_number++; + + /* If at EOF, quit the loop. */ + if (line == NULL) + break; + + s = line; + + /* Move ahead to the first nonblank character. */ + while (*s != 0 && ISSPACE (*s)) + s++; + + /* Keep going if the line was blank or a comment. */ + if (*s == 0 || *s == '%') + free (line); + else + skip = false; + } + while (skip); + + if (line != NULL) + { + s = strrchr (line, '%'); + if (s != NULL) + *s = 0; + } + + return line; +} diff --git a/lib/line.c b/lib/line.c new file mode 100644 index 0000000..6c2e16e --- /dev/null +++ b/lib/line.c @@ -0,0 +1,63 @@ +/* line.c: return the next line from a file, or NULL. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + + +#define BLOCK_SIZE 40 + +char * +read_line (f) + FILE *f; +{ + int c; + unsigned limit = BLOCK_SIZE; + unsigned loc = 0; + char *line = (char *) xmalloc (limit); + + while ((c = getc (f)) != EOF && c != '\n') + { + line[loc] = c; + loc++; + + /* By testing after the assignment, we guarantee that we'll always + have space for the null we append below. We know we always + have room for the first char, since we start with BLOCK_SIZE. */ + if (loc == limit) + { + limit += BLOCK_SIZE; + line = (char *) xrealloc (line, limit); + } + } + + /* If we read anything, return it. This can't represent a last + ``line'' which doesn't end in a newline, but so what. */ + if (c != EOF) + { + /* Terminate the string. We can't represent nulls in the file, + either. Again, it doesn't matter. */ + line[loc] = 0; + } + else /* At end of file. */ + { + free (line); + line = NULL; + } + + return line; +} diff --git a/lib/list.c b/lib/list.c new file mode 100644 index 0000000..8dcca72 --- /dev/null +++ b/lib/list.c @@ -0,0 +1,64 @@ +/* list.c: simple list (represented as arrays) manipulation. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "list.h" + + +list_type +list_init () +{ + list_type answer; + + LIST_DATA (answer) = NULL; + LIST_SIZE (answer) = 0; + + return answer; +} + + +/* Free the memory for both the elements and the list itself. */ + +void +list_free (list_type *list) +{ + if (list != NULL && LIST_DATA (*list) != NULL) + { + unsigned e; + + for (e = 0; e < LIST_SIZE (*list); e++) + free (LIST_ELT (*list, e)); + + free (LIST_DATA (*list)); + } +} + +/* The list consists entirely of pointers to objects. We allocate the + space for the objects pointed to here, though, and return a pointer to + the newly-created final element in the list. */ + +address +list_append (list_type *list, unsigned element_size) +{ + LIST_SIZE (*list)++; + XRETALLOC (LIST_DATA (*list), LIST_SIZE (*list), address); + LIST_LAST_ELT (*list) = xmalloc (element_size); + + return LIST_LAST_ELT (*list); +} diff --git a/lib/logreport.c b/lib/logreport.c new file mode 100644 index 0000000..93d2dff --- /dev/null +++ b/lib/logreport.c @@ -0,0 +1,36 @@ +/* logreport.c: showing information to the user. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "logreport.h" + + +/* Says whether to output detailed progress reports, i.e., all the data + on the fitting, as we run. (-log) */ +boolean logging = false; + +FILE *log_file = NULL; + + +void +flush_log_output () +{ + if (logging) + fflush (log_file); +} diff --git a/lib/make-prefix.c b/lib/make-prefix.c new file mode 100644 index 0000000..fe4fcd4 --- /dev/null +++ b/lib/make-prefix.c @@ -0,0 +1,41 @@ +/* make-prefix.c: construct a pathname prefix. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include <kpathsea/concatn.h> + + +string +make_prefix (string prefix, string pathname) +{ + string slash_pos = strrchr (pathname, '/'); + + if (slash_pos == NULL) + return concat (prefix, pathname); + else + { + string answer = NULL; + string path_only = xstrdup (pathname); + path_only[slash_pos - pathname] = 0; + answer = concatn (path_only, "/", prefix, slash_pos + 1, NULL); + free (path_only); + + return answer; + } +} diff --git a/lib/math.c b/lib/math.c new file mode 100644 index 0000000..0939d8e --- /dev/null +++ b/lib/math.c @@ -0,0 +1,173 @@ +/* math.c: define some simple array operations, and other functions. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + + +/* Numerical errors sometimes make a floating point number just slightly + larger or smaller than its true value. When it matters, we need to + compare with some tolerance, REAL_EPSILON, defined in kbase.h. */ + +const boolean +epsilon_equal (real v1, real v2) +{ + return + v1 == v2 /* Usually they'll be exactly equal, anyway. */ + || fabs (v1 - v2) <= REAL_EPSILON; +} + + +/* Return the Euclidean distance between P1 and P2. */ + +const real +distance (real_coordinate_type p1, real_coordinate_type p2) +{ + return hypot (p1.x - p2.x, p1.y - p2.y); +} + + +/* Same thing, for integer points. */ +const real +int_distance (coordinate_type p1, coordinate_type p2) +{ + return hypot ((double) p1.x - p2.x, (double) p1.y - p2.y); +} + + +/* Return the arc cosine of V, in degrees in the range zero to 180. V + is taken to be in radians. */ + +const real +acosd (real v) +{ + real a; + + if (epsilon_equal (v, 1.0)) + v = 1.0; + else if (epsilon_equal (v, -1.0)) + v = -1.0; + + errno = 0; + a = acos (v); + if (errno == ERANGE || errno == EDOM) + FATAL_PERROR ("acosd"); + + return a * 180.0 / M_PI; +} + + +/* The slope of the line defined by COORD1 and COORD2. */ + +const real +slope (real_coordinate_type coord1, real_coordinate_type coord2) +{ + assert (coord2.x - coord1.x != 0); + + return (coord2.y - coord1.y) / (coord2.x - coord1.x); +} + + +/* Turn an integer point into a real one, and vice versa. */ + +const real_coordinate_type +int_to_real_coord (coordinate_type int_coord) +{ + real_coordinate_type real_coord; + + real_coord.x = int_coord.x; + real_coord.y = int_coord.y; + + return real_coord; +} + + +const coordinate_type +real_to_int_coord (real_coordinate_type real_coord) +{ + coordinate_type int_coord; + + int_coord.x = ROUND (real_coord.x); + int_coord.y = ROUND (real_coord.y); + + return int_coord; +} + + +/* See if two points (described by their row and column) are adjacent. */ + +const boolean +points_adjacent_p (int row1, int col1, int row2, int col2) +{ + int row_diff = abs (row1 - row2); + int col_diff = abs (col1 - col2); + + return + (row_diff == 1 && col_diff == 1) + || (row_diff == 0 && col_diff == 1) + || (row_diff == 1 && col_diff == 0); +} + + + + +/* Find the largest and smallest elements in an array of reals. */ + +void +find_bounds (real *values, unsigned value_count, real *min, real *max) +{ + unsigned this_value; + + /* We must use FLT_MAX and FLT_MIN, instead of the corresponding + values for double, because gcc uses the native atof to parse + floating point constants, and many atof's choke on the extremes. */ + *min = FLT_MAX; + *max = FLT_MIN; + + for (this_value = 0; this_value < value_count; this_value++) + { + if (values[this_value] < *min) + *min = values[this_value]; + + if (values[this_value] > *max) + *max = values[this_value]; + } +} + + + +/* Map a range of numbers, some positive and some negative, into all + positive, with the greatest being at one and the least at zero. + + This allocates new memory. */ + +real * +map_to_unit (real *values, unsigned value_count) +{ + real smallest, largest; + int this_value; + real *mapped_values = xmalloc (sizeof (real) * value_count); + + find_bounds (values, value_count, &smallest, &largest); + + largest -= smallest; /* We never care about largest itself. */ + + for (this_value = 0; this_value < value_count; this_value++) + mapped_values[this_value] = (values[this_value] - smallest) / largest; + + return mapped_values; +} diff --git a/lib/now.c b/lib/now.c new file mode 100644 index 0000000..aabf718 --- /dev/null +++ b/lib/now.c @@ -0,0 +1,38 @@ +/* time.c: the current date and time. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + + +/* Get the current date and time as a string. The 26 here is defined in + the manual page for ctime(3). */ + +string +now () +{ + extern time_t time (long *); + extern string ctime (time_t *); + + string time_string = xmalloc (26); + time_t t = time (0); + + strcpy (time_string, ctime (&t)); + time_string[24] = 0; /* No newline. */ + + return time_string; +} diff --git a/lib/numtoa.c b/lib/numtoa.c new file mode 100644 index 0000000..53c1a7d --- /dev/null +++ b/lib/numtoa.c @@ -0,0 +1,50 @@ +/* numtoa.c: change numbers back to strings. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +/* Declarations for these are in global.h. */ + +string +itoa (int i) +{ + char a[MAX_INT_LENGTH]; + + sprintf (a, "%d", i); + return xstrdup (a); +} + +string +utoa (unsigned u) +{ + char a[MAX_INT_LENGTH]; + + sprintf (a, "%u", u); + return xstrdup (a); +} + +string +xdtoa (double d) +{ + /* I'm not sure if this is really enough, but I also don't know how to + compute what *would* be enough. */ + char a[500]; + + sprintf (a, "%f", d); + return xstrdup (a); +} diff --git a/lib/pathsrch.c b/lib/pathsrch.c new file mode 100644 index 0000000..e513df5 --- /dev/null +++ b/lib/pathsrch.c @@ -0,0 +1,509 @@ +/* pathsrch.c: look for files based on paths, i.e., colon-separated + lists of directories. + + We should allow % specifiers in the paths for the resolution, mode + name, etc. + +Copyright (C) 1992, 93 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include <kpathsea/c-stat.h> +#include "c-pathch.h" +#include "c-namemx.h" +#include "c-pathmx.h" +#include "paths.h" + +#include <kpathsea/c-ctype.h> +#if !defined (DOS) && !defined (VMS) && !defined (VMCMS) +#include <pwd.h> +#endif +#include "dirio.h" +#include "pathsrch.h" + +static boolean absolute_p P1H(string filename); +static void add_directory P3H(string **, unsigned *, string); +static void expand_subdir P3H(string **, unsigned *, string); +static string *find_dir_list P1H(string); +static string readable P1H(string); +static void save_dir_list P2H(string, string *); +static string truncate_pathname P1H(string); + +/* If FILENAME is absolute or explicitly relative (i.e., starts with + `/', `./', or `../'), or if DIR_LIST is null, we return whether + FILENAME is readable as-is. Otherwise, we test if FILENAME is in any of + the directories listed in DIR_LIST. (The last entry of DIR_LIST must + be null.) We return the complete path if found, NULL else. + + In the interests of doing minimal work here, we assume that each + element of DIR_LIST already ends with a `/'. + + DIR_LIST is most conveniently made by calling `initialize_path_list'. + This is a separate routine because we allow recursive searching, and + it may take some time to discover the list of directories. + We do not want to incur that overhead every time we want to look for + a file. + + (Actually, `/' is not hardwired into this routine; we use PATH_SEP, + defined above.) */ + +string +find_path_filename P2C(string, filename, string *, dir_list) +{ + string found_name = NULL; + + /* Do this before testing for absolute-ness, as a leading ~ will be an + absolute pathname. */ + filename = expand_tilde (filename); + + /* If FILENAME is absolute or explicitly relative, or if DIR_LIST is + null, only check if FILENAME is readable. */ + if (absolute_p (filename) || dir_list == NULL) + found_name = readable (filename); + else + { /* Test if FILENAME is in any of the directories in DIR_LIST. */ + string save_filename = filename; + + while (*dir_list != NULL) + { + filename = concat (*dir_list, save_filename); + found_name = readable (filename); + if (found_name == NULL) + { + free (filename); + dir_list++; + } + else + { + if (found_name != filename) + free (filename); + break; + } + } + } + + return found_name; +} + + +/* If NAME is readable, return it. If the error is ENAMETOOLONG, + truncate any too-long path components and return the result (unless + there were no too-long components, i.e., a overall too-long name + caused the error, in which case return NULL). On any other error, + return NULL. + + POSIX invented this brain-damage of not necessarily truncating + pathname components; the system's behavior is defined by the value of + the symbol _POSIX_NO_TRUNC, but you can't change it dynamically! */ + +static string +readable (name) + string name; +{ + string ret; + + if (access (name, R_OK) == 0 && !dir_p (name)) + ret = name; +#ifdef ENAMETOOLONG + else if (errno == ENAMETOOLONG) + { + ret = truncate_pathname (name); + + /* Perhaps some other error will occur with the truncated name, so + let's call access again. */ + if (!(access (ret, R_OK) == 0 && !dir_p (ret))) + { /* Failed. */ + free (ret); + ret = NULL; + } + } +#endif + else + ret = NULL; /* Some other error. */ + + return ret; +} + + + +/* Truncate any too-long path components in NAME, returning the result. */ + +static string +truncate_pathname (name) + string name; +{ + unsigned c_len = 0; /* Length of current component. */ + unsigned ret_len = 0; /* Length of constructed result. */ + string ret = (string) xmalloc (PATH_MAX + 1); + + for (; *name; name++) + { + if (IS_PATH_SEP (*name)) + { /* At a directory delimiter, reset component length. */ + c_len = 0; + } + else if (c_len > NAME_MAX) + { /* If past the max for a component, ignore this character. */ + continue; + } + + /* If we've already copied the max, give up. */ + if (ret_len == PATH_MAX) + { + free (ret); + return NULL; + } + + /* Copy this character. */ + ret[ret_len++] = *name; + c_len++; + } + ret[ret_len] = 0; + + return ret; +} + + +/* Return true if FILENAME is absolute or explicitly relative, else false. */ + +static boolean +absolute_p P1C(string, filename) +{ + boolean absolute = IS_PATH_SEP (*filename) +#ifdef DOS + || ISALPHA (*filename) && filename[1] == ':' +#endif + ; + boolean explicit_relative + = (*filename == '.' + && (IS_PATH_SEP (filename[1]) + || (filename[1] == '.' && IS_PATH_SEP (filename[2])))); + + return absolute || explicit_relative; +} + +/* Return a NULL-terminated array of directory names, each name ending + with PATH_SEP, created by parsing the PATH_DELIMITER-separated list + in the value of the environment variable ENV_NAME, or DEFAULT_PATH if + the envvar is not set. + + A leading or trailing colon in the value of ENV_NAME is replaced by + DEFAULT_PATH. + + Any element of the path that ends with double PATH_SEP characters + (e.g., `foo//') is replaced by all its subdirectories. + + If ENV_NAME is null, only parse DEFAULT_PATH. If both are null, do + nothing and return NULL. */ + +string * +initialize_path_list P2C(string, env_name, string, default_path) +{ + string dir, path; + string *dir_list; + unsigned dir_count = 0; + string env_value = env_name ? getenv (env_name) : NULL; + string orig_path = expand_default (env_value, default_path); + + if (orig_path == NULL || *orig_path == 0) + return NULL; + + /* If we've already seen this colon-separated list, then just get it + back instead of going back to the filesystem. */ + dir_list = find_dir_list (orig_path); + if (dir_list != NULL) + return dir_list; + + /* Be sure `path' is in writable memory. */ + path = (orig_path == env_value || orig_path == default_path + ? xstrdup (orig_path) : orig_path); + + /* Find each element in the path in turn. */ + for (dir = strtok (path, PATH_DELIMITER_STRING); dir != NULL; + dir = strtok (NULL, PATH_DELIMITER_STRING)) + { + int len; + /* If the path starts with ~ or ~user, expand it. Do this + before calling `expand_subdir' or `add_directory', so that + 1) we don't expand the same ~ for every subdirectory; and + 2) pathnames in `expand_subdir' don't have a `~' in them + (since the system won't grok `~/foo' as a directory). */ + dir = expand_tilde (dir); + len = strlen (dir); + + /* If `dir' is the empty string, ignore it. */ + if (len == 0) + continue; + + /* If `dir' ends in double slashes, do subdirectories (and remove + the second slash, so the final pathnames we return don't look + like foo//bar). Because we obviously want to do subdirectories + of `dir', we don't check if it is a leaf. This means that if + `dir' is `foo//', and `foo' contains only symlinks (so our leaf + test below would be true), the symlinks are chased. */ + if (len > 2 && IS_PATH_SEP (dir[len - 1]) && IS_PATH_SEP (dir[len - 2])) + { + dir[len - 1] = 0; + if (dir_p (dir)) + { + add_directory (&dir_list, &dir_count, dir); + expand_subdir (&dir_list, &dir_count, dir); + } + } + else + { /* Don't bother to add the directory if it doesn't exist. */ + if (dir_p (dir)) + add_directory (&dir_list, &dir_count, dir); + } + } + + /* Add the terminating null entry to `dir_list'. */ + dir_count++; + XRETALLOC (dir_list, dir_count, string); + dir_list[dir_count - 1] = NULL; + + /* Save the directory list we just found. */ + save_dir_list (orig_path, dir_list); + + return dir_list; +} + +/* Subroutines for `initialize_path_list'. */ + +/* Add a newly-allocated copy of DIR to the end of the array pointed to + by DIR_LIST_PTR. Increment DIR_COUNT_PTR. Append a `/' to DIR if + necessary. We assume DIR is a directory, to avoid unnecessary an + unnecessary call to `stat'. */ + +static void +add_directory (dir_list_ptr, dir_count_ptr, dir) + string **dir_list_ptr; + unsigned *dir_count_ptr; + string dir; +{ + /* If `dir' does not end with a `/', add it. We can't just + write it in place, since that would overwrite the null that + strtok may have put in. So we always make a copy of DIR. */ + dir = (IS_PATH_SEP (dir[strlen (dir) - 1]) ? xstrdup (dir) + : concat (dir, PATH_SEP_STRING)); + + /* Add `dir' to the list of the directories. */ + (*dir_count_ptr)++; + XRETALLOC (*dir_list_ptr, *dir_count_ptr, string); + (*dir_list_ptr)[*dir_count_ptr - 1] = dir; +} + + +/* Add DIRNAME to DIR_LIST and look for subdirectories, recursively. We + assume DIRNAME is the name of a directory. */ + +static void +expand_subdir (dir_list_ptr, dir_count_ptr, dirname) + string **dir_list_ptr; + unsigned *dir_count_ptr; + string dirname; +{ + DIR *dir; + struct dirent *e; + unsigned length; + char potential[PATH_MAX]; + struct stat st; + + /* We will be looking at its contents. */ + dir = opendir (dirname); + if (dir == NULL) + return; + + /* Compute the length of DIRNAME, since it's loop-invariant. */ + length = strlen (dirname); + + /* Construct the part of the pathname that doesn't change. */ + strcpy (potential, dirname); + if (!IS_PATH_SEP (potential[length - 1])) + { + potential[length] = PATH_SEP; + potential[length + 1] = 0; + length++; + } + + while ((e = readdir (dir)) != NULL) + { /* If it's . or .., never mind. */ + if (!(e->d_name[0] == '.' + && (e->d_name[1] == 0 + || (e->d_name[1] == '.' && e->d_name[2] == 0)))) + { /* If it's not a directory, we will skip it on the + recursive call. */ + strcat (potential, e->d_name); + + /* If we can't stat it, or if it isn't a directory, continue. */ + if (stat (potential, &st) == 0 && S_ISDIR (st.st_mode)) + { /* It's a subdirectory; add `potential' to the list. */ + add_directory (dir_list_ptr, dir_count_ptr, potential); + + /* If it's not a leaf, quit. Assume that leaf + directories have two links (one for . and one for ..). + This means that symbolic links to directories do not affect + the leaf-ness. This is arguably wrong, but the only + alternative I know of is to stat every entry in the + directory, and that is unacceptably slow. + + The #ifdef here at least makes this configurable at + compile-time, so that if we're using VMS directories or + some such, we can still find subdirectories, even if it + is much slower. */ +#ifdef UNIX_ST_NLINK + if (st.st_nlink > 2) +#endif + { /* All criteria are met; find subdirectories. */ + expand_subdir (dir_list_ptr, dir_count_ptr, potential); + } + } + + /* ``Remove'' the directory entry name. */ + potential[length] = 0; + } + } + + closedir (dir); +} + +/* These routines, while not strictly needed to be exported, are + plausibly useful to be called by outsiders. */ + +/* Replace a leading or trailing `:' in ENV_PATH with DEFAULT_PATH. If + neither is present, return ENV_PATH if that is non-null, else + DEFAULT_PATH. */ + +string +expand_default (env_path, default_path) + string env_path; + string default_path; +{ + string expansion; + + if (env_path == NULL) + expansion = default_path; + else if (*env_path == PATH_DELIMITER) + expansion = concat (default_path, env_path); + else if (env_path[strlen (env_path) - 1] == PATH_DELIMITER) + expansion = concat (env_path, default_path); + else + expansion = env_path; + + return expansion; +} + + +/* Expand a leading ~ or ~user, Unix-style, unless we are some weirdo + operating system. */ + +string +expand_tilde P1C(string, name) +{ +#if defined (DOS) || defined (VMS) || defined (VMCMS) + return name; +#else + string expansion; + string home; + + /* If no leading tilde, do nothing. */ + if (*name != '~') + expansion = name; + + /* If `~' or `~/', use $HOME if it exists, or `.' if it doesn't. */ + else if (IS_PATH_SEP (name[1]) || name[1] == 0) + { + home = getenv ("HOME"); + if (home == NULL) + home = "."; + + expansion + = name[1] == 0 ? home : concat3 (home, PATH_SEP_STRING, name + 2); + } + + /* If `~user' or `~user/', look up user in the passwd database. */ + else + { + struct passwd *p; + string user; + unsigned c = 2; + while (!IS_PATH_SEP (name[c]) && name[c] != 0) + c++; + + user = (string) xmalloc (c); + strncpy (user, name + 1, c - 1); + user[c - 1] = 0; + + /* We only need the cast here for those (old deficient) systems + which do not declare `getpwnam' in <pwd.h>. */ + p = (struct passwd *) getpwnam (user); + free (user); + /* If no such user, just use `.'. */ + home = p == NULL ? "." : p->pw_dir; + + expansion = name[c] == 0 ? home : concat (home, name + c); + } + + return expansion; +#endif /* not (DOS or VMS or VM/CMS) */ +} + +/* Routines to save and retrieve a directory list keyed by the original + colon-separated path. This is useful because 1) it can take a + significant amount of time to discover all the subdirectories of a + given directory, and 2) many paths all have the same basic default, + and thus would recompute the directory list. */ + +typedef struct +{ + string path; + string *dir_list; +} saved_path_entry; + +static saved_path_entry *saved_paths = NULL; +static unsigned saved_paths_length = 0; + + +/* We implement the data structure as a simple linear list, since it's + unlikely to ever be more than a dozen or so elements long. We don't + bother to check here if PATH has already been saved; we always add it + to our list. */ + +static void +save_dir_list P2C(string, path, string *, dir_list) +{ + saved_paths_length++; + XRETALLOC (saved_paths, saved_paths_length, saved_path_entry); + saved_paths[saved_paths_length - 1].path = path; + saved_paths[saved_paths_length - 1].dir_list = dir_list; +} + +/* When we retrieve, just check the list in order. */ + +static string * +find_dir_list P1C(string, path) +{ + unsigned p; + + for (p = 0; p < saved_paths_length; p++) + { + if (strcmp (saved_paths[p].path, path) == 0) + return saved_paths[p].dir_list; + } + + return NULL; +} diff --git a/lib/rand.c b/lib/rand.c new file mode 100644 index 0000000..78cc7fa --- /dev/null +++ b/lib/rand.c @@ -0,0 +1,70 @@ +/* rand.c: a simple pseudo-random number generator. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "rand.h" + + +/* Current state of the random number generator. ANSI C says that the + default should be as if `srand' was called with the value 1. At all + times this will be a random number between 1 and RAND_MAX+1. */ +static long rand_state = 2; + + +/* Set the state. It's ok if `seed' doesn't fit in a long, since we + check for negative values before we return anything. On the other + hand, we cannot allow our state to become zero, since then we will + produce zero forever. */ + +void +seed_rand (unsigned seed) +{ + rand_state = seed + 1; +} + + +/* Return a pseudo-random number based on `x' in the range [0, RAND_MAX]. + We use the Ghostscript computation (from the function `zrand' in the + file `zmath.c'). */ + +int +k_rand () +{ + /* We use an algorithm from CACM 31(10), pp. 1192-1201, October 1988. + According to a posting by Ed Taft on comp.lang.postscript, Level 2 + (Adobe) PostScript interpreters use this algorithm too: + + x[n+1] = (16807 * x[n]) mod (2^31 - 1) + + The complication ensues from the fact that the multiplication may + lead to a 46-bit number. */ + +#define A 16807 +#define M 0x7fffffff +#define Q 127773 /* M / A */ +#define R 2836 /* M % A */ + rand_state = A * (rand_state % Q) - R * (rand_state / Q); + while ( rand_state <= 0 ) rand_state += M; + + /* OK, `rand_state' is our new random number between 1 and 2^31 - 1. + Now we have to subtract one, so that we return a number in the + range zero to RAND_MAX (inclusive). We obviously must define our + RAND_MAX to be 2^31 - 2, which we do (in `rand.h'). */ + return rand_state - 1; +} diff --git a/lib/report.c b/lib/report.c new file mode 100644 index 0000000..fc732b2 --- /dev/null +++ b/lib/report.c @@ -0,0 +1,27 @@ +/* report.c: showing information to the user online. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + + +/* Says whether to output short progress reports as we run. (-verbose) */ +boolean verbose = false; + +/* Where to output the reports. If a particular program uses standard + output for real output, this gets changed to `stderr'. */ +FILE *report_file = stdout; diff --git a/lib/safe-free.c b/lib/safe-free.c new file mode 100644 index 0000000..7c56d0a --- /dev/null +++ b/lib/safe-free.c @@ -0,0 +1,37 @@ +/* safe-free.c: free with error checking. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + + +/* `free' itself does not return an error status. So all we can do here + is check for nulls. */ + +void +safe_free (address *item) +{ + if (item == NULL || *item == NULL) + { + fprintf (stderr, "safe_free: Attempt to free a null item.\n"); + abort (); + } + + free (*item); + + *item = NULL; +} diff --git a/lib/scaled-num.c b/lib/scaled-num.c new file mode 100644 index 0000000..cf4a18f --- /dev/null +++ b/lib/scaled-num.c @@ -0,0 +1,75 @@ +/* scaled-num.c: conversions on ``scaled'' numbers, which are a 32-bit + word with 16 bits of fraction. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "scaled-num.h" + + +#define SCALED_UNITY (1 << 16) /* 2^16, represents 1.00000. */ + + +/* This prints a scaled number, rounded to five digits. */ + +void +print_scaled (scaled s) +{ + scaled delta; + + if (s < 0) + { /* Print sign, if negative. */ + putchar ('-'); + s = -s; + } + + printf ("%u", s / SCALED_UNITY); /* Print integer part. */ + putchar ('.'); + + s = 10 * (s % SCALED_UNITY) + 5; + delta = 10; + + do + { + if (delta > SCALED_UNITY) + s += 0100000 - (delta / 2); /* Round the last digit. */ + + printf ("%c", '0' + (s / SCALED_UNITY)); + s = 10 * (s % SCALED_UNITY); + delta *= 10; + } + while (s > delta); +} + + +const real +scaled_to_real (scaled s) +{ + real r = (real) s / SCALED_UNITY; + + return r; +} + + +const scaled +real_to_scaled (real r) +{ + scaled s = r * SCALED_UNITY; + + return s; +} diff --git a/lib/spline.c b/lib/spline.c new file mode 100644 index 0000000..cdfc25f --- /dev/null +++ b/lib/spline.c @@ -0,0 +1,216 @@ +/* spline.c: spline and spline list (represented as arrays) manipulation. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "bounding-box.h" +#include "spline.h" +#include "vector.h" + + +/* Return a new spline structure, initialized with (recognizable) + garbage. */ + +spline_type +new_spline () +{ + spline_type spline; + + START_POINT (spline) + = CONTROL1 (spline) + = CONTROL2 (spline) + = END_POINT (spline) + = (real_coordinate_type) { -100.0, -100.0 }; + SPLINE_DEGREE (spline) = -1; + + return spline; +} + + +/* Print a spline in human-readable form. */ + +void +print_spline (FILE *f, spline_type s) +{ + if (SPLINE_DEGREE (s) == LINEAR) + fprintf (f, "(%.3f,%.3f)--(%.3f,%.3f).\n", + START_POINT (s).x, START_POINT (s).y, + END_POINT (s).x, END_POINT (s).y); + + else if (SPLINE_DEGREE (s) == CUBIC) + fprintf (f, "(%.3f,%.3f)..ctrls(%.3f,%.3f)&(%.3f,%.3f)..(%.3f,%.3f).\n", + START_POINT (s).x, START_POINT (s).y, + CONTROL1 (s).x, CONTROL1 (s).y, + CONTROL2 (s).x, CONTROL2 (s).y, + END_POINT (s).x, END_POINT (s).y); + + else + FATAL1 ("print_spline: strange degree (%d)", SPLINE_DEGREE (s)); +} + + + + +/* Evaluate the spline S at a given T value. This is an implementation + of de Casteljau's algorithm. See Schneider's thesis (reference in + ../limn/README), p.37. The variable names are taken from there. */ + +real_coordinate_type +evaluate_spline (spline_type s, real t) +{ + spline_type V[4]; /* We need degree+1 splines, but assert degree <= 3. */ + unsigned i, j; + real one_minus_t = 1.0 - t; + polynomial_degree degree = SPLINE_DEGREE (s); + + for (i = 0; i <= degree; i++) + V[0].v[i] = s.v[i]; + + for (j = 1; j <= degree; j++) + for (i = 0; i <= degree - j; i++) + { + real_coordinate_type t1 = Pmult_scalar (V[j - 1].v[i], one_minus_t); + real_coordinate_type t2 = Pmult_scalar (V[j - 1].v[i + 1], t); + V[j].v[i] = Padd (t1, t2); + } + + return V[degree].v[0]; +} + + + + +/* Return a new, empty, spline list. */ + +spline_list_type * +new_spline_list () +{ + spline_list_type *answer = xmalloc (sizeof (spline_list_type)); + + SPLINE_LIST_DATA (*answer) = NULL; + SPLINE_LIST_LENGTH (*answer) = 0; + + return answer; +} + + +/* Return a new spline list with SPLINE as the first element. */ + +spline_list_type * +init_spline_list (spline_type spline) +{ + spline_list_type *answer = xmalloc (sizeof (spline_list_type)); + + SPLINE_LIST_DATA (*answer) = xmalloc (sizeof (spline_type)); + SPLINE_LIST_ELT (*answer, 0) = spline; + SPLINE_LIST_LENGTH (*answer) = 1; + + return answer; +} + + +/* Free the storage in a spline list. We don't have to free the + elements, since they are arrays in automatic storage. And we don't + want to free the list if it was empty. */ + +void +free_spline_list (spline_list_type *spline_list) +{ + if (SPLINE_LIST_DATA (*spline_list) != NULL) + safe_free ((address *) &(SPLINE_LIST_DATA (*spline_list))); +} + + +/* Append the spline S to the list SPLINE_LIST. */ + +void +append_spline (spline_list_type *l, spline_type s) +{ + assert (l != NULL); + + SPLINE_LIST_LENGTH (*l)++; + SPLINE_LIST_DATA (*l) = xrealloc (SPLINE_LIST_DATA (*l), + SPLINE_LIST_LENGTH (*l) * sizeof (spline_type)); + LAST_SPLINE_LIST_ELT (*l) = s; +} + + +/* Tack the elements in the list S2 onto the end of S1. + S2 is not changed. */ + +void +concat_spline_lists (spline_list_type *s1, spline_list_type s2) +{ + unsigned this_spline; + unsigned new_length; + + assert (s1 != NULL); + + new_length = SPLINE_LIST_LENGTH (*s1) + SPLINE_LIST_LENGTH (s2); + + XRETALLOC (SPLINE_LIST_DATA (*s1), new_length, spline_type); + + for (this_spline = 0; this_spline < SPLINE_LIST_LENGTH (s2); this_spline++) + SPLINE_LIST_ELT (*s1, SPLINE_LIST_LENGTH (*s1)++) + = SPLINE_LIST_ELT (s2, this_spline); +} + + + +/* Return a new, empty, spline list array. */ + +spline_list_array_type +new_spline_list_array () +{ + spline_list_array_type answer; + + SPLINE_LIST_ARRAY_DATA (answer) = NULL; + SPLINE_LIST_ARRAY_LENGTH (answer) = 0; + + return answer; +} + + +/* Free the storage in a spline list array. We don't + want to free the list if it is empty. */ + +void +free_spline_list_array (spline_list_array_type *spline_list_array) +{ + unsigned this_list; + + for (this_list = 0; + this_list < SPLINE_LIST_ARRAY_LENGTH (*spline_list_array); + this_list++) + free_spline_list (&SPLINE_LIST_ARRAY_ELT (*spline_list_array, this_list)); + + if (SPLINE_LIST_ARRAY_DATA (*spline_list_array) != NULL) + safe_free ((address *) &(SPLINE_LIST_ARRAY_DATA (*spline_list_array))); +} + + +/* Append the spline S to the list SPLINE_LIST_ARRAY. */ + +void +append_spline_list (spline_list_array_type *l, spline_list_type s) +{ + SPLINE_LIST_ARRAY_LENGTH (*l)++; + XRETALLOC (SPLINE_LIST_ARRAY_DATA (*l), + SPLINE_LIST_ARRAY_LENGTH (*l), spline_list_type); + LAST_SPLINE_LIST_ARRAY_ELT (*l) = s; +} diff --git a/lib/statistics.c b/lib/statistics.c new file mode 100644 index 0000000..c786ce9 --- /dev/null +++ b/lib/statistics.c @@ -0,0 +1,79 @@ +/* statistics.c: find various statistics. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "statistics.h" + + +/* The mean. The array A might have been filtered (for example), in + which case it will have many zeros in it that shouldn't be counted + when computing the statistics. PERTINENT is the number of elements + that are actually valid. COUNT, on the other hand, is the number of + elements in the array. */ + +real +mean (real *a, unsigned count, unsigned pertinent) +{ + unsigned this_variable; + real sum = 0.0; + + assert (pertinent > 0); + + for (this_variable = 0; this_variable < count; this_variable++) + sum += a[this_variable]; + + return sum / pertinent; +} + + +/* The standard deviation. We have to subtract one from the number of + samples, because we lost a degree of freedom because of the mean. */ + +real +standard_deviation (real *a, real mean, unsigned count, unsigned pertinent) +{ + real sum = 0.0; + int this_variable; + + assert (pertinent > 0); + + for (this_variable = 0; this_variable < count; this_variable++) + { + real x = a[this_variable] - mean; + sum += x * x; + } + + return sqrt (sum / (pertinent > 1 ? (pertinent - 1) : 1)); +} + + +/* Here's a routine to fill up the statistics structure. */ + +statistics_type +statistics (real *data, unsigned data_length, unsigned pertinent) +{ + statistics_type s; + + s.mean = mean (data, data_length, pertinent); + + s.variance = standard_deviation (data, s.mean, data_length, pertinent); + s.variance *= s.variance; + + return s; +} diff --git a/lib/str-lcase.c b/lib/str-lcase.c new file mode 100644 index 0000000..0c21a4c --- /dev/null +++ b/lib/str-lcase.c @@ -0,0 +1,49 @@ +/* str-casefold.c: make a string either all uppercase or all lowercase. + +Copyright (C) 1992 Free Software Foundation, Inc. +This file was part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include <kpathsea/c-ctype.h> +#include "str-lcase.h" + + +/* Return a malloced copy of S with all its uppercase letters replaced + with their lowercase counterparts. S must not be NULL. */ + +string +str_to_lower (string s) +{ + unsigned c; + string lc; + unsigned length; + + assert (s != NULL); + + length = strlen (s); + lc = xmalloc (length + 1); + + for (c = 0; c < length; c++) + lc[c] = ISUPPER (s[c]) ? TOLOWER (s[c]) : s[c]; + + lc[length] = 0; + + return lc; + +} diff --git a/lib/str-to-bit.c b/lib/str-to-bit.c new file mode 100644 index 0000000..83ffa42 --- /dev/null +++ b/lib/str-to-bit.c @@ -0,0 +1,111 @@ +/* str-to-bit.c: typeset a text string in some font, producing a bitmap. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include <kpathsea/c-ctype.h> +#include "font.h" + + +/* Turn the C string TEXT into a bitmap, taking the characters from the + font FONT_NAME at resolution DPI. Any space characters in TEXT turn + into the natural interword space for this font. No escapes are + recognized in TEXT. */ + +bitmap_type +string_to_bitmap (string text, string font_name, unsigned dpi) +{ + bitmap_type b; + unsigned this_char; + char_info_type *chars[strlen (text)]; + font_info_type font = get_font (font_name, dpi); + int width = 0, height = 0, depth = 0; + int x = 0, y = 0; /* Our current position. */ + real tfm_space + = TFM_SAFE_FONTDIMEN (FONT_TFM_FONT (font), TFM_SPACE_PARAMETER, 0); + int font_space = POINTS_TO_PIXELS (tfm_space, dpi); + + for (this_char = 0; this_char < strlen (text); this_char++) + { + /* Turn any kind of space character into a normal interword space. */ + if (ISSPACE (text[this_char])) + width += font_space; + else + { + chars[this_char] = get_char (font_name, text[this_char]); + + /* If the character doesn't exist in this font, just keep + going. */ + if (chars[this_char] == NULL) + continue; + + /* The set width should be equal to the left side bearing plus + the bitmap width plus the right side bearing. */ + width += CHAR_SET_WIDTH (*chars[this_char]); + height = MAX (height, CHAR_HEIGHT (*chars[this_char])); + depth = MAX (depth, CHAR_DEPTH (*chars[this_char])); + } + } + + /* Unless the image is nonnegative both horizontally and vertically, + it is invisible. */ + if (width <= 0 || (height + depth + 1 <= 0)) + { + BITMAP_WIDTH (b) = 0; + BITMAP_HEIGHT (b) = 0; + BITMAP_BITS (b) = NULL; + return b; + } + + /* The image is going to be visible. */ + b = new_bitmap ((dimensions_type) { height + depth + 1, width }); + + for (this_char = 0; this_char < strlen (text); this_char++) + { + if (ISSPACE (text[this_char])) + x += font_space; + else + { + int char_x, char_y; + char_info_type c; + + if (chars[this_char] == NULL) + continue; + + c = *chars[this_char]; + + x += CHAR_LSB (c); + x = MAX (x, 0); /* In case the lsb was negative. */ + + /* Copy the character image to the bitmap we are building, one + column at a time, from top to bottom. */ + for (char_x = 0; char_x < CHAR_BITMAP_WIDTH (c); char_x++, x++) + for (char_y = 0, y = height - CHAR_HEIGHT (c); + char_y < CHAR_BITMAP_HEIGHT (c); + char_y++, y++) + BITMAP_PIXEL (b, y, x) + = BITMAP_PIXEL (CHAR_BITMAP (c), char_y, char_x); + + x += CHAR_RSB (c); + } + } + + close_font (font_name); + + return b; +} diff --git a/lib/strstr.o b/lib/strstr.o Binary files differnew file mode 100644 index 0000000..a882b08 --- /dev/null +++ b/lib/strstr.o diff --git a/lib/substring.c b/lib/substring.c new file mode 100644 index 0000000..8ef7174 --- /dev/null +++ b/lib/substring.c @@ -0,0 +1,50 @@ +/* substring.c: copy a chunk from a string. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + + +/* Return a fresh copy of SOURCE[START..LIMIT], or NULL if LIMIT<START. + If LIMIT>strlen(START), it is reassigned. */ + +string +substring (string source, const unsigned start, const unsigned limit) +{ + string result; + unsigned this_char; + unsigned length = strlen (source); + unsigned lim = limit; + + /* Upper bound out of range? */ + if (lim >= length) + lim = length - 1; + + /* Null substring? */ + if (start > limit) + return ""; + + /* The `2' here is one for the null and one for limit - start inclusive. */ + result = xmalloc (limit - start + 2); + + for (this_char = start; this_char <= limit; this_char++) + result[this_char - start] = source[this_char]; + + result[this_char - start] = 0; + + return result; +} diff --git a/lib/varstring.c b/lib/varstring.c new file mode 100644 index 0000000..0107abd --- /dev/null +++ b/lib/varstring.c @@ -0,0 +1,97 @@ +/* varstring.c: variable-length strings. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "varstring.h" + + +/* You use variable-length stringsd by calling `init_string' first, then + assigning to particular elements via `set_string_element'. The string + will initially be `INITIAL_SIZE' characters, and be incremented in + blocks of size `INCREMENT_SIZE'. */ + +#define INITIAL_SIZE 16 +#define INCREMENT_SIZE 64 + +variable_string +vs_init () +{ + variable_string vs; + + VS_CHARS (vs) = xmalloc (INITIAL_SIZE); + *VS_CHARS (vs) = 0; + VS_ALLOCATED (vs) = INITIAL_SIZE; + VS_USED (vs) = 0; + + return vs; +} + + +/* Free the data we've allocated for VS. */ + +void +vs_free (variable_string *vs) +{ + free (VS_CHARS (*vs)); + VS_CHARS (*vs) = NULL; +} + + +/* We do not put a NULL after we insert NEW_CHAR at the (zero-based) + index LOC. The caller is responsible for that. */ + +void +vs_set_char (variable_string *vs, unsigned loc, char new_char) +{ + /* Do we need more space? */ + if (loc >= VS_ALLOCATED (*vs)) + { /* Yes. Make sure to allocate enough. */ + unsigned extra = MAX (INCREMENT_SIZE, loc - VS_ALLOCATED (*vs) + 1); + VS_CHARS (*vs) = xrealloc (VS_CHARS (*vs), VS_ALLOCATED (*vs) + extra); + VS_ALLOCATED (*vs) += extra; + } + + VS_CHARS (*vs)[loc] = new_char; + VS_USED (*vs) = loc + 1; +} + + +/* Append NEW_CHAR to VS. */ + +void +vs_append_char (variable_string *vs, char new_char) +{ + vs_set_char (vs, VS_USED (*vs), new_char); +} + + +variable_string +vs_concat (variable_string vs1, variable_string vs2) +{ + variable_string vs; + unsigned used = VS_USED (vs1) + VS_USED (vs2); + + VS_CHARS (vs) = xmalloc (used + 1); + memcpy (VS_CHARS (vs), VS_CHARS (vs1), VS_USED (vs1)); + memcpy (VS_CHARS (vs) + VS_USED (vs1), VS_CHARS (vs2), VS_USED (vs2)); + VS_ALLOCATED (vs) = used + 1; + VS_USED (vs) = used; + + return vs; +} diff --git a/lib/vector.c b/lib/vector.c new file mode 100644 index 0000000..354af2d --- /dev/null +++ b/lib/vector.c @@ -0,0 +1,272 @@ +/* vector.c: vector/point operations. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "vector.h" + + +/* Given the point COORD, return the corresponding vector. */ + +const vector_type +make_vector (const real_coordinate_type c) +{ + vector_type v; + + v.dx = c.x; + v.dy = c.y; + + return v; +} + + +/* And the converse: given a vector, return the corresponding point. */ + +const real_coordinate_type +vector_to_point (const vector_type v) +{ + real_coordinate_type coord; + + coord.x = v.dx; + coord.y = v.dy; + + return coord; +} + + + +const real +magnitude (const vector_type v) +{ + return hypot (v.dx, v.dy); +} + + +const vector_type +normalize (const vector_type v) +{ + vector_type new_v; + real m = magnitude (v); + + assert (m > 0.0); + + new_v.dx = v.dx / m; + new_v.dy = v.dy / m; + + return new_v; +} + + +const vector_type +Vadd (const vector_type v1, const vector_type v2) +{ + vector_type new_v; + + new_v.dx = v1.dx + v2.dx; + new_v.dy = v1.dy + v2.dy; + + return new_v; +} + + +const real +Vdot (const vector_type v1, const vector_type v2) +{ + return v1.dx * v2.dx + v1.dy * v2.dy; +} + + +const vector_type +Vmult_scalar (const vector_type v, const real r) +{ + vector_type new_v; + + new_v.dx = v.dx * r; + new_v.dy = v.dy * r; + + return new_v; +} + + +/* Given the IN_VECTOR and OUT_VECTOR, return the angle between them in + degrees, in the range zero to 180. */ + +const real +Vangle (const vector_type in_vector, const vector_type out_vector) +{ + vector_type v1 = normalize (in_vector); + vector_type v2 = normalize (out_vector); + + return acosd (Vdot (v2, v1)); +} + + +const real_coordinate_type +Vadd_point (const real_coordinate_type c, const vector_type v) +{ + real_coordinate_type new_c; + + new_c.x = c.x + v.dx; + new_c.y = c.y + v.dy; + return new_c; +} + + +const real_coordinate_type +Vsubtract_point (const real_coordinate_type c, const vector_type v) +{ + real_coordinate_type new_c; + + new_c.x = c.x - v.dx; + new_c.y = c.y - v.dy; + return new_c; +} + + +const coordinate_type +Vadd_int_point (const coordinate_type c, const vector_type v) +{ + coordinate_type a; + + a.x = ROUND ((real) c.x + v.dx); + a.y = ROUND ((real) c.y + v.dy); + return a; +} + + +const vector_type +Vabs (const vector_type v) +{ + vector_type new_v; + + new_v.dx = fabs (v.dx); + new_v.dy = fabs (v.dy); + return new_v; +} + + + +/* Operations on points. */ + +/* This is a macro now. */ +#if 0 +const real_coordinate_type +Padd (real_coordinate_type coord1, real_coordinate_type coord2) +{ + real_coordinate_type sum; + + sum.x = coord1.x + coord2.x; + sum.y = coord1.y + coord2.y; + + return sum; +} + + +const real_coordinate_type +Pmult_scalar (const real_coordinate_type coord, const real r) +{ + real_coordinate_type answer; + + answer.x = coord.x * r; + answer.y = coord.y * r; + + return answer; +} +#endif /* 0 */ + + +const vector_type +Psubtract (const real_coordinate_type c1, const real_coordinate_type c2) +{ + vector_type v; + + v.dx = c1.x - c2.x; + v.dy = c1.y - c2.y; + + return v; +} + + + +/* Operations on integer points. */ + +const vector_type +IPsubtract (const coordinate_type coord1, const coordinate_type coord2) +{ + vector_type v; + + v.dx = coord1.x - coord2.x; + v.dy = coord1.y - coord2.y; + + return v; +} + + +const coordinate_type +IPsubtractP (const coordinate_type c1, const coordinate_type c2) +{ + coordinate_type c; + + c.x = c1.x - c2.x; + c.y = c1.y - c2.y; + + return c; +} + + +const coordinate_type +IPadd (const coordinate_type c1, const coordinate_type c2) +{ + coordinate_type c; + + c.x = c1.x + c2.x; + c.y = c1.y + c2.y; + + return c; +} + + +const coordinate_type +IPmult_scalar (const coordinate_type c, const int i) +{ + coordinate_type a; + + a.x = c.x * i; + a.y = c.y * i; + + return a; +} + + +const real_coordinate_type +IPmult_real (const coordinate_type c, const real r) +{ + real_coordinate_type a; + + a.x = c.x * r; + a.y = c.y * r; + + return a; +} + + +const boolean +IPequal (const coordinate_type c1, const coordinate_type c2) +{ + return c1.x == c2.x && c1.y == c2.y; +} diff --git a/lib/xchdir.c b/lib/xchdir.c new file mode 100644 index 0000000..9831663 --- /dev/null +++ b/lib/xchdir.c @@ -0,0 +1,29 @@ +/* xchdir.c: chdir with error checking. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "dirio.h" + + +void +xchdir (string dirname) +{ + if (chdir (dirname) != 0) + FATAL_PERROR (dirname); +} diff --git a/lib/xfseek.o b/lib/xfseek.o Binary files differnew file mode 100644 index 0000000..fc2e725 --- /dev/null +++ b/lib/xfseek.o diff --git a/lib/xftell.o b/lib/xftell.o Binary files differnew file mode 100644 index 0000000..0dfe6f8 --- /dev/null +++ b/lib/xftell.o diff --git a/lib/xgetcwd.c b/lib/xgetcwd.c new file mode 100644 index 0000000..8f3e4a9 --- /dev/null +++ b/lib/xgetcwd.c @@ -0,0 +1,104 @@ +/* xgetcwd.c: a from-scratch version of getwd. Based on the tcsh 5.20 + source, apparently uncopyrighted. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" +#include "c-pathmx.h" + +#include "dirio.h" +#include "xstat.h" + +/* Return the pathname of the current directory, or give a fatal error. */ + +string +xgetcwd () +{ + /* If the system provides getwd, use it. But don't use getcwd; + forking a process is even more expensive than all the stat calls we + make figuring out the cwd. */ +#ifdef GETWD_MISSING /* whole function */ + struct stat root_stat, cwd_stat; + string cwd_path = xmalloc (1); + + *cwd_path = 0; + + /* Find the inodes of the root and current directories. */ + root_stat = xstat ("/"); + cwd_stat = xstat ("."); + + /* Go up the directory hierarchy until we get to root, prepending each + directory we pass through to `cwd_path'. */ + while (!SAME_FILE_P (root_stat, cwd_stat)) + { + struct dirent *e; + DIR *parent_dir; + boolean found = false; + + xchdir (".."); + parent_dir = xopendir ("."); + + /* Look through the parent directory for the entry with the same + inode, so we can get its name. */ + while ((e = readdir (parent_dir)) != NULL && !found) + { + struct stat test_stat = xlstat (e->d_name); + + if (SAME_FILE_P (test_stat, cwd_stat)) + { + /* We've found it. Prepend the pathname. */ + string temp = cwd_path; + cwd_path = concat3 ("/", e->d_name, cwd_path); + free (temp); + + /* Set up to test the next parent. */ + cwd_stat = xstat ("."); + + /* Stop reading this directory. */ + found = true; + } + } + if (!found) + FATAL2 ("No inode %d/device %d in parent directory", + cwd_stat.st_ino, cwd_stat.st_dev); + + xclosedir (parent_dir); + } + + /* If the current directory is the root, cwd_path will be the empty + string, and we will have not gone through the loop. */ + if (*cwd_path == 0) + cwd_path = "/"; + else + /* Go back to where we were. */ + xchdir (cwd_path); + + return cwd_path; + +#else /* not GETWD_MISSING */ + + string path = xmalloc (PATH_MAX + 1); + + if (getwd (path) == 0) + { + fprintf (stderr, "getwd: %s", path); + exit (1); + } + + return path; +#endif /* not GETWD_MISSING */ +} diff --git a/lib/xmessage.c b/lib/xmessage.c new file mode 100644 index 0000000..1b8331a --- /dev/null +++ b/lib/xmessage.c @@ -0,0 +1,101 @@ +/* xmessage.c: pop up a message for five seconds and then go away. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef X_DISPLAY_MISSING /* whole file */ + +#include "config.h" + +#include "xt-common.h" +#include <X11/Shell.h> +#include <X11/Xaw/Label.h> + +#include "xmessage.h" + +static void message_over (XtPointer, XtIntervalId *); + + + +/* Make a popup child of the widget PARENT displaying the string S. We + pass the ARGS and N_ARGS parameters to the creation routine. */ + +void +x_message (Widget parent, string s, ArgList args, Cardinal n_args) +{ + Dimension parent_height; + Position popup_x, popup_y; + Widget popup; + + XtAppContext app_con = XtWidgetToApplicationContext (parent); + Arg parent_args[] + = { { XtNheight, (XtArgVal) &parent_height }, + }; + Arg popup_args[] + = { { XtNx, 0 }, /* We assign to the position below. */ + { XtNy, 0 }, + { XtNgeometry, (XtArgVal) NULL }, /* Don't use parent's geometry. */ + }; + + Arg default_args[] = { { XtNlabel, (XtArgVal) s } }; + ArgList all_args + = XtMergeArgLists (args, n_args, default_args, XtNumber (default_args)); + + /* Put the message at the left edge of and about halfway down PARENT's + window. We pass the address of true Position variables rather + than the address of the Arg values; in the latter case, the + endianness of the computer determines which half of the word the + answers get stored in, which is clearly bad. */ + XtGetValues (parent, parent_args, XtNumber (parent_args)); + XtTranslateCoords (parent, 0, parent_height / 2, &popup_x, &popup_y); + popup_args[0].value = popup_x; + popup_args[1].value = popup_y; + + popup = XtCreatePopupShell ("message shell", transientShellWidgetClass, + parent, popup_args, XtNumber (popup_args)); + + /* We can't use XtNumber on `all_args', since it's a pointer. */ + (void) + XtCreateManagedWidget ("message", labelWidgetClass, popup, all_args, + n_args + XtNumber (default_args)); + + /* XtPopup realizes the window, etc. */ + XtPopup (popup, XtGrabNone); + + /* Leave the message there for five seconds. */ + (void) XtAppAddTimeOut (app_con, 5000, message_over, popup); +} + + +/* Just a convenient interface to the above. */ + +void +x_warning (Widget parent, string s) +{ + x_message (parent, concat (s, "."), NULL, 0); +} + + + +static void +message_over (XtPointer client_data, XtIntervalId *interval_id) +{ + Widget popup = (Widget) client_data; + + XtPopdown (popup); +} + +#endif /* not X_DISPLAY_MISSING */ diff --git a/lib/xopendir.c b/lib/xopendir.c new file mode 100644 index 0000000..02709ac --- /dev/null +++ b/lib/xopendir.c @@ -0,0 +1,47 @@ +/* xopendir.c: opendir and closedir with error checking. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "dirio.h" + + +DIR * +xopendir P1C(string, dirname) +{ + DIR *d = opendir (dirname); + + if (d == NULL) + FATAL_PERROR (dirname); + + return d; +} + + +void +xclosedir P1C(DIR *, d) +{ +#ifdef VOID_CLOSEDIR + closedir (d); +#else + int ret = closedir (d); + + if (ret != 0) + FATAL ("closedir failed"); +#endif +} diff --git a/lib/xrename.c b/lib/xrename.c new file mode 100644 index 0000000..c840805 --- /dev/null +++ b/lib/xrename.c @@ -0,0 +1,44 @@ +/* xrename.c: conceptually rename with error checking. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + + +/* Copy FROM to TO, then unlink FROM. It would probably be faster to + read and write buffers, but the files we use this for aren't big + enough for it to make a substantial difference. */ + +void +xrename (string from, string to) +{ + int c; + FILE *input = xfopen (from, "r"); + FILE *output = xfopen (to, "w"); + + while ((c = getc (input)) != EOF || !feof (input)) + putc (c, output); + + xfclose (input, from); + xfclose (output, to); + + if (unlink (from) != 0) + { + fprintf (stderr, "warning: Could not unlink "); + perror (from); + } +} diff --git a/lib/xstrdup.c b/lib/xstrdup.c new file mode 100644 index 0000000..3ce69e9 --- /dev/null +++ b/lib/xstrdup.c @@ -0,0 +1,29 @@ +/* xstrdup.c: strdup with error checking. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + + +/* Return a copy of S in new storage. */ + +string +xstrdup P1C(string, s) +{ + string new_string = (string) xmalloc (strlen (s) + 1); + return strcpy (new_string, s); +} |
