diff options
Diffstat (limited to 'Build/source/texk/web2c/mplibdir/mpost.w')
-rw-r--r-- | Build/source/texk/web2c/mplibdir/mpost.w | 939 |
1 files changed, 939 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mplibdir/mpost.w b/Build/source/texk/web2c/mplibdir/mpost.w new file mode 100644 index 00000000000..79ade1ead57 --- /dev/null +++ b/Build/source/texk/web2c/mplibdir/mpost.w @@ -0,0 +1,939 @@ +% $Id: mpost.w 892 2009-04-14 14:28:42Z taco $ +% +% Copyright 2008 Taco Hoekwater. +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU Lesser General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU Lesser General Public License for more details. +% +% You should have received a copy of the GNU Lesser General Public License +% along with this program. If not, see <http://www.gnu.org/licenses/>. + +\font\tenlogo=logo10 % font used for the METAFONT logo +\def\MP{{\tenlogo META}\-{\tenlogo POST}} + +\def\title{MetaPost executable} +\def\[#1]{#1.} +\pdfoutput=1 + +@* \[1] Metapost executable. + +Now that all of \MP\ is a library, a separate program is needed to +have our customary command-line interface. + +@ First, here are the C includes. |avl.h| is needed because of an +|avl_allocator| that is defined in |mplib.h| + +@d true 1 +@d false 0 + +@c +#include "config.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#if defined (HAVE_SYS_TIME_H) +#include <sys/time.h> +#elif defined (HAVE_SYS_TIMEB_H) +#include <sys/timeb.h> +#endif +#include <mplib.h> +#include <mpxout.h> +#ifdef WIN32 +#include <process.h> +#endif +#include <kpathsea/kpathsea.h> +extern char *kpathsea_version_string; +@= /*@@null@@*/ @> static char *mpost_tex_program = NULL; +static int debug = 0; /* debugging for makempx */ +#ifdef WIN32 +#define GETCWD _getcwd +#else +#define GETCWD getcwd +#endif +static boolean recorder_enabled = false; +static string recorder_name = NULL; +static FILE *recorder_file = NULL; +static char *job_name = NULL; +static int dvitomp_only = 0; + +@ Allocating a bit of memory, with error detection: + +@d mpost_xfree(A) do { if (A!=NULL) free(A); A=NULL; } while (0) + +@c +@= /*@@only@@*/ /*@@out@@*/ @> static void *mpost_xmalloc (size_t bytes) { + void *w = malloc (bytes); + if (w==NULL) { + fprintf(stderr,"Out of memory!\n"); + exit(EXIT_FAILURE); + } + return w; +} +@= /*@@only@@*/ @> static char *mpost_xstrdup(const char *s) { + char *w; + w = strdup(s); + if (w==NULL) { + fprintf(stderr,"Out of memory!\n"); + exit(EXIT_FAILURE); + } + return w; +} +static char *mpost_itoa (int i) { + char res[32] ; + unsigned idx = 30; + unsigned v = (unsigned)abs(i); + memset(res,0,32*sizeof(char)); + while (v>=10) { + char d = (char)(v % 10); + v = v / 10; + res[idx--] = d; + } + res[idx--] = (char)v; + if (i<0) { + res[idx--] = '-'; + } + return mpost_xstrdup(res+idx); +} + + +@ @c +static void mpost_run_editor (MP mp, char *fname, int fline) { + char *temp, *command, *edit_value; + char c; + boolean sdone, ddone; + sdone = ddone = false; + edit_value = kpse_var_value ("MPEDIT"); + if (edit_value == NULL) + edit_value = getenv("EDITOR"); + if (edit_value == NULL) { + fprintf (stderr,"call_edit: can't find a suitable MPEDIT or EDITOR variable\n"); + exit(mp_status(mp)); + } + command = (string) mpost_xmalloc (strlen (edit_value) + strlen(fname) + 11 + 3); + temp = command; + while ((c = *edit_value++) != (char)0) { + if (c == '%') { + switch (c = *edit_value++) { + case 'd': + if (ddone) { + fprintf (stderr,"call_edit: `%%d' appears twice in editor command\n"); + exit(EXIT_FAILURE); + } else { + char *s = mpost_itoa(fline); + if (s != NULL) { + while (*s != '\0') + *temp++ = *s++; + free(s); + } + ddone = true; + } + break; + case 's': + if (sdone) { + fprintf (stderr,"call_edit: `%%s' appears twice in editor command\n"); + exit(EXIT_FAILURE); + } else { + while (*fname != '\0') + *temp++ = *fname++; + *temp++ = '.'; + *temp++ = 'm'; + *temp++ = 'p'; + sdone = true; + } + break; + case '\0': + *temp++ = '%'; + /* Back up to the null to force termination. */ + edit_value--; + break; + default: + *temp++ = '%'; + *temp++ = c; + break; + } + } else { + *temp++ = c; + } + } + *temp = '\0'; + if (system (command) != 0) + fprintf (stderr, "! Trouble executing `%s'.\n", command); + exit(EXIT_FAILURE); +} + +@ +@<Register the callback routines@>= +options->run_editor = mpost_run_editor; + +@ +@c +static string normalize_quotes (const char *name, const char *mesg) { + boolean quoted = false; + boolean must_quote = (strchr(name, ' ') != NULL); + /* Leave room for quotes and NUL. */ + string ret = (string)mpost_xmalloc(strlen(name)+3); + string p; + const_string q; + p = ret; + if (must_quote) + *p++ = '"'; + for (q = name; *q != '\0'; q++) { + if (*q == '"') + quoted = !quoted; + else + *p++ = *q; + } + if (must_quote) + *p++ = '"'; + *p = '\0'; + if (quoted) { + fprintf(stderr, "! Unbalanced quotes in %s %s\n", mesg, name); + exit(EXIT_FAILURE); + } + return ret; +} + +@ Helpers for the filename recorder. + +@c +void recorder_start(char *jobname) { + char cwd[1024]; + recorder_name = (string)xmalloc((unsigned int)(strlen(jobname)+5)); + strcpy(recorder_name, jobname); + strcat(recorder_name, ".fls"); + recorder_file = xfopen(recorder_name, FOPEN_W_MODE); + + if(GETCWD(cwd,1020) != NULL) { + fprintf(recorder_file, "PWD %s\n", cwd); + } else { + fprintf(recorder_file, "PWD <unknown>\n"); + } +} + + +@ @c +@= /*@@null@@*/ @> static char *makempx_find_file (MPX mpx, const char *nam, + const char *mode, int ftype) { + int fmt; + boolean req; + (void) mpx; + if (mode[0] != 'r') { + return strdup(nam); + } + req = true; fmt = -1; + switch(ftype) { + case mpx_tfm_format: fmt = kpse_tfm_format; break; + case mpx_vf_format: fmt = kpse_vf_format; req = false; break; + case mpx_trfontmap_format: fmt = kpse_mpsupport_format; break; + case mpx_trcharadj_format: fmt = kpse_mpsupport_format; break; + case mpx_desc_format: fmt = kpse_troff_font_format; break; + case mpx_fontdesc_format: fmt = kpse_troff_font_format; break; + case mpx_specchar_format: fmt = kpse_mpsupport_format; break; + } + if (fmt<0) return NULL; + return kpse_find_file (nam, fmt, req); +} + +@ Invoke makempx (or troffmpx) to make sure there is an up-to-date + .mpx file for a given .mp file. (Original from John Hobby 3/14/90) + +@d default_args " --parse-first-line --interaction=nonstopmode" +@d TEX "tex" +@d TROFF "soelim | eqn -Tps -d$$ | troff -Tps" + +@c +#ifndef MPXCOMMAND +#define MPXCOMMAND "makempx" +#endif +static int mpost_run_make_mpx (MP mp, char *mpname, char *mpxname) { + int ret; + char *cnf_cmd = kpse_var_value ("MPXCOMMAND"); + + if (cnf_cmd != NULL && (strcmp (cnf_cmd, "0")==0)) { + /* If they turned off this feature, just return success. */ + ret = 0; + + } else { + /* We will invoke something. Compile-time default if nothing else. */ + char *cmd; + char *tmp = normalize_quotes(mpname, "mpname"); + char *qmpname = kpse_find_file (tmp,kpse_mp_format, true); + char *qmpxname = normalize_quotes(mpxname, "mpxname"); + mpost_xfree(tmp); + if (cnf_cmd!=NULL && (strcmp (cnf_cmd, "1")!=0)) { + if (mp_troff_mode(mp)!=0) + cmd = concatn (cnf_cmd, " -troff ", + qmpname, " ", qmpxname, NULL); + else if (mpost_tex_program!=NULL && *mpost_tex_program != '\0') + cmd = concatn (cnf_cmd, " -tex=", mpost_tex_program, " ", + qmpname, " ", qmpxname, NULL); + else + cmd = concatn (cnf_cmd, " -tex ", qmpname, " ", qmpxname, NULL); + + /* Run it. */ + ret = system (cmd); + free (cmd); + mpost_xfree(qmpname); + mpost_xfree(qmpxname); + } else { + mpx_options * mpxopt; + char *s = NULL; + char *maincmd = NULL; + int mpxmode = mp_troff_mode(mp); + char *mpversion = mp_metapost_version () ; + mpxopt = mpost_xmalloc(sizeof(mpx_options)); + if (mpost_tex_program != NULL && *mpost_tex_program != '\0') { + maincmd = mpost_xstrdup(mpost_tex_program); + } else { + if (mpxmode == mpx_tex_mode) { + s = kpse_var_value("TEX"); + if (s==NULL) s = kpse_var_value("MPXMAINCMD"); + if (s==NULL) s = mpost_xstrdup (TEX); + maincmd = (char *)mpost_xmalloc (strlen(s)+strlen(default_args)+1); + strcpy(maincmd,s); + strcat(maincmd,default_args); + free(s); + } else { + s = kpse_var_value("TROFF"); + if (s==NULL) s = kpse_var_value("MPXMAINCMD"); + if (s==NULL) s = mpost_xstrdup (TROFF); + maincmd = s; + } + } + mpxopt->mode = mpxmode; + mpxopt->cmd = maincmd; + mpxopt->mptexpre = kpse_var_value("MPTEXPRE"); + mpxopt->debug = debug; + mpxopt->mpname = qmpname; + mpxopt->mpxname = qmpxname; + mpxopt->find_file = makempx_find_file; + { + char *banner = "% Written by metapost version "; + mpxopt->banner = mpost_xmalloc(strlen(mpversion)+strlen(banner)+1); + strcpy (mpxopt->banner, banner); + strcat (mpxopt->banner, mpversion); + } + ret = mpx_makempx(mpxopt); + mpost_xfree(mpxopt->cmd); + mpost_xfree(mpxopt->mptexpre); + mpost_xfree(mpxopt->banner); + mpost_xfree(mpxopt->mpname); + mpost_xfree(mpxopt->mpxname); + mpost_xfree(mpxopt); + mpost_xfree(mpversion); + } + } + + mpost_xfree (cnf_cmd); + return (int)(ret == 0); +} + +static int mpost_run_dvitomp (char *dviname, char *mpxname) { + int i, ret; + char *m, *d; + mpx_options * mpxopt; + char *mpversion = mp_metapost_version () ; + mpxopt = mpost_xmalloc(sizeof(mpx_options)); + memset(mpxopt,0,sizeof(mpx_options)); + mpxopt->mode = mpx_tex_mode; + if (dviname == NULL) + return EXIT_FAILURE; + i = strlen(dviname); + if (mpxname==NULL) { + m = mpost_xstrdup(dviname); + if (i>4 && *(m+i-4)=='.' + && *(m+i-3)=='d' && *(m+i-2)=='v' && *(m+i-1)=='i') + *(m+i-4)='\0' ; + } else { + m = mpost_xstrdup(mpxname); + } + d = mpost_xstrdup(dviname); + if (!(i>4 && *(d+i-4)=='.' + && *(d+i-3)=='d' && *(d+i-2)=='v' && *(d+i-1)=='i')) { + char *s = malloc (i+5); + memset(s,0,i+5); + s = strcat(s, d); + (void)strcat(s+i-1, ".dvi"); + mpost_xfree (d); + d = s ; + } + + i = strlen(m); + if (i>4 && *(m+i-4)=='.' + && *(m+i-3)=='m' && *(m+i-2)=='p' && *(m+i-1)=='x') { + } else { + char *s = malloc (i+5); + memset(s,0,i+5); + s = strcat(s, m); + (void)strcat(s+i-1, ".mpx"); + mpost_xfree (m); + m = s ; + } + mpxopt->mpname = d; + mpxopt->mpxname = m; + + mpxopt->find_file = makempx_find_file; + { + char *banner = "% Written by dvitomp version "; + mpxopt->banner = mpost_xmalloc(strlen(mpversion)+strlen(banner)+1); + strcpy (mpxopt->banner, banner); + strcat (mpxopt->banner, mpversion); + } + ret = mpx_run_dvitomp(mpxopt); + mpost_xfree(mpxopt->banner); + mpost_xfree(mpxopt); + mpost_xfree(mpversion); + return ret; +} + + +@ +@<Register the callback routines@>= +if (!nokpse) + options->run_make_mpx = mpost_run_make_mpx; + + +@ @c +static int get_random_seed (void) { + int ret = 0; +#if defined (HAVE_GETTIMEOFDAY) + struct timeval tv; + gettimeofday(&tv, NULL); + ret = (tv.tv_usec + 1000000 * tv.tv_usec); +#elif defined (HAVE_FTIME) + struct timeb tb; + ftime(&tb); + ret = (tb.millitm + 1000 * tb.time); +#else + time_t clock = time ((time_t*)NULL); + struct tm *tmptr = localtime(&clock); + if (tmptr!=NULL) + ret = (tmptr->tm_sec + 60*(tmptr->tm_min + 60*tmptr->tm_hour)); +#endif + return ret; +} + +@ @<Register the callback routines@>= +options->random_seed = get_random_seed(); + +@ @c +static char *mpost_find_file(MP mp, const char *fname, const char *fmode, int ftype) { + size_t l ; + char *s; + (void)mp; + s = NULL; + if (fmode[0]=='r') { + if (ftype>=mp_filetype_text) { + s = kpse_find_file (fname, kpse_mp_format, 0); + } else { + switch(ftype) { + case mp_filetype_program: + l = strlen(fname); + if (l>3 && strcmp(fname+l-3,".mf")==0) { + s = kpse_find_file (fname, kpse_mf_format, 0); + } else { + s = kpse_find_file (fname, kpse_mp_format, 0); + } + break; + case mp_filetype_memfile: + s = kpse_find_file (fname, kpse_mem_format, 1); + break; + case mp_filetype_metrics: + s = kpse_find_file (fname, kpse_tfm_format, 0); + break; + case mp_filetype_fontmap: + s = kpse_find_file (fname, kpse_fontmap_format, 0); + break; + case mp_filetype_font: + s = kpse_find_file (fname, kpse_type1_format, 0); + break; + case mp_filetype_encoding: + s = kpse_find_file (fname, kpse_enc_format, 0); + break; + } + } + } else { + if (fname!=NULL) + s = mpost_xstrdup(fname); /* when writing */ + } + return s; +} + +@ @<Register the callback routines@>= +if (!nokpse) + options->find_file = mpost_find_file; + +@ @c +static void *mpost_open_file(MP mp, const char *fname, const char *fmode, int ftype) { + char realmode[3]; + char *s; + if (ftype==mp_filetype_terminal) { + return (fmode[0] == 'r' ? stdin : stdout); + } else if (ftype==mp_filetype_error) { + return stderr; + } else { + s = mpost_find_file (mp, fname, fmode, ftype); + if (s!=NULL) { + void *ret = NULL; + realmode[0] = *fmode; + realmode[1] = 'b'; + realmode[2] = '\0'; + ret = (void *)fopen(s,realmode); + if (recorder_enabled) { + if (!recorder_file) + recorder_start(job_name); + if (*fmode == 'r') + fprintf(recorder_file, "INPUT %s\n", s); + else + fprintf(recorder_file, "OUTPUT %s\n", s); + } + free(s); + return ret; + } + } + return NULL; +} + +@ @<Register the callback routines@>= +if (!nokpse) + options->open_file = mpost_open_file; + + +@ At the moment, the command line is very simple. + +@d option_is(A) ((strncmp(argv[a],"--" A, strlen(A)+2)==0) || + (strncmp(argv[a],"-" A, strlen(A)+1)==0)) +@d option_arg(B) (mpost_optarg != NULL && strncmp(mpost_optarg,B, strlen(B))==0) + + +@<Read and set command line options@>= +{ + char *mpost_optarg; + boolean ini_version_test = false; + while (++a<argc) { + mpost_optarg = strstr(argv[a],"=") ; + if (mpost_optarg!=NULL) { + mpost_optarg++; + if (*mpost_optarg == '\0') mpost_optarg=NULL; + } + if (option_is("ini")) { + ini_version_test = true; + } else if (option_is("debug")) { + debug = 1; + } else if (option_is ("kpathsea-debug")) { + if (mpost_optarg!=NULL) + kpathsea_debug |= atoi (mpost_optarg); + } else if (option_is("mem")) { + if (mpost_optarg!=NULL) { + mpost_xfree(options->mem_name); + options->mem_name = mpost_xstrdup(mpost_optarg); + if (user_progname == NULL) + user_progname = mpost_optarg; + } + } else if (option_is("jobname")) { + if (mpost_optarg!=NULL) { + mpost_xfree(options->job_name); + options->job_name = mpost_xstrdup(mpost_optarg); + } + } else if (option_is ("progname")) { + user_progname = mpost_optarg; + } else if (option_is("troff") || option_is("T")) { + options->troff_mode = (int)true; + } else if (option_is("recorder")) { + recorder_enabled = true; + } else if (option_is ("tex")) { + mpost_tex_program = mpost_optarg; + } else if (option_is("interaction")) { + if (option_arg("batchmode")) { + options->interaction = mp_batch_mode; + } else if (option_arg("nonstopmode")) { + options->interaction = mp_nonstop_mode; + } else if (option_arg("scrollmode")) { + options->interaction = mp_scroll_mode; + } else if (option_arg("errorstopmode")) { + options->interaction = mp_error_stop_mode; + } else { + fprintf(stdout,"warning: %s: unknown option argument %s\n", argv[0], argv[a]); + } + } else if (option_is("no-kpathsea")) { + nokpse=true; + } else if (option_is("file-line-error")) { + options->file_line_error_style=true; + } else if (option_is("no-file-line-error")) { + options->file_line_error_style=false; + } else if (option_is("dvitomp")) { + dvitomp_only = 1; + } else if (option_is("help")) { + @<Show help and exit@>; + } else if (option_is("version")) { + @<Show version and exit@>; + } else if (option_is("8bit") || + option_is("parse-first-line")) { + /* do nothing, these are always on */ + } else if (option_is("halt-on-error")) { + options->halt_on_error = true; + } else if (option_is("translate-file") || + option_is("output-directory") || + option_is("no-parse-first-line")) { + fprintf(stdout,"warning: %s: unimplemented option %s\n", argv[0], argv[a]); + } else if (option_is("")) { + fprintf(stdout,"fatal error: %s: unknown option %s\n", argv[0], argv[a]); + exit(EXIT_FAILURE); + } else { + break; + } + } + options->ini_version = (int)ini_version_test; +} + +@ +@<Show help...@>= +{ +fprintf(stdout, +"\n" +"Usage: mpost [OPTION] [&MEMNAME] [MPNAME[.mp]] [COMMANDS]\n" +" mpost --dvitomp DVINAME[.dvi] [MPXNAME[.mpx]]\n" +"\n" +" Run MetaPost on MPNAME, usually creating MPNAME.NNN (and perhaps\n" +" MPNAME.tfm), where NNN are the character numbers generated.\n" +" Any remaining COMMANDS are processed as MetaPost input,\n" +" after MPNAME is read.\n\n" +" With a --dvitomp argument, MetaPost acts as DVI-to-MPX converter only.\n\n"); +fprintf(stdout, +" -ini be inimpost, for dumping mem files\n" +" -interaction=STRING set interaction mode (STRING=batchmode/nonstopmode/\n" +" scrollmode/errorstopmode)\n" +" -jobname=STRING set the job name to STRING\n" +" -progname=STRING set program (and mem) name to STRING\n" +" -tex=TEXPROGRAM use TEXPROGRAM for text labels\n" +" [-no]-file-line-error disable/enable file:line:error style messages\n" +); +fprintf(stdout, +" -kpathsea-debug=NUMBER set path searching debugging flags according to\n" +" the bits of NUMBER\n" +" -mem=MEMNAME or &MEMNAME use MEMNAME instead of program name or a %%& line\n" +" -recorder enable filename recorder\n" +" -troff set prologues:=1 and assume TEXPROGRAM is really troff\n" +" -help display this help and exit\n" +" -version output version information and exit\n" +"\n" +"Email bug reports to mp-implementors@@tug.org.\n" +"\n"); + exit(EXIT_SUCCESS); +} + +@ +@<Show version...@>= +{ + char *s = mp_metapost_version(); +fprintf(stdout, +"\n" +"MetaPost %s\n" +"Copyright 2008 AT&T Bell Laboratories.\n" +"There is NO warranty. Redistribution of this software is\n" +"covered by the terms of both the MetaPost copyright and\n" +"the Lesser GNU Lesser General Public License.\n" +"For more information about these matters, see the files\n" +"named COPYING, COPYING.LESSER and the MetaPost source.\n" +"Primary author of MetaPost: John Hobby.\n" +"Current maintainer of MetaPost: Taco Hoekwater.\n" +"\n", s); + mpost_xfree(s); + exit(EXIT_SUCCESS); +} + +@ The final part of the command line, after option processing, is +stored in the \MP\ instance, this will be taken as the first line of +input. + +@d command_line_size 256 + +@<Copy the rest of the command line@>= +{ + mpost_xfree(options->command_line); + options->command_line = mpost_xmalloc(command_line_size); + strcpy(options->command_line,""); + if (a<argc) { + k=0; + for(;a<argc;a++) { + char *c = argv[a]; + while (*c != '\0') { + if (k<(command_line_size-1)) { + options->command_line[k++] = *c; + } + c++; + } + options->command_line[k++] = ' '; + } + while (k>0) { + if (options->command_line[(k-1)] == ' ') + k--; + else + break; + } + options->command_line[k] = '\0'; + } +} + +@ A simple function to get numerical |texmf.cnf| values +@c +static int setup_var (int def, const char *var_name, boolean nokpse) { + if (!nokpse) { + char * expansion = kpse_var_value (var_name); + if (expansion) { + int conf_val = atoi (expansion); + free (expansion); + if (conf_val > 0) { + return conf_val; + } + } + } + return def; +} + +@ @<Set up the banner line@>= +{ + char * mpversion = mp_metapost_version () ; + const char * banner = "This is MetaPost, version "; + const char * kpsebanner_start = " ("; + const char * kpsebanner_stop = ")"; + mpost_xfree(options->banner); + options->banner = mpost_xmalloc(strlen(banner)+ + strlen(mpversion)+ + strlen(kpsebanner_start)+ + strlen(kpathsea_version_string)+ + strlen(kpsebanner_stop)+1); + strcpy (options->banner, banner); + strcat (options->banner, mpversion); + strcat (options->banner, kpsebanner_start); + strcat (options->banner, kpathsea_version_string); + strcat (options->banner, kpsebanner_stop); + mpost_xfree(mpversion); +} + +@ Precedence order is: + +\item {} \.{-mem=MEMNAME} on the command line +\item {} \.{\&MEMNAME} on the command line +\item {} \.{\%\&MEM} as first line inside input file +\item {} \.{argv[0]} if all else fails + +@<Discover the mem name@>= +{ + char *m = NULL; /* head of potential |mem_name| */ + char *n = NULL; /* a moving pointer */ + if (options->command_line != NULL && *(options->command_line) == '&'){ + m = mpost_xstrdup(options->command_line+1); + n = m; + while (*n != '\0' && *n != ' ') n++; + while (*n == ' ') n++; + if (*n != '\0') { /* more command line to follow */ + char *s = mpost_xstrdup(n); + if (n>m) n--; + while (*n == ' ' && n>m) n--; + n++; + *n ='\0'; /* this terminates |m| */ + mpost_xfree(options->command_line); + options->command_line = s; + } else { /* only \.{\&MEMNAME} on command line */ + if (n>m) n--; + while (*n == ' ' && n>m) n--; + n++; + *n ='\0'; /* this terminates |m| */ + mpost_xfree(options->command_line); + } + if ( options->mem_name == NULL && *m != '\0') { + mpost_xfree(options->mem_name); /* for lint only */ + options->mem_name = m; + } else { + mpost_xfree(m); + } + } +} +if ( options->mem_name == NULL ) { + char *m = NULL; /* head of potential |job_name| */ + char *n = NULL; /* a moving pointer */ + if (options->command_line != NULL && *(options->command_line) != '\\'){ + m = mpost_xstrdup(options->command_line); + n = m; + while (*n != '\0' && *n != ' ') n++; + if (n>m) { + char *fname; + *n='\0'; + fname = m; + if (!nokpse) + fname = kpse_find_file(m,kpse_mp_format,true); + if (fname == NULL) { + mpost_xfree(m); + } else { + FILE *F = fopen(fname,"r"); + if (F==NULL) { + mpost_xfree(fname); + } else { + char *line = mpost_xmalloc(256); + if (fgets(line,255,F) == NULL) { + (void)fclose(F); + mpost_xfree(fname); + mpost_xfree(line); + } else { + (void)fclose(F); + while (*line != '\0' && *line == ' ') line++; + if (*line == '%') { + n = m = line+1; + while (*n != '\0' && *n == ' ') n++; + if (*n == '&') { + m = n+1; + while (*n != '\0' && *n != ' ') n++; + if (n>(m+1)) { + n--; + while (*n == ' ' && n>m) n--; + *n ='\0'; /* this terminates |m| */ + options->mem_name = mpost_xstrdup(m); + mpost_xfree(fname); + } else { + mpost_xfree(fname); + mpost_xfree(line); + } + } + } + } + } + } + } else { + mpost_xfree(m); + } + } +} +if ( options->mem_name == NULL ) + if (kpse_program_name!=NULL) + options->mem_name = mpost_xstrdup(kpse_program_name); + + +@ The jobname needs to be known for the recorder to work. + +@<Discover the job name@>= +if ( options->job_name == NULL ) { + char *m = NULL; /* head of potential |job_name| */ + char *n = NULL; /* a moving pointer */ + if (options->command_line != NULL){ + m = mpost_xstrdup(options->command_line); + n = m; + if (*(options->command_line) != '\\') { /* this is the simple case */ + while (*n != '\0' && *n != ' ') n++; + if (n>m) { + *n='\0'; + job_name = mpost_xstrdup(m); + } + } else { /* this is still not perfect, but better */ + char *mm = strstr(m,"input "); + if (mm != NULL) { + mm += 6; + n = mm; + while (*n != '\0' && *n != ' ' && *n!=';') n++; + if (n>mm) { + *n='\0'; + job_name = mpost_xstrdup(mm); + } + } + } + free(m); + } + if (job_name == NULL) { + if (options->ini_version == 1 && + options->mem_name != NULL) { + job_name = mpost_xstrdup(options->mem_name); + } + } + if (job_name == NULL) { + job_name = mpost_xstrdup("mpout"); + } else { + size_t i = strlen(job_name); + if (i>3 + && *(job_name+i-3)=='.' + && *(job_name+i-2)=='m' + && *(job_name+i-1)=='p') + *(job_name+i-3)='\0'; + } + options->job_name = job_name; +} else { + job_name = mpost_xstrdup(options->job_name); +} + + +@ Now this is really it: \MP\ starts and ends here. + +@c +int main (int argc, char **argv) { /* |start_here| */ + int k; /* index into buffer */ + int history; /* the exit status */ + MP mp; /* a metapost instance */ + struct MP_options * options; /* instance options */ + int a=0; /* argc counter */ + boolean nokpse = false; /* switch to {\it not} enable kpse */ + char *user_progname = NULL; /* If the user overrides argv[0] with -progname. */ + options = mp_options(); + options->ini_version = (int)false; + options->print_found_names = (int)true; + @<Read and set command line options@>; + if (dvitomp_only) { + char *mpx = NULL, *dvi = NULL; + if (a==argc) { + /* error ? */ + } else { + dvi = argv[a++]; + if (a<argc) { + mpx = argv[a++]; + } + } + if (!nokpse) + kpse_set_program_name("dvitomp", user_progname); + exit (mpost_run_dvitomp(dvi, mpx)); + } + + @= /*@@-nullpass@@*/ @> + if (!nokpse) { + kpse_set_program_enabled (kpse_mem_format, MAKE_TEX_FMT_BY_DEFAULT, + kpse_src_compile); + kpse_set_program_name("mpost", user_progname); + } + @= /*@@=nullpass@@*/ @> + if(putenv((char *)"engine=metapost")) + fprintf(stdout,"warning: could not set up $engine\n"); + options->main_memory = setup_var (50000,"main_memory",nokpse); + options->hash_size = (unsigned)setup_var (16384,"hash_size",nokpse); + options->max_in_open = setup_var (25,"max_in_open",nokpse); + options->param_size = setup_var (1500,"param_size",nokpse); + options->error_line = setup_var (79,"error_line",nokpse); + options->half_error_line = setup_var (50,"half_error_line",nokpse); + options->max_print_line = setup_var (100,"max_print_line",nokpse); + @<Set up the banner line@>; + @<Copy the rest of the command line@>; + if (options->ini_version!=(int)true) { + @<Discover the mem name@>; + } + @<Discover the job name@>; + @<Register the callback routines@>; + mp = mp_initialize(options); + mpost_xfree(options->command_line); + mpost_xfree(options->mem_name); + mpost_xfree(options->job_name); + mpost_xfree(options->banner); + free(options); + if (mp==NULL) + exit(EXIT_FAILURE); + history = mp_status(mp); + if (history!=0) + exit(history); + history = mp_run(mp); + (void)mp_finish(mp); + exit(history); +} + |