| 4153 | /* Sort NFILES FILES onto OUTPUT_FILE. Use at most NTHREADS threads. */ |
| 4154 | |
| 4155 | static void |
| 4156 | sort (char *const *files, size_t nfiles, char const *output_file, |
| 4157 | size_t nthreads) |
| 4158 | { |
| 4159 | struct buffer buf; |
| 4160 | size_t ntemps = 0; |
| 4161 | bool output_file_created = false; |
| 4162 | |
| 4163 | buf.alloc = 0; |
| 4164 | |
| 4165 | while (nfiles) |
| 4166 | { |
| 4167 | char const *temp_output; |
| 4168 | char const *file = *files; |
| 4169 | FILE *fp = xfopen (file, "r"); |
| 4170 | FILE *tfp; |
| 4171 | |
| 4172 | size_t bytes_per_line; |
| 4173 | if (nthreads > 1) |
| 4174 | { |
| 4175 | /* Get log P. */ |
| 4176 | size_t tmp = 1; |
| 4177 | size_t mult = 1; |
| 4178 | while (tmp < nthreads) |
| 4179 | { |
| 4180 | tmp *= 2; |
| 4181 | mult++; |
| 4182 | } |
| 4183 | bytes_per_line = (mult * sizeof (struct line)); |
| 4184 | } |
| 4185 | else |
| 4186 | bytes_per_line = sizeof (struct line) * 3 / 2; |
| 4187 | |
| 4188 | if (! buf.alloc) |
| 4189 | initbuf (&buf, bytes_per_line, |
| 4190 | sort_buffer_size (&fp, 1, files, nfiles, bytes_per_line)); |
| 4191 | buf.eof = false; |
| 4192 | files++; |
| 4193 | nfiles--; |
| 4194 | |
| 4195 | while (fillbuf (&buf, fp, file)) |
| 4196 | { |
| 4197 | struct line *line; |
| 4198 | |
| 4199 | if (buf.eof && nfiles |
| 4200 | && (bytes_per_line + 1 |
| 4201 | < (buf.alloc - buf.used - bytes_per_line * buf.nlines))) |
| 4202 | { |
| 4203 | /* End of file, but there is more input and buffer room. |
| 4204 | Concatenate the next input file; this is faster in |
| 4205 | the usual case. */ |
| 4206 | buf.left = buf.used; |
| 4207 | break; |
| 4208 | } |
| 4209 | |
| 4210 | saved_line.text = NULL; |
| 4211 | line = buffer_linelim (&buf); |
| 4212 | if (buf.eof && !nfiles && !ntemps && !buf.left) |
no test coverage detected