170 {
172 char *input, *output;
173 long i_arg, non_dominate_sort = 0;
174 SCANNED_ARG *s_arg;
175
176 long tmpfile_used, sort_requests, noWarnings, uniqueRows, provideIdenticalCount, tmpfileForInternalPipe;
177 long sort_parameters;
179 unsigned long pipeFlags, majorOrderFlag;
180 short columnMajorOrder = -1;
181
183 argc =
scanargs(&s_arg, argc, argv);
184 if (argc < 2) {
186 }
187
188 input = output = NULL;
189 tmpfile_used = sort_requests = noWarnings = sort_parameters = tmpfileForInternalPipe = 0;
190 sort_request = sort_parameter = NULL;
191 pipeFlags = 0;
192 uniqueRows = provideIdenticalCount = 0;
193 for (i_arg = 1; i_arg < argc; i_arg++) {
194 if (s_arg[i_arg].arg_type == OPTION) {
195 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
196 case SET_MAJOR_ORDER:
197 majorOrderFlag = 0;
198 s_arg[i_arg].n_items--;
199 if (s_arg[i_arg].n_items > 0 &&
200 (!
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
201 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
202 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
203 SDDS_Bomb(
"invalid -majorOrder syntax/values");
204 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
205 columnMajorOrder = 1;
206 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
207 columnMajorOrder = 0;
208 break;
209 case SET_NON_DOMINATE_SORT:
210 non_dominate_sort = 1;
211 break;
212 case SET_HYPERVOLUME:
213 if (s_arg[i_arg].n_items < 2)
214 SDDS_Bomb(
"invalid -hypervolume syntax; give a reference point: -hypervolume=<ref1>,<ref2>,...");
215 hypervolume_flag = 1;
216 hv_nref = s_arg[i_arg].n_items - 1;
217 hv_reference =
trealloc(hv_reference,
sizeof(*hv_reference) * hv_nref);
218 {
219 long jref;
220 for (jref = 0; jref < hv_nref; jref++)
221 if (sscanf(s_arg[i_arg].list[jref + 1], "%lf", &hv_reference[jref]) != 1)
222 SDDS_Bomb(
"invalid -hypervolume reference value");
223 }
224 break;
225 case SET_COLUMN:
226 if (s_arg[i_arg].n_items < 2 || s_arg[i_arg].n_items > 4)
228 sort_request =
trealloc(sort_request,
sizeof(*sort_request) * (sort_requests + 1));
229 sort_request[sort_requests].name = s_arg[i_arg].list[1];
230 sort_request[sort_requests].maximize_order = 0;
231 sort_request[sort_requests].decreasing_order = 0;
232 sort_request[sort_requests].absolute = 0;
233 if (s_arg[i_arg].n_items >= 3) {
234 int j;
235 for (j = 2; j < s_arg[i_arg].n_items; j++) {
236 switch (
match_string(s_arg[i_arg].list[j], order_mode, 5, 0)) {
237 case 0:
238 break;
239 case 1:
240 sort_request[sort_requests].decreasing_order = 1;
241 break;
242 case 2:
243 break;
244 case 3:
245 sort_request[sort_requests].maximize_order = 1;
246 break;
247 case 4:
248 sort_request[sort_requests].absolute = 1;
249 break;
250 default:
251 fprintf(stderr, "unknown sort order specified--give 'increasing' or 'decreasing' for dominated sorting\n or'maximize' or 'minimize' for non-dominated-sorting.\n");
252 exit(EXIT_FAILURE);
253 break;
254 }
255 }
256 }
257 sort_requests++;
258 break;
259 case SET_PARAMETER:
260 if (s_arg[i_arg].n_items < 2 || s_arg[i_arg].n_items > 3)
262 sort_parameter =
trealloc(sort_parameter,
sizeof(*sort_parameter) * (sort_parameters + 1));
263 sort_parameter[sort_parameters].name = s_arg[i_arg].list[1];
264 if (s_arg[i_arg].n_items == 3) {
265 if ((sort_parameter[sort_parameters].decreasing_order =
match_string(s_arg[i_arg].list[2], order_mode, 2, 0)) < 0)
266 SDDS_Bomb(
"unknown sort order specified--give 'increasing' or 'decreasing'");
267 } else
268 sort_parameter[sort_parameters].decreasing_order = 0;
269 sort_parameters++;
270 break;
271 case SET_NOWARNINGS:
272 noWarnings = 1;
273 break;
274 case SET_NUMERICHIGH:
275 numericHigh = 1;
276 break;
277 case SET_PIPE:
278 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
280 break;
281 case SET_UNIQUE:
282 uniqueRows = 1;
283 if (s_arg[i_arg].n_items > 1) {
285 if (s_arg[i_arg].n_items > 2 ||
286 strncmp("count", s_arg[i_arg].list[1], strlen(s_arg[i_arg].list[1])) != 0)
288 provideIdenticalCount = 1;
289 }
290 break;
291 default:
292 fprintf(stderr, "error: unknown switch: %s\n", s_arg[i_arg].list[0]);
293 exit(EXIT_FAILURE);
294 break;
295 }
296 } else {
297 if (input == NULL)
298 input = s_arg[i_arg].list[0];
299 else if (output == NULL)
300 output = s_arg[i_arg].list[0];
301 else
303 }
304 }
305
306 if (!sort_requests && !sort_parameters)
308 processFilenames(
"sddssort", &input, &output, pipeFlags, noWarnings, &tmpfile_used);
311 exit(EXIT_FAILURE);
312 }
313 if (sort_requests <= 1)
314 non_dominate_sort = 0;
315
316 if (hypervolume_flag) {
317 if (!non_dominate_sort)
318 SDDS_Bomb(
"-hypervolume requires -nonDominateSort with two or more -column objectives");
319 if (hv_nref != sort_requests)
320 SDDS_Bomb(
"-hypervolume reference point must have one value per -column objective");
321 }
322
323 if (SDDS_input.layout.popenUsed) {
324
325
326
327 pid_t pid;
328 char tmpfileName[1024];
329 pid = getpid();
330 sprintf(tmpfileName, "/tmp/sddssort.%ld", (long)pid);
331 tmpfileForInternalPipe = 1;
334 exit(EXIT_FAILURE);
335 }
336 if (columnMajorOrder != -1)
337 SDDS_tmp.layout.data_mode.column_major = columnMajorOrder;
338 else
339 SDDS_tmp.layout.data_mode.column_major = SDDS_input.layout.data_mode.column_major;
340 if (non_dominate_sort) {
344 exit(EXIT_FAILURE);
345 }
349 constDefined = 1;
350 }
351 }
352
355 exit(EXIT_FAILURE);
356 }
360 exit(EXIT_FAILURE);
361 }
362 }
365 exit(EXIT_FAILURE);
366 }
369 exit(EXIT_FAILURE);
370 }
371 }
374 exit(EXIT_FAILURE);
375 }
376 if (columnMajorOrder != -1)
377 SDDS_output.layout.data_mode.column_major = columnMajorOrder;
378 else
379 SDDS_output.layout.data_mode.column_major = SDDS_input.layout.data_mode.column_major;
380 if (provideIdenticalCount &&
383 exit(EXIT_FAILURE);
384 }
385 if (non_dominate_sort) {
389 exit(EXIT_FAILURE);
390 }
394 constDefined = 1;
395 }
396 if (hypervolume_flag &&
399 }
402 if (!SDDS_SortAll(&SDDS_input, &SDDS_output, sort_request, sort_requests, sort_parameter, sort_parameters,
403 uniqueRows, provideIdenticalCount, pipeFlags, non_dominate_sort)) {
406 }
409 exit(EXIT_FAILURE);
410 }
412 exit(EXIT_FAILURE);
414
415
416 return EXIT_SUCCESS;
417}
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_DefineSimpleParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data parameter within the SDDS dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
int32_t SDDS_CheckColumn(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a column exists in the SDDS dataset with the specified name, units, and type.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
#define SDDS_ANY_NUMERIC_TYPE
Special identifier used by SDDS_Check*() routines to accept any numeric type.
#define SDDS_DOUBLE
Identifier for the double data type.
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
long replaceFileAndBackUp(char *file, char *replacement)
Replaces a file with a replacement file and creates a backup of the original.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
void free_scanargs(SCANNED_ARG **scanned, int argc)
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.
char * str_tolower(char *s)
Convert a string to lower case.