comparison src/fileio.c @ 665:fdefd0186b75

[xemacs-hg @ 2001-09-20 06:28:42 by ben] The great integral types renaming. The purpose of this is to rationalize the names used for various integral types, so that they match their intended uses and follow consist conventions, and eliminate types that were not semantically different from each other. The conventions are: -- All integral types that measure quantities of anything are signed. Some people disagree vociferously with this, but their arguments are mostly theoretical, and are vastly outweighed by the practical headaches of mixing signed and unsigned values, and more importantly by the far increased likelihood of inadvertent bugs: Because of the broken "viral" nature of unsigned quantities in C (operations involving mixed signed/unsigned are done unsigned, when exactly the opposite is nearly always wanted), even a single error in declaring a quantity unsigned that should be signed, or even the even more subtle error of comparing signed and unsigned values and forgetting the necessary cast, can be catastrophic, as comparisons will yield wrong results. -Wsign-compare is turned on specifically to catch this, but this tends to result in a great number of warnings when mixing signed and unsigned, and the casts are annoying. More has been written on this elsewhere. -- All such quantity types just mentioned boil down to EMACS_INT, which is 32 bits on 32-bit machines and 64 bits on 64-bit machines. This is guaranteed to be the same size as Lisp objects of type `int', and (as far as I can tell) of size_t (unsigned!) and ssize_t. The only type below that is not an EMACS_INT is Hashcode, which is an unsigned value of the same size as EMACS_INT. -- Type names should be relatively short (no more than 10 characters or so), with the first letter capitalized and no underscores if they can at all be avoided. -- "count" == a zero-based measurement of some quantity. Includes sizes, offsets, and indexes. -- "bpos" == a one-based measurement of a position in a buffer. "Charbpos" and "Bytebpos" count text in the buffer, rather than bytes in memory; thus Bytebpos does not directly correspond to the memory representation. Use "Membpos" for this. -- "Char" refers to internal-format characters, not to the C type "char", which is really a byte. -- For the actual name changes, see the script below. I ran the following script to do the conversion. (NOTE: This script is idempotent. You can safely run it multiple times and it will not screw up previous results -- in fact, it will do nothing if nothing has changed. Thus, it can be run repeatedly as necessary to handle patches coming in from old workspaces, or old branches.) There are two tags, just before and just after the change: `pre-integral-type-rename' and `post-integral-type-rename'. When merging code from the main trunk into a branch, the best thing to do is first merge up to `pre-integral-type-rename', then apply the script and associated changes, then merge from `post-integral-type-change' to the present. (Alternatively, just do the merging in one operation; but you may then have a lot of conflicts needing to be resolved by hand.) Script `fixtypes.sh' follows: ----------------------------------- cut ------------------------------------ files="*.[ch] s/*.h m/*.h config.h.in ../configure.in Makefile.in.in ../lib-src/*.[ch] ../lwlib/*.[ch]" gr Memory_Count Bytecount $files gr Lstream_Data_Count Bytecount $files gr Element_Count Elemcount $files gr Hash_Code Hashcode $files gr extcount bytecount $files gr bufpos charbpos $files gr bytind bytebpos $files gr memind membpos $files gr bufbyte intbyte $files gr Extcount Bytecount $files gr Bufpos Charbpos $files gr Bytind Bytebpos $files gr Memind Membpos $files gr Bufbyte Intbyte $files gr EXTCOUNT BYTECOUNT $files gr BUFPOS CHARBPOS $files gr BYTIND BYTEBPOS $files gr MEMIND MEMBPOS $files gr BUFBYTE INTBYTE $files gr MEMORY_COUNT BYTECOUNT $files gr LSTREAM_DATA_COUNT BYTECOUNT $files gr ELEMENT_COUNT ELEMCOUNT $files gr HASH_CODE HASHCODE $files ----------------------------------- cut ------------------------------------ `fixtypes.sh' is a Bourne-shell script; it uses 'gr': ----------------------------------- cut ------------------------------------ #!/bin/sh # Usage is like this: # gr FROM TO FILES ... # globally replace FROM with TO in FILES. FROM and TO are regular expressions. # backup files are stored in the `backup' directory. from="$1" to="$2" shift 2 echo ${1+"$@"} | xargs global-replace "s/$from/$to/g" ----------------------------------- cut ------------------------------------ `gr' in turn uses a Perl script to do its real work, `global-replace', which follows: ----------------------------------- cut ------------------------------------ : #-*- Perl -*- ### global-modify --- modify the contents of a file by a Perl expression ## Copyright (C) 1999 Martin Buchholz. ## Copyright (C) 2001 Ben Wing. ## Authors: Martin Buchholz <martin@xemacs.org>, Ben Wing <ben@xemacs.org> ## Maintainer: Ben Wing <ben@xemacs.org> ## Current Version: 1.0, May 5, 2001 # 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 XEmacs; see the file COPYING. If not, write to the Free # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. eval 'exec perl -w -S $0 ${1+"$@"}' if 0; use strict; use FileHandle; use Carp; use Getopt::Long; use File::Basename; (my $myName = $0) =~ s@.*/@@; my $usage=" Usage: $myName [--help] [--backup-dir=DIR] [--line-mode] [--hunk-mode] PERLEXPR FILE ... Globally modify a file, either line by line or in one big hunk. Typical usage is like this: [with GNU print, GNU xargs: guaranteed to handle spaces, quotes, etc. in file names] find . -name '*.[ch]' -print0 | xargs -0 $0 's/\bCONST\b/const/g'\n [with non-GNU print, xargs] find . -name '*.[ch]' -print | xargs $0 's/\bCONST\b/const/g'\n The file is read in, either line by line (with --line-mode specified) or in one big hunk (with --hunk-mode specified; it's the default), and the Perl expression is then evalled with \$_ set to the line or hunk of text, including the terminating newline if there is one. It should destructively modify the value there, storing the changed result in \$_. Files in which any modifications are made are backed up to the directory specified using --backup-dir, or to `backup' by default. To disable this, use --backup-dir= with no argument. Hunk mode is the default because it is MUCH MUCH faster than line-by-line. Use line-by-line only when it matters, e.g. you want to do a replacement only once per line (the default without the `g' argument). Conversely, when using hunk mode, *ALWAYS* use `g'; otherwise, you will only make one replacement in the entire file! "; my %options = (); $Getopt::Long::ignorecase = 0; &GetOptions ( \%options, 'help', 'backup-dir=s', 'line-mode', 'hunk-mode', ); die $usage if $options{"help"} or @ARGV <= 1; my $code = shift; die $usage if grep (-d || ! -w, @ARGV); sub SafeOpen { open ((my $fh = new FileHandle), $_[0]); confess "Can't open $_[0]: $!" if ! defined $fh; return $fh; } sub SafeClose { close $_[0] or confess "Can't close $_[0]: $!"; } sub FileContents { my $fh = SafeOpen ("< $_[0]"); my $olddollarslash = $/; local $/ = undef; my $contents = <$fh>; $/ = $olddollarslash; return $contents; } sub WriteStringToFile { my $fh = SafeOpen ("> $_[0]"); binmode $fh; print $fh $_[1] or confess "$_[0]: $!\n"; SafeClose $fh; } foreach my $file (@ARGV) { my $changed_p = 0; my $new_contents = ""; if ($options{"line-mode"}) { my $fh = SafeOpen $file; while (<$fh>) { my $save_line = $_; eval $code; $changed_p = 1 if $save_line ne $_; $new_contents .= $_; } } else { my $orig_contents = $_ = FileContents $file; eval $code; if ($_ ne $orig_contents) { $changed_p = 1; $new_contents = $_; } } if ($changed_p) { my $backdir = $options{"backup-dir"}; $backdir = "backup" if !defined ($backdir); if ($backdir) { my ($name, $path, $suffix) = fileparse ($file, ""); my $backfulldir = $path . $backdir; my $backfile = "$backfulldir/$name"; mkdir $backfulldir, 0755 unless -d $backfulldir; print "modifying $file (original saved in $backfile)\n"; rename $file, $backfile; } WriteStringToFile ($file, $new_contents); } } ----------------------------------- cut ------------------------------------ In addition to those programs, I needed to fix up a few other things, particularly relating to the duplicate definitions of types, now that some types merged with others. Specifically: 1. in lisp.h, removed duplicate declarations of Bytecount. The changed code should now look like this: (In each code snippet below, the first and last lines are the same as the original, as are all lines outside of those lines. That allows you to locate the section to be replaced, and replace the stuff in that section, verifying that there isn't anything new added that would need to be kept.) --------------------------------- snip ------------------------------------- /* Counts of bytes or chars */ typedef EMACS_INT Bytecount; typedef EMACS_INT Charcount; /* Counts of elements */ typedef EMACS_INT Elemcount; /* Hash codes */ typedef unsigned long Hashcode; /* ------------------------ dynamic arrays ------------------- */ --------------------------------- snip ------------------------------------- 2. in lstream.h, removed duplicate declaration of Bytecount. Rewrote the comment about this type. The changed code should now look like this: --------------------------------- snip ------------------------------------- #endif /* The have been some arguments over the what the type should be that specifies a count of bytes in a data block to be written out or read in, using Lstream_read(), Lstream_write(), and related functions. Originally it was long, which worked fine; Martin "corrected" these to size_t and ssize_t on the grounds that this is theoretically cleaner and is in keeping with the C standards. Unfortunately, this practice is horribly error-prone due to design flaws in the way that mixed signed/unsigned arithmetic happens. In fact, by doing this change, Martin introduced a subtle but fatal error that caused the operation of sending large mail messages to the SMTP server under Windows to fail. By putting all values back to be signed, avoiding any signed/unsigned mixing, the bug immediately went away. The type then in use was Lstream_Data_Count, so that it be reverted cleanly if a vote came to that. Now it is Bytecount. Some earlier comments about why the type must be signed: This MUST BE SIGNED, since it also is used in functions that return the number of bytes actually read to or written from in an operation, and these functions can return -1 to signal error. Note that the standard Unix read() and write() functions define the count going in as a size_t, which is UNSIGNED, and the count going out as an ssize_t, which is SIGNED. This is a horrible design flaw. Not only is it highly likely to lead to logic errors when a -1 gets interpreted as a large positive number, but operations are bound to fail in all sorts of horrible ways when a number in the upper-half of the size_t range is passed in -- this number is unrepresentable as an ssize_t, so code that checks to see how many bytes are actually written (which is mandatory if you are dealing with certain types of devices) will get completely screwed up. --ben */ typedef enum lstream_buffering --------------------------------- snip ------------------------------------- 3. in dumper.c, there are four places, all inside of switch() statements, where XD_BYTECOUNT appears twice as a case tag. In each case, the two case blocks contain identical code, and you should *REMOVE THE SECOND* and leave the first.
author ben
date Thu, 20 Sep 2001 06:31:11 +0000
parents 6e99cc8c6ca5
children a307f9a2021d
comparison
equal deleted inserted replaced
664:6e99cc8c6ca5 665:fdefd0186b75
66 #ifndef CORRECT_DIR_SEPS 66 #ifndef CORRECT_DIR_SEPS
67 #define CORRECT_DIR_SEPS(s) \ 67 #define CORRECT_DIR_SEPS(s) \
68 normalize_filename(s, DIRECTORY_SEP) 68 normalize_filename(s, DIRECTORY_SEP)
69 /* Default implementation that coerces a file to use path_sep. */ 69 /* Default implementation that coerces a file to use path_sep. */
70 static void 70 static void
71 normalize_filename (Bufbyte *fp, Bufbyte path_sep) 71 normalize_filename (Intbyte *fp, Intbyte path_sep)
72 { 72 {
73 /* Always lower-case drive letters a-z, even if the filesystem 73 /* Always lower-case drive letters a-z, even if the filesystem
74 preserves case in filenames. 74 preserves case in filenames.
75 This is so filenames can be compared by string comparison 75 This is so filenames can be compared by string comparison
76 functions that are case-sensitive. Even case-preserving filesystems 76 functions that are case-sensitive. Even case-preserving filesystems
159 /* DATA can be anything acceptable to signal_error (). 159 /* DATA can be anything acceptable to signal_error ().
160 */ 160 */
161 161
162 DOESNT_RETURN 162 DOESNT_RETURN
163 report_file_type_error (Lisp_Object errtype, Lisp_Object oserrmess, 163 report_file_type_error (Lisp_Object errtype, Lisp_Object oserrmess,
164 const CBufbyte *string, Lisp_Object data) 164 const CIntbyte *string, Lisp_Object data)
165 { 165 {
166 struct gcpro gcpro1; 166 struct gcpro gcpro1;
167 Lisp_Object errdata = build_error_data (NULL, data); 167 Lisp_Object errdata = build_error_data (NULL, data);
168 168
169 GCPRO1 (errdata); 169 GCPRO1 (errdata);
173 UNGCPRO; /* not reached */ 173 UNGCPRO; /* not reached */
174 } 174 }
175 175
176 DOESNT_RETURN 176 DOESNT_RETURN
177 report_error_with_errno (Lisp_Object errtype, 177 report_error_with_errno (Lisp_Object errtype,
178 const CBufbyte *string, Lisp_Object data) 178 const CIntbyte *string, Lisp_Object data)
179 { 179 {
180 report_file_type_error (errtype, lisp_strerror (errno), string, data); 180 report_file_type_error (errtype, lisp_strerror (errno), string, data);
181 } 181 }
182 182
183 /* signal a file error when errno contains a meaningful value. */ 183 /* signal a file error when errno contains a meaningful value. */
184 184
185 DOESNT_RETURN 185 DOESNT_RETURN
186 report_file_error (const CBufbyte *string, Lisp_Object data) 186 report_file_error (const CIntbyte *string, Lisp_Object data)
187 { 187 {
188 report_error_with_errno (Qfile_error, string, data); 188 report_error_with_errno (Qfile_error, string, data);
189 } 189 }
190 190
191 191
235 signal handler) because that's way too losing. 235 signal handler) because that's way too losing.
236 236
237 (#### Actually, longjmp()ing out of the signal handler may not be 237 (#### Actually, longjmp()ing out of the signal handler may not be
238 as losing as I thought. See qxe_reliable_signal() in sysdep.c.) */ 238 as losing as I thought. See qxe_reliable_signal() in sysdep.c.) */
239 239
240 Memory_Count 240 Bytecount
241 read_allowing_quit (int fildes, void *buf, Memory_Count size) 241 read_allowing_quit (int fildes, void *buf, Bytecount size)
242 { 242 {
243 QUIT; 243 QUIT;
244 return sys_read_1 (fildes, buf, size, 1); 244 return sys_read_1 (fildes, buf, size, 1);
245 } 245 }
246 246
247 Memory_Count 247 Bytecount
248 write_allowing_quit (int fildes, const void *buf, Memory_Count size) 248 write_allowing_quit (int fildes, const void *buf, Bytecount size)
249 { 249 {
250 QUIT; 250 QUIT;
251 return sys_write_1 (fildes, buf, size, 1); 251 return sys_write_1 (fildes, buf, size, 1);
252 } 252 }
253 253
367 Given a Unix syntax file name, returns a string ending in slash. 367 Given a Unix syntax file name, returns a string ending in slash.
368 */ 368 */
369 (filename)) 369 (filename))
370 { 370 {
371 /* This function can GC. GC checked 2000-07-28 ben */ 371 /* This function can GC. GC checked 2000-07-28 ben */
372 Bufbyte *beg; 372 Intbyte *beg;
373 Bufbyte *p; 373 Intbyte *p;
374 Lisp_Object handler; 374 Lisp_Object handler;
375 375
376 CHECK_STRING (filename); 376 CHECK_STRING (filename);
377 377
378 /* If the file name has special constructs in it, 378 /* If the file name has special constructs in it,
400 /* Expansion of "c:" to drive and default directory. */ 400 /* Expansion of "c:" to drive and default directory. */
401 /* (NT does the right thing.) */ 401 /* (NT does the right thing.) */
402 if (p == beg + 2 && beg[1] == ':') 402 if (p == beg + 2 && beg[1] == ':')
403 { 403 {
404 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */ 404 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */
405 Bufbyte *res = (Bufbyte*) alloca (MAXPATHLEN + 1); 405 Intbyte *res = (Intbyte*) alloca (MAXPATHLEN + 1);
406 if (_getdcwd (toupper (*beg) - 'A' + 1, (char *)res, MAXPATHLEN)) 406 if (_getdcwd (toupper (*beg) - 'A' + 1, (char *)res, MAXPATHLEN))
407 { 407 {
408 char *c=((char *) res) + strlen ((char *) res); 408 char *c=((char *) res) + strlen ((char *) res);
409 if (!IS_DIRECTORY_SEP (*c)) 409 if (!IS_DIRECTORY_SEP (*c))
410 { 410 {
426 or the entire name if it contains no slash. 426 or the entire name if it contains no slash.
427 */ 427 */
428 (filename)) 428 (filename))
429 { 429 {
430 /* This function can GC. GC checked 2000-07-28 ben */ 430 /* This function can GC. GC checked 2000-07-28 ben */
431 Bufbyte *beg, *p, *end; 431 Intbyte *beg, *p, *end;
432 Lisp_Object handler; 432 Lisp_Object handler;
433 433
434 CHECK_STRING (filename); 434 CHECK_STRING (filename);
435 435
436 /* If the file name has special constructs in it, 436 /* If the file name has special constructs in it,
618 '4','5','6','7','8','9','-','_' 618 '4','5','6','7','8','9','-','_'
619 }; 619 };
620 620
621 Lisp_Object val; 621 Lisp_Object val;
622 Bytecount len; 622 Bytecount len;
623 Bufbyte *p, *data; 623 Intbyte *p, *data;
624 624
625 CHECK_STRING (prefix); 625 CHECK_STRING (prefix);
626 626
627 /* I was tempted to apply Fexpand_file_name on PREFIX here, but it's 627 /* I was tempted to apply Fexpand_file_name on PREFIX here, but it's
628 a bad idea because: 628 a bad idea because:
709 See also the function `substitute-in-file-name'. 709 See also the function `substitute-in-file-name'.
710 */ 710 */
711 (name, default_directory)) 711 (name, default_directory))
712 { 712 {
713 /* This function can GC. GC-checked 2000-11-18 */ 713 /* This function can GC. GC-checked 2000-11-18 */
714 Bufbyte *nm; 714 Intbyte *nm;
715 715
716 Bufbyte *newdir, *p, *o; 716 Intbyte *newdir, *p, *o;
717 int tlen; 717 int tlen;
718 Bufbyte *target; 718 Intbyte *target;
719 #ifdef WIN32_FILENAMES 719 #ifdef WIN32_FILENAMES
720 int drive = 0; 720 int drive = 0;
721 int collapse_newdir = 1; 721 int collapse_newdir = 1;
722 #endif 722 #endif
723 #ifndef WIN32_NATIVE 723 #ifndef WIN32_NATIVE
796 nm = XSTRING_DATA (name); 796 nm = XSTRING_DATA (name);
797 797
798 #ifdef WIN32_FILENAMES 798 #ifdef WIN32_FILENAMES
799 /* We will force directory separators to be either all \ or /, so make 799 /* We will force directory separators to be either all \ or /, so make
800 a local copy to modify, even if there ends up being no change. */ 800 a local copy to modify, even if there ends up being no change. */
801 nm = (Bufbyte *) strcpy ((char *) alloca (strlen ((char *) nm) + 1), 801 nm = (Intbyte *) strcpy ((char *) alloca (strlen ((char *) nm) + 1),
802 (char *) nm); 802 (char *) nm);
803 803
804 /* Find and remove drive specifier if present; this makes nm absolute 804 /* Find and remove drive specifier if present; this makes nm absolute
805 even if the rest of the name appears to be relative. */ 805 even if the rest of the name appears to be relative. */
806 { 806 {
807 Bufbyte *colon = (Bufbyte *) strrchr ((char *)nm, ':'); 807 Intbyte *colon = (Intbyte *) strrchr ((char *)nm, ':');
808 808
809 if (colon) 809 if (colon)
810 { 810 {
811 /* Only recognize colon as part of drive specifier if there is a 811 /* Only recognize colon as part of drive specifier if there is a
812 single alphabetic character preceding the colon (and if the 812 single alphabetic character preceding the colon (and if the
882 required. */ 882 required. */
883 CORRECT_DIR_SEPS (nm); 883 CORRECT_DIR_SEPS (nm);
884 if (IS_DIRECTORY_SEP (nm[1])) 884 if (IS_DIRECTORY_SEP (nm[1]))
885 { 885 {
886 if (strcmp ((char *) nm, (char *) XSTRING_DATA (name)) != 0) 886 if (strcmp ((char *) nm, (char *) XSTRING_DATA (name)) != 0)
887 name = build_string ((CBufbyte *) nm); 887 name = build_string ((CIntbyte *) nm);
888 } 888 }
889 /* drive must be set, so this is okay */ 889 /* drive must be set, so this is okay */
890 else if (strcmp ((char *) nm - 2, 890 else if (strcmp ((char *) nm - 2,
891 (char *) XSTRING_DATA (name)) != 0) 891 (char *) XSTRING_DATA (name)) != 0)
892 { 892 {
929 || nm[1] == 0) /* ~ by itself */ 929 || nm[1] == 0) /* ~ by itself */
930 { 930 {
931 Extbyte *newdir_external = get_home_directory (); 931 Extbyte *newdir_external = get_home_directory ();
932 932
933 if (newdir_external == NULL) 933 if (newdir_external == NULL)
934 newdir = (Bufbyte *) ""; 934 newdir = (Intbyte *) "";
935 else 935 else
936 TO_INTERNAL_FORMAT (C_STRING, newdir_external, 936 TO_INTERNAL_FORMAT (C_STRING, newdir_external,
937 C_STRING_ALLOCA, (* ((char **) &newdir)), 937 C_STRING_ALLOCA, (* ((char **) &newdir)),
938 Qfile_name); 938 Qfile_name);
939 939
944 } 944 }
945 else /* ~user/filename */ 945 else /* ~user/filename */
946 { 946 {
947 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++) 947 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++)
948 DO_NOTHING; 948 DO_NOTHING;
949 o = (Bufbyte *) alloca (p - nm + 1); 949 o = (Intbyte *) alloca (p - nm + 1);
950 memcpy (o, (char *) nm, p - nm); 950 memcpy (o, (char *) nm, p - nm);
951 o [p - nm] = 0; 951 o [p - nm] = 0;
952 952
953 /* #### While NT is single-user (for the moment) you still 953 /* #### While NT is single-user (for the moment) you still
954 can have multiple user profiles users defined, each with 954 can have multiple user profiles users defined, each with
959 if ((user = user_login_name (NULL)) != NULL) 959 if ((user = user_login_name (NULL)) != NULL)
960 { 960 {
961 /* Does the user login name match the ~name? */ 961 /* Does the user login name match the ~name? */
962 if (strcmp (user, (char *) o + 1) == 0) 962 if (strcmp (user, (char *) o + 1) == 0)
963 { 963 {
964 newdir = (Bufbyte *) get_home_directory(); 964 newdir = (Intbyte *) get_home_directory();
965 nm = p; 965 nm = p;
966 } 966 }
967 } 967 }
968 if (! newdir) 968 if (! newdir)
969 { 969 {
973 slow_down_interrupts (); 973 slow_down_interrupts ();
974 pw = (struct passwd *) getpwnam ((char *) o + 1); 974 pw = (struct passwd *) getpwnam ((char *) o + 1);
975 speed_up_interrupts (); 975 speed_up_interrupts ();
976 if (pw) 976 if (pw)
977 { 977 {
978 newdir = (Bufbyte *) pw -> pw_dir; 978 newdir = (Intbyte *) pw -> pw_dir;
979 nm = p; 979 nm = p;
980 } 980 }
981 #ifdef CYGWIN 981 #ifdef CYGWIN
982 } 982 }
983 #endif 983 #endif
995 { 995 {
996 #ifdef WIN32_NATIVE 996 #ifdef WIN32_NATIVE
997 /* Get default directory if needed to make nm absolute. */ 997 /* Get default directory if needed to make nm absolute. */
998 if (!IS_DIRECTORY_SEP (nm[0])) 998 if (!IS_DIRECTORY_SEP (nm[0]))
999 { 999 {
1000 newdir = (Bufbyte *) alloca (MAXPATHLEN + 1); 1000 newdir = (Intbyte *) alloca (MAXPATHLEN + 1);
1001 if (!_getdcwd (toupper (drive) - 'A' + 1, newdir, MAXPATHLEN)) 1001 if (!_getdcwd (toupper (drive) - 'A' + 1, newdir, MAXPATHLEN))
1002 newdir = NULL; 1002 newdir = NULL;
1003 } 1003 }
1004 #endif /* WIN32_NATIVE */ 1004 #endif /* WIN32_NATIVE */
1005 if (!newdir) 1005 if (!newdir)
1006 { 1006 {
1007 /* Either nm starts with /, or drive isn't mounted. */ 1007 /* Either nm starts with /, or drive isn't mounted. */
1008 newdir = (Bufbyte *) alloca (4); 1008 newdir = (Intbyte *) alloca (4);
1009 newdir[0] = DRIVE_LETTER (drive); 1009 newdir[0] = DRIVE_LETTER (drive);
1010 newdir[1] = ':'; 1010 newdir[1] = ':';
1011 newdir[2] = '/'; 1011 newdir[2] = '/';
1012 newdir[3] = 0; 1012 newdir[3] = 0;
1013 } 1013 }
1059 drive = newdir[0]; 1059 drive = newdir[0];
1060 newdir += 2; 1060 newdir += 2;
1061 } 1061 }
1062 if (!IS_DIRECTORY_SEP (nm[0])) 1062 if (!IS_DIRECTORY_SEP (nm[0]))
1063 { 1063 {
1064 Bufbyte *tmp = (Bufbyte *) alloca (strlen ((char *) newdir) + 1064 Intbyte *tmp = (Intbyte *) alloca (strlen ((char *) newdir) +
1065 strlen ((char *) nm) + 2); 1065 strlen ((char *) nm) + 2);
1066 file_name_as_directory ((char *) tmp, (char *) newdir); 1066 file_name_as_directory ((char *) tmp, (char *) newdir);
1067 strcat ((char *) tmp, (char *) nm); 1067 strcat ((char *) tmp, (char *) nm);
1068 nm = tmp; 1068 nm = tmp;
1069 } 1069 }
1070 newdir = (Bufbyte *) alloca (MAXPATHLEN + 1); 1070 newdir = (Intbyte *) alloca (MAXPATHLEN + 1);
1071 if (drive) 1071 if (drive)
1072 { 1072 {
1073 #ifdef WIN32_NATIVE 1073 #ifdef WIN32_NATIVE
1074 if (!_getdcwd (toupper (drive) - 'A' + 1, newdir, MAXPATHLEN)) 1074 if (!_getdcwd (toupper (drive) - 'A' + 1, newdir, MAXPATHLEN))
1075 #endif 1075 #endif
1076 newdir = (Bufbyte *) "/"; 1076 newdir = (Intbyte *) "/";
1077 } 1077 }
1078 else 1078 else
1079 getcwd ((char *) newdir, MAXPATHLEN); 1079 getcwd ((char *) newdir, MAXPATHLEN);
1080 } 1080 }
1081 1081
1095 && collapse_newdir) 1095 && collapse_newdir)
1096 { 1096 {
1097 if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1])) 1097 if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
1098 { 1098 {
1099 newdir = 1099 newdir =
1100 (Bufbyte *) 1100 (Intbyte *)
1101 strcpy ((char *) alloca (strlen ((char *) newdir) + 1), 1101 strcpy ((char *) alloca (strlen ((char *) newdir) + 1),
1102 (char *) newdir); 1102 (char *) newdir);
1103 p = newdir + 2; 1103 p = newdir + 2;
1104 while (*p && !IS_DIRECTORY_SEP (*p)) p++; 1104 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1105 p++; 1105 p++;
1106 while (*p && !IS_DIRECTORY_SEP (*p)) p++; 1106 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1107 *p = 0; 1107 *p = 0;
1108 } 1108 }
1109 else 1109 else
1110 newdir = (Bufbyte *) ""; 1110 newdir = (Intbyte *) "";
1111 } 1111 }
1112 } 1112 }
1113 #endif /* WIN32_FILENAMES */ 1113 #endif /* WIN32_FILENAMES */
1114 1114
1115 if (newdir) 1115 if (newdir)
1121 #ifdef WIN32_FILENAMES 1121 #ifdef WIN32_FILENAMES
1122 && !(length == 2 && IS_DIRECTORY_SEP (newdir[0])) 1122 && !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
1123 #endif 1123 #endif
1124 ) 1124 )
1125 { 1125 {
1126 Bufbyte *temp = (Bufbyte *) alloca (length); 1126 Intbyte *temp = (Intbyte *) alloca (length);
1127 memcpy (temp, newdir, length - 1); 1127 memcpy (temp, newdir, length - 1);
1128 temp[length - 1] = 0; 1128 temp[length - 1] = 0;
1129 newdir = temp; 1129 newdir = temp;
1130 } 1130 }
1131 tlen = length + 1; 1131 tlen = length + 1;
1136 /* Now concatenate the directory and name to new space in the stack frame */ 1136 /* Now concatenate the directory and name to new space in the stack frame */
1137 tlen += strlen ((char *) nm) + 1; 1137 tlen += strlen ((char *) nm) + 1;
1138 #ifdef WIN32_FILENAMES 1138 #ifdef WIN32_FILENAMES
1139 /* Add reserved space for drive name. (The Microsoft x86 compiler 1139 /* Add reserved space for drive name. (The Microsoft x86 compiler
1140 produces incorrect code if the following two lines are combined.) */ 1140 produces incorrect code if the following two lines are combined.) */
1141 target = (Bufbyte *) alloca (tlen + 2); 1141 target = (Intbyte *) alloca (tlen + 2);
1142 target += 2; 1142 target += 2;
1143 #else /* not WIN32_FILENAMES */ 1143 #else /* not WIN32_FILENAMES */
1144 target = (Bufbyte *) alloca (tlen); 1144 target = (Intbyte *) alloca (tlen);
1145 #endif /* not WIN32_FILENAMES */ 1145 #endif /* not WIN32_FILENAMES */
1146 *target = 0; 1146 *target = 0;
1147 1147
1148 if (newdir) 1148 if (newdir)
1149 { 1149 {
1258 1258
1259 { 1259 {
1260 char resolved_path[MAXPATHLEN]; 1260 char resolved_path[MAXPATHLEN];
1261 Extbyte *path; 1261 Extbyte *path;
1262 Extbyte *p; 1262 Extbyte *p;
1263 Extcount elen; 1263 Bytecount elen;
1264 1264
1265 TO_EXTERNAL_FORMAT (LISP_STRING, expanded_name, 1265 TO_EXTERNAL_FORMAT (LISP_STRING, expanded_name,
1266 ALLOCA, (path, elen), 1266 ALLOCA, (path, elen),
1267 Qfile_name); 1267 Qfile_name);
1268 p = path; 1268 p = path;
1388 If `/~' appears, all of FILENAME through that `/' is discarded. 1388 If `/~' appears, all of FILENAME through that `/' is discarded.
1389 */ 1389 */
1390 (filename)) 1390 (filename))
1391 { 1391 {
1392 /* This function can GC. GC checked 2000-07-28 ben. */ 1392 /* This function can GC. GC checked 2000-07-28 ben. */
1393 Bufbyte *nm; 1393 Intbyte *nm;
1394 1394
1395 Bufbyte *s, *p, *o, *x, *endp; 1395 Intbyte *s, *p, *o, *x, *endp;
1396 Bufbyte *target = 0; 1396 Intbyte *target = 0;
1397 int total = 0; 1397 int total = 0;
1398 int substituted = 0; 1398 int substituted = 0;
1399 Bufbyte *xnm; 1399 Intbyte *xnm;
1400 Lisp_Object handler; 1400 Lisp_Object handler;
1401 1401
1402 CHECK_STRING (filename); 1402 CHECK_STRING (filename);
1403 1403
1404 /* If the file name has special constructs in it, 1404 /* If the file name has special constructs in it,
1472 while (p != endp && (isalnum (*p) || *p == '_')) p++; 1472 while (p != endp && (isalnum (*p) || *p == '_')) p++;
1473 s = p; 1473 s = p;
1474 } 1474 }
1475 1475
1476 /* Copy out the variable name */ 1476 /* Copy out the variable name */
1477 target = (Bufbyte *) alloca (s - o + 1); 1477 target = (Intbyte *) alloca (s - o + 1);
1478 strncpy ((char *) target, (char *) o, s - o); 1478 strncpy ((char *) target, (char *) o, s - o);
1479 target[s - o] = 0; 1479 target[s - o] = 0;
1480 #ifdef WIN32_NATIVE 1480 #ifdef WIN32_NATIVE
1481 strupr (target); /* $home == $HOME etc. */ 1481 strupr (target); /* $home == $HOME etc. */
1482 #endif /* WIN32_NATIVE */ 1482 #endif /* WIN32_NATIVE */
1483 1483
1484 /* Get variable value */ 1484 /* Get variable value */
1485 o = (Bufbyte *) egetenv ((char *) target); 1485 o = (Intbyte *) egetenv ((char *) target);
1486 if (!o) goto badvar; 1486 if (!o) goto badvar;
1487 total += strlen ((char *) o); 1487 total += strlen ((char *) o);
1488 substituted = 1; 1488 substituted = 1;
1489 } 1489 }
1490 1490
1491 if (!substituted) 1491 if (!substituted)
1492 return filename; 1492 return filename;
1493 1493
1494 /* If substitution required, recopy the filename and do it */ 1494 /* If substitution required, recopy the filename and do it */
1495 /* Make space in stack frame for the new copy */ 1495 /* Make space in stack frame for the new copy */
1496 xnm = (Bufbyte *) alloca (XSTRING_LENGTH (filename) + total + 1); 1496 xnm = (Intbyte *) alloca (XSTRING_LENGTH (filename) + total + 1);
1497 x = xnm; 1497 x = xnm;
1498 1498
1499 /* Copy the rest of the name through, replacing $ constructs with values */ 1499 /* Copy the rest of the name through, replacing $ constructs with values */
1500 for (p = nm; *p;) 1500 for (p = nm; *p;)
1501 if (*p != '$') 1501 if (*p != '$')
1523 while (p != endp && (isalnum (*p) || *p == '_')) p++; 1523 while (p != endp && (isalnum (*p) || *p == '_')) p++;
1524 s = p; 1524 s = p;
1525 } 1525 }
1526 1526
1527 /* Copy out the variable name */ 1527 /* Copy out the variable name */
1528 target = (Bufbyte *) alloca (s - o + 1); 1528 target = (Intbyte *) alloca (s - o + 1);
1529 strncpy ((char *) target, (char *) o, s - o); 1529 strncpy ((char *) target, (char *) o, s - o);
1530 target[s - o] = 0; 1530 target[s - o] = 0;
1531 #ifdef WIN32_NATIVE 1531 #ifdef WIN32_NATIVE
1532 strupr (target); /* $home == $HOME etc. */ 1532 strupr (target); /* $home == $HOME etc. */
1533 #endif /* WIN32_NATIVE */ 1533 #endif /* WIN32_NATIVE */
1534 1534
1535 /* Get variable value */ 1535 /* Get variable value */
1536 o = (Bufbyte *) egetenv ((char *) target); 1536 o = (Intbyte *) egetenv ((char *) target);
1537 if (!o) 1537 if (!o)
1538 goto badvar; 1538 goto badvar;
1539 1539
1540 strcpy ((char *) x, (char *) o); 1540 strcpy ((char *) x, (char *) o);
1541 x += strlen ((char *) o); 1541 x += strlen ((char *) o);
1625 { 1625 {
1626 Lisp_Object prompt; 1626 Lisp_Object prompt;
1627 struct gcpro gcpro1; 1627 struct gcpro gcpro1;
1628 1628
1629 prompt = emacs_doprnt_string_c 1629 prompt = emacs_doprnt_string_c
1630 ((const Bufbyte *) GETTEXT ("File %s already exists; %s anyway? "), 1630 ((const Intbyte *) GETTEXT ("File %s already exists; %s anyway? "),
1631 Qnil, -1, XSTRING_DATA (absname), 1631 Qnil, -1, XSTRING_DATA (absname),
1632 GETTEXT (querystring)); 1632 GETTEXT (querystring));
1633 1633
1634 GCPRO1 (prompt); 1634 GCPRO1 (prompt);
1635 tem = call1 (Qyes_or_no_p, prompt); 1635 tem = call1 (Qyes_or_no_p, prompt);
2146 On Unix, this is a name starting with a `/' or a `~'. 2146 On Unix, this is a name starting with a `/' or a `~'.
2147 */ 2147 */
2148 (filename)) 2148 (filename))
2149 { 2149 {
2150 /* This function does not GC */ 2150 /* This function does not GC */
2151 Bufbyte *ptr; 2151 Intbyte *ptr;
2152 2152
2153 CHECK_STRING (filename); 2153 CHECK_STRING (filename);
2154 ptr = XSTRING_DATA (filename); 2154 ptr = XSTRING_DATA (filename);
2155 return (IS_DIRECTORY_SEP (*ptr) || *ptr == '~' 2155 return (IS_DIRECTORY_SEP (*ptr) || *ptr == '~'
2156 #ifdef WIN32_FILENAMES 2156 #ifdef WIN32_FILENAMES
2371 if (valsize == -1) 2371 if (valsize == -1)
2372 { 2372 {
2373 xfree (buf); 2373 xfree (buf);
2374 return Qnil; 2374 return Qnil;
2375 } 2375 }
2376 val = make_string ((Bufbyte *) buf, valsize); 2376 val = make_string ((Intbyte *) buf, valsize);
2377 xfree (buf); 2377 xfree (buf);
2378 return val; 2378 return val;
2379 #else /* not S_IFLNK */ 2379 #else /* not S_IFLNK */
2380 return Qnil; 2380 return Qnil;
2381 #endif /* not S_IFLNK */ 2381 #endif /* not S_IFLNK */
2673 Charcount inserted = 0; 2673 Charcount inserted = 0;
2674 int speccount; 2674 int speccount;
2675 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; 2675 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
2676 Lisp_Object handler = Qnil, val; 2676 Lisp_Object handler = Qnil, val;
2677 int total; 2677 int total;
2678 Bufbyte read_buf[READ_BUF_SIZE]; 2678 Intbyte read_buf[READ_BUF_SIZE];
2679 int mc_count; 2679 int mc_count;
2680 struct buffer *buf = current_buffer; 2680 struct buffer *buf = current_buffer;
2681 Lisp_Object curbuf; 2681 Lisp_Object curbuf;
2682 int not_regular = 0; 2682 int not_regular = 0;
2683 2683
2812 } 2812 }
2813 #else /* FSFMACS_SPEEDY_INSERT */ 2813 #else /* FSFMACS_SPEEDY_INSERT */
2814 if (!NILP (replace)) 2814 if (!NILP (replace))
2815 { 2815 {
2816 char buffer[1 << 14]; 2816 char buffer[1 << 14];
2817 Bufpos same_at_start = BUF_BEGV (buf); 2817 Charbpos same_at_start = BUF_BEGV (buf);
2818 Bufpos same_at_end = BUF_ZV (buf); 2818 Charbpos same_at_end = BUF_ZV (buf);
2819 int overlap; 2819 int overlap;
2820 2820
2821 /* Count how many chars at the start of the file 2821 /* Count how many chars at the start of the file
2822 match the text at the beginning of the buffer. */ 2822 match the text at the beginning of the buffer. */
2823 while (1) 2823 while (1)
2824 { 2824 {
2825 int nread; 2825 int nread;
2826 Bufpos bufpos; 2826 Charbpos charbpos;
2827 nread = read_allowing_quit (fd, buffer, sizeof (buffer)); 2827 nread = read_allowing_quit (fd, buffer, sizeof (buffer));
2828 if (nread < 0) 2828 if (nread < 0)
2829 report_file_error ("Reading", filename); 2829 report_file_error ("Reading", filename);
2830 else if (nread == 0) 2830 else if (nread == 0)
2831 break; 2831 break;
2832 bufpos = 0; 2832 charbpos = 0;
2833 while (bufpos < nread && same_at_start < BUF_ZV (buf) 2833 while (charbpos < nread && same_at_start < BUF_ZV (buf)
2834 && BUF_FETCH_CHAR (buf, same_at_start) == buffer[bufpos]) 2834 && BUF_FETCH_CHAR (buf, same_at_start) == buffer[charbpos])
2835 same_at_start++, bufpos++; 2835 same_at_start++, charbpos++;
2836 /* If we found a discrepancy, stop the scan. 2836 /* If we found a discrepancy, stop the scan.
2837 Otherwise loop around and scan the next bufferful. */ 2837 Otherwise loop around and scan the next bufferful. */
2838 if (bufpos != nread) 2838 if (charbpos != nread)
2839 break; 2839 break;
2840 } 2840 }
2841 /* If the file matches the buffer completely, 2841 /* If the file matches the buffer completely,
2842 there's no need to replace anything. */ 2842 there's no need to replace anything. */
2843 if (same_at_start - BUF_BEGV (buf) == st.st_size) 2843 if (same_at_start - BUF_BEGV (buf) == st.st_size)
2852 /* Count how many chars at the end of the file 2852 /* Count how many chars at the end of the file
2853 match the text at the end of the buffer. */ 2853 match the text at the end of the buffer. */
2854 while (1) 2854 while (1)
2855 { 2855 {
2856 int total_read, nread; 2856 int total_read, nread;
2857 Bufpos bufpos, curpos, trial; 2857 Charbpos charbpos, curpos, trial;
2858 2858
2859 /* At what file position are we now scanning? */ 2859 /* At what file position are we now scanning? */
2860 curpos = st.st_size - (BUF_ZV (buf) - same_at_end); 2860 curpos = st.st_size - (BUF_ZV (buf) - same_at_end);
2861 /* If the entire file matches the buffer tail, stop the scan. */ 2861 /* If the entire file matches the buffer tail, stop the scan. */
2862 if (curpos == 0) 2862 if (curpos == 0)
2863 break; 2863 break;
2864 /* How much can we scan in the next step? */ 2864 /* How much can we scan in the next step? */
2865 trial = min (curpos, (Bufpos) sizeof (buffer)); 2865 trial = min (curpos, (Charbpos) sizeof (buffer));
2866 if (lseek (fd, curpos - trial, 0) < 0) 2866 if (lseek (fd, curpos - trial, 0) < 0)
2867 report_file_error ("Setting file position", filename); 2867 report_file_error ("Setting file position", filename);
2868 2868
2869 total_read = 0; 2869 total_read = 0;
2870 while (total_read < trial) 2870 while (total_read < trial)
2875 report_file_error ("IO error reading file", filename); 2875 report_file_error ("IO error reading file", filename);
2876 total_read += nread; 2876 total_read += nread;
2877 } 2877 }
2878 /* Scan this bufferful from the end, comparing with 2878 /* Scan this bufferful from the end, comparing with
2879 the Emacs buffer. */ 2879 the Emacs buffer. */
2880 bufpos = total_read; 2880 charbpos = total_read;
2881 /* Compare with same_at_start to avoid counting some buffer text 2881 /* Compare with same_at_start to avoid counting some buffer text
2882 as matching both at the file's beginning and at the end. */ 2882 as matching both at the file's beginning and at the end. */
2883 while (bufpos > 0 && same_at_end > same_at_start 2883 while (charbpos > 0 && same_at_end > same_at_start
2884 && BUF_FETCH_CHAR (buf, same_at_end - 1) == 2884 && BUF_FETCH_CHAR (buf, same_at_end - 1) ==
2885 buffer[bufpos - 1]) 2885 buffer[charbpos - 1])
2886 same_at_end--, bufpos--; 2886 same_at_end--, charbpos--;
2887 /* If we found a discrepancy, stop the scan. 2887 /* If we found a discrepancy, stop the scan.
2888 Otherwise loop around and scan the preceding bufferful. */ 2888 Otherwise loop around and scan the preceding bufferful. */
2889 if (bufpos != 0) 2889 if (charbpos != 0)
2890 break; 2890 break;
2891 /* If display current starts at beginning of line, 2891 /* If display current starts at beginning of line,
2892 keep it that way. */ 2892 keep it that way. */
2893 if (XBUFFER (XWINDOW (Fselected_window (Qnil))->buffer) == buf) 2893 if (XBUFFER (XWINDOW (Fselected_window (Qnil))->buffer) == buf)
2894 XWINDOW (Fselected_window (Qnil))->start_at_line_beg = 2894 XWINDOW (Fselected_window (Qnil))->start_at_line_beg =
2937 if (lseek (fd, XINT (start), 0) < 0) 2937 if (lseek (fd, XINT (start), 0) < 0)
2938 report_file_error ("Setting file position", filename); 2938 report_file_error ("Setting file position", filename);
2939 } 2939 }
2940 2940
2941 { 2941 {
2942 Bufpos cur_point = BUF_PT (buf); 2942 Charbpos cur_point = BUF_PT (buf);
2943 struct gcpro ngcpro1; 2943 struct gcpro ngcpro1;
2944 Lisp_Object stream = make_filedesc_input_stream (fd, 0, total, 2944 Lisp_Object stream = make_filedesc_input_stream (fd, 0, total,
2945 LSTR_ALLOW_QUIT); 2945 LSTR_ALLOW_QUIT);
2946 2946
2947 NGCPRO1 (stream); 2947 NGCPRO1 (stream);
2958 /* No need to limit the amount of stuff we attempt to read. (It would 2958 /* No need to limit the amount of stuff we attempt to read. (It would
2959 be incorrect, anyway, when Mule is enabled.) Instead, the limiting 2959 be incorrect, anyway, when Mule is enabled.) Instead, the limiting
2960 occurs inside of the filedesc stream. */ 2960 occurs inside of the filedesc stream. */
2961 while (1) 2961 while (1)
2962 { 2962 {
2963 Lstream_Data_Count this_len; 2963 Bytecount this_len;
2964 Charcount cc_inserted; 2964 Charcount cc_inserted;
2965 2965
2966 QUIT; 2966 QUIT;
2967 this_len = Lstream_read (XLSTREAM (stream), read_buf, 2967 this_len = Lstream_read (XLSTREAM (stream), read_buf,
2968 sizeof (read_buf)); 2968 sizeof (read_buf));
3126 int visiting = (EQ (visit, Qt) || visiting_other); 3126 int visiting = (EQ (visit, Qt) || visiting_other);
3127 int quietly = (!visiting && !NILP (visit)); 3127 int quietly = (!visiting && !NILP (visit));
3128 Lisp_Object visit_file = Qnil; 3128 Lisp_Object visit_file = Qnil;
3129 Lisp_Object annotations = Qnil; 3129 Lisp_Object annotations = Qnil;
3130 struct buffer *given_buffer; 3130 struct buffer *given_buffer;
3131 Bufpos start1, end1; 3131 Charbpos start1, end1;
3132 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; 3132 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
3133 struct gcpro ngcpro1, ngcpro2; 3133 struct gcpro ngcpro1, ngcpro2;
3134 Lisp_Object curbuf; 3134 Lisp_Object curbuf;
3135 3135
3136 XSETBUFFER (curbuf, current_buffer); 3136 XSETBUFFER (curbuf, current_buffer);
3996 these buffers, record visited name (if any) and 3996 these buffers, record visited name (if any) and
3997 auto save name. */ 3997 auto save name. */
3998 if (listdesc >= 0) 3998 if (listdesc >= 0)
3999 { 3999 {
4000 const Extbyte *auto_save_file_name_ext; 4000 const Extbyte *auto_save_file_name_ext;
4001 Extcount auto_save_file_name_ext_len; 4001 Bytecount auto_save_file_name_ext_len;
4002 4002
4003 TO_EXTERNAL_FORMAT (LISP_STRING, b->auto_save_file_name, 4003 TO_EXTERNAL_FORMAT (LISP_STRING, b->auto_save_file_name,
4004 ALLOCA, (auto_save_file_name_ext, 4004 ALLOCA, (auto_save_file_name_ext,
4005 auto_save_file_name_ext_len), 4005 auto_save_file_name_ext_len),
4006 Qfile_name); 4006 Qfile_name);
4007 if (!NILP (b->filename)) 4007 if (!NILP (b->filename))
4008 { 4008 {
4009 const Extbyte *filename_ext; 4009 const Extbyte *filename_ext;
4010 Extcount filename_ext_len; 4010 Bytecount filename_ext_len;
4011 4011
4012 TO_EXTERNAL_FORMAT (LISP_STRING, b->filename, 4012 TO_EXTERNAL_FORMAT (LISP_STRING, b->filename,
4013 ALLOCA, (filename_ext, 4013 ALLOCA, (filename_ext,
4014 filename_ext_len), 4014 filename_ext_len),
4015 Qfile_name); 4015 Qfile_name);