+static char make_temp_name_tbl[64] =
+{
+ 'A','B','C','D','E','F','G','H',
+ 'I','J','K','L','M','N','O','P',
+ 'Q','R','S','T','U','V','W','X',
+ 'Y','Z','a','b','c','d','e','f',
+ 'g','h','i','j','k','l','m','n',
+ 'o','p','q','r','s','t','u','v',
+ 'w','x','y','z','0','1','2','3',
+ '4','5','6','7','8','9','-','_'
+};
+
+static unsigned make_temp_name_count, make_temp_name_count_initialized_p;
+
+/* Value is a temporary file name starting with PREFIX, a string.
+
+ The Emacs process number forms part of the result, so there is
+ no danger of generating a name being used by another process.
+ In addition, this function makes an attempt to choose a name
+ which has no existing file. To make this work, PREFIX should be
+ an absolute file name.
+
+ BASE64_P non-zero means add the pid as 3 characters in base64
+ encoding. In this case, 6 characters will be added to PREFIX to
+ form the file name. Otherwise, if Emacs is running on a system
+ with long file names, add the pid as a decimal number.
+
+ This function signals an error if no unique file name could be
+ generated. */
+
+Lisp_Object
+make_temp_name (prefix, base64_p)
+ Lisp_Object prefix;
+ int base64_p;
+{
+ Lisp_Object val;
+ int len;
+ int pid;
+ unsigned char *p, *data;
+ char pidbuf[20];
+ int pidlen;
+
+ CHECK_STRING (prefix, 0);
+
+ /* VAL is created by adding 6 characters to PREFIX. The first
+ three are the PID of this process, in base 64, and the second
+ three are incremented if the file already exists. This ensures
+ 262144 unique file names per PID per PREFIX. */
+
+ pid = (int) getpid ();
+
+ if (base64_p)
+ {
+ pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6;
+ pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6;
+ pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6;
+ pidlen = 3;
+ }
+ else
+ {
+#ifdef HAVE_LONG_FILE_NAMES
+ sprintf (pidbuf, "%d", pid);
+ pidlen = strlen (pidbuf);
+#else
+ pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6;
+ pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6;
+ pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6;
+ pidlen = 3;
+#endif
+ }
+
+ len = XSTRING (prefix)->size;
+ val = make_uninit_string (len + 3 + pidlen);
+ data = XSTRING (val)->data;
+ bcopy(XSTRING (prefix)->data, data, len);
+ p = data + len;
+
+ bcopy (pidbuf, p, pidlen);
+ p += pidlen;
+
+ /* Here we try to minimize useless stat'ing when this function is
+ invoked many times successively with the same PREFIX. We achieve
+ this by initializing count to a random value, and incrementing it
+ afterwards.
+
+ We don't want make-temp-name to be called while dumping,
+ because then make_temp_name_count_initialized_p would get set
+ and then make_temp_name_count would not be set when Emacs starts. */
+
+ if (!make_temp_name_count_initialized_p)
+ {
+ make_temp_name_count = (unsigned) time (NULL);
+ make_temp_name_count_initialized_p = 1;
+ }
+
+ while (1)
+ {
+ struct stat ignored;
+ unsigned num = make_temp_name_count;
+
+ p[0] = make_temp_name_tbl[num & 63], num >>= 6;
+ p[1] = make_temp_name_tbl[num & 63], num >>= 6;
+ p[2] = make_temp_name_tbl[num & 63], num >>= 6;
+
+ /* Poor man's congruential RN generator. Replace with
+ ++make_temp_name_count for debugging. */
+ make_temp_name_count += 25229;
+ make_temp_name_count %= 225307;
+
+ if (stat (data, &ignored) < 0)
+ {
+ /* We want to return only if errno is ENOENT. */
+ if (errno == ENOENT)
+ return val;
+ else
+ /* The error here is dubious, but there is little else we
+ can do. The alternatives are to return nil, which is
+ as bad as (and in many cases worse than) throwing the
+ error, or to ignore the error, which will likely result
+ in looping through 225307 stat's, which is not only
+ dog-slow, but also useless since it will fallback to
+ the errow below, anyway. */
+ report_file_error ("Cannot create temporary name for prefix",
+ Fcons (prefix, Qnil));
+ /* not reached */
+ }
+ }
+
+ error ("Cannot create temporary name for prefix `%s'",
+ XSTRING (prefix)->data);
+ return Qnil;
+}
+
+