Mercurial > hg > xemacs-beta
annotate lib-src/gnuclient.c @ 5157:1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
-------------------- ChangeLog entries follow: --------------------
lisp/ChangeLog addition:
2010-03-18 Ben Wing <ben@xemacs.org>
* diagnose.el (show-memory-usage):
Rewrite to take into account API changes in memory-usage functions.
src/ChangeLog addition:
2010-03-18 Ben Wing <ben@xemacs.org>
* alloc.c:
* alloc.c (disksave_object_finalization_1):
* alloc.c (lisp_object_storage_size):
* alloc.c (listu):
* alloc.c (listn):
* alloc.c (Fobject_memory_usage_stats):
* alloc.c (compute_memusage_stats_length):
* alloc.c (Fobject_memory_usage):
* alloc.c (Ftotal_object_memory_usage):
* alloc.c (malloced_storage_size):
* alloc.c (common_init_alloc_early):
* alloc.c (reinit_alloc_objects_early):
* alloc.c (reinit_alloc_early):
* alloc.c (init_alloc_once_early):
* alloc.c (syms_of_alloc):
* alloc.c (reinit_vars_of_alloc):
* buffer.c:
* buffer.c (struct buffer_stats):
* buffer.c (compute_buffer_text_usage):
* buffer.c (compute_buffer_usage):
* buffer.c (buffer_memory_usage):
* buffer.c (buffer_objects_create):
* buffer.c (syms_of_buffer):
* buffer.c (vars_of_buffer):
* console-impl.h (struct console_methods):
* dynarr.c (Dynarr_memory_usage):
* emacs.c (main_1):
* events.c (clear_event_resource):
* extents.c:
* extents.c (compute_buffer_extent_usage):
* extents.c (extent_objects_create):
* extents.h:
* faces.c:
* faces.c (compute_face_cachel_usage):
* faces.c (face_objects_create):
* faces.h:
* general-slots.h:
* glyphs.c:
* glyphs.c (compute_glyph_cachel_usage):
* glyphs.c (glyph_objects_create):
* glyphs.h:
* lisp.h:
* lisp.h (struct usage_stats):
* lrecord.h:
* lrecord.h (enum lrecord_type):
* lrecord.h (struct lrecord_implementation):
* lrecord.h (MC_ALLOC_CALL_FINALIZER_FOR_DISKSAVE):
* lrecord.h (DEFINE_DUMPABLE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_FROB_BLOCK_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_SIZABLE_INTERNAL_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_FROB_BLOCK_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_FROB_BLOCK_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_INTERNAL_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_SIZABLE_INTERNAL_LISP_OBJECT):
* lrecord.h (MAKE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_MODULE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_MODULE_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_MODULE_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_MODULE_SIZABLE_LISP_OBJECT):
* lrecord.h (MAKE_MODULE_LISP_OBJECT):
* lrecord.h (INIT_LISP_OBJECT):
* lrecord.h (INIT_MODULE_LISP_OBJECT):
* lrecord.h (UNDEF_LISP_OBJECT):
* lrecord.h (UNDEF_MODULE_LISP_OBJECT):
* lrecord.h (DECLARE_LISP_OBJECT):
* lrecord.h (DECLARE_MODULE_API_LISP_OBJECT):
* lrecord.h (DECLARE_MODULE_LISP_OBJECT):
* lstream.c:
* lstream.c (syms_of_lstream):
* lstream.c (vars_of_lstream):
* marker.c:
* marker.c (compute_buffer_marker_usage):
* mc-alloc.c (mc_alloced_storage_size):
* mc-alloc.h:
* mule-charset.c:
* mule-charset.c (struct charset_stats):
* mule-charset.c (compute_charset_usage):
* mule-charset.c (charset_memory_usage):
* mule-charset.c (mule_charset_objects_create):
* mule-charset.c (syms_of_mule_charset):
* mule-charset.c (vars_of_mule_charset):
* redisplay.c:
* redisplay.c (compute_rune_dynarr_usage):
* redisplay.c (compute_display_block_dynarr_usage):
* redisplay.c (compute_glyph_block_dynarr_usage):
* redisplay.c (compute_display_line_dynarr_usage):
* redisplay.c (compute_line_start_cache_dynarr_usage):
* redisplay.h:
* scrollbar-gtk.c (gtk_compute_scrollbar_instance_usage):
* scrollbar-msw.c (mswindows_compute_scrollbar_instance_usage):
* scrollbar-x.c (x_compute_scrollbar_instance_usage):
* scrollbar.c (compute_scrollbar_instance_usage):
* scrollbar.h:
* symbols.c:
* symbols.c (reinit_symbol_objects_early):
* symbols.c (init_symbols_once_early):
* symbols.c (reinit_symbols_early):
* symbols.c (defsymbol_massage_name_1):
* symsinit.h:
* ui-gtk.c:
* ui-gtk.c (emacs_gtk_object_getprop):
* ui-gtk.c (emacs_gtk_object_putprop):
* ui-gtk.c (ui_gtk_objects_create):
* unicode.c (compute_from_unicode_table_size_1):
* unicode.c (compute_to_unicode_table_size_1):
* unicode.c (compute_from_unicode_table_size):
* unicode.c (compute_to_unicode_table_size):
* window.c:
* window.c (struct window_stats):
* window.c (compute_window_mirror_usage):
* window.c (compute_window_usage):
* window.c (window_memory_usage):
* window.c (window_objects_create):
* window.c (syms_of_window):
* window.c (vars_of_window):
* window.h:
Redo memory-usage mechanism, make it general; add way of dynamically
initializing Lisp object types -- OBJECT_HAS_METHOD(), similar to
CONSOLE_HAS_METHOD().
(1) Create OBJECT_HAS_METHOD(), OBJECT_HAS_PROPERTY() etc. for
specifying that a Lisp object type has a particular method or
property. Call such methods with OBJECT_METH, MAYBE_OBJECT_METH,
OBJECT_METH_OR_GIVEN; retrieve properties with OBJECT_PROPERTY.
Methods that formerly required a DEFINE_*GENERAL_LISP_OBJECT() to
specify them (getprop, putprop, remprop, plist, disksave) now
instead use the dynamic-method mechanism. The main benefit of
this is that new methods or properties can be added without
requiring that the declaration statements of all existing methods
be modified. We have to make the `struct lrecord_implementation'
non-const, but I don't think this should have any effect on speed --
the only possible method that's really speed-critical is the
mark method, and we already extract those out into a separate
(non-const) array for increased cache locality.
Object methods need to be reinitialized after pdump, so we put
them in separate functions such as face_objects_create(),
extent_objects_create() and call them appropriately from emacs.c
The only current object property (`memusage_stats_list') that
objects can specify is a Lisp object and gets staticpro()ed so it
only needs to be set during dump time, but because it references
symbols that might not exist in a syms_of_() function, we
initialize it in vars_of_(). There is also an object property
(`num_extra_memusage_stats') that is automatically initialized based
on `memusage_stats_list'; we do that in reinit_vars_of_alloc(),
which is called after all vars_of_() functions are called.
`disksaver' method was renamed `disksave' to correspond with the
name normally given to the function (e.g. disksave_lstream()).
(2) Generalize the memory-usage mechanism in `buffer-memory-usage',
`window-memory-usage', `charset-memory-usage' into an object-type-
specific mechanism called by a single function
`object-memory-usage'. (Former function `object-memory-usage'
renamed to `total-object-memory-usage'). Generalize the mechanism
of different "slices" so that we can have different "classes" of
memory described and different "slices" onto each class; `t'
separates classes, `nil' separates slices. Currently we have
three classes defined: the memory of an object itself,
non-Lisp-object memory associated with the object (e.g. arrays or
dynarrs stored as fields in the object), and Lisp-object memory
associated with the object (other internal Lisp objects stored in
the object). This isn't completely finished yet and we might need
to further separate the "other internal Lisp objects" class into
two classes.
The memory-usage mechanism uses a `struct usage_stats' (renamed
from `struct overhead_stats') to describe a malloc-view onto a set
of allocated memory (listing how much was requested and various
types of overhead) and a more general `struct generic_usage_stats'
(with a `struct usage_stats' in it) to hold all statistics about
object memory. `struct generic_usage_stats' contains an array of
32 Bytecounts, which are statistics of unspecified semantics. The
intention is that individual types declare a corresponding struct
(e.g. `struct window_stats') with the same structure but with
specific fields in place of the array, corresponding to specific
statistics. The number of such statistics is an object property
computed from the list of tags (Lisp symbols describing the
statistics) stored in `memusage_stats_list'. The idea here is to
allow particular object types to customize the number and
semantics of the statistics where completely avoiding consing.
This doesn't matter so much yet, but the intention is to have the
memory usage of all objects computed at the end of GC, at the same
time as other statistics are currently computed. The values for
all statistics for a single type would be added up to compute
aggregate values for all objects of a specific type. To make this
efficient, we can't allow any memory allocation at all.
(3) Create some additional functions for creating lists that
specify the elements directly as args rather than indirectly through
an array: listn() (number of args given), listu() (list terminated
by Qunbound).
(4) Delete a bit of remaining unused C window_config stuff, also
unused lrecord_type_popup_data.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Thu, 18 Mar 2010 10:50:06 -0500 |
parents | aa5ed11f473b |
children | 1086297242fe |
rev | line source |
---|---|
428 | 1 /* -*-C-*- |
2 Client code to allow local and remote editing of files by XEmacs. | |
3 Copyright (C) 1989 Free Software Foundation, Inc. | |
4 Copyright (C) 1995 Sun Microsystems, Inc. | |
5 Copyright (C) 1997 Free Software Foundation, Inc. | |
6 | |
7 This file is part of XEmacs. | |
8 | |
9 XEmacs is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 2, or (at your option) any | |
12 later version. | |
13 | |
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with XEmacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 Boston, MA 02111-1307, USA. | |
23 | |
24 Author: Andy Norman (ange@hplb.hpl.hp.com), based on | |
25 'etc/emacsclient.c' from the GNU Emacs 18.52 distribution. | |
26 | |
27 Please mail bugs and suggestions to the XEmacs maintainer. | |
28 */ | |
29 | |
442 | 30 /* #### This file should be a windows-mode, not console-mode program under |
31 Windows. (i.e. its entry point should be WinMain.) gnuattach functionality, | |
32 to the extent it's used at all, should be retrieved using a script that | |
33 calls the i.exe wrapper program, to obtain stdio handles. | |
34 | |
35 #### For that matter, both the functionality of gnuclient and gnuserv | |
36 should be merged into XEmacs itself using a -remote arg, just like | |
37 Netscape and other modern programs. | |
38 | |
39 --ben */ | |
40 | |
428 | 41 /* |
42 * This file incorporates new features added by Bob Weiner <weiner@mot.com>, | |
43 * Darrell Kindred <dkindred@cmu.edu> and Arup Mukherjee <arup@cmu.edu>. | |
44 * GNUATTACH support added by Ben Wing <wing@xemacs.org>. | |
45 * Please see the note at the end of the README file for details. | |
46 * | |
47 * (If gnuserv came bundled with your emacs, the README file is probably | |
48 * ../etc/gnuserv.README relative to the directory containing this file) | |
49 */ | |
50 | |
464 | 51 #ifdef CYGWIN |
52 extern void cygwin_conv_to_posix_path(const char *path, char *posix_path); | |
53 #endif | |
54 | |
456 | 55 #include "gnuserv.h" |
2286 | 56 #include "compiler.h" |
428 | 57 |
456 | 58 char gnuserv_version[] = "gnuclient version " GNUSERV_VERSION; |
59 | |
428 | 60 #include "getopt.h" |
61 | |
62 #include <sysfile.h> | |
63 | |
64 #if !defined(SYSV_IPC) && !defined(UNIX_DOMAIN_SOCKETS) && \ | |
65 !defined(INTERNET_DOMAIN_SOCKETS) | |
66 int | |
67 main (int argc, char *argv[]) | |
68 { | |
69 fprintf (stderr, "Sorry, the Emacs server is only " | |
70 "supported on systems that have\n"); | |
71 fprintf (stderr, "Unix Domain sockets, Internet Domain " | |
72 "sockets or System V IPC.\n"); | |
73 exit (1); | |
74 } /* main */ | |
75 #else /* SYSV_IPC || UNIX_DOMAIN_SOCKETS || INTERNET_DOMAIN_SOCKETS */ | |
76 | |
2424 | 77 static char cwd[QXE_PATH_MAX+2];/* current working directory when calculated */ |
428 | 78 static char *cp = NULL; /* ptr into valid bit of cwd above */ |
79 | |
2424 | 80 static pid_t emacs_pid; /* Process id for emacs process */ |
428 | 81 |
82 void initialize_signals (void); | |
83 | |
84 static void | |
2286 | 85 tell_emacs_to_resume (int UNUSED (sig)) |
428 | 86 { |
87 char buffer[GSERV_BUFSZ+1]; | |
88 int s; /* socket / msqid to server */ | |
89 int connect_type; /* CONN_UNIX, CONN_INTERNET, or | |
90 ONN_IPC */ | |
91 | |
92 /* Why is SYSV so retarded? */ | |
93 /* We want emacs to realize that we are resuming */ | |
94 #ifdef SIGCONT | |
95 signal(SIGCONT, tell_emacs_to_resume); | |
96 #endif | |
97 | |
458 | 98 connect_type = make_connection (NULL, 0, &s); |
428 | 99 |
100 sprintf(buffer,"(gnuserv-eval '(resume-pid-console %d))", (int)getpid()); | |
101 send_string(s, buffer); | |
102 | |
103 #ifdef SYSV_IPC | |
104 if (connect_type == (int) CONN_IPC) | |
105 disconnect_from_ipc_server (s, msgp, FALSE); | |
106 #else /* !SYSV_IPC */ | |
107 if (connect_type != (int) CONN_IPC) | |
108 disconnect_from_server (s, FALSE); | |
109 #endif /* !SYSV_IPC */ | |
110 } | |
111 | |
112 static void | |
113 pass_signal_to_emacs (int sig) | |
114 { | |
115 if (kill (emacs_pid, sig) == -1) | |
116 { | |
117 fprintf (stderr, "gnuattach: Could not pass signal to emacs process\n"); | |
118 exit (1); | |
119 } | |
120 initialize_signals (); | |
121 } | |
122 | |
123 void | |
442 | 124 initialize_signals (void) |
428 | 125 { |
126 /* Set up signal handler to pass relevant signals to emacs process. | |
127 We used to send SIGSEGV, SIGBUS, SIGPIPE, SIGILL and others to | |
128 Emacs, but I think it's better not to. I can see no reason why | |
129 Emacs should SIGSEGV whenever gnuclient SIGSEGV-s, etc. */ | |
130 signal (SIGQUIT, pass_signal_to_emacs); | |
131 signal (SIGINT, pass_signal_to_emacs); | |
132 #ifdef SIGWINCH | |
133 signal (SIGWINCH, pass_signal_to_emacs); | |
134 #endif | |
135 | |
136 #ifdef SIGCONT | |
137 /* We want emacs to realize that we are resuming */ | |
138 signal (SIGCONT, tell_emacs_to_resume); | |
139 #endif | |
140 } | |
141 | |
142 | |
143 /* | |
144 get_current_working_directory -- return the cwd. | |
145 */ | |
146 static char * | |
147 get_current_working_directory (void) | |
148 { | |
149 if (cp == NULL) | |
150 { /* haven't calculated it yet */ | |
458 | 151 #ifdef HAVE_GETCWD |
2424 | 152 if (getcwd (cwd,QXE_PATH_MAX) == NULL) |
458 | 153 #else |
428 | 154 if (getwd (cwd) == 0) |
458 | 155 #endif /* HAVE_GETCWD */ |
428 | 156 { |
157 perror (progname); | |
158 fprintf (stderr, "%s: unable to get current working directory\n", | |
159 progname); | |
160 exit (1); | |
161 } /* if */ | |
162 | |
163 /* on some systems, cwd can look like '@machine/' ... */ | |
164 /* ignore everything before the first '/' */ | |
165 for (cp = cwd; *cp && *cp != '/'; ++cp) | |
166 ; | |
167 | |
168 } /* if */ | |
169 | |
170 return cp; | |
171 | |
172 } /* get_current_working_directory */ | |
173 | |
174 | |
175 /* | |
176 filename_expand -- try to convert the given filename into a fully-qualified | |
177 pathname. | |
178 */ | |
179 static void | |
180 filename_expand (char *fullpath, char *filename) | |
181 /* fullpath - returned full pathname */ | |
182 /* filename - filename to expand */ | |
183 { | |
464 | 184 #ifdef CYGWIN |
2424 | 185 char cygwinFilename[QXE_PATH_MAX+1]; |
502 | 186 extern void cygwin_conv_to_posix_path(const char *, char *); |
464 | 187 #endif |
188 | |
428 | 189 int len; |
3556 | 190 fullpath[0] = fullpath[QXE_PATH_MAX] = '\0'; |
428 | 191 |
464 | 192 #ifdef CYGWIN |
193 /* | |
194 If we're in cygwin, just convert it and let the unix stuff handle it. | |
195 */ | |
196 cygwin_conv_to_posix_path(filename, cygwinFilename); | |
197 filename = cygwinFilename; | |
198 #endif | |
428 | 199 |
200 if (filename[0] && filename[0] == '/') | |
201 { | |
202 /* Absolute (unix-style) pathname. Do nothing */ | |
3556 | 203 strncat (fullpath, filename, QXE_PATH_MAX); |
428 | 204 } |
205 else | |
206 { | |
207 /* Assume relative Unix style path. Get the current directory | |
208 and prepend it. FIXME: need to fix the case of DOS paths like | |
209 "\foo", where we need to get the current drive. */ | |
442 | 210 |
3556 | 211 strncat (fullpath, get_current_working_directory (), QXE_PATH_MAX); |
428 | 212 len = strlen (fullpath); |
213 | |
3556 | 214 /* If no trailing slash, add one */ |
215 if (len <= 0 || (fullpath[len - 1] != '/' && len < QXE_PATH_MAX)) | |
216 { | |
217 strcat (fullpath, "/"); | |
218 len++; | |
219 } | |
220 | |
428 | 221 /* Don't forget to add the filename! */ |
3556 | 222 strncat (fullpath, filename, QXE_PATH_MAX - len); |
428 | 223 } |
224 } /* filename_expand */ | |
225 | |
226 /* Encase the string in quotes, escape all the backslashes and quotes | |
227 in string. */ | |
228 static char * | |
442 | 229 clean_string (const char *s) |
428 | 230 { |
231 int i = 0; | |
232 char *p, *res; | |
233 | |
234 { | |
442 | 235 const char *const_p; |
428 | 236 for (const_p = s; *const_p; const_p++, i++) |
237 { | |
238 if (*const_p == '\\' || *const_p == '\"') | |
239 ++i; | |
240 else if (*const_p == '\004') | |
241 i += 3; | |
242 } | |
243 } | |
244 | |
245 p = res = (char *) malloc (i + 2 + 1); | |
246 *p++ = '\"'; | |
247 for (; *s; p++, s++) | |
248 { | |
249 switch (*s) | |
250 { | |
251 case '\\': | |
252 *p++ = '\\'; | |
253 *p = '\\'; | |
254 break; | |
255 case '\"': | |
256 *p++ = '\\'; | |
257 *p = '\"'; | |
258 break; | |
259 case '\004': | |
260 *p++ = '\\'; | |
261 *p++ = 'C'; | |
262 *p++ = '-'; | |
263 *p = 'd'; | |
264 break; | |
265 default: | |
266 *p = *s; | |
267 } | |
268 } | |
269 *p++ = '\"'; | |
270 *p = '\0'; | |
271 return res; | |
272 } | |
273 | |
274 #define GET_ARGUMENT(var, desc) do { \ | |
275 if (*(p + 1)) (var) = p + 1; \ | |
276 else \ | |
277 { \ | |
278 if (!argv[++i]) \ | |
279 { \ | |
280 fprintf (stderr, "%s: `%s' must be followed by an argument\n", \ | |
281 progname, desc); \ | |
282 exit (1); \ | |
283 } \ | |
284 (var) = argv[i]; \ | |
285 } \ | |
286 over = 1; \ | |
287 } while (0) | |
288 | |
440 | 289 /* A strdup imitation. */ |
428 | 290 static char * |
442 | 291 my_strdup (const char *s) |
428 | 292 { |
440 | 293 char *new_s = (char *) malloc (strlen (s) + 1); |
294 if (new_s) | |
295 strcpy (new_s, s); | |
296 return new_s; | |
428 | 297 } |
298 | |
299 int | |
300 main (int argc, char *argv[]) | |
301 { | |
4684
15c42a3f4065
Do not move cursor position in gnuclient started buffer if user did
It's me FKtPp \;) <m_pupil@yahoo.com.cn>
parents:
3556
diff
changeset
|
302 int starting_line = 0; /* line to start editing at */ |
2424 | 303 char command[QXE_PATH_MAX+50];/* emacs command buffer */ |
304 char fullpath[QXE_PATH_MAX+1];/* full pathname to file */ | |
428 | 305 char *eval_form = NULL; /* form to evaluate with `-eval' */ |
306 char *eval_function = NULL; /* function to evaluate with `-f' */ | |
307 char *load_library = NULL; /* library to load */ | |
308 int quick = 0; /* quick edit, don't wait for user to | |
309 finish */ | |
310 int batch = 0; /* batch mode */ | |
311 int view = 0; /* view only. */ | |
312 int nofiles = 0; | |
313 int errflg = 0; /* option error */ | |
314 int s; /* socket / msqid to server */ | |
315 int connect_type; /* CONN_UNIX, CONN_INTERNET, or | |
316 * CONN_IPC */ | |
317 int suppress_windows_system = 0; | |
318 char *display = NULL; | |
319 #ifdef INTERNET_DOMAIN_SOCKETS | |
320 char *hostarg = NULL; /* remote hostname */ | |
321 char *remotearg; | |
322 char thishost[HOSTNAMSZ]; /* this hostname */ | |
2424 | 323 char remotepath[QXE_PATH_MAX+1]; /* remote pathname */ |
428 | 324 char *path; |
325 int rflg = 0; /* pathname given on cmdline */ | |
326 char *portarg; | |
458 | 327 unsigned short port = 0; /* port to server */ |
428 | 328 #endif /* INTERNET_DOMAIN_SOCKETS */ |
329 #ifdef SYSV_IPC | |
330 struct msgbuf *msgp; /* message */ | |
331 #endif /* SYSV_IPC */ | |
332 char *tty = NULL; | |
333 char buffer[GSERV_BUFSZ + 1]; /* buffer to read pid */ | |
334 char result[GSERV_BUFSZ + 1]; | |
335 int i; | |
336 | |
337 #ifdef INTERNET_DOMAIN_SOCKETS | |
338 memset (remotepath, 0, sizeof (remotepath)); | |
339 #endif /* INTERNET_DOMAIN_SOCKETS */ | |
340 | |
341 progname = strrchr (argv[0], '/'); | |
342 if (progname) | |
343 ++progname; | |
344 else | |
345 progname = argv[0]; | |
346 | |
771 | 347 #ifdef WIN32_NATIVE |
348 tmpdir = getenv ("TEMP"); | |
349 if (!tmpdir) | |
350 tmpdir = getenv ("TMP"); | |
351 if (!tmpdir) | |
352 tmpdir = "c:\\"; | |
353 #else | |
428 | 354 #ifdef USE_TMPDIR |
355 tmpdir = getenv ("TMPDIR"); | |
356 #endif | |
357 if (!tmpdir) | |
358 tmpdir = "/tmp"; | |
771 | 359 #endif /* WIN32_NATIVE */ |
428 | 360 display = getenv ("DISPLAY"); |
361 if (display) | |
362 display = my_strdup (display); | |
363 #ifndef HAVE_MS_WINDOWS | |
364 else | |
365 suppress_windows_system = 1; | |
366 #endif | |
367 | |
368 for (i = 1; argv[i] && !errflg; i++) | |
369 { | |
370 if (*argv[i] != '-') | |
371 break; | |
372 else if (*argv[i] == '-' | |
373 && (*(argv[i] + 1) == '\0' | |
374 || (*(argv[i] + 1) == '-' && *(argv[i] + 2) == '\0'))) | |
375 { | |
376 /* `-' or `--' */ | |
377 ++i; | |
378 break; | |
379 } | |
380 | |
381 if (!strcmp (argv[i], "-batch") || !strcmp (argv[i], "--batch")) | |
382 batch = 1; | |
383 else if (!strcmp (argv[i], "-eval") || !strcmp (argv[i], "--eval")) | |
384 { | |
385 if (!argv[++i]) | |
386 { | |
387 fprintf (stderr, "%s: `-eval' must be followed by an argument\n", | |
388 progname); | |
389 exit (1); | |
390 } | |
391 eval_form = argv[i]; | |
392 } | |
393 else if (!strcmp (argv[i], "-display") || !strcmp (argv[i], "--display")) | |
394 { | |
395 suppress_windows_system = 0; | |
396 if (!argv[++i]) | |
397 { | |
398 fprintf (stderr, | |
399 "%s: `-display' must be followed by an argument\n", | |
400 progname); | |
401 exit (1); | |
402 } | |
403 if (display) | |
404 free (display); | |
405 /* no need to strdup. */ | |
406 display = argv[i]; | |
407 } | |
408 else if (!strcmp (argv[i], "-nw")) | |
409 suppress_windows_system = 1; | |
410 else | |
411 { | |
412 /* Iterate over one-letter options. */ | |
413 char *p; | |
414 int over = 0; | |
415 for (p = argv[i] + 1; *p && !over; p++) | |
416 { | |
417 switch (*p) | |
418 { | |
419 case 'q': | |
420 quick = 1; | |
421 break; | |
422 case 'v': | |
423 view = 1; | |
424 break; | |
425 case 'f': | |
426 GET_ARGUMENT (eval_function, "-f"); | |
427 break; | |
428 case 'l': | |
429 GET_ARGUMENT (load_library, "-l"); | |
430 break; | |
431 #ifdef INTERNET_DOMAIN_SOCKETS | |
432 case 'h': | |
433 GET_ARGUMENT (hostarg, "-h"); | |
434 break; | |
435 case 'p': | |
436 GET_ARGUMENT (portarg, "-p"); | |
437 port = atoi (portarg); | |
438 break; | |
439 case 'r': | |
440 GET_ARGUMENT (remotearg, "-r"); | |
3556 | 441 strncpy (remotepath, remotearg, QXE_PATH_MAX); |
428 | 442 rflg = 1; |
443 break; | |
444 #endif /* INTERNET_DOMAIN_SOCKETS */ | |
445 default: | |
446 errflg = 1; | |
447 } | |
448 } /* for */ | |
449 } /* else */ | |
450 } /* for */ | |
451 | |
452 if (errflg) | |
453 { | |
454 fprintf (stderr, | |
455 #ifdef INTERNET_DOMAIN_SOCKETS | |
442 | 456 "Usage: %s [-nw] [-display display] [-q] [-v] [-l library]\n" |
428 | 457 " [-batch] [-f function] [-eval form]\n" |
458 " [-h host] [-p port] [-r remote-path] [[+line] file] ...\n", | |
459 #else /* !INTERNET_DOMAIN_SOCKETS */ | |
442 | 460 "Usage: %s [-nw] [-q] [-v] [-l library] [-f function] [-eval form] " |
428 | 461 "[[+line] path] ...\n", |
462 #endif /* !INTERNET_DOMAIN_SOCKETS */ | |
463 progname); | |
464 exit (1); | |
465 } | |
466 if (batch && argv[i]) | |
467 { | |
468 fprintf (stderr, "%s: Cannot specify `-batch' with file names\n", | |
469 progname); | |
470 exit (1); | |
471 } | |
881 | 472 #if defined(INTERNET_DOMAIN_SOCKETS) |
428 | 473 if (suppress_windows_system && hostarg) |
474 { | |
475 fprintf (stderr, "%s: Remote editing is available only on X\n", | |
476 progname); | |
477 exit (1); | |
478 } | |
881 | 479 #endif |
428 | 480 *result = '\0'; |
481 if (eval_function || eval_form || load_library) | |
482 { | |
483 #if defined(INTERNET_DOMAIN_SOCKETS) | |
484 connect_type = make_connection (hostarg, port, &s); | |
485 #else | |
458 | 486 connect_type = make_connection (NULL, 0, &s); |
428 | 487 #endif |
488 sprintf (command, "(gnuserv-eval%s '(progn ", quick ? "-quickly" : ""); | |
489 send_string (s, command); | |
490 if (load_library) | |
491 { | |
492 send_string (s , "(load-library "); | |
493 send_string (s, clean_string(load_library)); | |
494 send_string (s, ") "); | |
495 } | |
496 if (eval_form) | |
497 { | |
498 send_string (s, eval_form); | |
499 } | |
500 if (eval_function) | |
501 { | |
502 send_string (s, "("); | |
503 send_string (s, eval_function); | |
504 send_string (s, ")"); | |
505 } | |
506 send_string (s, "))"); | |
507 /* disconnect already sends EOT_STR */ | |
508 #ifdef SYSV_IPC | |
509 if (connect_type == (int) CONN_IPC) | |
510 disconnect_from_ipc_server (s, msgp, batch && !quick); | |
511 #else /* !SYSV_IPC */ | |
512 if (connect_type != (int) CONN_IPC) | |
513 disconnect_from_server (s, batch && !quick); | |
514 #endif /* !SYSV_IPC */ | |
515 } /* eval_function || eval_form || load_library */ | |
516 else if (batch) | |
517 { | |
518 /* no sexp on the command line, so read it from stdin */ | |
519 int nb; | |
520 | |
521 #if defined(INTERNET_DOMAIN_SOCKETS) | |
522 connect_type = make_connection (hostarg, port, &s); | |
523 #else | |
458 | 524 connect_type = make_connection (NULL, 0, &s); |
428 | 525 #endif |
526 sprintf (command, "(gnuserv-eval%s '(progn ", quick ? "-quickly" : ""); | |
527 send_string (s, command); | |
528 | |
529 while ((nb = read(fileno(stdin), buffer, GSERV_BUFSZ-1)) > 0) | |
530 { | |
531 buffer[nb] = '\0'; | |
532 send_string(s, buffer); | |
533 } | |
534 send_string(s,"))"); | |
535 /* disconnect already sends EOT_STR */ | |
536 #ifdef SYSV_IPC | |
537 if (connect_type == (int) CONN_IPC) | |
538 disconnect_from_ipc_server (s, msgp, batch && !quick); | |
539 #else /* !SYSV_IPC */ | |
540 if (connect_type != (int) CONN_IPC) | |
541 disconnect_from_server (s, batch && !quick); | |
542 #endif /* !SYSV_IPC */ | |
543 } | |
544 | |
545 if (!batch) | |
546 { | |
547 if (suppress_windows_system) | |
548 { | |
549 tty = ttyname (0); | |
550 if (!tty) | |
551 { | |
552 fprintf (stderr, "%s: Not connected to a tty", progname); | |
553 exit (1); | |
554 } | |
555 #if defined(INTERNET_DOMAIN_SOCKETS) | |
556 connect_type = make_connection (hostarg, port, &s); | |
557 #else | |
458 | 558 connect_type = make_connection (NULL, 0, &s); |
428 | 559 #endif |
560 send_string (s, "(gnuserv-eval '(emacs-pid))"); | |
561 send_string (s, EOT_STR); | |
562 | |
563 if (read_line (s, buffer) == 0) | |
564 { | |
565 fprintf (stderr, "%s: Could not establish Emacs process id\n", | |
566 progname); | |
567 exit (1); | |
568 } | |
442 | 569 /* Don't do disconnect_from_server because we have already read |
428 | 570 data, and disconnect doesn't do anything else. */ |
881 | 571 #ifdef SYSV_IPC |
428 | 572 if (connect_type == (int) CONN_IPC) |
573 disconnect_from_ipc_server (s, msgp, FALSE); | |
574 #endif /* !SYSV_IPC */ | |
575 | |
576 emacs_pid = (pid_t)atol(buffer); | |
577 initialize_signals(); | |
578 } /* suppress_windows_system */ | |
579 | |
580 #if defined(INTERNET_DOMAIN_SOCKETS) | |
581 connect_type = make_connection (hostarg, port, &s); | |
582 #else | |
458 | 583 connect_type = make_connection (NULL, 0, &s); |
428 | 584 #endif |
585 | |
586 #ifdef INTERNET_DOMAIN_SOCKETS | |
587 if (connect_type == (int) CONN_INTERNET) | |
588 { | |
589 char *ptr; | |
590 gethostname (thishost, HOSTNAMSZ); | |
591 if (!rflg) | |
592 { /* attempt to generate a path | |
593 * to this machine */ | |
594 if ((ptr = getenv ("GNU_NODE")) != NULL) | |
595 /* user specified a path */ | |
3556 | 596 strncpy (remotepath, ptr, QXE_PATH_MAX); |
428 | 597 } |
598 #if 0 /* This is really bogus... re-enable it if you must have it! */ | |
4759
aa5ed11f473b
Remove support for obsolete systems. See xemacs-patches message with ID
Jerry James <james@xemacs.org>
parents:
4684
diff
changeset
|
599 #if defined (hp9000s800) |
428 | 600 else if (strcmp (thishost,hostarg)) |
601 { /* try /net/thishost */ | |
602 strcpy (remotepath, "/net/"); /* (this fails using internet | |
603 addresses) */ | |
604 strcat (remotepath, thishost); | |
605 } | |
606 #endif | |
607 #endif | |
608 } | |
609 else | |
610 { /* same machines, no need for path */ | |
611 remotepath[0] = '\0'; /* default is the empty path */ | |
612 } | |
613 #endif /* INTERNET_DOMAIN_SOCKETS */ | |
614 | |
615 #ifdef SYSV_IPC | |
616 if ((msgp = (struct msgbuf *) | |
617 malloc (sizeof *msgp + GSERV_BUFSZ)) == NULL) | |
618 { | |
619 fprintf (stderr, "%s: not enough memory for message buffer\n", progname); | |
620 exit (1); | |
621 } /* if */ | |
622 | |
623 msgp->mtext[0] = '\0'; /* ready for later strcats */ | |
624 #endif /* SYSV_IPC */ | |
625 | |
626 if (suppress_windows_system) | |
627 { | |
628 char *term = getenv ("TERM"); | |
629 if (!term) | |
630 { | |
631 fprintf (stderr, "%s: unknown terminal type\n", progname); | |
632 exit (1); | |
633 } | |
634 sprintf (command, "(gnuserv-edit-files '(tty %s %s %d) '(", | |
635 clean_string (tty), clean_string (term), (int)getpid ()); | |
636 } | |
637 else /* !suppress_windows_system */ | |
638 { | |
462 | 639 if (0) |
640 ; | |
641 #ifdef HAVE_X_WINDOWS | |
642 else if (display) | |
428 | 643 sprintf (command, "(gnuserv-edit-files '(x %s) '(", |
644 clean_string (display)); | |
462 | 645 #endif |
646 #ifdef HAVE_GTK | |
647 else if (display) | |
648 strcpy (command, "(gnuserv-edit-files '(gtk nil) '("); | |
649 #endif | |
428 | 650 #ifdef HAVE_MS_WINDOWS |
651 else | |
652 sprintf (command, "(gnuserv-edit-files '(mswindows nil) '("); | |
653 #endif | |
654 } /* !suppress_windows_system */ | |
655 send_string (s, command); | |
656 | |
657 if (!argv[i]) | |
658 nofiles = 1; | |
659 | |
660 for (; argv[i]; i++) | |
661 { | |
662 if (i < argc - 1 && *argv[i] == '+') | |
663 starting_line = atoi (argv[i++]); | |
4684
15c42a3f4065
Do not move cursor position in gnuclient started buffer if user did
It's me FKtPp \;) <m_pupil@yahoo.com.cn>
parents:
3556
diff
changeset
|
664 |
428 | 665 /* If the last argument is +something, treat it as a file. */ |
4684
15c42a3f4065
Do not move cursor position in gnuclient started buffer if user did
It's me FKtPp \;) <m_pupil@yahoo.com.cn>
parents:
3556
diff
changeset
|
666 if (i == argc) --i; |
15c42a3f4065
Do not move cursor position in gnuclient started buffer if user did
It's me FKtPp \;) <m_pupil@yahoo.com.cn>
parents:
3556
diff
changeset
|
667 |
428 | 668 filename_expand (fullpath, argv[i]); |
669 #ifdef INTERNET_DOMAIN_SOCKETS | |
440 | 670 path = (char *) malloc (strlen (remotepath) + strlen (fullpath) + 1); |
428 | 671 sprintf (path, "%s%s", remotepath, fullpath); |
672 #else | |
673 path = my_strdup (fullpath); | |
674 #endif | |
4684
15c42a3f4065
Do not move cursor position in gnuclient started buffer if user did
It's me FKtPp \;) <m_pupil@yahoo.com.cn>
parents:
3556
diff
changeset
|
675 if ( starting_line ) { |
15c42a3f4065
Do not move cursor position in gnuclient started buffer if user did
It's me FKtPp \;) <m_pupil@yahoo.com.cn>
parents:
3556
diff
changeset
|
676 sprintf (command, "(%d . %s)", starting_line, clean_string (path)); |
15c42a3f4065
Do not move cursor position in gnuclient started buffer if user did
It's me FKtPp \;) <m_pupil@yahoo.com.cn>
parents:
3556
diff
changeset
|
677 } else { |
15c42a3f4065
Do not move cursor position in gnuclient started buffer if user did
It's me FKtPp \;) <m_pupil@yahoo.com.cn>
parents:
3556
diff
changeset
|
678 sprintf (command, "(nil . %s)", clean_string (path)); |
15c42a3f4065
Do not move cursor position in gnuclient started buffer if user did
It's me FKtPp \;) <m_pupil@yahoo.com.cn>
parents:
3556
diff
changeset
|
679 } |
15c42a3f4065
Do not move cursor position in gnuclient started buffer if user did
It's me FKtPp \;) <m_pupil@yahoo.com.cn>
parents:
3556
diff
changeset
|
680 |
428 | 681 send_string (s, command); |
682 free (path); | |
683 } /* for */ | |
684 | |
685 sprintf (command, ")%s%s", | |
686 (quick || (nofiles && !suppress_windows_system)) ? " 'quick" : "", | |
687 view ? " 'view" : ""); | |
688 send_string (s, command); | |
689 send_string (s, ")"); | |
690 | |
691 #ifdef SYSV_IPC | |
692 if (connect_type == (int) CONN_IPC) | |
693 disconnect_from_ipc_server (s, msgp, FALSE); | |
694 #else /* !SYSV_IPC */ | |
695 if (connect_type != (int) CONN_IPC) | |
696 disconnect_from_server (s, FALSE); | |
697 #endif /* !SYSV_IPC */ | |
698 } /* not batch */ | |
699 | |
700 | |
701 return 0; | |
702 | |
703 } /* main */ | |
704 | |
705 #endif /* SYSV_IPC || UNIX_DOMAIN_SOCKETS || INTERNET_DOMAIN_SOCKETS */ |