os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/win/nmakehlp.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
 * ----------------------------------------------------------------------------
sl@0
     3
 * nmakehlp.c --
sl@0
     4
 *
sl@0
     5
 *	This is used to fix limitations within nmake and the environment.
sl@0
     6
 *
sl@0
     7
 * Copyright (c) 2002 by David Gravereaux.
sl@0
     8
 *
sl@0
     9
 * See the file "license.terms" for information on usage and redistribution
sl@0
    10
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
sl@0
    11
 *
sl@0
    12
 * ----------------------------------------------------------------------------
sl@0
    13
 * RCS: @(#) $Id: nmakehlp.c,v 1.1.4.4 2006/10/18 08:49:33 patthoyts Exp $
sl@0
    14
 * ----------------------------------------------------------------------------
sl@0
    15
 */
sl@0
    16
sl@0
    17
#define _CRT_SECURE_NO_DEPRECATE
sl@0
    18
#include <windows.h>
sl@0
    19
#pragma comment (lib, "user32.lib")
sl@0
    20
#pragma comment (lib, "kernel32.lib")
sl@0
    21
#include <stdio.h>
sl@0
    22
#include <math.h>
sl@0
    23
#if defined(_M_IA64) || defined(_M_AMD64)
sl@0
    24
#pragma comment(lib, "bufferoverflowU")
sl@0
    25
#endif
sl@0
    26
sl@0
    27
/* ISO hack for dumb VC++ */
sl@0
    28
#ifdef _MSC_VER
sl@0
    29
#define   snprintf	_snprintf
sl@0
    30
#endif
sl@0
    31
sl@0
    32
sl@0
    33
sl@0
    34
/* protos */
sl@0
    35
sl@0
    36
int		CheckForCompilerFeature(const char *option);
sl@0
    37
int		CheckForLinkerFeature(const char *option);
sl@0
    38
int		IsIn(const char *string, const char *substring);
sl@0
    39
int		GrepForDefine(const char *file, const char *string);
sl@0
    40
DWORD WINAPI	ReadFromPipe(LPVOID args);
sl@0
    41
sl@0
    42
/* globals */
sl@0
    43
sl@0
    44
#define CHUNK	25
sl@0
    45
#define STATICBUFFERSIZE    1000
sl@0
    46
typedef struct {
sl@0
    47
    HANDLE pipe;
sl@0
    48
    char buffer[STATICBUFFERSIZE];
sl@0
    49
} pipeinfo;
sl@0
    50
sl@0
    51
pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
sl@0
    52
pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
sl@0
    53

sl@0
    54
/*
sl@0
    55
 * exitcodes: 0 == no, 1 == yes, 2 == error
sl@0
    56
 */
sl@0
    57
sl@0
    58
int
sl@0
    59
main(
sl@0
    60
    int argc,
sl@0
    61
    char *argv[])
sl@0
    62
{
sl@0
    63
    char msg[300];
sl@0
    64
    DWORD dwWritten;
sl@0
    65
    int chars;
sl@0
    66
sl@0
    67
    /*
sl@0
    68
     * Make sure children (cl.exe and link.exe) are kept quiet.
sl@0
    69
     */
sl@0
    70
sl@0
    71
    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
sl@0
    72
sl@0
    73
    /*
sl@0
    74
     * Make sure the compiler and linker aren't effected by the outside world.
sl@0
    75
     */
sl@0
    76
sl@0
    77
    SetEnvironmentVariable("CL", "");
sl@0
    78
    SetEnvironmentVariable("LINK", "");
sl@0
    79
sl@0
    80
    if (argc > 1 && *argv[1] == '-') {
sl@0
    81
	switch (*(argv[1]+1)) {
sl@0
    82
	case 'c':
sl@0
    83
	    if (argc != 3) {
sl@0
    84
		chars = snprintf(msg, sizeof(msg) - 1,
sl@0
    85
		        "usage: %s -c <compiler option>\n"
sl@0
    86
			"Tests for whether cl.exe supports an option\n"
sl@0
    87
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
sl@0
    88
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
sl@0
    89
			&dwWritten, NULL);
sl@0
    90
		return 2;
sl@0
    91
	    }
sl@0
    92
	    return CheckForCompilerFeature(argv[2]);
sl@0
    93
	case 'l':
sl@0
    94
	    if (argc != 3) {
sl@0
    95
		chars = snprintf(msg, sizeof(msg) - 1,
sl@0
    96
	       		"usage: %s -l <linker option>\n"
sl@0
    97
			"Tests for whether link.exe supports an option\n"
sl@0
    98
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
sl@0
    99
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
sl@0
   100
			&dwWritten, NULL);
sl@0
   101
		return 2;
sl@0
   102
	    }
sl@0
   103
	    return CheckForLinkerFeature(argv[2]);
sl@0
   104
	case 'f':
sl@0
   105
	    if (argc == 2) {
sl@0
   106
		chars = snprintf(msg, sizeof(msg) - 1,
sl@0
   107
			"usage: %s -f <string> <substring>\n"
sl@0
   108
			"Find a substring within another\n"
sl@0
   109
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
sl@0
   110
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
sl@0
   111
			&dwWritten, NULL);
sl@0
   112
		return 2;
sl@0
   113
	    } else if (argc == 3) {
sl@0
   114
		/*
sl@0
   115
		 * If the string is blank, there is no match.
sl@0
   116
		 */
sl@0
   117
sl@0
   118
		return 0;
sl@0
   119
	    } else {
sl@0
   120
		return IsIn(argv[2], argv[3]);
sl@0
   121
	    }
sl@0
   122
	case 'g':
sl@0
   123
	    if (argc == 2) {
sl@0
   124
		chars = snprintf(msg, sizeof(msg) - 1,
sl@0
   125
			"usage: %s -g <file> <string>\n"
sl@0
   126
			"grep for a #define\n"
sl@0
   127
			"exitcodes: integer of the found string (no decimals)\n",
sl@0
   128
			argv[0]);
sl@0
   129
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
sl@0
   130
			&dwWritten, NULL);
sl@0
   131
		return 2;
sl@0
   132
	    }
sl@0
   133
	    return GrepForDefine(argv[2], argv[3]);
sl@0
   134
	}
sl@0
   135
    }
sl@0
   136
    chars = snprintf(msg, sizeof(msg) - 1,
sl@0
   137
	    "usage: %s -c|-l|-f ...\n"
sl@0
   138
	    "This is a little helper app to equalize shell differences between WinNT and\n"
sl@0
   139
	    "Win9x and get nmake.exe to accomplish its job.\n",
sl@0
   140
	    argv[0]);
sl@0
   141
    WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
sl@0
   142
    return 2;
sl@0
   143
}
sl@0
   144

sl@0
   145
int
sl@0
   146
CheckForCompilerFeature(
sl@0
   147
    const char *option)
sl@0
   148
{
sl@0
   149
    STARTUPINFO si;
sl@0
   150
    PROCESS_INFORMATION pi;
sl@0
   151
    SECURITY_ATTRIBUTES sa;
sl@0
   152
    DWORD threadID;
sl@0
   153
    char msg[300];
sl@0
   154
    BOOL ok;
sl@0
   155
    HANDLE hProcess, h, pipeThreads[2];
sl@0
   156
    char cmdline[100];
sl@0
   157
sl@0
   158
    hProcess = GetCurrentProcess();
sl@0
   159
sl@0
   160
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
sl@0
   161
    ZeroMemory(&si, sizeof(STARTUPINFO));
sl@0
   162
    si.cb = sizeof(STARTUPINFO);
sl@0
   163
    si.dwFlags   = STARTF_USESTDHANDLES;
sl@0
   164
    si.hStdInput = INVALID_HANDLE_VALUE;
sl@0
   165
sl@0
   166
    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
sl@0
   167
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sl@0
   168
    sa.lpSecurityDescriptor = NULL;
sl@0
   169
    sa.bInheritHandle = FALSE;
sl@0
   170
sl@0
   171
    /*
sl@0
   172
     * Create a non-inheritible pipe.
sl@0
   173
     */
sl@0
   174
sl@0
   175
    CreatePipe(&Out.pipe, &h, &sa, 0);
sl@0
   176
sl@0
   177
    /*
sl@0
   178
     * Dupe the write side, make it inheritible, and close the original.
sl@0
   179
     */
sl@0
   180
sl@0
   181
    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
sl@0
   182
	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
sl@0
   183
sl@0
   184
    /*
sl@0
   185
     * Same as above, but for the error side.
sl@0
   186
     */
sl@0
   187
sl@0
   188
    CreatePipe(&Err.pipe, &h, &sa, 0);
sl@0
   189
    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
sl@0
   190
	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
sl@0
   191
sl@0
   192
    /*
sl@0
   193
     * Base command line.
sl@0
   194
     */
sl@0
   195
sl@0
   196
    lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X ");
sl@0
   197
sl@0
   198
    /*
sl@0
   199
     * Append our option for testing
sl@0
   200
     */
sl@0
   201
sl@0
   202
    lstrcat(cmdline, option);
sl@0
   203
sl@0
   204
    /*
sl@0
   205
     * Filename to compile, which exists, but is nothing and empty.
sl@0
   206
     */
sl@0
   207
sl@0
   208
    lstrcat(cmdline, " .\\nul");
sl@0
   209
sl@0
   210
    ok = CreateProcess(
sl@0
   211
	    NULL,	    /* Module name. */
sl@0
   212
	    cmdline,	    /* Command line. */
sl@0
   213
	    NULL,	    /* Process handle not inheritable. */
sl@0
   214
	    NULL,	    /* Thread handle not inheritable. */
sl@0
   215
	    TRUE,	    /* yes, inherit handles. */
sl@0
   216
	    DETACHED_PROCESS, /* No console for you. */
sl@0
   217
	    NULL,	    /* Use parent's environment block. */
sl@0
   218
	    NULL,	    /* Use parent's starting directory. */
sl@0
   219
	    &si,	    /* Pointer to STARTUPINFO structure. */
sl@0
   220
	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */
sl@0
   221
sl@0
   222
    if (!ok) {
sl@0
   223
	DWORD err = GetLastError();
sl@0
   224
	int chars = snprintf(msg, sizeof(msg) - 1,
sl@0
   225
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
sl@0
   226
sl@0
   227
	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
sl@0
   228
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
sl@0
   229
		(300-chars), 0);
sl@0
   230
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
sl@0
   231
	return 2;
sl@0
   232
    }
sl@0
   233
sl@0
   234
    /*
sl@0
   235
     * Close our references to the write handles that have now been inherited.
sl@0
   236
     */
sl@0
   237
sl@0
   238
    CloseHandle(si.hStdOutput);
sl@0
   239
    CloseHandle(si.hStdError);
sl@0
   240
sl@0
   241
    WaitForInputIdle(pi.hProcess, 5000);
sl@0
   242
    CloseHandle(pi.hThread);
sl@0
   243
sl@0
   244
    /*
sl@0
   245
     * Start the pipe reader threads.
sl@0
   246
     */
sl@0
   247
sl@0
   248
    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
sl@0
   249
    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
sl@0
   250
sl@0
   251
    /*
sl@0
   252
     * Block waiting for the process to end.
sl@0
   253
     */
sl@0
   254
sl@0
   255
    WaitForSingleObject(pi.hProcess, INFINITE);
sl@0
   256
    CloseHandle(pi.hProcess);
sl@0
   257
sl@0
   258
    /*
sl@0
   259
     * Wait for our pipe to get done reading, should it be a little slow.
sl@0
   260
     */
sl@0
   261
sl@0
   262
    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
sl@0
   263
    CloseHandle(pipeThreads[0]);
sl@0
   264
    CloseHandle(pipeThreads[1]);
sl@0
   265
sl@0
   266
    /*
sl@0
   267
     * Look for the commandline warning code in both streams.
sl@0
   268
     *  - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002.
sl@0
   269
     */
sl@0
   270
sl@0
   271
    return !(strstr(Out.buffer, "D4002") != NULL
sl@0
   272
             || strstr(Err.buffer, "D4002") != NULL
sl@0
   273
             || strstr(Out.buffer, "D9002") != NULL
sl@0
   274
             || strstr(Err.buffer, "D9002") != NULL);
sl@0
   275
}
sl@0
   276

sl@0
   277
int
sl@0
   278
CheckForLinkerFeature(
sl@0
   279
    const char *option)
sl@0
   280
{
sl@0
   281
    STARTUPINFO si;
sl@0
   282
    PROCESS_INFORMATION pi;
sl@0
   283
    SECURITY_ATTRIBUTES sa;
sl@0
   284
    DWORD threadID;
sl@0
   285
    char msg[300];
sl@0
   286
    BOOL ok;
sl@0
   287
    HANDLE hProcess, h, pipeThreads[2];
sl@0
   288
    char cmdline[100];
sl@0
   289
sl@0
   290
    hProcess = GetCurrentProcess();
sl@0
   291
sl@0
   292
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
sl@0
   293
    ZeroMemory(&si, sizeof(STARTUPINFO));
sl@0
   294
    si.cb = sizeof(STARTUPINFO);
sl@0
   295
    si.dwFlags   = STARTF_USESTDHANDLES;
sl@0
   296
    si.hStdInput = INVALID_HANDLE_VALUE;
sl@0
   297
sl@0
   298
    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
sl@0
   299
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sl@0
   300
    sa.lpSecurityDescriptor = NULL;
sl@0
   301
    sa.bInheritHandle = TRUE;
sl@0
   302
sl@0
   303
    /*
sl@0
   304
     * Create a non-inheritible pipe.
sl@0
   305
     */
sl@0
   306
sl@0
   307
    CreatePipe(&Out.pipe, &h, &sa, 0);
sl@0
   308
sl@0
   309
    /*
sl@0
   310
     * Dupe the write side, make it inheritible, and close the original.
sl@0
   311
     */
sl@0
   312
sl@0
   313
    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
sl@0
   314
	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
sl@0
   315
sl@0
   316
    /*
sl@0
   317
     * Same as above, but for the error side.
sl@0
   318
     */
sl@0
   319
sl@0
   320
    CreatePipe(&Err.pipe, &h, &sa, 0);
sl@0
   321
    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
sl@0
   322
	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
sl@0
   323
sl@0
   324
    /*
sl@0
   325
     * Base command line.
sl@0
   326
     */
sl@0
   327
sl@0
   328
    lstrcpy(cmdline, "link.exe -nologo ");
sl@0
   329
sl@0
   330
    /*
sl@0
   331
     * Append our option for testing.
sl@0
   332
     */
sl@0
   333
sl@0
   334
    lstrcat(cmdline, option);
sl@0
   335
sl@0
   336
    ok = CreateProcess(
sl@0
   337
	    NULL,	    /* Module name. */
sl@0
   338
	    cmdline,	    /* Command line. */
sl@0
   339
	    NULL,	    /* Process handle not inheritable. */
sl@0
   340
	    NULL,	    /* Thread handle not inheritable. */
sl@0
   341
	    TRUE,	    /* yes, inherit handles. */
sl@0
   342
	    DETACHED_PROCESS, /* No console for you. */
sl@0
   343
	    NULL,	    /* Use parent's environment block. */
sl@0
   344
	    NULL,	    /* Use parent's starting directory. */
sl@0
   345
	    &si,	    /* Pointer to STARTUPINFO structure. */
sl@0
   346
	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */
sl@0
   347
sl@0
   348
    if (!ok) {
sl@0
   349
	DWORD err = GetLastError();
sl@0
   350
	int chars = snprintf(msg, sizeof(msg) - 1,
sl@0
   351
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
sl@0
   352
sl@0
   353
	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
sl@0
   354
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
sl@0
   355
		(300-chars), 0);
sl@0
   356
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
sl@0
   357
	return 2;
sl@0
   358
    }
sl@0
   359
sl@0
   360
    /*
sl@0
   361
     * Close our references to the write handles that have now been inherited.
sl@0
   362
     */
sl@0
   363
sl@0
   364
    CloseHandle(si.hStdOutput);
sl@0
   365
    CloseHandle(si.hStdError);
sl@0
   366
sl@0
   367
    WaitForInputIdle(pi.hProcess, 5000);
sl@0
   368
    CloseHandle(pi.hThread);
sl@0
   369
sl@0
   370
    /*
sl@0
   371
     * Start the pipe reader threads.
sl@0
   372
     */
sl@0
   373
sl@0
   374
    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
sl@0
   375
    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
sl@0
   376
sl@0
   377
    /*
sl@0
   378
     * Block waiting for the process to end.
sl@0
   379
     */
sl@0
   380
sl@0
   381
    WaitForSingleObject(pi.hProcess, INFINITE);
sl@0
   382
    CloseHandle(pi.hProcess);
sl@0
   383
sl@0
   384
    /*
sl@0
   385
     * Wait for our pipe to get done reading, should it be a little slow.
sl@0
   386
     */
sl@0
   387
sl@0
   388
    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
sl@0
   389
    CloseHandle(pipeThreads[0]);
sl@0
   390
    CloseHandle(pipeThreads[1]);
sl@0
   391
sl@0
   392
    /*
sl@0
   393
     * Look for the commandline warning code in the stderr stream.
sl@0
   394
     */
sl@0
   395
sl@0
   396
    return !(strstr(Out.buffer, "LNK1117") != NULL ||
sl@0
   397
             strstr(Err.buffer, "LNK1117") != NULL ||
sl@0
   398
             strstr(Out.buffer, "LNK4044") != NULL ||
sl@0
   399
             strstr(Err.buffer, "LNK4044") != NULL);
sl@0
   400
}
sl@0
   401

sl@0
   402
DWORD WINAPI
sl@0
   403
ReadFromPipe(
sl@0
   404
    LPVOID args)
sl@0
   405
{
sl@0
   406
    pipeinfo *pi = (pipeinfo *) args;
sl@0
   407
    char *lastBuf = pi->buffer;
sl@0
   408
    DWORD dwRead;
sl@0
   409
    BOOL ok;
sl@0
   410
sl@0
   411
  again:
sl@0
   412
    if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {
sl@0
   413
	CloseHandle(pi->pipe);
sl@0
   414
	return (DWORD)-1;
sl@0
   415
    }
sl@0
   416
    ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);
sl@0
   417
    if (!ok || dwRead == 0) {
sl@0
   418
	CloseHandle(pi->pipe);
sl@0
   419
	return 0;
sl@0
   420
    }
sl@0
   421
    lastBuf += dwRead;
sl@0
   422
    goto again;
sl@0
   423
sl@0
   424
    return 0;  /* makes the compiler happy */
sl@0
   425
}
sl@0
   426

sl@0
   427
int
sl@0
   428
IsIn(
sl@0
   429
    const char *string,
sl@0
   430
    const char *substring)
sl@0
   431
{
sl@0
   432
    return (strstr(string, substring) != NULL);
sl@0
   433
}
sl@0
   434

sl@0
   435
/*
sl@0
   436
 * Find a specified #define by name.
sl@0
   437
 *
sl@0
   438
 * If the line is '#define TCL_VERSION "8.5"', it returns 85 as the result.
sl@0
   439
 */
sl@0
   440
sl@0
   441
int
sl@0
   442
GrepForDefine(
sl@0
   443
    const char *file,
sl@0
   444
    const char *string)
sl@0
   445
{
sl@0
   446
    FILE *f;
sl@0
   447
    char s1[51], s2[51], s3[51];
sl@0
   448
    int r = 0;
sl@0
   449
    double d1;
sl@0
   450
sl@0
   451
    f = fopen(file, "rt");
sl@0
   452
    if (f == NULL) {
sl@0
   453
	return 0;
sl@0
   454
    }
sl@0
   455
sl@0
   456
    do {
sl@0
   457
	r = fscanf(f, "%50s", s1);
sl@0
   458
	if (r == 1 && !strcmp(s1, "#define")) {
sl@0
   459
	    /*
sl@0
   460
	     * Get next two words.
sl@0
   461
	     */
sl@0
   462
sl@0
   463
	    r = fscanf(f, "%50s %50s", s2, s3);
sl@0
   464
	    if (r != 2) {
sl@0
   465
		continue;
sl@0
   466
	    }
sl@0
   467
sl@0
   468
	    /*
sl@0
   469
	     * Is the first word what we're looking for?
sl@0
   470
	     */
sl@0
   471
sl@0
   472
	    if (!strcmp(s2, string)) {
sl@0
   473
		fclose(f);
sl@0
   474
sl@0
   475
		/*
sl@0
   476
		 * Add 1 past first double quote char. "8.5"
sl@0
   477
		 */
sl@0
   478
sl@0
   479
		d1 = atof(s3 + 1);		  /*    8.5  */
sl@0
   480
		while (floor(d1) != d1) {
sl@0
   481
		    d1 *= 10.0;
sl@0
   482
		}
sl@0
   483
		return ((int) d1);		  /*    85   */
sl@0
   484
	    }
sl@0
   485
	}
sl@0
   486
    } while (!feof(f));
sl@0
   487
sl@0
   488
    fclose(f);
sl@0
   489
    return 0;
sl@0
   490
}