// // PDF merge program for PDFio. // // Copyright © 2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // Usage: // // ./pdfmerge [-o OUTPUT.pdf] INPUT.pdf [... INPUT.pdf] // ./pdfmerge INPUT.pdf [... INPUT.pdf] >OUTPUT.pdf // #include #include // // Local functions... // static ssize_t output_cb(void *output_cbdata, const void *buffer, size_t bytes); static int usage(FILE *out); // // 'main()' - Main entry. // int // O - Exit status main(int argc, // I - Number of command-line arguments char *argv[]) // I - Command-line arguments { int i; // Looping var const char *opt; // Current option pdfio_file_t *inpdf, // Input PDF file *outpdf = NULL; // Output PDF file // Parse command-line... for (i = 1; i < argc; i ++) { if (!strcmp(argv[i], "--help")) { return (usage(stdout)); } else if (!strncmp(argv[i], "--", 2)) { fprintf(stderr, "pdfmerge: Unknown option '%s'.\n", argv[i]); return (usage(stderr)); } else if (argv[i][0] == '-') { for (opt = argv[i] + 1; *opt; opt ++) { switch (*opt) { case 'o' : // -o OUTPUT.pdf if (outpdf) { fputs("pdfmerge: Only one output file can be specified.\n", stderr); return (usage(stderr)); } i ++; if (i >= argc) { fputs("pdfmerge: Missing output filename after '-o'.\n", stderr); return (usage(stderr)); } if ((outpdf = pdfioFileCreate(argv[i], /*version*/NULL, /*media_box*/NULL, /*crop_box*/NULL, /*error_cb*/NULL, /*error_data*/NULL)) == NULL) return (1); break; default : fprintf(stderr, "pdfmerge: Unknown option '-%c'.\n", *opt); return (usage(stderr)); } } } else if ((inpdf = pdfioFileOpen(argv[i], /*password_cb*/NULL, /*password_data*/NULL, /*error_cb*/NULL, /*error_data*/NULL)) == NULL) { return (1); } else { // Copy PDF file... size_t p, // Current page nump; // Number of pages if (!outpdf) { if ((outpdf = pdfioFileCreateOutput(output_cb, /*output_cbdata*/NULL, /*version*/NULL, /*media_box*/NULL, /*crop_box*/NULL, /*error_cb*/NULL, /*error_data*/NULL)) == NULL) return (1); } for (p = 0, nump = pdfioFileGetNumPages(inpdf); p < nump; p ++) { if (!pdfioPageCopy(outpdf, pdfioFileGetPage(inpdf, p))) return (1); } pdfioFileClose(inpdf); } } if (!outpdf) return (usage(stderr)); pdfioFileClose(outpdf); return (0); } // // 'output_cb()' - Write PDF data to the standard output... // static ssize_t // O - Number of bytes written output_cb(void *output_cbdata, // I - Callback data (not used) const void *buffer, // I - Buffer to write size_t bytes) // I - Number of bytes to write { (void)output_cbdata; return ((ssize_t)fwrite(buffer, 1, bytes, stdout)); } // // 'usage()' - Show program usage. // static int // O - Exit status usage(FILE *out) // I - stdout or stderr { fputs("Usage: pdfmerge [OPTIONS] INPUT.pdf [... INPUT.pdf] >OUTPUT.pdf\n", out); fputs("Options:\n", out); fputs(" --help Show help.\n", out); fputs(" -o OUTPUT.pdf Send output to filename instead of stdout.\n", out); return (out == stdout ? 0 : 1); }