~vcs-imports/gawk/master

« back to all changes in this revision

Viewing changes to pc/gawkmisc.pc

Update README.solaris.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* gawkmisc.c --- miscellaneous gawk routines that are OS specific. -*-C-*- */
 
1
/*
 
2
 * gawkmisc.c --- miscellaneous gawk routines that are OS specific.
 
3
 */
2
4
 
3
5
/* 
4
 
 * Copyright (C) 1986, 1988, 1989, 1991 - 2003, 2012, 2016-2019, 2021, 2022, 2023
5
 
 * the Free Software Foundation, Inc.
 
6
 * Copyright (C) 1986, 1988, 1989, 1991 - 2003, 2012 the Free Software Foundation, Inc.
6
7
 * 
7
8
 * This file is part of GAWK, the GNU implementation of the
8
9
 * AWK Progamming Language.
22
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
23
24
 */
24
25
 
25
 
const char quote = '\'';
26
 
const char envsep = ';';
 
26
char quote = '\'';
 
27
char envsep = ';';
27
28
 
28
29
# ifdef DEFPATH
29
 
const char *defpath = DEFPATH;
 
30
char *defpath = DEFPATH;
30
31
# else
31
 
const char *defpath = ".;c:\\lib\\awk;c:\\gnu\\lib\\awk";
 
32
char *defpath = ".;c:\\lib\\awk;c:\\gnu\\lib\\awk";
32
33
# endif
33
34
/* the Makefile should define DEFLIBPATH */
34
 
const char *deflibpath = DEFLIBPATH;
 
35
char *deflibpath = DEFLIBPATH;
 
36
 
 
37
#ifdef __EMX__
 
38
#include<io.h>
 
39
 
 
40
static int _os2_is_abs_path(const char *dirname);
 
41
static char* _os2_unixroot(const char *path);
 
42
static const char* _os2_unixroot_path(const char *path);
 
43
#endif
35
44
 
36
45
#ifdef __MINGW32__
37
 
 
38
46
#ifdef HAVE_SOCKETS
39
47
#include <socket.h>
40
48
 
50
58
 
51
59
#define WIN32_LEAN_AND_MEAN
52
60
#include <windows.h>
 
61
#endif
53
62
 
54
63
/* gawk_name --- pull out the "gawk" part from how the OS called us */
55
64
 
56
 
const char *
 
65
char *
57
66
gawk_name(filespec)
58
67
const char *filespec;
59
68
{
73
82
}
74
83
 
75
84
 
 
85
/*
 
86
 * memcpy_long() & memset_ulong() are 32-bit replacements for MSC which
 
87
 * has a 16-bit size_t.
 
88
 */
 
89
char *
 
90
memcpy_ulong (dest, src, l)
 
91
register char *dest;
 
92
register const char *src;
 
93
register unsigned long l;
 
94
{
 
95
        register char *ret = dest;
 
96
 
 
97
        while (l--)
 
98
                *dest++ = *src++;
 
99
 
 
100
        return ret;
 
101
}
 
102
 
 
103
 
 
104
void *
 
105
memset_ulong(dest, val, l)
 
106
void *dest;
 
107
register int val;
 
108
register unsigned long l;
 
109
{
 
110
        register char *ret = dest;
 
111
        register char *d = dest;
 
112
 
 
113
        while (l--)
 
114
                *d++ = val;
 
115
 
 
116
        return ((void *) ret);
 
117
}
 
118
 
 
119
 
76
120
/* os_arg_fixup --- fixup the command line */
77
121
 
78
122
void
80
124
int *argcp;
81
125
char ***argvp;
82
126
{
 
127
#ifdef __EMX__
 
128
# ifdef initialize_main
 
129
        initialize_main(argcp, argvp);
 
130
# else
 
131
        _wildcard(argcp, argvp);
 
132
        _response(argcp, argvp);
 
133
# endif
 
134
 
 
135
        setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
 
136
        defpath = (char*) _os2_unixroot_path(defpath);
 
137
#endif /* __EMX__ */
83
138
        return;
84
139
}
85
140
 
90
145
const char *name;
91
146
int flag;
92
147
{
 
148
#ifdef __EMX__
 
149
        /* do not use open(name, flag) here !!! */
 
150
        return -1;
 
151
#else
93
152
        if (strcmp(name, "/dev/null") == 0)
94
153
                return open("NUL", flag);
95
154
        /* FIXME: */
97
156
         *      return open("???", flag);
98
157
         */
99
158
        return -1;
 
159
#endif
100
160
}
101
161
 
102
162
/* optimal_bufsize --- determine optimal buffer size */
106
166
int fd;
107
167
struct stat *stb;
108
168
{
 
169
        /* force all members to zero in case OS doesn't use all of them. */
 
170
        memset(stb, '\0', sizeof(struct stat));
 
171
 
109
172
        /*
110
173
         * DOS doesn't have the file system block size in the
111
174
         * stat structure. So we have to make some sort of reasonable
114
177
         */
115
178
#define DEFBLKSIZE      BUFSIZ
116
179
 
117
 
        if (S_ISDIR(stb->st_mode))
118
 
                return DEFBLKSIZE;
119
 
 
120
 
        /* force all members to zero in case OS doesn't use all of them. */
121
 
        memset(stb, '\0', sizeof(struct stat));
122
 
 
123
180
        if (fstat(fd, stb) == -1)
124
181
                fatal("can't stat fd %d (%s)", fd, strerror(errno));
125
182
        if (S_ISREG(stb->st_mode)
134
191
ispath(file)
135
192
const char *file;
136
193
{
 
194
#ifdef __EMX__
 
195
        return (strpbrk(file, "/\\") != NULL ||
 
196
                (toupper(file[0]) >= 'A' && toupper(file[0]) <= 'Z' && file[1] == ':'));
 
197
#else
137
198
        for (; *file; file++) {
138
199
                switch (*file) {
139
200
                case '/':
143
204
                }
144
205
        }
145
206
        return 0;
 
207
#endif
146
208
}
147
209
 
148
210
/* isdirpunct --- return true if char is a directory separator */
161
223
int fd;
162
224
const char *name, *what, *dir;
163
225
{
 
226
#if (defined(__DJGPP__) && (__DJGPP__ > 2 || __DJGPP_MINOR__ >= 4)) || defined __EMX__
 
227
        if (fd <= 2)    /* sanity */
 
228
                return;
 
229
 
 
230
        if (fcntl(fd, F_SETFD, 1) < 0)
 
231
                warning("%s %s `%s': could not set close-on-exec: %s",
 
232
                        what, dir, name, strerror(errno));
 
233
#endif
 
234
#ifdef __MINGW32__
164
235
        HANDLE fh = (HANDLE)_get_osfhandle(fd);
165
236
 
166
237
        if (fh && fh != INVALID_HANDLE_VALUE)
167
238
                SetHandleInformation(fh, HANDLE_FLAG_INHERIT, 0);
 
239
#endif
168
240
}
169
241
 
170
242
/* os_isdir --- is this an fd on a directory? */
212
284
int
213
285
os_is_setuid()
214
286
{
 
287
#ifdef __EMX__
 
288
        long uid, euid;
 
289
 
 
290
        uid = getuid();
 
291
        euid = geteuid();
 
292
 
 
293
        return (euid == 0 && euid != uid);
 
294
#else
215
295
        return 0;
 
296
#endif
216
297
}
217
298
 
218
299
/* os_setbinmode --- set binary mode on file */
219
300
 
 
301
#ifdef __DJGPP__
 
302
#include <sys/exceptn.h>
 
303
#endif
220
304
static int orig_tty_mode = -1;
221
305
 
222
306
int
225
309
{
226
310
        int prev_mode = setmode(fd, mode);
227
311
 
 
312
#ifdef __DJGPP__
 
313
        if ((mode & O_BINARY) != 0)
 
314
                __djgpp_set_ctrl_c(1); /* allow to interrupt with Ctrl-C */
 
315
#endif
228
316
        /* Save the original tty mode as we found it.  */
229
317
        if (orig_tty_mode == -1 && fd >= 0 && fd <= 2)
230
318
                orig_tty_mode = prev_mode;
247
335
int
248
336
os_isatty(int fd)
249
337
{
 
338
#if defined(__MINGW32__) || defined(_MSC_VER)
250
339
        return (isatty(fd) && lseek(fd, SEEK_CUR, 0) == -1);
 
340
#else
 
341
        return isatty(fd);
 
342
#endif
251
343
}
252
344
 
253
345
/* files_are_same --- return true if files are identical */
285
377
        return 0;
286
378
}
287
379
 
 
380
 
 
381
#ifdef __EMX__ 
 
382
# ifndef PATH_SEPARATOR
 
383
#  define PATH_SEPARATOR ';'
 
384
# endif
 
385
 
 
386
/* result is 0 if dirname is no absolute path, 1 otherwise */
 
387
 
 
388
static int
 
389
_os2_is_abs_path(const char *dirname)
 
390
{
 
391
  int result = 0;
 
392
  if (dirname != NULL && dirname[0] != '\0') {
 
393
    /* if dirname contains a valid drive letter like "c:" */
 
394
    if (((dirname[0] >= 'A' && dirname[0] <= 'Z') || (dirname[0] >= 'a' && dirname[0] <= 'z'))
 
395
        && dirname[1] == ':') dirname += 2; /* remove the drive letter */
 
396
 
 
397
    if (dirname[0] == '/' || dirname[0] == '\\') result = 1; /* asbolute path */
 
398
  }
 
399
 
 
400
  return result;
 
401
}
 
402
 
 
403
 
 
404
/* path is assumed to be a list of directories separated by PATH_SEPARATOR.
 
405
   This function determines if the first directory of path is on the
 
406
   drive specified by the environment variable UNIXROOT.
 
407
   If it is the case, NULL is returned, otherwise a new directory name
 
408
   is allocated using the drive letter from UNIXROOT and returned as result.
 
409
   If the first directory is a relative path NULL is returned, too.
 
410
   The new directory name is allocated by malloc().
 
411
   Example (UNIXROOT is set to "e:"):
 
412
     "c:/usr/share" -> "e:/usr/share"
 
413
     "e:/usr/share" -> NULL             (already on the $UNIXROOT drive)
 
414
     "/usr/share"   -> "e:/usr/share"
 
415
     "."            -> NULL             (not an absolute path)
 
416
     "usr/share"    -> NULL             (not an absolute path)
 
417
     "c:usr/share"  -> NULL             (not an absolute path)
 
418
     "c:/usr/share;d:/etc" -> "e:/usr/share" (only the first directory in path is used) */
 
419
 
 
420
static char*
 
421
_os2_unixroot(const char *path)
 
422
{
 
423
  static const char *unixroot = NULL;
 
424
  static int unixroot_init = 0; 
 
425
  char *result = NULL; 
 
426
 
 
427
  if (unixroot_init == 0) {
 
428
    /* get $UNIXROOT only one time */
 
429
    unixroot = getenv("UNIXROOT");
 
430
 
 
431
    /* check whether unixroot is valid (must be "x:") */
 
432
    if (unixroot != NULL) {
 
433
      int drive = toupper(unixroot[0]);
 
434
      if (drive < 'A' || drive > 'Z' || unixroot[1] != ':' || unixroot[2] != '\0')
 
435
        unixroot = NULL; /* unixroot not valid */
 
436
    }
 
437
 
 
438
    unixroot_init = 1; /* initialized */
 
439
  }
 
440
 
 
441
  /* note: if unixroot != NULL then it contains a valid drive letter */
 
442
  if (unixroot != NULL && _os2_is_abs_path(path)) {
 
443
    /* dirname is an absolute path and unixroot is a drive letter, "c:" for example */
 
444
    size_t old_path_len = strlen(path);
 
445
 
 
446
    /* end points to the first ';' in path or to NULL */
 
447
    const char *end = strchr(path, PATH_SEPARATOR);
 
448
 
 
449
    /* dir_len is the length of the first directory in path */
 
450
    size_t dir_len = (end) ? end - path : old_path_len;
 
451
 
 
452
    if (toupper(unixroot[0]) != toupper(path[0]) || path[1] != ':') {
 
453
      /* the first directory of path does not start with the string $UNIXROOT */
 
454
      if (path[1] == ':') {
 
455
        /* if there is a drive letter remove it */
 
456
        dir_len -= 2;
 
457
        path += 2;
 
458
      } 
 
459
 
 
460
      result = malloc(dir_len + 3);
 
461
      if (result) { /* do nothing if we are out of memory */
 
462
        result[0] = unixroot[0];
 
463
        result[1] = unixroot[1];
 
464
        memcpy(result + 2, path, dir_len);
 
465
        result[dir_len + 2] = '\0';
 
466
      }
 
467
    }
 
468
  }
 
469
  return result;
 
470
}
 
471
 
 
472
/* path is assumed to be a list of directories separated by PATH_SEPARATOR.
 
473
   Every directory is processed. _os2_unixroot() is used to find out whether
 
474
   these directories are on the drive specified by the environment variable
 
475
   UNIXROOT. If this is not the case the same directory on the UNIXROOT drive
 
476
   is added to the end of path. If path is a valid path this function returns a valid path, too.
 
477
   Example ($UNIXROOT is set to "e:"):
 
478
   ".;c:/usr/local;d:/usr/local;d:/etc;e:/etc"
 
479
   -> ".;c:/usr/local;d:/usr/local;d:/etc;e:/etc;e:/usr/local;e:/usr/local;e:/etc" */
 
480
 
 
481
static const char*
 
482
_os2_unixroot_path(const char *path)
 
483
{
 
484
  char *result = NULL;
 
485
  const char *p = path;
 
486
  unsigned dir_count = 1;
 
487
 
 
488
  if (path == NULL || path[0] == '\0') return NULL; /* empty path */
 
489
 
 
490
  /* save number of path components in dir_count */
 
491
  while(*p) {
 
492
    if (*p++ == PATH_SEPARATOR && *p != '\0' && *p != PATH_SEPARATOR)
 
493
      dir_count += 1;
 
494
  }
 
495
 
 
496
  {
 
497
    const char *list[dir_count]; /* list of char pointers */
 
498
    size_t dir_len[dir_count]; /* the according directory length */
 
499
    size_t old_path_len = strlen(path); /* the old path length */
 
500
    size_t total_len;
 
501
    unsigned i = 0;
 
502
 
 
503
    if (path[old_path_len - 1] == PATH_SEPARATOR) /* last character is ';' */
 
504
      old_path_len--;
 
505
 
 
506
    list[0] = p = path; /* first directory */
 
507
 
 
508
    while(*p) {
 
509
    if (*p++ == PATH_SEPARATOR && *p != '\0' && *p != PATH_SEPARATOR)
 
510
      list[++i] = p;
 
511
    }
 
512
    /* now list[i] contains the ith directory of path (no 0-terminated strings!!!) */
 
513
 
 
514
    /* determine the total length for the new path */
 
515
    total_len = old_path_len;
 
516
 
 
517
    for(i = 0; i < dir_count; i++) {
 
518
      list[i] = _os2_unixroot(list[i]);
 
519
      if (list[i] != NULL) {
 
520
        dir_len[i] = strlen(list[i]);
 
521
        total_len += dir_len[i] + 1; /* one character for ';' or '\0' */
 
522
      }
 
523
      else dir_len[i] = 0;
 
524
    }
 
525
    /* now list[] contains the according directories on the UNIXROOT drive or NULL
 
526
       total_len contains the total length for the new path */
 
527
    result = malloc(total_len + 1);
 
528
 
 
529
    if (result) {
 
530
      /* copy the old path and the new directories into the new path */
 
531
      char *q = result;
 
532
      memcpy(q, path, old_path_len);
 
533
      q += old_path_len;
 
534
 
 
535
      for(i = 0; i < dir_count; i++) {
 
536
        if (dir_len[i] != 0) {
 
537
          *q++ = PATH_SEPARATOR;
 
538
          memcpy(q, list[i], dir_len[i]);
 
539
          q += dir_len[i];
 
540
        }
 
541
      }
 
542
 
 
543
      *q = '\0'; /* terminating '\0' */
 
544
    }
 
545
 
 
546
    for(i = 0; i < dir_count; i++) free((void*) list[i]);
 
547
  }
 
548
 
 
549
  return (result) ? (const char*) result : path;
 
550
}
 
551
#endif /* __EMX__ */
 
552
 
 
553
#ifdef __MINGW32__
 
554
 
288
555
extern void *xmalloc (size_t);
289
556
 
290
 
/* Emulate setenv and unsetenv.
291
 
 
292
 
   Note: this is only actually used in MinGW64 builds, since
293
 
   mingw.org's MinGW has these functions as inlines in stdlib.h since
294
 
   mingwrt-5.0.  */
295
557
int
296
558
setenv (const char *name, const char *value, int rewrite)
297
559
{
322
584
  return setenv (name, "", 1);
323
585
}
324
586
 
325
 
/* MinGW 3.21 and later defines usleep as an inline function in
326
 
   unistd.h, which conflicts with the version below.  */
327
 
#if __MINGW32_MAJOR_VERSION + (__MINGW32_MINOR_VERSION > 20) < 4
328
587
int
329
588
usleep(unsigned int usec)
330
589
{
334
593
 
335
594
  return usec - msecf * 1000 < 0 ? 0 : (int)(usec - msecf * 1000);
336
595
}
337
 
#endif
338
596
 
339
597
/* The implementation of wctob in the MS runtime is problematic
340
598
   because it doesn't allow to distinguish between WEOF and 0xff, due
358
616
  return EOF;
359
617
}
360
618
 
361
 
 
362
 
#undef setlocale
363
 
#include <locale.h>
364
 
 
365
 
/* On Posix systems, 'setlocale' looks at LC_* variables in the
366
 
   environment, and Gawk users might expect that on Windows as well.
367
 
   The replacement implementation below does that, and also fixes a
368
 
   few additional quirks with locales on Windows.  */
369
 
static const char *
370
 
lc_var (int category)
371
 
{
372
 
  static const char *loc_name[LC_MAX - LC_MIN + 1] = {
373
 
    "LC_ALL", "LC_COLLATE", "LC_CTYPE", "LC_MONETARY", "LC_NUMERIC", "LC_TIME"
374
 
  };
375
 
 
376
 
  /* This function assumes LC_* categories are small numbers between 0
377
 
     and 5, as shown above, so if that changes at some point, complain
378
 
     vociferously.  */
379
 
  if (LC_ALL != 0 || LC_CTYPE != 2 || LC_TIME != 5)
380
 
    abort ();
381
 
  /* Ensured by the caller, so should never happen.  */
382
 
  if (category < LC_MIN || category > LC_MAX)
383
 
    return "????";
384
 
  return loc_name[category];
385
 
}
386
 
 
387
 
char *
388
 
w32_setlocale (int category, const char *value)
389
 
{
390
 
  const char *new_locale = value;
391
 
 
392
 
  if (LC_MIN <= category && category <= LC_MAX
393
 
      && value && *value == '\0')
394
 
    {
395
 
      const char *lc_val = getenv ("LC_ALL");
396
 
 
397
 
      if (!lc_val)
398
 
        lc_val = getenv (lc_var (category));
399
 
      if (!lc_val)
400
 
        lc_val = getenv ("LANG");
401
 
      if (lc_val)
402
 
        new_locale = lc_val;
403
 
    }
404
 
 
405
 
  /* If VALUE includes a codeset, i.e. a Windows codepage number, we
406
 
     must also set the LC_CTYPE locale to the same value, because
407
 
     LC_CTYPE is the only category which is documented to be able to
408
 
     change the codepage.  */
409
 
  if (category != LC_ALL && category != LC_CTYPE)
410
 
    {
411
 
      const char *p = strchr (new_locale, '.');
412
 
 
413
 
      if (p && isdigit (p[1]))
414
 
        setlocale (LC_CTYPE, new_locale);
415
 
    }
416
 
  return setlocale (category, new_locale);
417
 
}
418
 
 
419
 
/* Replacement for the missing nl_langinfo.  Only CODESET is currently
420
 
   supported.  */
421
 
#include <langinfo.h>
422
 
 
423
 
char *
424
 
nl_langinfo (int item)
425
 
{
426
 
  switch (item)
427
 
    {
428
 
      case CODESET:
429
 
        {
430
 
          /* Shamelessly stolen from Gnulib's nl_langinfo.c.  */
431
 
          static char buf[2 + 10 + 1];
432
 
          char const *locale = setlocale (LC_CTYPE, NULL);
433
 
          char *codeset = buf;
434
 
          size_t codesetlen;
435
 
          codeset[0] = '\0';
436
 
 
437
 
          if (locale && locale[0])
438
 
            {
439
 
              /* If the locale name contains an encoding after the
440
 
                 dot, return it.  */
441
 
              char *dot = strchr (locale, '.');
442
 
 
443
 
              if (dot)
444
 
                {
445
 
                  /* Look for the possible @... trailer and remove it,
446
 
                     if any.  */
447
 
                  char *codeset_start = dot + 1;
448
 
                  char const *modifier = strchr (codeset_start, '@');
449
 
 
450
 
                  if (! modifier)
451
 
                    codeset = codeset_start;
452
 
                  else
453
 
                    {
454
 
                      codesetlen = modifier - codeset_start;
455
 
                      if (codesetlen < sizeof buf)
456
 
                        {
457
 
                          codeset = memcpy (buf, codeset_start, codesetlen);
458
 
                          codeset[codesetlen] = '\0';
459
 
                        }
460
 
                    }
461
 
                }
462
 
            }
463
 
          /* If setlocale is successful, it returns the number of the
464
 
             codepage, as a string.  Otherwise, fall back on Windows
465
 
             API GetACP, which returns the locale's codepage as a
466
 
             number (although this doesn't change according to what
467
 
             the 'setlocale' call specified).  Either way, prepend
468
 
             "CP" to make it a valid codeset name.  */
469
 
          codesetlen = strlen (codeset);
470
 
          if (0 < codesetlen && codesetlen < sizeof buf - 2)
471
 
            memmove (buf + 2, codeset, codesetlen + 1);
472
 
          else
473
 
            sprintf (buf + 2, "%u", GetACP ());
474
 
          codeset = memcpy (buf, "CP", 2);
475
 
 
476
 
          return codeset;
477
 
        }
478
 
      default:
479
 
        return (char *) "";
480
 
    }
481
 
}
482
 
 
483
 
/* Convert a Unicode codepoint UC to the corresponding multibyte string
484
 
   STR in the current system codepage.  Return the number of bytes in
485
 
   STR, or -1 if the codepage does not support UC.  */
486
 
size_t w32_wc_to_lc (int uc, char *str)
487
 
{
488
 
  BOOL used_default = FALSE;
489
 
  wchar_t wc[3];
490
 
  int retval;
491
 
 
492
 
  if (uc > 0x10FFFF)
493
 
    return (size_t) -1;
494
 
 
495
 
  /* Convert UC to UTF-16.  */
496
 
  wc[1] = wc[2] = 0;
497
 
  if (uc < 0x10000)
498
 
    wc[0] = uc;
499
 
  else
500
 
    {
501
 
      wc[0] = ((uc - 0x10000) >> 10) + 0xD800; /* high surrogate */
502
 
      wc[1] = (uc & 0x3FF) + 0xDC00;           /* low surrogate */
503
 
    }
504
 
  /* WideCharToMultiByte returns the number of bytes, including the
505
 
     terminating null, written to STR on success, zero on falure.  */
506
 
  retval = WideCharToMultiByte (CP_ACP, 0, wc, -1,
507
 
                                str, MB_LEN_MAX, NULL, &used_default);
508
 
  if (!retval || used_default)
509
 
    return (size_t) -1;
510
 
  return retval - 1;    /* exclude the terminating null */
511
 
}
512
 
 
513
619
/*
514
620
 * On MS-Windows with MinGW, execvp causes the shell and the re-exec'ed
515
621
 * dgawk to compete for the keyboard input.
516
622
 *
517
623
 * This will need work if we ever need a real version of execvp.
518
624
 */
519
 
int w32_execvp(const char *file, char **argv)
 
625
int execvp(const char *file, const char *const *argv)
520
626
{
521
627
        if (_spawnvp(_P_WAIT, file, (const char * const *)argv) != -1)
522
628
                exit(EXIT_SUCCESS);
526
632
 
527
633
#ifdef DYNAMIC
528
634
 
529
 
#include <winerror.h>
530
635
#include <dlfcn.h>
531
636
 
532
637
static DWORD last_err;
743
848
 
744
849
#endif  /* HAVE_SOCKETS */
745
850
 
746
 
/* Translate abnormal exit status of Windows programs into the signal
747
 
   that terminated the program.  This is required to support scm_kill
748
 
   and WTERMSIG.  */
749
 
 
750
 
#include <signal.h>
751
 
 
752
 
struct signal_and_status {
753
 
  int sig;
754
 
  unsigned status;
755
 
};
756
 
 
757
 
static const struct signal_and_status sigtbl[] = {
758
 
  {SIGSEGV, 0xC0000005},        /* access to invalid address */
759
 
  {SIGSEGV, 0xC0000008},        /* invalid handle */
760
 
  {SIGILL,  0xC000001D},        /* illegal instruction */
761
 
  {SIGILL,  0xC0000025},        /* non-continuable instruction */
762
 
  {SIGSEGV, 0xC000008C},        /* array bounds exceeded */
763
 
  {SIGFPE,  0xC000008D},        /* float denormal */
764
 
  {SIGFPE,  0xC000008E},        /* float divide by zero */
765
 
  {SIGFPE,  0xC000008F},        /* float inexact */
766
 
  {SIGFPE,  0xC0000090},        /* float invalid operation */
767
 
  {SIGFPE,  0xC0000091},        /* float overflow */
768
 
  {SIGFPE,  0xC0000092},        /* float stack check */
769
 
  {SIGFPE,  0xC0000093},        /* float underflow */
770
 
  {SIGFPE,  0xC0000094},        /* integer divide by zero */
771
 
  {SIGFPE,  0xC0000095},        /* integer overflow */
772
 
  {SIGILL,  0xC0000096},        /* privileged instruction */
773
 
  {SIGSEGV, 0xC00000FD},        /* stack overflow */
774
 
  {SIGTERM, 0xC000013A},        /* Ctrl-C exit */
775
 
  {SIGINT,  0xC000013A}
776
 
};
777
 
 
778
 
int
779
 
w32_status_to_termsig (unsigned status)
780
 
{
781
 
  int i;
782
 
 
783
 
  for (i = 0; i < sizeof (sigtbl) / sizeof (sigtbl[0]); i++)
784
 
    if (status == sigtbl[i].status)
785
 
      return sigtbl[i].sig;
786
 
 
787
 
  return SIGTERM;
788
 
}
789
 
 
790
 
/* Emulate the missing strsignal.  */
791
 
char *
792
 
strsignal (int signo)
793
 
{
794
 
  switch (signo)
795
 
    {
796
 
      case SIGINT:
797
 
        return "SIGINT";
798
 
      case SIGILL:
799
 
        return "SIGILL";
800
 
      case SIGFPE:
801
 
        return "SIGFPE";
802
 
      case SIGSEGV:
803
 
        return "SIGSEGV";
804
 
      case SIGTERM:
805
 
        return "SIGTERM";
806
 
      case SIGBREAK:
807
 
        return "SIGBREAK";
808
 
      case SIGABRT:
809
 
        return "SIGABRT";
810
 
      default:
811
 
        return "Unknown signal";
812
 
    }
813
 
}
814
 
 
815
 
void
816
 
os_maybe_set_errno (void)
817
 
{
818
 
  if (errno == 0 || errno == EINVAL) {
819
 
    DWORD w32err = GetLastError ();
820
 
 
821
 
    switch (w32err)
822
 
      {
823
 
        /* When stdout is redirected to a pipe, and the program that
824
 
         reads the pipe (e.g., a pager) exits, Windows doesn't set
825
 
         errno to a useful value.  Help it DTRT.  */
826
 
        case ERROR_BAD_PIPE:
827
 
        case ERROR_PIPE_BUSY:
828
 
        case ERROR_NO_DATA:
829
 
        case ERROR_PIPE_NOT_CONNECTED:
830
 
        errno = EPIPE;
831
 
        break;
832
 
        default:
833
 
        errno = EINVAL;
834
 
        break;
835
 
      }
836
 
  }
837
 
}
 
851
#endif  /* __MINGW32__ */
 
852
 
 
853
#if defined(__DJGPP__) || defined(__MINGW32__)
838
854
 
839
855
void
840
856
init_sockets(void)
841
857
{
842
 
#if defined(HAVE_SOCKETS)
 
858
#ifdef HAVE_SOCKETS
843
859
  WSADATA  winsockData;
844
860
  int errcode;
845
861
 
849
865
#endif
850
866
}
851
867
 
852
 
#endif  /* __MINGW32__ */
 
868
#endif  /* __DJGPP__ || __MINGW32__ */
 
869
 
 
870
#ifdef __DJGPP__
 
871
 
 
872
int
 
873
unsetenv (const char *name)
 
874
{
 
875
  if (!name || !*name || strchr (name, '=') != NULL)
 
876
    return -1;
 
877
 
 
878
  return putenv (name);
 
879
}
 
880
 
 
881
/* This is needed to defeat too-clever GCC warnings in dfa.c about
 
882
   comparison being always false due to limited range of data type.  */
 
883
wint_t
 
884
btowc (int c)
 
885
{
 
886
  return c;
 
887
}
 
888
 
 
889
#endif /* __DJGPP__ */