1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: fileio.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $";
3 #endif
4
5 /*
6 * ========================================================================
7 * Copyright 2006 University of Washington
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * ========================================================================
16 *
17 * Program: file reading routines
18 *
19 */
20
21 /*
22 * The routines in this file read and write ASCII files from the disk. All of
23 * the knowledge about files are here. A better message writing scheme should
24 * be used.
25 */
26 #include "headers.h"
27 #include "../pith/charconv/filesys.h"
28
29
30 #if defined(bsd) || defined(lnx)
31 extern int errno;
32 #endif
33
34
35
36 FIOINFO g_pico_fio;
37
38 /*
39 * Open a file for reading.
40 */
41 int
ffropen(char * fn)42 ffropen(char *fn)
43 {
44 int status;
45
46 if ((status = fexist(g_pico_fio.name = fn, "r", (off_t *)NULL)) == FIOSUC){
47 g_pico_fio.flags = FIOINFO_READ;
48 if((g_pico_fio.fp = our_fopen(g_pico_fio.name, "r")) == NULL)
49 status = FIOFNF;
50 }
51
52 return (status);
53 }
54
55
56 /*
57 * Write a line to the already opened file. The "buf" points to the buffer,
58 * and the "nbuf" is its length, less the free newline. Return the status.
59 * Check only at the newline.
60 */
61 int
ffputline(CELL buf[],int nbuf)62 ffputline(CELL buf[], int nbuf)
63 {
64 register int i;
65 EML eml;
66
67 for(i = 0; i < nbuf; ++i)
68 if(write_a_wide_char((UCS) buf[i].c, g_pico_fio.fp) == EOF)
69 break;
70
71 if(i == nbuf)
72 write_a_wide_char((UCS) '\n', g_pico_fio.fp);
73
74 if(ferror(g_pico_fio.fp)){
75 eml.s = errstr(errno);
76 emlwwrite(_("Write error: %s"), &eml);
77 sleep(5);
78 return FIOERR;
79 }
80
81 return FIOSUC;
82 }
83
84
85 /*
86 * Read a line from a file, and store the bytes in the supplied buffer. The
87 * "nbuf" is the length of the buffer. Complain about long lines and lines
88 * at the end of the file that don't have a newline present. Check for I/O
89 * errors too. Return status.
90 *
91 * Translate the line from the user's locale charset to UCS-4.
92 */
93 int
ffgetline(UCS buf[],size_t nbuf,size_t * charsreturned,int msg)94 ffgetline(UCS buf[], size_t nbuf, size_t *charsreturned, int msg)
95 {
96 size_t i;
97 UCS ucs;
98 static int displayed = 0;
99
100 if(charsreturned)
101 *charsreturned = 0;
102
103 i = 0;
104
105 while((ucs = read_a_wide_char(g_pico_fio.fp, input_cs)) != CCONV_EOF && ucs != '\n'){
106 /*
107 * Don't blat the CR should the newline be CRLF and we're
108 * running on a unix system. NOTE: this takes care of itself
109 * under DOS since the non-binary open turns newlines into '\n'.
110 */
111 if(ucs == '\r'){
112 if((ucs = read_a_wide_char(g_pico_fio.fp, input_cs)) == CCONV_EOF || ucs == '\n')
113 break;
114
115 if(i < nbuf-2) /* Bare CR. Insert it and go on... */
116 buf[i++] = '\r'; /* else, we're up a creek */
117 }
118
119 if(i >= nbuf-2){
120 buf[nbuf - 2] = ucs; /* store last char read */
121 buf[nbuf - 1] = '\0'; /* and terminate it */
122 if(charsreturned)
123 *charsreturned = nbuf - 1;
124
125 if(msg && displayed == 0){
126 emlwrite("File has long line", NULL);
127 displayed = 1;
128 }
129
130 return FIOLNG;
131 }
132
133 buf[i++] = ucs;
134 }
135
136 if(ucs == CCONV_EOF){
137 if(ferror(g_pico_fio.fp)){
138 emlwrite("File read error", NULL);
139 if(charsreturned)
140 *charsreturned = i;
141
142 return FIOERR;
143 }
144
145 if(i != 0)
146 emlwrite("File doesn't end with newline. Adding one.", NULL);
147 else{
148 if(charsreturned)
149 *charsreturned = i;
150 return FIOEOF;
151 }
152 }
153
154 buf[i] = '\0';
155
156 if(charsreturned)
157 *charsreturned = i;
158
159 return FIOSUC;
160 }
161