Back to index

tetex-bin  3.0
omegabis.c
Go to the documentation of this file.
00001 /* omegabis.c: C routines to support external OCPs
00002 
00003 This file is part of Omega,
00004 which is based on the web2c distribution of TeX,
00005 
00006 Copyright (c) 1994--2001 John Plaice and Yannis Haralambous
00007 Copyright (c) 2002 Behdad Esfahbod
00008 Copyright (c) 2002 Roozbeh Pournader
00009 
00010 Omega is free software; you can redistribute it and/or modify
00011 it under the terms of the GNU General Public License as published by
00012 the Free Software Foundation; either version 2 of the License, or
00013 (at your option) any later version.
00014 
00015 Omega is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with Omega; if not, write to the Free Software Foundation, Inc.,
00022 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00023 
00024 */
00025 #define EXTERN extern
00026 #include <stdlib.h>
00027 #include <stdio.h>
00028 #include <errno.h>
00029 #include <string.h>
00030 #ifndef WIN32
00031 #include <unistd.h>
00032 #endif /* not WIN32 */
00033 #include "omegad.h"
00034 
00035 #if 1
00036 
00037 void
00038 runexternalocp P1C(string, external_ocp_name)
00039 {
00040   char *in_file_name;
00041   char *out_file_name;
00042   FILE *in_file;
00043   FILE *out_file;
00044   int in_file_fd;
00045   int out_file_fd;
00046   char command_line[400];
00047   int i;
00048   unsigned c;
00049   int c_in;
00050 #ifdef WIN32
00051   char *tempenv;
00052 
00053 #define null_string(s) ((s == NULL) || (*s == '\0'))
00054 
00055   tempenv = getenv("TMPDIR");
00056   if (null_string(tempenv))
00057     tempenv = getenv("TEMP");
00058   if (null_string(tempenv))
00059     tempenv = getenv("TMP");
00060   if (null_string(tempenv))
00061     tempenv = "c:/tmp";     /* "/tmp" is not good if we are on a CD-ROM */
00062   in_file_name = concat(tempenv, "/__omega__in__XXXXXX");
00063   mktemp(in_file_name);
00064   in_file = fopen(in_file_name, FOPEN_WBIN_MODE);
00065 #else
00066 
00067 #if HAVE_MKSTEMP
00068   in_file_name = xstrdup("/tmp/__omega__in__XXXXXX");
00069   in_file_fd = mkstemp(in_file_name);
00070   in_file = fdopen(in_file_fd, FOPEN_WBIN_MODE);
00071 #else
00072 #if HAVE_MKTEMP
00073   in_file_name = xstrdup("/tmp/__omega__in__XXXXXX");
00074   mktemp(in_file_name);
00075 #else
00076   in_file_name = xstrdup(tmpnam(NULL));
00077 #endif /* HAVE_MKTEMP */
00078   in_file = fopen(in_file_name, FOPEN_WBIN_MODE);
00079 #endif /* HAVE_MKSTEMP */
00080 
00081 #endif /* WIN32 */
00082 
00083   if (in_file == NULL)
00084     fprintf(stderr, "omega: error opening file: %s\n", strerror(errno));
00085   
00086   for (i=1; i<=otpinputend; i++) {
00087       c = otpinputbuf[i];
00088       if (c>0xffff) {
00089           fprintf(stderr, "Omega does not currently support 31-bit chars\n");
00090           exit(1);
00091       }
00092       if (c<0x80) {
00093           fputc(c & 0x7f, in_file);
00094       } else if (c<0x800) {
00095           fputc(0xc0 | ((c>>6) & 0x1f), in_file);
00096           fputc(0x80 | (c & 0x3f), in_file);
00097       } else if (c<0x10000) {
00098           fputc(0xe0 | ((c>>12) & 0xf), in_file);
00099           fputc(0x80 | ((c>>6) & 0x3f), in_file);
00100           fputc(0x80 | (c & 0x3f), in_file);
00101       } else if (c<0x200000) {
00102           fputc(0xf0 | ((c>>18) & 0x7), in_file);
00103           fputc(0x80 | ((c>>12) & 0x3f), in_file);
00104           fputc(0x80 | ((c>>6) & 0x3f), in_file);
00105           fputc(0x80 | (c & 0x3f), in_file);
00106       } else if (c<0x4000000) {
00107           fputc(0xf8 | ((c>>24) & 0x3), in_file);
00108           fputc(0x80 | ((c>>18) & 0x3f), in_file);
00109           fputc(0x80 | ((c>>12) & 0x3f), in_file);
00110           fputc(0x80 | ((c>>6) & 0x3f), in_file);
00111           fputc(0x80 | (c & 0x3f), in_file);
00112       } else { /* c>=0x4000000 */
00113           fputc(0xfc | ((c>>30) & 0x1), in_file);
00114           fputc(0x80 | ((c>>24) & 0x3f), in_file);
00115           fputc(0x80 | ((c>>18) & 0x3f), in_file);
00116           fputc(0x80 | ((c>>12) & 0x3f), in_file);
00117           fputc(0x80 | ((c>>6) & 0x3f), in_file);
00118           fputc(0x80 | (c & 0x3f), in_file);
00119       }
00120   }
00121   fclose(in_file);
00122   
00123 #define advance_cin do { if ((c_in = fgetc(out_file)) == -1) { \
00124                          fprintf(stderr, "File contains bad char\n"); \
00125                          goto end_of_while; \
00126                     } } while (0)
00127                     
00128 #ifdef WIN32
00129   out_file_name = concat(tempenv, "/__omega__out__XXXXXX");
00130   mktemp(out_file_name);
00131   out_file = fopen(out_file_name, FOPEN_RBIN_MODE);
00132 #else
00133 
00134 #if HAVE_MKSTEMP
00135   out_file_name = xstrdup("/tmp/__omega__out__XXXXXX");
00136   out_file_fd = mkstemp(out_file_name);
00137   out_file = fdopen(out_file_fd, FOPEN_RBIN_MODE);
00138 #else
00139 #if HAVE_MKTEMP
00140   out_file_name = xstrdup("/tmp/__omega__out__XXXXXX");
00141   mktemp(out_file_name);
00142 #else
00143   out_file_name = xstrdup(tmpnam(NULL));
00144 #endif /* HAVE_MKTEMP */
00145   out_file = fopen(out_file_name, FOPEN_RBIN_MODE);
00146 #endif /* HAVE_MKSTEMP */
00147 
00148 #endif /* WIN32 */
00149  
00150   if (out_file == NULL)
00151     fprintf(stderr, "omega: error opening file: %s\n", strerror(errno));
00152   
00153   sprintf(command_line, "%s <%s >%s\n",
00154           external_ocp_name+1, in_file_name, out_file_name);
00155   system(command_line);
00156   otpoutputend = 0;
00157   otpoutputbuf[otpoutputend] = 0;
00158   while ((c_in = fgetc(out_file)) != -1) {
00159      if (c_in<0x80) {
00160          c = c_in & 0x7f;
00161      } else if (c_in<0xe0) {
00162          c = (c_in & 0x1f) << 6;
00163          advance_cin;
00164          c |= c_in & 0x3f;
00165      } else if (c_in<=0xf0) {
00166          c = (c_in & 0xf) << 12;
00167          advance_cin;
00168          c |= (c_in & 0x3f) << 6;
00169          advance_cin;
00170          c |= c_in & 0x3f;
00171      } else if (c_in<0xf8) {
00172          c = (c_in & 0x7) << 18;
00173          advance_cin;
00174          c |= (c_in & 0x3f) << 12;
00175          advance_cin;
00176          c |= (c_in & 0x3f) << 6;
00177          advance_cin;
00178          c |= c_in & 0x3f;
00179      } else if (c_in<0xfc) {
00180          c = (c_in & 0x3) << 24;
00181          advance_cin;
00182          c |= (c_in & 0x3f) << 18;
00183          advance_cin;
00184          c |= (c_in & 0x3f) << 12;
00185          advance_cin;
00186          c |= (c_in & 0x3f) << 6;
00187          advance_cin;
00188          c |= c_in & 0x3f;
00189      } else { /* c>=0xfc */
00190          c = (c_in & 0x1)   << 30;
00191          advance_cin;
00192          c |= (c_in & 0x3f) << 24;
00193          advance_cin;
00194          c |= (c_in & 0x3f) << 18;
00195          advance_cin;
00196          c |= (c_in & 0x3f) << 12;
00197          advance_cin;
00198          c |= (c_in & 0x3f) << 6;
00199          advance_cin;
00200          c |= c_in & 0x3f;
00201      }
00202      otpoutputbuf[++otpoutputend] = c;
00203   }
00204 end_of_while:
00205   fclose(out_file);
00206 
00207   remove(in_file_name);
00208   remove(out_file_name);
00209   free(in_file_name);
00210   free(out_file_name);
00211 }
00212 
00213 #else
00214 
00215 void
00216 runexternalocp P1C(string, external_ocp_name)
00217 {
00218   int outpipes[2], inpipes[2];
00219   char *outbuf;
00220   char *inbuf;
00221   int n;
00222   int chars_read_in, chars_to_go_out;
00223   int myerrno;
00224 
00225 #ifdef WIN32
00226   STARTUPINFO si;
00227   PROCESS_INFORMATION pi;
00228   HANDLE hIn, hOut, hPipeIn, hPipeOut;
00229   SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
00230   DWORD ret = 0;
00231 
00232   /* Make pipes to send data from the parent to the child.  The parent
00233      writes to outpipes[0], and the child reads from outpipes[1].  */
00234   _pipe (outpipes, 0, _O_BINARY);
00235   /* Make pipes to send data from the child to the parent.  The child
00236      writes to inpipes[0], and the parent reads from inpipes[1].  */
00237   _pipe (inpipes, 0, _O_BINARY);
00238 
00239   ZeroMemory( &si, sizeof(STARTUPINFO) );
00240   si.cb = sizeof(STARTUPINFO);
00241   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
00242   si.wShowWindow = SW_SHOW;
00243   si.hStdInput = _get_osfhandle(outpipes[0]);
00244   si.hStdOutput = _get_osfhandle(inpipes[1]);
00245   si.hStdError = _get_osfhandle(_fileno(stderr));
00246 
00247   /* Close unnecessary pipes.  */
00248   close (outpipes[1]);
00249   close (inpipes[0]);
00250 
00251   if (CreateProcess(external_ocp_name+1,
00252                   NULL, /* Use lpApplicationName */
00253                   NULL,
00254                   NULL,
00255                   TRUE, /* bInheritHandles */
00256                   0,
00257                   NULL,
00258                   NULL,
00259                   &si,
00260                   &pi) == 0) {
00261     fprintf(stderr, "Failed to create process for %s (Error %d).\n", external_ocp_name+1, GetLastError());
00262     return;
00263   }
00264   
00265 #else /* ! WIN32 */
00266 
00267   /* Make pipes to send data from the parent to the child.  The parent
00268      writes to outpipes[0], and the child reads from outpipes[1].  */
00269   pipe (outpipes);
00270   /* Make pipes to send data from the child to the parent.  The child
00271      writes to inpipes[0], and the parent reads from inpipes[1].  */
00272   pipe (inpipes);
00273 
00274   /* For a child process.  */
00275   if (fork () == 0)
00276     {
00277       /* This part is executed by the child process.  It translates
00278          lower case letters to upper case.  */
00279 
00280       char *prog = external_ocp_name+1;
00281       char *args[] = {external_ocp_name+1, NULL};
00282 
00283       /* Close unnecessary pipes.  They are for the parent.  */
00284       close (outpipes[1]);
00285       close (inpipes[0]);
00286 
00287       /* Connect pipes to stdin and stdout.  */
00288       dup2 (outpipes[0], 0);
00289       dup2 (inpipes[1], 1);
00290 
00291       /* Overlays a new process image on an old process. */
00292       execv (prog, args);
00293 
00294       /* We should never reach here. */
00295     }
00296   else
00297     {
00298       /* Close unnecessary pipes.  They are for the child.  */
00299       close (outpipes[0]);
00300       close (inpipes[1]);
00301 
00302 #endif /* WIN32 */
00303 
00304 /* Here is the interesting part */
00305       outbuf = ((char *) otpinputbuf)+2;
00306       inbuf = ((char *) otpoutputbuf)+2;
00307       chars_to_go_out = 2*otpinputend;
00308       chars_read_in = 0;
00309       while ((n = write (outpipes[1], outbuf, chars_to_go_out))>0) {
00310 fprintf(stderr, "Wrote (1) %d characters\n", n);
00311         outbuf+=n;
00312         chars_to_go_out-=n;
00313         if (chars_to_go_out==0) goto done_writing;
00314 /*
00315         n = read (inpipes[0], inbuf, 1024);
00316 fprintf(stderr, "Read (1) %d characters\n", n);
00317         inbuf+=n;
00318         chars_read_in+=n;
00319 */
00320       }
00321 fprintf(stderr, "Wrote (2) %d characters\n", n);
00322 
00323 done_writing:
00324       close (outpipes[1]);
00325       while ((n = read (inpipes[0], inbuf, 1024)) > 0) {
00326 fprintf(stderr, "Read (2) %d characters\n", n);
00327         inbuf+=n;
00328         chars_read_in+=n;
00329       }
00330 fprintf(stderr, "Read (3) %d characters\n", n);
00331       otpoutputend = chars_read_in / 2;
00332 
00333       close (inpipes[0]);
00334 #ifndef WIN32
00335     }
00336 #endif /* not WIN32 */
00337 }
00338 
00339 #endif