diff options
Diffstat (limited to 'win32')
| -rw-r--r-- | win32/build-tcc.bat | 31 | ||||
| -rw-r--r-- | win32/tcc-win32.txt | 22 | ||||
| -rw-r--r-- | win32/tools/tiny_impdef.c | 249 | ||||
| -rw-r--r-- | win32/tools/tiny_libmaker.c | 278 |
4 files changed, 23 insertions, 557 deletions
diff --git a/win32/build-tcc.bat b/win32/build-tcc.bat index daf5a12..924e808 100644 --- a/win32/build-tcc.bat +++ b/win32/build-tcc.bat @@ -5,10 +5,6 @@ @echo off setlocal -set VSCOMNTOOLS=%VS150COMNTOOLS% -if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS% -if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS% -if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS% set CC=gcc -Os -s set /p VERSION= < ..\VERSION set INST= @@ -70,10 +66,17 @@ goto :a1 if not (%1)==() goto :usage if not "%CC%"=="@call :cl" goto :p1 +set VSCOMNTOOLS=%VS150COMNTOOLS% +if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS% +if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS% +if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS% if %T%_==32_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\vcvars32.bat" if %T%_==64_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\amd64\vcvars64.bat" if %T%_==_ set T=32& if %Platform%_==X64_ set T=64 +if %CLVARS%_==_ goto :p1 +if exist %CLVARS% call %CLVARS% :p1 + if not %T%_==_ goto :p2 set T=32 if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=64 @@ -97,9 +100,6 @@ set PX=i386-win32 @echo on -@if %CLVARS%_==_ goto :config.h -call %CLVARS% - :config.h echo>..\config.h #define TCC_VERSION "%VERSION%" echo>> ..\config.h #ifdef TCC_TARGET_X86_64 @@ -108,7 +108,7 @@ echo>> ..\config.h #else echo>> ..\config.h #define CONFIG_TCC_LIBPATHS "{B}/lib/32;{B}/lib" echo>> ..\config.h #endif -@del /q *tcc.exe tiny_*.exe *tcc.dll +for %%f in (*tcc.exe *tcc.dll) do @del %%f :compiler %CC% -o libtcc.dll -shared ..\libtcc.c %D% -DONE_SOURCE -DLIBTCC_AS_DLL @@ -116,10 +116,6 @@ echo>> ..\config.h #endif %CC% -o tcc.exe ..\tcc.c libtcc.dll %D% %CC% -o %PX%-tcc.exe ..\tcc.c %DX% -DONE_SOURCE -:tools -%CC% -o tiny_impdef.exe tools\tiny_impdef.c %D% -%CC% -o tiny_libmaker.exe tools\tiny_libmaker.c %D% - @if (%TCC_FILES%)==(no) goto :files-done if not exist libtcc mkdir libtcc @@ -129,12 +125,11 @@ if not exist lib\64 mkdir lib\64 copy>nul ..\include\*.h include copy>nul ..\tcclib.h include copy>nul ..\libtcc.h libtcc -tiny_impdef libtcc.dll -o libtcc\libtcc.def copy>nul ..\tests\libtcc_test.c examples copy>nul tcc-win32.txt doc -copy>nul tiny_libmaker.exe tiny_libmaker-m%T%.exe -%CC% -o tiny_libmaker-m%TX%.exe tools\tiny_libmaker.c %DX% +.\tcc -impdef libtcc.dll -o libtcc\libtcc.def +@if errorlevel 1 goto :the_end :libtcc1.a @set O1=libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o bcheck.o @@ -149,7 +144,7 @@ copy>nul tiny_libmaker.exe tiny_libmaker-m%T%.exe .\tcc -m32 %D32% -w -c ../lib/bcheck.c .\tcc -m32 %D32% -c ../lib/alloca86.S .\tcc -m32 %D32% -c ../lib/alloca86-bt.S -tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o +.\tcc -m32 -ar lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o @if errorlevel 1 goto :the_end .\tcc -m64 %D64% -c ../lib/libtcc1.c .\tcc -m64 %D64% -c lib/crt1.c @@ -162,7 +157,7 @@ tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o .\tcc -m64 %D64% -w -c ../lib/bcheck.c .\tcc -m64 %D64% -c ../lib/alloca86_64.S .\tcc -m64 %D64% -c ../lib/alloca86_64-bt.S -tiny_libmaker-m64 lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o +.\tcc -m64 -ar lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o @if errorlevel 1 goto :the_end :tcc-doc.html @@ -172,7 +167,7 @@ cmd /c makeinfo --html --no-split ../tcc-doc.texi -o doc/tcc-doc.html :doc-done :files-done -@del /q *.o *.def *-m??.exe +for %%f in (*.o *.def) do @del %%f :copy-install @if (%INST%)==() goto :the_end diff --git a/win32/tcc-win32.txt b/win32/tcc-win32.txt index dfcfb1b..3609684 100644 --- a/win32/tcc-win32.txt +++ b/win32/tcc-win32.txt @@ -39,7 +39,7 @@ For the 'Hello DLL' example type tcc -shared dll.c - tiny_impdef dll.dll (optional) + tcc -impdef dll.dll (optional) tcc hello_dll.c dll.def @@ -66,10 +66,10 @@ To link with Windows system DLLs, TCC uses import definition files (.def) instead of libraries. - The included 'tiny_impdef' program may be used to make additional - .def files for any DLL. For example: + The now built-in 'tiny_impdef' program may be used to make + additional .def files for any DLL. For example - tiny_impdef.exe opengl32.dll + tcc -impdef [-v] opengl32.dll [-o opengl32.def] Put opengl32.def into the tcc/lib directory. Specify -lopengl32 at the TCC commandline to link a program that uses opengl32.dll. @@ -98,10 +98,10 @@ Tiny Libmaker: -------------- - The included tiny_libmaker tool by Timovj Lahde can be used as + The now built-in tiny_libmaker tool by Timovj Lahde can be used as 'ar' replacement to make a library from several object files: - tiny_libmaker [rcs] library objectfiles ... + tcc -ar [rcsv] library objectfiles ... Compilation from source: @@ -143,14 +143,12 @@ ------------ - On the object file level, currently TCC supports only the ELF format, not COFF as used by MinGW and MSVC. It is not possible to exchange - object files or libraries between TCC and these compilers. However - libraries for TCC from objects by TCC can be made using tiny_libmaker - or MinGW's ar. + object files or libraries between TCC and these compilers. - - No leading underscore is generated in the ELF symbols. - - - Bounds checking (option -b) is not supported on 64-bit OS. + However libraries for TCC from objects by TCC can be made using + tcc -ar lib.a files.o ,,, + - No leading underscore is generated in the ELF symbols. Documentation and License: -------------------------- diff --git a/win32/tools/tiny_impdef.c b/win32/tools/tiny_impdef.c deleted file mode 100644 index b6debe6..0000000 --- a/win32/tools/tiny_impdef.c +++ /dev/null @@ -1,249 +0,0 @@ -/* -------------------------------------------------------------- */ -/* - * tiny_impdef creates an export definition file (.def) from a dll - * on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]" - * - * Copyright (c) 2005,2007 grischka - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef TINY_IMPDEF_GET_EXPORT_NAMES_ONLY - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <stdio.h> -#include <io.h> -#include <malloc.h> - -static char *get_export_names(int fd); -#define tcc_free free -#define tcc_realloc realloc - -/* extract the basename of a file */ -static char *file_basename(const char *name) -{ - const char *p = strchr(name, 0); - while (p > name - && p[-1] != '/' - && p[-1] != '\\' - ) - --p; - return (char*)p; -} - -int main(int argc, char **argv) -{ - int ret, v, i; - char infile[MAX_PATH]; - char outfile[MAX_PATH]; - - static const char *ext[] = { ".dll", ".exe", NULL }; - const char *file, **pp; - char path[MAX_PATH], *p, *q; - FILE *fp, *op; - - infile[0] = 0; - outfile[0] = 0; - fp = op = NULL; - v = 0; - ret = 1; - p = NULL; - - for (i = 1; i < argc; ++i) { - const char *a = argv[i]; - if ('-' == a[0]) { - if (0 == strcmp(a, "-v")) { - v = 1; - } else if (0 == strcmp(a, "-o")) { - if (++i == argc) - goto usage; - strcpy(outfile, argv[i]); - } else - goto usage; - } else if (0 == infile[0]) - strcpy(infile, a); - else - goto usage; - } - - if (0 == infile[0]) { -usage: - fprintf(stderr, - "tiny_impdef: create export definition file (.def) from a dll\n" - "Usage: tiny_impdef library.dll [-o outputfile]\n" - ); - goto the_end; - } - - if (0 == outfile[0]) - { - strcpy(outfile, file_basename(infile)); - q = strrchr(outfile, '.'); - if (NULL == q) - q = strchr(outfile, 0); - strcpy(q, ".def"); - } - - file = infile; - -#ifdef _WIN32 - pp = ext; - do if (SearchPath(NULL, file, *pp, sizeof path, path, NULL)) { - file = path; - break; - } while (*pp++); -#endif - - fp = fopen(file, "rb"); - if (NULL == fp) { - fprintf(stderr, "tiny_impdef: no such file: %s\n", infile); - goto the_end; - } - if (v) - printf("--> %s\n", file); - - p = get_export_names(fileno(fp)); - if (NULL == p) { - fprintf(stderr, "tiny_impdef: could not get exported function names.\n"); - goto the_end; - } - - op = fopen(outfile, "w"); - if (NULL == op) { - fprintf(stderr, "tiny_impdef: could not create output file: %s\n", outfile); - goto the_end; - } - - fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(file)); - for (q = p, i = 0; *q; ++i) { - fprintf(op, "%s\n", q); - q += strlen(q) + 1; - } - - if (v) { - printf("<-- %s\n", outfile); - printf("%d symbol(s) found\n", i); - } - - ret = 0; - -the_end: - if (p) - free(p); - if (fp) - fclose(fp); - if (op) - fclose(op); - return ret; -} - -int read_mem(int fd, unsigned offset, void *buffer, unsigned len) -{ - lseek(fd, offset, SEEK_SET); - return len == read(fd, buffer, len); -} - -/* -------------------------------------------------------------- */ - -#if defined TCC_TARGET_X86_64 -# define IMAGE_FILE_MACHINE 0x8664 -#elif defined TCC_TARGET_ARM -# define IMAGE_FILE_MACHINE 0x01C0 -#elif 1 /* defined TCC_TARGET_I386 */ -# define IMAGE_FILE_MACHINE 0x014C -#endif - -/* -------------------------------------------------------------- */ -#endif - -static char *get_export_names(int fd) -{ - int l, i, n, n0; - char *p; - - IMAGE_SECTION_HEADER ish; - IMAGE_EXPORT_DIRECTORY ied; - IMAGE_DOS_HEADER dh; - IMAGE_FILE_HEADER ih; - DWORD sig, ref, addr, ptr, namep; -#ifdef TCC_TARGET_X86_64 - IMAGE_OPTIONAL_HEADER64 oh; -#else - IMAGE_OPTIONAL_HEADER32 oh; -#endif - int pef_hdroffset, opt_hdroffset, sec_hdroffset; - - n = n0 = 0; - p = NULL; - - if (!read_mem(fd, 0, &dh, sizeof dh)) - goto the_end; - if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig)) - goto the_end; - if (sig != 0x00004550) - goto the_end; - pef_hdroffset = dh.e_lfanew + sizeof sig; - if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih)) - goto the_end; - if (IMAGE_FILE_MACHINE != ih.Machine) - goto the_end; - opt_hdroffset = pef_hdroffset + sizeof ih; - sec_hdroffset = opt_hdroffset + sizeof oh; - if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) - goto the_end; - - if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) - goto the_end; - - addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; - //printf("addr: %08x\n", addr); - for (i = 0; i < ih.NumberOfSections; ++i) { - if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish)) - goto the_end; - //printf("vaddr: %08x\n", ish.VirtualAddress); - if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData) - goto found; - } - goto the_end; - -found: - ref = ish.VirtualAddress - ish.PointerToRawData; - if (!read_mem(fd, addr - ref, &ied, sizeof ied)) - goto the_end; - - namep = ied.AddressOfNames - ref; - for (i = 0; i < ied.NumberOfNames; ++i) { - if (!read_mem(fd, namep, &ptr, sizeof ptr)) - goto the_end; - namep += sizeof ptr; - for (l = 0;;) { - if (n+1 >= n0) - p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256); - if (!read_mem(fd, ptr - ref + l++, p + n, 1)) { - tcc_free(p), p = NULL; - goto the_end; - } - if (p[n++] == 0) - break; - } - } - if (p) - p[n] = 0; -the_end: - return p; -} - -/* -------------------------------------------------------------- */ diff --git a/win32/tools/tiny_libmaker.c b/win32/tools/tiny_libmaker.c deleted file mode 100644 index a694915..0000000 --- a/win32/tools/tiny_libmaker.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * This program is for making libtcc1.a without ar - * tiny_libmaker - tiny elf lib maker - * usage: tiny_libmaker [lib] files... - * Copyright (c) 2007 Timppa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "../../elf.h" - -#ifdef TCC_TARGET_X86_64 -# define ELFCLASSW ELFCLASS64 -# define ElfW(type) Elf##64##_##type -# define ELFW(type) ELF##64##_##type -#else -# define ELFCLASSW ELFCLASS32 -# define ElfW(type) Elf##32##_##type -# define ELFW(type) ELF##32##_##type -#endif - -#define ARMAG "!<arch>\n" -#define ARFMAG "`\n" - -typedef struct ArHdr { - char ar_name[16]; - char ar_date[12]; - char ar_uid[6]; - char ar_gid[6]; - char ar_mode[8]; - char ar_size[10]; - char ar_fmag[2]; -} ArHdr; - -unsigned long le2belong(unsigned long ul) { - return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) + - ((ul & 0xFF)<<24)+((ul & 0xFF00)<<8); -} - -ArHdr arhdr = { - "/ ", - " ", - "0 ", - "0 ", - "0 ", - " ", - ARFMAG - }; - -ArHdr arhdro = { - " ", - " ", - "0 ", - "0 ", - "0 ", - " ", - ARFMAG - }; - -/* Returns 1 if s contains any of the chars of list, else 0 */ -int contains_any(const char *s, const char *list) { - const char *l; - for (; *s; s++) { - for (l = list; *l; l++) { - if (*s == *l) - return 1; - } - } - return 0; -} - -int usage(int ret) { - fprintf(stderr, "usage: tiny_libmaker [rcsv] lib file...\n"); - fprintf(stderr, "Always creates a new lib. [abdioptxN] are explicitly rejected.\n"); - return ret; -} - -int main(int argc, char **argv) -{ - FILE *fi, *fh = NULL, *fo = NULL; - ElfW(Ehdr) *ehdr; - ElfW(Shdr) *shdr; - ElfW(Sym) *sym; - int i, fsize, i_lib, i_obj; - char *buf, *shstr, *symtab = NULL, *strtab = NULL; - int symtabsize = 0;//, strtabsize = 0; - char *anames = NULL; - int *afpos = NULL; - int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs; - char tfile[260], stmp[20]; - char *file, *name; - int ret = 2; - char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored. - int verbose = 0; - - i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj - for (i = 1; i < argc; i++) { - const char *a = argv[i]; - if (*a == '-' && strstr(a, ".")) - return usage(1); // -x.y is always invalid (same as gnu ar) - if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument - if (contains_any(a, ops_conflict)) - return usage(1); - if (strstr(a, "v")) - verbose = 1; - } else { // lib or obj files: don't abort - keep validating all args. - if (!i_lib) // first file is the lib - i_lib = i; - else if (!i_obj) // second file is the first obj - i_obj = i; - } - } - if (!i_obj) // i_obj implies also i_lib. we require both. - return usage(1); - - if ((fh = fopen(argv[i_lib], "wb")) == NULL) - { - fprintf(stderr, "Can't open file %s \n", argv[i_lib]); - goto the_end; - } - - sprintf(tfile, "%s.tmp", argv[i_lib]); - if ((fo = fopen(tfile, "wb+")) == NULL) - { - fprintf(stderr, "Can't create temporary file %s\n", tfile); - goto the_end; - } - - funcmax = 250; - afpos = realloc(NULL, funcmax * sizeof *afpos); // 250 func - memcpy(&arhdro.ar_mode, "100666", 6); - - // i_obj = first input object file - while (i_obj < argc) - { - if (*argv[i_obj] == '-') { // by now, all options start with '-' - i_obj++; - continue; - } - if (verbose) - printf("a - %s\n", argv[i_obj]); - - if ((fi = fopen(argv[i_obj], "rb")) == NULL) - { - fprintf(stderr, "Can't open file %s \n", argv[i_obj]); - goto the_end; - } - fseek(fi, 0, SEEK_END); - fsize = ftell(fi); - fseek(fi, 0, SEEK_SET); - buf = malloc(fsize + 1); - fread(buf, fsize, 1, fi); - fclose(fi); - - // elf header - ehdr = (ElfW(Ehdr) *)buf; - if (ehdr->e_ident[4] != ELFCLASSW) - { - fprintf(stderr, "Unsupported Elf Class: %s\n", argv[i_obj]); - goto the_end; - } - - shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize); - shstr = (char *)(buf + shdr->sh_offset); - for (i = 0; i < ehdr->e_shnum; i++) - { - shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize); - if (!shdr->sh_offset) - continue; - if (shdr->sh_type == SHT_SYMTAB) - { - symtab = (char *)(buf + shdr->sh_offset); - symtabsize = shdr->sh_size; - } - if (shdr->sh_type == SHT_STRTAB) - { - if (!strcmp(shstr + shdr->sh_name, ".strtab")) - { - strtab = (char *)(buf + shdr->sh_offset); - //strtabsize = shdr->sh_size; - } - } - } - - if (symtab && symtabsize) - { - int nsym = symtabsize / sizeof(ElfW(Sym)); - //printf("symtab: info size shndx name\n"); - for (i = 1; i < nsym; i++) - { - sym = (ElfW(Sym) *) (symtab + i * sizeof(ElfW(Sym))); - if (sym->st_shndx && - (sym->st_info == 0x10 - || sym->st_info == 0x11 - || sym->st_info == 0x12 - )) { - //printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name); - istrlen = strlen(strtab + sym->st_name)+1; - anames = realloc(anames, strpos+istrlen); - strcpy(anames + strpos, strtab + sym->st_name); - strpos += istrlen; - if (++funccnt >= funcmax) { - funcmax += 250; - afpos = realloc(afpos, funcmax * sizeof *afpos); // 250 func more - } - afpos[funccnt] = fpos; - } - } - } - - file = argv[i_obj]; - for (name = strchr(file, 0); - name > file && name[-1] != '/' && name[-1] != '\\'; - --name); - istrlen = strlen(name); - if (istrlen >= sizeof(arhdro.ar_name)) - istrlen = sizeof(arhdro.ar_name) - 1; - memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name)); - memcpy(arhdro.ar_name, name, istrlen); - arhdro.ar_name[istrlen] = '/'; - sprintf(stmp, "%-10d", fsize); - memcpy(&arhdro.ar_size, stmp, 10); - fwrite(&arhdro, sizeof(arhdro), 1, fo); - fwrite(buf, fsize, 1, fo); - free(buf); - i_obj++; - fpos += (fsize + sizeof(arhdro)); - } - hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int); - fpos = 0; - if ((hofs & 1)) // align - hofs++, fpos = 1; - // write header - fwrite("!<arch>\n", 8, 1, fh); - sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int))); - memcpy(&arhdr.ar_size, stmp, 10); - fwrite(&arhdr, sizeof(arhdr), 1, fh); - afpos[0] = le2belong(funccnt); - for (i=1; i<=funccnt; i++) - afpos[i] = le2belong(afpos[i] + hofs); - fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh); - fwrite(anames, strpos, 1, fh); - if (fpos) - fwrite("", 1, 1, fh); - // write objects - fseek(fo, 0, SEEK_END); - fsize = ftell(fo); - fseek(fo, 0, SEEK_SET); - buf = malloc(fsize + 1); - fread(buf, fsize, 1, fo); - fwrite(buf, fsize, 1, fh); - free(buf); - ret = 0; -the_end: - if (anames) - free(anames); - if (afpos) - free(afpos); - if (fh) - fclose(fh); - if (fo) - fclose(fo), remove(tfile); - return ret; -} |
