xref: /openbsd-src/gnu/usr.bin/perl/os2/os2ish.h (revision 47911bd667ac77dc523b8a13ef40b012dbffa741)
1 #include <signal.h>
2 #include <io.h>
3 /* #include <sys/select.h> */
4 
5 /* HAS_IOCTL:
6  *	This symbol, if defined, indicates that the ioctl() routine is
7  *	available to set I/O characteristics
8  */
9 #define	HAS_IOCTL		/**/
10 
11 /* HAS_UTIME:
12  *	This symbol, if defined, indicates that the routine utime() is
13  *	available to update the access and modification times of files.
14  */
15 #define HAS_UTIME		/**/
16 
17 #define HAS_KILL
18 #define HAS_WAIT
19 #define HAS_DLERROR
20 #define HAS_WAITPID_RUNTIME (_emx_env & 0x200)
21 
22 /* HAS_PASSWD
23  *	This symbol, if defined, indicates that the getpwnam() and
24  *	getpwuid() routines are available to get password entries.
25  *	The getpwent() has a separate definition, HAS_GETPWENT.
26  */
27 #define HAS_PASSWD
28 
29 /* HAS_GROUP
30  *	This symbol, if defined, indicates that the getgrnam() and
31  *	getgrgid() routines are available to get group entries.
32  *	The getgrent() has a separate definition, HAS_GETGRENT.
33  */
34 #define HAS_GROUP
35 #define HAS_GETGRENT			/* fake */
36 #define HAS_SETGRENT			/* fake */
37 #define HAS_ENDGRENT			/* fake */
38 
39 /* USEMYBINMODE
40  *	This symbol, if defined, indicates that the program should
41  *	use the routine my_binmode(FILE *fp, char iotype, int mode) to insure
42  *	that a file is in "binary" mode -- that is, that no translation
43  *	of bytes occurs on read or write operations.
44  */
45 #undef USEMYBINMODE
46 
47 /* Stat_t:
48  *	This symbol holds the type used to declare buffers for information
49  *	returned by stat().  It's usually just struct stat.  It may be necessary
50  *	to include <sys/stat.h> and <sys/types.h> to get any typedef'ed
51  *	information.
52  */
53 #define Stat_t struct stat
54 
55 /* USE_STAT_RDEV:
56  *	This symbol is defined if this system has a stat structure declaring
57  *	st_rdev
58  */
59 #define USE_STAT_RDEV 	/**/
60 
61 /* ACME_MESS:
62  *	This symbol, if defined, indicates that error messages should be
63  *	should be generated in a format that allows the use of the Acme
64  *	GUI/editor's autofind feature.
65  */
66 #undef ACME_MESS	/**/
67 
68 /* ALTERNATE_SHEBANG:
69  *	This symbol, if defined, contains a "magic" string which may be used
70  *	as the first line of a Perl program designed to be executed directly
71  *	by name, instead of the standard Unix #!.  If ALTERNATE_SHEBANG
72  *	begins with a character other then #, then Perl will only treat
73  *	it as a command line if if finds the string "perl" in the first
74  *	word; otherwise it's treated as the first line of code in the script.
75  *	(IOW, Perl won't hand off to another interpreter via an alternate
76  *	shebang sequence that might be legal Perl code.)
77  */
78 #define ALTERNATE_SHEBANG "extproc "
79 
80 #ifndef SIGABRT
81 #    define SIGABRT SIGILL
82 #endif
83 #ifndef SIGILL
84 #    define SIGILL 6         /* blech */
85 #endif
86 #define ABORT() kill(PerlProc_getpid(),SIGABRT);
87 
88 #define BIT_BUCKET "/dev/nul"  /* Will this work? */
89 
90 /* Apparently TCPIPV4 defines may be included even with only IAK present */
91 
92 #if !defined(NO_TCPIPV4) && !defined(TCPIPV4)
93 #  define TCPIPV4
94 #  define TCPIPV4_FORCED		/* Just in case */
95 #endif
96 
97 #if defined(I_SYS_UN) && !defined(TCPIPV4)
98 /* It is not working without TCPIPV4 defined. */
99 # undef I_SYS_UN
100 #endif
101 
102 #ifdef USE_5005THREADS
103 
104 #define do_spawn(a)      os2_do_spawn(aTHX_ (a))
105 #define do_aspawn(a,b,c) os2_do_aspawn(aTHX_ (a),(b),(c))
106 
107 #define OS2_ERROR_ALREADY_POSTED 299	/* Avoid os2.h */
108 
109 extern int rc;
110 
111 #define MUTEX_INIT(m) \
112     STMT_START {						\
113 	int rc;							\
114 	if ((rc = _rmutex_create(m,0)))				\
115 	    Perl_croak_nocontext("panic: MUTEX_INIT: rc=%i", rc);	\
116     } STMT_END
117 #define MUTEX_LOCK(m) \
118     STMT_START {						\
119 	int rc;							\
120 	if ((rc = _rmutex_request(m,_FMR_IGNINT)))		\
121 	    Perl_croak_nocontext("panic: MUTEX_LOCK: rc=%i", rc);	\
122     } STMT_END
123 #define MUTEX_UNLOCK(m) \
124     STMT_START {						\
125 	int rc;							\
126 	if ((rc = _rmutex_release(m)))				\
127 	    Perl_croak_nocontext("panic: MUTEX_UNLOCK: rc=%i", rc);	\
128     } STMT_END
129 #define MUTEX_DESTROY(m) \
130     STMT_START {						\
131 	int rc;							\
132 	if ((rc = _rmutex_close(m)))				\
133 	    Perl_croak_nocontext("panic: MUTEX_DESTROY: rc=%i", rc);	\
134     } STMT_END
135 
136 #define COND_INIT(c) \
137     STMT_START {						\
138 	int rc;							\
139 	if ((rc = DosCreateEventSem(NULL,c,0,0)))		\
140 	    Perl_croak_nocontext("panic: COND_INIT: rc=%i", rc);	\
141     } STMT_END
142 #define COND_SIGNAL(c) \
143     STMT_START {						\
144 	int rc;							\
145 	if ((rc = DosPostEventSem(*(c))) && rc != OS2_ERROR_ALREADY_POSTED)\
146 	    Perl_croak_nocontext("panic: COND_SIGNAL, rc=%ld", rc);	\
147     } STMT_END
148 #define COND_BROADCAST(c) \
149     STMT_START {						\
150 	int rc;							\
151 	if ((rc = DosPostEventSem(*(c))) && rc != OS2_ERROR_ALREADY_POSTED)\
152 	    Perl_croak_nocontext("panic: COND_BROADCAST, rc=%i", rc);	\
153     } STMT_END
154 /* #define COND_WAIT(c, m) \
155     STMT_START {						\
156 	if (WaitForSingleObject(*(c),INFINITE) == WAIT_FAILED)	\
157 	    Perl_croak_nocontext("panic: COND_WAIT");		\
158     } STMT_END
159 */
160 #define COND_WAIT(c, m) os2_cond_wait(c,m)
161 
162 #define COND_WAIT_win32(c, m) \
163     STMT_START {						\
164 	int rc;							\
165 	if ((rc = SignalObjectAndWait(*(m),*(c),INFINITE,FALSE)))	\
166 	    Perl_croak_nocontext("panic: COND_WAIT");			\
167 	else							\
168 	    MUTEX_LOCK(m);					\
169     } STMT_END
170 #define COND_DESTROY(c) \
171     STMT_START {						\
172 	int rc;							\
173 	if ((rc = DosCloseEventSem(*(c))))			\
174 	    Perl_croak_nocontext("panic: COND_DESTROY, rc=%i", rc);	\
175     } STMT_END
176 /*#define THR ((struct thread *) TlsGetValue(PL_thr_key))
177 */
178 
179 #ifdef USE_SLOW_THREAD_SPECIFIC
180 #  define pthread_getspecific(k)	(*_threadstore())
181 #  define pthread_setspecific(k,v)	(*_threadstore()=v,0)
182 #  define pthread_key_create(keyp,flag)	(*keyp=_gettid(),0)
183 #else /* USE_SLOW_THREAD_SPECIFIC */
184 #  define pthread_getspecific(k)	(*(k))
185 #  define pthread_setspecific(k,v)	(*(k)=(v),0)
186 #  define pthread_key_create(keyp,flag)			\
187 	( DosAllocThreadLocalMemory(1,(U32*)keyp)	\
188 	  ? Perl_croak_nocontext("LocalMemory"),1	\
189 	  : 0						\
190 	)
191 #endif /* USE_SLOW_THREAD_SPECIFIC */
192 #define pthread_key_delete(keyp)
193 #define pthread_self()			_gettid()
194 #define YIELD				DosSleep(0)
195 
196 #ifdef PTHREADS_INCLUDED		/* For ./x2p stuff. */
197 int pthread_join(pthread_t tid, void **status);
198 int pthread_detach(pthread_t tid);
199 int pthread_create(pthread_t *tid, const pthread_attr_t *attr,
200 		   void *(*start_routine)(void*), void *arg);
201 #endif /* PTHREAD_INCLUDED */
202 
203 #define THREADS_ELSEWHERE
204 
205 #else /* USE_5005THREADS */
206 
207 #define do_spawn(a)      os2_do_spawn(a)
208 #define do_aspawn(a,b,c) os2_do_aspawn((a),(b),(c))
209 
210 #endif /* USE_5005THREADS */
211 
212 void Perl_OS2_init(char **);
213 void Perl_OS2_init3(char **envp, void **excH, int flags);
214 void Perl_OS2_term(void **excH, int exitstatus, int flags);
215 
216 /* The code without INIT3 hideously puts env inside: */
217 
218 /* These ones should be in the same block as PERL_SYS_TERM() */
219 #ifdef PERL_CORE
220 
221 #  define PERL_SYS_INIT3(argcp, argvp, envp)	\
222   { void *xreg[2];				\
223     _response(argcp, argvp);			\
224     _wildcard(argcp, argvp);			\
225     Perl_OS2_init3(*envp, xreg, 0)
226 
227 #  define PERL_SYS_INIT(argcp, argvp)  {	\
228   { void *xreg[2];				\
229     _response(argcp, argvp);			\
230     _wildcard(argcp, argvp);			\
231     Perl_OS2_init3(NULL, xreg, 0)
232 
233 #else  /* Compiling embedded Perl or Perl extension */
234 
235 #  define PERL_SYS_INIT3(argcp, argvp, envp)	\
236   { void *xreg[2];				\
237     Perl_OS2_init3(*envp, xreg, 0)
238 #  define PERL_SYS_INIT(argcp, argvp)	{	\
239   { void *xreg[2];				\
240     Perl_OS2_init3(NULL, xreg, 0)
241 #endif
242 
243 #define FORCE_EMX_DEINIT_EXIT		1
244 #define FORCE_EMX_DEINIT_CRT_TERM	2
245 #define FORCE_EMX_DEINIT_RUN_ATEXIT	4
246 
247 #define PERL_SYS_TERM2(xreg,flags)					\
248   Perl_OS2_term(xreg, 0, flags);					\
249   MALLOC_TERM
250 
251 #define PERL_SYS_TERM1(xreg)						\
252      Perl_OS2_term(xreg, 0, FORCE_EMX_DEINIT_RUN_ATEXIT)
253 
254 /* This one should come in pair with PERL_SYS_INIT() and in the same block */
255 #define PERL_SYS_TERM()							\
256      PERL_SYS_TERM1(xreg);						\
257   }
258 
259 #ifndef __EMX__
260 #  define PERL_CALLCONV _System
261 #endif
262 
263 /* #define PERL_SYS_TERM() STMT_START {	\
264     if (Perl_HAB_set) WinTerminate(Perl_hab);	} STMT_END */
265 
266 #define dXSUB_SYS OS2_XS_init()
267 
268 #ifdef PERL_IS_AOUT
269 /* #  define HAS_FORK */
270 /* #  define HIDEMYMALLOC */
271 /* #  define PERL_SBRK_VIA_MALLOC */ /* gets off-page sbrk... */
272 #else /* !PERL_IS_AOUT */
273 #  ifndef PERL_FOR_X2P
274 #    ifdef EMX_BAD_SBRK
275 #      define USE_PERL_SBRK
276 #    endif
277 #  else
278 #    define PerlIO FILE
279 #  endif
280 #  define SYSTEM_ALLOC(a) sys_alloc(a)
281 
282 void *sys_alloc(int size);
283 
284 #endif /* !PERL_IS_AOUT */
285 #if !defined(PERL_CORE) && !defined(PerlIO) /* a2p */
286 #  define PerlIO FILE
287 #endif
288 
289 /* os2ish is used from a2p/a2p.h without pTHX/pTHX_ first being
290  * defined.  Hack around this to get us to compile.
291 */
292 #ifdef PTHX_UNUSED
293 # ifndef pTHX
294 #  define pTHX
295 # endif
296 # ifndef pTHX_
297 #  define pTHX_
298 # endif
299 #endif
300 
301 #define TMPPATH1 "plXXXXXX"
302 extern char *tmppath;
303 PerlIO *my_syspopen(pTHX_ char *cmd, char *mode);
304 /* Cannot prototype with I32 at this point. */
305 int my_syspclose(PerlIO *f);
306 FILE *my_tmpfile (void);
307 char *my_tmpnam (char *);
308 int my_mkdir (__const__ char *, long);
309 int my_rmdir (__const__ char *);
310 struct passwd *my_getpwent (void);
311 void my_setpwent (void);
312 void my_endpwent (void);
313 char *gcvt_os2(double value, int digits, char *buffer);
314 
315 struct group *getgrent (void);
316 void setgrent (void);
317 void endgrent (void);
318 
319 struct passwd *my_getpwuid (uid_t);
320 struct passwd *my_getpwnam (__const__ char *);
321 
322 #undef L_tmpnam
323 #define L_tmpnam MAXPATHLEN
324 
325 #define tmpfile	my_tmpfile
326 #define tmpnam	my_tmpnam
327 #define isatty	_isterm
328 #define rand	random
329 #define srand	srandom
330 #define strtoll	_strtoll
331 #define strtoull	_strtoull
332 
333 /*
334  * fwrite1() should be a routine with the same calling sequence as fwrite(),
335  * but which outputs all of the bytes requested as a single stream (unlike
336  * fwrite() itself, which on some systems outputs several distinct records
337  * if the number_of_items parameter is >1).
338  */
339 #define fwrite1 fwrite
340 
341 #define my_getenv(var) getenv(var)
342 #define flock	my_flock
343 #define rmdir	my_rmdir
344 #define mkdir	my_mkdir
345 #define setpwent	my_setpwent
346 #define getpwent	my_getpwent
347 #define endpwent	my_endpwent
348 #define getpwuid	my_getpwuid
349 #define getpwnam	my_getpwnam
350 
351 void *emx_calloc (size_t, size_t);
352 void emx_free (void *);
353 void *emx_malloc (size_t);
354 void *emx_realloc (void *, size_t);
355 
356 /*****************************************************************************/
357 
358 #include <stdlib.h>	/* before the following definitions */
359 #include <unistd.h>	/* before the following definitions */
360 #include <fcntl.h>
361 #include <sys/stat.h>
362 
363 #define chdir	_chdir2
364 #define getcwd	_getcwd2
365 
366 /* This guy is needed for quick stdstd  */
367 
368 #if defined(USE_STDIO_PTR) && defined(STDIO_PTR_LVALUE) && defined(STDIO_CNT_LVALUE)
369 	/* Perl uses ungetc only with successful return */
370 #  define ungetc(c,fp) \
371 	(FILE_ptr(fp) > FILE_base(fp) && c == (int)*(FILE_ptr(fp) - 1) \
372 	 ? (--FILE_ptr(fp), ++FILE_cnt(fp), (int)c) : ungetc(c,fp))
373 #endif
374 
375 #define PERLIO_IS_BINMODE_FD(fd) _PERLIO_IS_BINMODE_FD(fd)
376 
377 #ifdef __GNUG__
378 # define HAS_BOOL
379 #endif
380 #ifndef HAS_BOOL
381 # define bool char
382 # define HAS_BOOL 1
383 #endif
384 
385 #include <emx/io.h> /* for _fd_flags() prototype */
386 
387 static inline bool
388 _PERLIO_IS_BINMODE_FD(int fd)
389 {
390     int *pflags = _fd_flags(fd);
391 
392     return pflags && (*pflags) & O_BINARY;
393 }
394 
395 /* ctermid is missing from emx0.9d */
396 char *ctermid(char *s);
397 
398 #define OP_BINARY O_BINARY
399 
400 #define OS2_STAT_HACK 1
401 #if OS2_STAT_HACK
402 
403 #define Stat(fname,bufptr) os2_stat((fname),(bufptr))
404 #define Fstat(fd,bufptr)   fstat((fd),(bufptr))
405 #define Fflush(fp)         fflush(fp)
406 #define Mkdir(path,mode)   mkdir((path),(mode))
407 
408 #undef S_IFBLK
409 #undef S_ISBLK
410 #define S_IFBLK		0120000
411 #define S_ISBLK(mode)	(((mode) & S_IFMT) == S_IFBLK)
412 
413 #else
414 
415 #define Stat(fname,bufptr) stat((fname),(bufptr))
416 #define Fstat(fd,bufptr)   fstat((fd),(bufptr))
417 #define Fflush(fp)         fflush(fp)
418 #define Mkdir(path,mode)   mkdir((path),(mode))
419 
420 #endif
421 
422 /* With SD386 it is impossible to debug register variables. */
423 #if !defined(PERL_IS_AOUT) && defined(DEBUGGING) && !defined(register)
424 #  define register
425 #endif
426 
427 /* Our private OS/2 specific data. */
428 
429 typedef struct OS2_Perl_data {
430   unsigned long flags;
431   unsigned long phab;
432   int (*xs_init)();
433   unsigned long rc;
434   unsigned long severity;
435   unsigned long	phmq;			/* Handle to message queue */
436   unsigned long	phmq_refcnt;
437   unsigned long	phmq_servers;
438   unsigned long	initial_mode;		/* VIO etc. mode we were started in */
439 } OS2_Perl_data_t;
440 
441 extern OS2_Perl_data_t OS2_Perl_data;
442 
443 #define Perl_hab		((HAB)OS2_Perl_data.phab)
444 #define Perl_rc			(OS2_Perl_data.rc)
445 #define Perl_severity		(OS2_Perl_data.severity)
446 #define errno_isOS2		12345678
447 #define errno_isOS2_set		12345679
448 #define OS2_Perl_flags	(OS2_Perl_data.flags)
449 #define Perl_HAB_set_f	1
450 #define Perl_HAB_set	(OS2_Perl_flags & Perl_HAB_set_f)
451 #define set_Perl_HAB_f	(OS2_Perl_flags |= Perl_HAB_set_f)
452 #define set_Perl_HAB(h) (set_Perl_HAB_f, Perl_hab = h)
453 #define _obtain_Perl_HAB (init_PMWIN_entries(),				\
454 			  Perl_hab = (*PMWIN_entries.Initialize)(0),	\
455 			  set_Perl_HAB_f, Perl_hab)
456 #define perl_hab_GET()	(Perl_HAB_set ? Perl_hab : _obtain_Perl_HAB)
457 #define Acquire_hab()	perl_hab_GET()
458 #define Perl_hmq	((HMQ)OS2_Perl_data.phmq)
459 #define Perl_hmq_refcnt	(OS2_Perl_data.phmq_refcnt)
460 #define Perl_hmq_servers	(OS2_Perl_data.phmq_servers)
461 #define Perl_os2_initial_mode	(OS2_Perl_data.initial_mode)
462 
463 unsigned long Perl_hab_GET();
464 unsigned long Perl_Register_MQ(int serve);
465 void	Perl_Deregister_MQ(int serve);
466 int	Perl_Serve_Messages(int force);
467 /* Cannot prototype with I32 at this point. */
468 int	Perl_Process_Messages(int force, long *cntp);
469 char	*os2_execname(pTHX);
470 
471 struct _QMSG;
472 struct PMWIN_entries_t {
473     unsigned long (*Initialize)( unsigned long fsOptions );
474     unsigned long (*CreateMsgQueue)(unsigned long hab, long cmsg);
475     int (*DestroyMsgQueue)(unsigned long hmq);
476     int (*PeekMsg)(unsigned long hab, struct _QMSG *pqmsg,
477 		   unsigned long hwndFilter, unsigned long msgFilterFirst,
478 		   unsigned long msgFilterLast, unsigned long fl);
479     int (*GetMsg)(unsigned long hab, struct _QMSG *pqmsg,
480 		  unsigned long hwndFilter, unsigned long msgFilterFirst,
481 		  unsigned long msgFilterLast);
482     void * (*DispatchMsg)(unsigned long hab, struct _QMSG *pqmsg);
483     unsigned long (*GetLastError)(unsigned long hab);
484     unsigned long (*CancelShutdown)(unsigned long hmq, unsigned long fCancelAlways);
485 };
486 extern struct PMWIN_entries_t PMWIN_entries;
487 void init_PMWIN_entries(void);
488 
489 #define perl_hmq_GET(serve)	Perl_Register_MQ(serve)
490 #define perl_hmq_UNSET(serve)	Perl_Deregister_MQ(serve)
491 
492 #define OS2_XS_init() (*OS2_Perl_data.xs_init)(aTHX)
493 
494 #if _EMX_CRT_REV_ >= 60
495 # define os2_setsyserrno(rc)	(Perl_rc = rc, errno = errno_isOS2_set, \
496 				_setsyserrno(rc))
497 #else
498 # define os2_setsyserrno(rc)	(Perl_rc = rc, errno = errno_isOS2)
499 #endif
500 
501 /* The expressions below return true on error. */
502 /* INCL_DOSERRORS needed. rc should be declared outside. */
503 #define CheckOSError(expr) (!(rc = (expr)) ? 0 : (FillOSError(rc), 1))
504 /* INCL_WINERRORS needed. */
505 #define CheckWinError(expr) ((expr) ? 0: (FillWinError, 1))
506 
507 /* This form propagates the return value, setting $^E if needed */
508 #define SaveWinError(expr) ((expr) ? : (FillWinError, 0))
509 
510 /* This form propagates the return value, dieing with $^E if needed */
511 #define SaveCroakWinError(expr,die,name1,name2)		\
512   ((expr) ? : (CroakWinError(die,name1 name2), 0))
513 
514 #define FillOSError(rc) (os2_setsyserrno(rc),				\
515 			Perl_severity = SEVERITY_ERROR)
516 
517 #define WinError_2_Perl_rc	\
518  (	init_PMWIN_entries(),	\
519 	Perl_rc=(*PMWIN_entries.GetLastError)(perl_hab_GET()) )
520 
521 /* Calling WinGetLastError() resets the error code of the current thread.
522    Since for some Win* API return value 0 is normal, one needs to call
523    this before calling them to distinguish normal and anomalous returns.  */
524 /*#define ResetWinError()	WinError_2_Perl_rc */
525 
526 /* At this moment init_PMWIN_entries() should be a nop (WinInitialize should
527    be called already, right?), so we do not risk stepping over our own error */
528 #define FillWinError (	WinError_2_Perl_rc,				\
529 			Perl_severity = ERRORIDSEV(Perl_rc),		\
530 			Perl_rc = ERRORIDERROR(Perl_rc),		\
531 			os2_setsyserrno(Perl_rc))
532 
533 #define STATIC_FILE_LENGTH 127
534 
535     /* This should match loadOrdinals[] array in os2.c */
536 enum entries_ordinals {
537     ORD_DosQueryExtLibpath,
538     ORD_DosSetExtLibpath,
539     ORD_DosVerifyPidTid,
540     ORD_SETHOSTENT,
541     ORD_SETNETENT,
542     ORD_SETPROTOENT,
543     ORD_SETSERVENT,
544     ORD_GETHOSTENT,
545     ORD_GETNETENT,
546     ORD_GETPROTOENT,
547     ORD_GETSERVENT,
548     ORD_ENDHOSTENT,
549     ORD_ENDNETENT,
550     ORD_ENDPROTOENT,
551     ORD_ENDSERVENT,
552     ORD_WinInitialize,
553     ORD_WinCreateMsgQueue,
554     ORD_WinDestroyMsgQueue,
555     ORD_WinPeekMsg,
556     ORD_WinGetMsg,
557     ORD_WinDispatchMsg,
558     ORD_WinGetLastError,
559     ORD_WinCancelShutdown,
560     ORD_RexxStart,
561     ORD_RexxVariablePool,
562     ORD_RexxRegisterFunctionExe,
563     ORD_RexxDeregisterFunction,
564     ORD_DOSSMSETTITLE,
565     ORD_PRF32QUERYPROFILESIZE,
566     ORD_PRF32OPENPROFILE,
567     ORD_PRF32CLOSEPROFILE,
568     ORD_PRF32QUERYPROFILE,
569     ORD_PRF32RESET,
570     ORD_PRF32QUERYPROFILEDATA,
571     ORD_PRF32WRITEPROFILEDATA,
572 
573     ORD_WinChangeSwitchEntry,
574     ORD_WinQuerySwitchEntry,
575     ORD_WinQuerySwitchHandle,
576     ORD_WinQuerySwitchList,
577     ORD_WinSwitchToProgram,
578     ORD_WinBeginEnumWindows,
579     ORD_WinEndEnumWindows,
580     ORD_WinEnumDlgItem,
581     ORD_WinGetNextWindow,
582     ORD_WinIsChild,
583     ORD_WinQueryActiveWindow,
584     ORD_WinQueryClassName,
585     ORD_WinQueryFocus,
586     ORD_WinQueryWindow,
587     ORD_WinQueryWindowPos,
588     ORD_WinQueryWindowProcess,
589     ORD_WinQueryWindowText,
590     ORD_WinQueryWindowTextLength,
591     ORD_WinSetFocus,
592     ORD_WinSetWindowPos,
593     ORD_WinSetWindowText,
594     ORD_WinShowWindow,
595     ORD_WinIsWindow,
596     ORD_WinWindowFromId,
597     ORD_WinWindowFromPoint,
598     ORD_WinPostMsg,
599     ORD_WinEnableWindow,
600     ORD_WinEnableWindowUpdate,
601     ORD_WinIsWindowEnabled,
602     ORD_WinIsWindowShowing,
603     ORD_WinIsWindowVisible,
604     ORD_WinQueryWindowPtr,
605     ORD_WinQueryWindowULong,
606     ORD_WinQueryWindowUShort,
607     ORD_WinSetWindowBits,
608     ORD_WinSetWindowPtr,
609     ORD_WinSetWindowULong,
610     ORD_WinSetWindowUShort,
611     ORD_WinQueryDesktopWindow,
612     ORD_WinSetActiveWindow,
613     ORD_DosQueryModFromEIP,
614     ORD_NENTRIES
615 };
616 
617 /* RET: return type, AT: argument signature in (), ARGS: should be in () */
618 #define CallORD(ret,o,at,args)	(((ret (*)at) loadByOrdinal(o, 1))args)
619 #define DeclFuncByORD(ret,name,o,at,args)	\
620   ret name at { return CallORD(ret,o,at,args); }
621 #define DeclVoidFuncByORD(name,o,at,args)	\
622   void name at { CallORD(void,o,at,args); }
623 
624 /* These functions return false on error, and save the error info in $^E */
625 #define DeclOSFuncByORD(ret,name,o,at,args)	\
626   ret name at { unsigned long rc; return !CheckOSError(CallORD(ret,o,at,args)); }
627 #define DeclWinFuncByORD(ret,name,o,at,args)	\
628   ret name at { return SaveWinError(CallORD(ret,o,at,args)); }
629 
630 #define AssignFuncPByORD(p,o)	(*(Perl_PFN*)&(p) = (loadByOrdinal(o, 1)))
631 
632 /* This flavor caches the procedure pointer (named as p__Win#name) locally */
633 #define DeclWinFuncByORD_CACHE(ret,name,o,at,args)	\
634 	DeclWinFuncByORD_CACHE_r(ret,name,o,at,args,0,1)
635 
636 /* This flavor may reset the last error before the call (if ret=0 may be OK) */
637 #define DeclWinFuncByORD_CACHE_resetError(ret,name,o,at,args)	\
638 	DeclWinFuncByORD_CACHE_r(ret,name,o,at,args,1,1)
639 
640 /* Two flavors below do the same as above, but do not auto-croak */
641 /* This flavor caches the procedure pointer (named as p__Win#name) locally */
642 #define DeclWinFuncByORD_CACHE_survive(ret,name,o,at,args)	\
643 	DeclWinFuncByORD_CACHE_r(ret,name,o,at,args,0,0)
644 
645 /* This flavor may reset the last error before the call (if ret=0 may be OK) */
646 #define DeclWinFuncByORD_CACHE_resetError_survive(ret,name,o,at,args)	\
647 	DeclWinFuncByORD_CACHE_r(ret,name,o,at,args,1,0)
648 
649 #define DeclWinFuncByORD_CACHE_r(ret,name,o,at,args,r,die)	\
650   static ret (*CAT2(p__Win,name)) at;				\
651   static ret name at {						\
652 	if (!CAT2(p__Win,name))					\
653 	    AssignFuncPByORD(CAT2(p__Win,name), o);		\
654 	if (r) ResetWinError();					\
655 	return SaveCroakWinError(CAT2(p__Win,name) args, die, "[Win]", STRINGIFY(name)); }
656 
657 /* These flavors additionally assume ORD is name with prepended ORD_Win  */
658 #define DeclWinFunc_CACHE(ret,name,at,args)	\
659 	DeclWinFuncByORD_CACHE(ret,name,CAT2(ORD_Win,name),at,args)
660 #define DeclWinFunc_CACHE_resetError(ret,name,at,args)	\
661 	DeclWinFuncByORD_CACHE_resetError(ret,name,CAT2(ORD_Win,name),at,args)
662 #define DeclWinFunc_CACHE_survive(ret,name,at,args)	\
663 	DeclWinFuncByORD_CACHE_survive(ret,name,CAT2(ORD_Win,name),at,args)
664 #define DeclWinFunc_CACHE_resetError_survive(ret,name,at,args)	\
665 	DeclWinFuncByORD_CACHE_resetError_survive(ret,name,CAT2(ORD_Win,name),at,args)
666 
667 void ResetWinError(void);
668 void CroakWinError(int die, char *name);
669 
670 #define PERLLIB_MANGLE(s, n) perllib_mangle((s), (n))
671 char *perllib_mangle(char *, unsigned int);
672 
673 typedef int (*Perl_PFN)();
674 Perl_PFN loadByOrdinal(enum entries_ordinals ord, int fail);
675 extern const Perl_PFN * const pExtFCN;
676 char *os2error(int rc);
677 int os2_stat(const char *name, struct stat *st);
678 int setpriority(int which, int pid, int val);
679 int getpriority(int which /* ignored */, int pid);
680 
681 #ifdef PERL_CORE
682 int os2_do_spawn(pTHX_ char *cmd);
683 int os2_do_aspawn(pTHX_ SV *really, void **vmark, void **vsp);
684 #endif
685 
686 #ifndef LOG_DAEMON
687 
688 /* Replacement for syslog.h */
689 #  define	LOG_EMERG	0	/* system is unusable */
690 #  define	LOG_ALERT	1	/* action must be taken immediately */
691 #  define	LOG_CRIT	2	/* critical conditions */
692 #  define	LOG_ERR	3	/* error conditions */
693 #  define	LOG_WARNING	4	/* warning conditions */
694 #  define	LOG_NOTICE	5	/* normal but significant condition */
695 #  define	LOG_INFO	6	/* informational */
696 #  define	LOG_DEBUG	7	/* debug-level messages */
697 
698 #  define	LOG_PRIMASK	0x007	/* mask to extract priority part (internal) */
699 				/* extract priority */
700 #  define	LOG_PRI(p)	((p) & LOG_PRIMASK)
701 #  define	LOG_MAKEPRI(fac, pri)	(((fac) << 3) | (pri))
702 
703 /* facility codes */
704 #  define	LOG_KERN	(0<<3)	/* kernel messages */
705 #  define	LOG_USER	(1<<3)	/* random user-level messages */
706 #  define	LOG_MAIL	(2<<3)	/* mail system */
707 #  define	LOG_DAEMON	(3<<3)	/* system daemons */
708 #  define	LOG_AUTH	(4<<3)	/* security/authorization messages */
709 #  define	LOG_SYSLOG	(5<<3)	/* messages generated internally by syslogd */
710 #  define	LOG_LPR	(6<<3)	/* line printer subsystem */
711 #  define	LOG_NEWS	(7<<3)	/* network news subsystem */
712 #  define	LOG_UUCP	(8<<3)	/* UUCP subsystem */
713 #  define	LOG_CRON	(15<<3)	/* clock daemon */
714 	/* other codes through 15 reserved for system use */
715 #  define	LOG_LOCAL0	(16<<3)	/* reserved for local use */
716 #  define	LOG_LOCAL1	(17<<3)	/* reserved for local use */
717 #  define	LOG_LOCAL2	(18<<3)	/* reserved for local use */
718 #  define	LOG_LOCAL3	(19<<3)	/* reserved for local use */
719 #  define	LOG_LOCAL4	(20<<3)	/* reserved for local use */
720 #  define	LOG_LOCAL5	(21<<3)	/* reserved for local use */
721 #  define	LOG_LOCAL6	(22<<3)	/* reserved for local use */
722 #  define	LOG_LOCAL7	(23<<3)	/* reserved for local use */
723 
724 #  define	LOG_NFACILITIES	24	/* current number of facilities */
725 #  define	LOG_FACMASK	0x03f8	/* mask to extract facility part */
726 				/* facility of pri */
727 #  define	LOG_FAC(p)	(((p) & LOG_FACMASK) >> 3)
728 
729 /*
730  * arguments to setlogmask.
731  */
732 #  define	LOG_MASK(pri)	(1 << (pri))		/* mask for one priority */
733 #  define	LOG_UPTO(pri)	((1 << ((pri)+1)) - 1)	/* all priorities through pri */
734 
735 /*
736  * Option flags for openlog.
737  *
738  * LOG_ODELAY no longer does anything.
739  * LOG_NDELAY is the inverse of what it used to be.
740  */
741 #  define	LOG_PID		0x01	/* log the pid with each message */
742 #  define	LOG_CONS	0x02	/* log on the console if errors in sending */
743 #  define	LOG_ODELAY	0x04	/* delay open until first syslog() (default) */
744 #  define	LOG_NDELAY	0x08	/* don't delay open */
745 #  define	LOG_NOWAIT	0x10	/* don't wait for console forks: DEPRECATED */
746 #  define	LOG_PERROR	0x20	/* log to stderr as well */
747 
748 #endif
749 
750 /* ************************************************************ */
751 #define Dos32QuerySysState DosQuerySysState
752 #define QuerySysState(flags, pid, buf, bufsz) \
753 	Dos32QuerySysState(flags, 0,  pid, 0, buf, bufsz)
754 
755 #define QSS_PROCESS	1
756 #define QSS_MODULE	4
757 #define QSS_SEMAPHORES	2
758 #define QSS_FILE	8		/* Buggy until fixpack18 */
759 #define QSS_SHARED	16
760 
761 #ifdef _OS2_H
762 
763 APIRET APIENTRY Dos32QuerySysState(ULONG func,ULONG arg1,ULONG pid,
764 			ULONG _res_,PVOID buf,ULONG bufsz);
765 typedef struct {
766 	ULONG	threadcnt;
767 	ULONG	proccnt;
768 	ULONG	modulecnt;
769 } QGLOBAL, *PQGLOBAL;
770 
771 typedef struct {
772 	ULONG	rectype;
773 	USHORT	threadid;
774 	USHORT	slotid;
775 	ULONG	sleepid;
776 	ULONG	priority;
777 	ULONG	systime;
778 	ULONG	usertime;
779 	UCHAR	state;
780 	UCHAR	_reserved1_;	/* padding to ULONG */
781 	USHORT	_reserved2_;	/* padding to ULONG */
782 } QTHREAD, *PQTHREAD;
783 
784 typedef struct {
785 	USHORT	sfn;
786 	USHORT	refcnt;
787 	USHORT	flags1;
788 	USHORT	flags2;
789 	USHORT	accmode1;
790 	USHORT	accmode2;
791 	ULONG	filesize;
792 	USHORT  volhnd;
793 	USHORT	attrib;
794 	USHORT	_reserved_;
795 } QFDS, *PQFDS;
796 
797 typedef struct qfile {
798 	ULONG		rectype;
799 	struct qfile	*next;
800 	ULONG		opencnt;
801 	PQFDS		filedata;
802 	char		name[1];
803 } QFILE, *PQFILE;
804 
805 typedef struct {
806 	ULONG	rectype;
807 	PQTHREAD threads;
808 	USHORT	pid;
809 	USHORT	ppid;
810 	ULONG	type;
811 	ULONG	state;
812 	ULONG	sessid;
813 	USHORT	hndmod;
814 	USHORT	threadcnt;
815 	ULONG	privsem32cnt;
816 	ULONG	_reserved2_;
817 	USHORT	sem16cnt;
818 	USHORT	dllcnt;
819 	USHORT	shrmemcnt;
820 	USHORT	fdscnt;
821 	PUSHORT	sem16s;
822 	PUSHORT	dlls;
823 	PUSHORT	shrmems;
824 	PUSHORT	fds;
825 } QPROCESS, *PQPROCESS;
826 
827 typedef struct sema {
828 	struct sema *next;
829 	USHORT	refcnt;
830 	UCHAR	sysflags;
831 	UCHAR	sysproccnt;
832 	ULONG	_reserved1_;
833 	USHORT	index;
834 	CHAR	name[1];
835 } QSEMA, *PQSEMA;
836 
837 typedef struct {
838 	ULONG	rectype;
839 	ULONG	_reserved1_;
840 	USHORT	_reserved2_;
841 	USHORT	syssemidx;
842 	ULONG	index;
843 	QSEMA	sema;
844 } QSEMSTRUC, *PQSEMSTRUC;
845 
846 typedef struct {
847 	USHORT	pid;
848 	USHORT	opencnt;
849 } QSEMOWNER32, *PQSEMOWNER32;
850 
851 typedef struct {
852 	PQSEMOWNER32	own;
853 	PCHAR		name;
854 	PVOID		semrecs; /* array of associated sema's */
855 	USHORT		flags;
856 	USHORT		semreccnt;
857 	USHORT		waitcnt;
858 	USHORT		_reserved_;	/* padding to ULONG */
859 } QSEMSMUX32, *PQSEMSMUX32;
860 
861 typedef struct {
862 	PQSEMOWNER32	own;
863 	PCHAR		name;
864 	PQSEMSMUX32	mux;
865 	USHORT		flags;
866 	USHORT		postcnt;
867 } QSEMEV32, *PQSEMEV32;
868 
869 typedef struct {
870 	PQSEMOWNER32	own;
871 	PCHAR		name;
872 	PQSEMSMUX32	mux;
873 	USHORT		flags;
874 	USHORT		refcnt;
875 	USHORT		thrdnum;
876 	USHORT		_reserved_;	/* padding to ULONG */
877 } QSEMMUX32, *PQSEMMUX32;
878 
879 typedef struct semstr32 {
880 	struct semstr *next;
881 	QSEMEV32 evsem;
882 	QSEMMUX32  muxsem;
883 	QSEMSMUX32 smuxsem;
884 } QSEMSTRUC32, *PQSEMSTRUC32;
885 
886 typedef struct shrmem {
887 	struct shrmem *next;
888 	USHORT	hndshr;
889 	USHORT	selshr;
890 	USHORT	refcnt;
891 	CHAR	name[1];
892 } QSHRMEM, *PQSHRMEM;
893 
894 typedef struct module {
895 	struct module *next;
896 	USHORT	hndmod;
897 	USHORT	type;
898 	ULONG	refcnt;
899 	ULONG	segcnt;
900 	PVOID	_reserved_;
901 	PCHAR	name;
902 	USHORT	modref[1];
903 } QMODULE, *PQMODULE;
904 
905 typedef struct {
906 	PQGLOBAL	gbldata;
907 	PQPROCESS	procdata;
908 	PQSEMSTRUC	semadata;
909 	PQSEMSTRUC32	sem32data;
910 	PQSHRMEM	shrmemdata;
911 	PQMODULE	moddata;
912 	PVOID		_reserved2_;
913 	PQFILE		filedata;
914 } QTOPLEVEL, *PQTOPLEVEL;
915 /* ************************************************************ */
916 
917 PQTOPLEVEL get_sysinfo(ULONG pid, ULONG flags);
918 
919 #endif /* _OS2_H */
920 
921