1%%	options
2
3copyright owner	=	Dirk Krause
4copyright year	=	2015-xxxx
5SPDX-License-Identifier:	BSD-3-Clause
6
7
8
9%%	header
10
11/**	@file
12	File functions for dkChar characters
13	and strings.
14
15	CRT on Windows: Required.
16*/
17
18#ifndef DK4CONF_H_INCLUDED
19#if DK4_BUILDING_DKTOOLS4
20#include "dk4conf.h"
21#else
22#include <dktools-4/dk4conf.h>
23#endif
24#endif
25
26#ifndef DK4TYPES_H_INCLUDED
27#if DK4_BUILDING_DKTOOLS4
28#include <libdk4base/dk4types.h>
29#else
30#include <dktools-4/dk4types.h>
31#endif
32#endif
33
34#ifndef DK4ERROR_H_INCLUDED
35#if DK4_BUILDING_DKTOOLS4
36#include <libdk4base/dk4error.h>
37#else
38#include <dktools-4/dk4error.h>
39#endif
40#endif
41
42#ifndef STDIO_H_INCLUDED
43#include <stdio.h>
44#define	STDIO_H_INCLUDED 1
45#endif
46
47#if DK4_HAVE_ERRNO_H
48#ifndef ERRNO_H_INCLUDED
49#include <errno.h>
50#define	ERRNO_H_INCLUDED 1
51#endif
52#endif
53
54#ifdef __cplusplus
55extern "C" {
56#endif
57
58/**	On Windows, initialize stdout to write dkChar and write a BOM.
59*/
60void
61dk4fput_initialize_stdout(void);
62
63/**	On Windows, initialize stdout to write dkChar.
64*/
65void
66dk4fput_initialize_stdout_no_bom(void);
67
68/**	On Windows, initialize stderr to write dkChar and write a BOM.
69*/
70void
71dk4fput_initialize_stderr(void);
72
73/**	On Windows, initialize stderr to write dkChar.
74*/
75void
76dk4fput_initialize_stderr_no_bom(void);
77
78/**	On Windows, initialize file to write dkChar and write a BOM.
79	@param	fipo	File to set up.
80*/
81void
82dk4fput_initialize_file(FILE *fipo);
83
84/**	On Windows, initialize file to write dkChar.
85	@param	fipo	File to set up.
86*/
87void
88dk4fput_initialize_file_no_bom(FILE *fipo);
89
90/**	On Windows, return to the default file encoding for stdout.
91*/
92void
93dk4fput_cleanup_stdout(void);
94
95/**	On Windows, return to the default file encoding for stderr.
96*/
97void
98dk4fput_cleanup_stderr(void);
99
100/**	Write one character to file.
101	@param	c	Character to write.
102	@param	fipo	File to write to.
103	@param	erp	Error report, may be NULL.
104	@return	1 on success, 0 on error.
105
106	Error codes:
107	- DK4_E_NOT_SUPPORTED<br>
108	  if writing wide characters is not supported on the system,
109	- DK4_E_INVALID_ARGUMENTS<br>
110	  if fipo is NULL,
111	- DK4_E_WRITE_FAILED<br>
112	  with errno value in iDetails1 if the write attempt failed.
113*/
114int
115dk4fputc(dkChar c, FILE *fipo, dk4_er_t *erp);
116
117/**	Write one string to file.
118	@param	s	String to write.
119	@param	fipo	File to write to.
120	@param	erp	Error report, may be NULL.
121	@return	1 on success, 0 on error.
122
123	Error codes:
124	- DK4_E_NOT_SUPPORTED<br>
125	  if writing wide character strings is not supported on the system,
126	- DK4_E_INVALID_ARGUMENTS<br>
127	  if fipo is NULL,
128	- DK4_E_WRITE_FAILED<br>
129	  with errno in iDetails1 if the write attempt failed.
130*/
131int
132dk4fputs(const dkChar *s, FILE *fipo, dk4_er_t *erp);
133
134#ifdef __cplusplus
135}
136#endif
137
138
139
140%%	module
141
142#include "dk4conf.h"
143#include <libdk4c/dk4fput.h>
144
145#if DK4_HAVE_IO_H
146#ifndef IO_H_INCLUDED
147#include <io.h>
148#define IO_H_INCLUDED 1
149#endif
150#endif
151
152#if DK4_HAVE_FCNTL_H
153#ifndef FCNTL_H_INCLUDED
154#include <fcntl.h>
155#define	FCNTL_H_INCLUDED 1
156#endif
157#endif
158
159#ifndef	DK4REC26_H_INCLUDED
160#include <libdk4c/dk4rec26.h>
161#endif
162
163#include <libdk4base/dk4unused.h>
164
165#if DK4_HAVE_ASSERT_H
166#ifndef	ASSERT_H_INCLUDED
167#include <assert.h>
168#define	ASSERT_H_INCLUDED 1
169#endif
170#endif
171
172
173$!trace-include
174
175
176
177#if _WIN32 && (DK4_CHAR_SIZE > 1) && DK4_HAVE__SETMODE && defined(_MSC_VER)
178
179/**	Flag: Standard output initialized to write dkChar.
180*/
181static int dk4fput_stdout_initialized = 0;
182
183/**	Standard output mode at startup (should be restored before exiting).
184*/
185static int dk4fput_stdout_oldmode = _O_TEXT;
186
187/**	Flag: Standard error output initialized to write dkChar.
188*/
189static int dk4fput_stderr_initialized = 0;
190
191/**	Standard error mode at startup (should be restored before exiting).
192*/
193static int dk4fput_stderr_oldmode = _O_TEXT;
194
195#endif
196
197
198
199void
200dk4fput_initialize_stdout(void)
201{
202#if _WIN32 && (DK4_CHAR_SIZE > 1) && DK4_HAVE__SETMODE && defined(_MSC_VER)
203  if (0 == dk4fput_stdout_initialized) {
204    dk4fput_stdout_oldmode = _setmode(_fileno(stdout), _O_U16TEXT);
205    if (0 == _isatty(_fileno(stdout))) {
206      fputwc((wchar_t)0xFEFF, stdout);
207    }
208    dk4fput_stdout_initialized = 1;
209  }
210#endif
211}
212
213
214
215void
216dk4fput_initialize_stdout_no_bom(void)
217{
218#if _WIN32 && (DK4_CHAR_SIZE > 1) && DK4_HAVE__SETMODE && defined(_MSC_VER)
219  if (0 == dk4fput_stdout_initialized) {
220    dk4fput_stdout_oldmode = _setmode(_fileno(stdout), _O_U16TEXT);
221    dk4fput_stdout_initialized = 1;
222  }
223#endif
224}
225
226
227void
228dk4fput_cleanup_stdout(void)
229{
230#if _WIN32 && (DK4_CHAR_SIZE > 1) && DK4_HAVE__SETMODE && defined(_MSC_VER)
231  if (0 != dk4fput_stdout_initialized) {
232    fflush(stdout);
233    (void)_setmode(_fileno(stdout), dk4fput_stdout_oldmode);
234  }
235#endif
236}
237
238
239
240void
241dk4fput_initialize_stderr(void)
242{
243#if _WIN32 && (DK4_CHAR_SIZE > 1) && DK4_HAVE__SETMODE && defined(_MSC_VER)
244  if (0 == dk4fput_stderr_initialized) {
245    dk4fput_stderr_oldmode = _setmode(_fileno(stderr), _O_U16TEXT);
246    if (0 == _isatty(_fileno(stderr))) {
247      fputwc((wchar_t)0xFEFF, stderr);
248    }
249    dk4fput_stderr_initialized = 1;
250  }
251#endif
252}
253
254
255
256void
257dk4fput_initialize_stderr_no_bom(void)
258{
259#if _WIN32 && (DK4_CHAR_SIZE > 1) && DK4_HAVE__SETMODE && defined(_MSC_VER)
260  if (0 == dk4fput_stderr_initialized) {
261    dk4fput_stderr_oldmode = _setmode(_fileno(stderr), _O_U16TEXT);
262    dk4fput_stderr_initialized = 1;
263  }
264#endif
265}
266
267
268
269void
270dk4fput_cleanup_stderr(void)
271{
272#if _WIN32 && (DK4_CHAR_SIZE > 1) && DK4_HAVE__SETMODE && defined(_MSC_VER)
273  if (0 != dk4fput_stderr_initialized) {
274    fflush(stderr);
275    (void)_setmode(_fileno(stdout), dk4fput_stderr_oldmode);
276  }
277#endif
278}
279
280
281void
282dk4fput_initialize_file(
283#if _WIN32 && (DK4_CHAR_SIZE > 1) && DK4_HAVE__SETMODE && defined(_MSC_VER)
284  FILE *fipo
285#else
286  FILE * DK4_ARG_UNUSED(fipo)
287#endif
288)
289{
290#if _WIN32 && (DK4_CHAR_SIZE > 1) && DK4_HAVE__SETMODE && defined(_MSC_VER)
291#if	DK4_USE_ASSERT
292  assert(NULL != fipo);
293#endif
294  if (NULL != fipo) {
295    (void)_setmode(_fileno(fipo), _O_U16TEXT);
296    fputwc(0xFEFF, fipo);
297  }
298#else
299  DK4_UNUSED_ARG(fipo)
300#endif
301}
302
303
304
305void
306dk4fput_initialize_file_no_bom(
307#if _WIN32 && (DK4_CHAR_SIZE > 1) && DK4_HAVE__SETMODE && defined(_MSC_VER)
308  FILE *fipo
309#else
310  FILE * DK4_ARG_UNUSED(fipo)
311#endif
312)
313{
314#if _WIN32 && (DK4_CHAR_SIZE > 1) && DK4_HAVE__SETMODE && defined(_MSC_VER)
315#if	DK4_USE_ASSERT
316  assert(NULL != fipo);
317#endif
318  if (NULL != fipo) {
319    (void)_setmode(_fileno(fipo), _O_U16TEXT);
320  }
321#else
322  DK4_UNUSED_ARG(fipo)
323#endif
324}
325
326
327
328int
329dk4fputc(dkChar c, FILE *fipo, dk4_er_t *erp)
330{
331#if DK4_CHAR_SIZE > 1
332#if DK4_CHAR_SIZE == DK4_SIZEOF_WCHAR_T
333#if DK4_HAVE_FPUTWC
334  int	back = 0;
335  $? "+ dk4fputc (wide) %lx", dk4recode_dk_to_ul(c)
336#if	DK4_USE_ASSERT
337  assert(NULL != fipo);
338#endif
339  if (NULL != fipo) {
340    errno = 0;
341    if (WEOF != fputwc(c, fipo)) {
342      back = 1;
343    } else {
344      dk4error_set_idetails(erp, DK4_E_WRITE_FAILED, errno);
345    }
346  } else {
347    dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
348  } $? "- dk4fputc (wide) %d", back
349  return back;
350#else
351  dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
352  return 0;
353#endif
354#else
355  dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
356  return 0;
357#endif
358#else
359  int	back = 0;
360#if	DK4_USE_ASSERT
361  assert(NULL != fipo);
362#endif
363  if (NULL != fipo) {
364    errno = 0;
365    if (EOF != fputc(c, fipo)) {
366      back = 1;
367    } else {
368      dk4error_set_idetails(erp, DK4_E_WRITE_FAILED, errno);
369    }
370  } else {
371    dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
372  }
373  return back;
374#endif
375}
376
377
378
379int
380dk4fputs(const dkChar *s, FILE *fipo, dk4_er_t *erp)
381{
382#if DK4_CHAR_SIZE > 1
383#if DK4_CHAR_SIZE == DK4_SIZEOF_WCHAR_T
384#if DK4_HAVE_FPUTWS
385  int	back = 0;
386#if	DK4_USE_ASSERT
387  assert(NULL != fipo);
388  assert(NULL != s);
389#endif
390  if ((NULL != s) && (NULL != fipo)) {
391    errno = 0;
392    if (WEOF != fputws(s, fipo)) {
393      back = 1;
394    } else {
395      dk4error_set_idetails(erp, DK4_E_WRITE_FAILED, errno);
396    }
397  } else {
398    dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
399  }
400  return back;
401#else
402  dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
403  return 0;
404#endif
405#else
406  dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
407  return 0;
408#endif
409#else
410  int	back = 0;
411#if	DK4_USE_ASSERT
412  assert(NULL != fipo);
413  assert(NULL != s);
414#endif
415  if ((NULL != s) && (NULL != fipo)) {
416    errno = 0;
417    if (EOF != fputs(s, fipo)) {
418      back = 1;
419    } else {
420      dk4error_set_idetails(erp, DK4_E_WRITE_FAILED, errno);
421    }
422  } else {
423    dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
424  }
425  return back;
426#endif
427}
428
429