/* * jcabc2ps: a program to typeset tunes written in abc format using PostScript * Copyright (C) 1996,1997,1998 Michael Methfessel * Copyright (C) 1999, 2001, 2002, 2003 John Chambers * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., 675 * Mass Ave, Cambridge, MA 02139, USA. Or visit www.fsf.org, especially the * http://www.fsf.org/licenses/licenses.html page. * * The authors can be contacted as follows: * * John Chambers * jc@ecf-guest.mit.edu * * Michael Methfessel * methfessel@ihp-ffo.de * Institute for Semiconductor Physics, PO Box 409, * D-15204 Frankfurt (Oder), Germany */ /* Main program jcabc2ps.c */ #include #include "jcabc2ps.h" #include "subs.h" #include "format.h" #include "util.h" #include "parse.h" #include "music.h" /* ----- definitions of global variables ----- */ int db = DB_DF; /* debug control */ int vb = VB_DF; /* verbosity, global */ int verbose = VB_DF; /* verbosity, within tune */ int tunebuffsz = TUNEBUFFSZ; // Actual size of tunebuf[] int staffbufsz = STAFFBUFSZ; // Actual size of staffbuf[] int maxSyms,maxVc; /* for malloc */ Info default_info; /* information fields */ Info info; char lvoiceid[256]; /* string from last V: line */ int nvoice,mvoice; /* number of voices defd, nonempty */ int ivc; /* current voice */ int ivc0; /* top nonempty voice */ int ixpfree; /* first free element in xp array */ Msig default_meter; /* data to specify the meter */ /* * Keysig stuff: */ Ksig default_key = {0}; /* The key in the K: header line */ //Ksig*ksiglist = &default_key; /* List of Ksigs */ //Ksig*ksiglast = &default_key; /* List end */ //int ksignum = 0; /* Highest number of Ksigs so far */ /* things to alloc: */ Sym* sym = 0; /* symbol list */ Sym** symv = 0; /* symbols for voices */ struct XPOS *xp = 0; /* shared horizontal positions */ Voice* voice = 0; /* characteristics of a voice */ Sym** sym_st = 0; /* symbols a staff start */ int* nsym_st = 0; int halftones = 0; /* number of halftones to transpose by */ float f0p,f5p,f1p,f0x,f5x,f1x; /* mapping fct */ float lnnp,bnnp,fnnp,lnnx,bnnx,fnnx; /* note-note spacing */ float lbnp,bbnp,rbnp,lbnx,bbnx,rbnx; /* bar-note spacing */ float lnbp,bnbp,rnbp,lnbx,bnbx,rnbx; /* note-bar spacing */ char wpool[NWPOOL]; /* pool for vocal strings */ int nwpool,nwline; /* globals to handle wpool */ struct FORMAT sfmt; /* format after initialization */ struct FORMAT dfmt; /* format at start of tune */ struct FORMAT cfmt; /* current format for output */ char fontnames[50][STRLFMT]; /* list of needed fonts */ int nfontnames; char txt[MAXNTEXT][MAXWLEN]; /* for output of text */ int ntxt; char vcselstr[101] = {0}; /* string for voice selection */ char mbf[501] = {0}; /* mini-buffer for one line */ char *tunebuf = 0; // output buffer.. should hold one tune char *staffbuf = 0; // output buffer.. should hold one staff int nbuf = 0; /* number of bytes buffered */ float bposy = 0.0; /* current position in buffered data */ int ln_num = 0; /* number of lines in buffer */ float ln_pos[BUFFLN] = {0}; /* vertical positions of buffered lines */ int ln_buf[BUFFLN] = {0}; /* buffer location of buffered lines */ int use_buffer = 0; /* 1 if lines are being accumulated */ char text[NTEXT][STRL]; /* pool for history, words, etc. lines */ int text_type[NTEXT]; /* type of each text line */ int ntext; /* number of text lines */ char page_init[201]; /* initialization string after page break */ int do_mode = DO_OUTPUT; /* control whether to do index or output */ char escseq[81]; /* escape sequence string */ int linenum; /* current line number in input file */ int tunenum; /* number of current tune */ int tnum1,tnum2; int numtitle; /* how many titles were read */ int mline; /* number music lines in current tune */ int nsym; /* number of symbols in line */ int nsym0; /* nsym at start of parsing a line */ int pagenum; /* current page in output file */ int writenum; /* calls to write_buffer for each one tune */ int xrefnum; /* xref number of current tune */ int do_meter, do_indent; /* how to start next block */ int index_pagenum; /* for index file */ float index_posx, index_posy; int index_initialized; char ach[201]; /* accompaniment chord string */ Text* ann = 0; /* Global anotation string */ int bagpipe; /* switch for HP mode */ int within_tune, within_block; /* where we are in the file */ int do_this_tune; /* are we typesetting the current one ? */ float posx,posy; /* overall scale, position on page */ int barinit; /* carryover bar number between parts */ char *P, *Q; /* global pointers for parsing music line */ int word,slur; /* variables used for parsing... */ int last_note,last_real_note; int pplet,qplet,rplet; int carryover; /* for interpreting > and < chars */ int ntinext,tinext[MAXHD]; /* for chord ties */ struct ENDINGS ending[20]; /* where to draw endings */ int num_ending; /* number of endings to draw */ int mes1,mes2; /* to count measures in an ending */ int slur1[20],slur2[20]; /* needed for drawing slurs */ int overfull; /* flag if staff overfull */ //int do_words; /* flag if staff has words under it */ int in_page = 0; /* switches modified by flags: */ int gmode; /* switch for glue treatment */ int include_xrefs; /* to include xref numbers in title */ int one_per_page; /* new page for each tune ? */ int pagenumbers; /* write page numbers ? */ int write_history; /* write history and notes ? */ int interactive; /* interactive mode ? */ int help_me; /* need help ? */ int select_all; /* select all tunes ? */ int epsf; /* for EPSF postscript output */ int choose_outname; /* 1 names outfile w. title/fnam */ int break_continues = 0; /* ignore continuations ? */ int search_field0; /* default search field */ int pretty; /* for pretty but sprawling layout */ int bars_per_line = 0; /* bars for auto linebreaking */ int continue_lines = 0; /* flag to continue all lines */ int landscape = 0; /* flag for landscape output */ int slurgraces = 0; /* flag for slurring grace notes */ int barnums = 0; /* interval for bar numbers */ int make_index = 0; /* write index file ? */ int make_audio = 0; /* write audio playback file ? */ int make_ps = 1; /* write PostScript output file ? */ float alfa_c = 1.0; /* max compression allowed */ float scalefac; /* scale factor for symbol size */ float lmargin; /* left margin */ float swidth; /* staff width */ float staffsep,dstaffsep; /* staff separation */ float strict1,strict2; /* 1stave, mstave strictness */ float playtempo; /* tempo for audio output */ char transpose[21]; /* target key for transposition */ char au_qstr[21]; /* code for au quality selection */ float alfa_last,beta_last; /* for last short short line.. */ char in_file[MAXINF][STRL1]; /* list of input file names */ int ninf; /* number of input file names */ FILE *fin; /* for input file */ char outf[STRL1]; /* output file name */ char outfnam[STRL1]; /* internal file name for open/close */ char styf[STRL1]; /* layout style file name */ char styd[STRL1]; /* layout style directory */ char infostr[STRL1]; /* title string in PS file */ int file_open; /* for output file */ int file_initialized; /* for output file */ FILE *fout,*findex; /* for output file */ int nepsf; /* counter for epsf output files */ char sel_str[MAXINF][STRL1]; /* list of selector strings */ int s_field[MAXINF]; /* type of selection for each file */ int psel[MAXINF]; /* pointers from files to selectors */ int temp_switch; char *mypath = "???"; // argv[0], the program's invoked pathname char *myname = "abc2ps"; // Program name minus directories int use_stdin = 1; // reading standard input int use_stdout = 1; // writing standard output /* ----- start of main ------ */ int main(argc, argv) int argc; char *argv[]; { char *F="main"; char aaa[501],bbb[501],ccc[501],ext[41]; char xref_str[STRL1], pat[30][STRL1]; char *urgv[100]; char *p; int isel,j,npat,search_field,urgc,retcode,rc1; for (p = myname = mypath = argv[0]; *p; p++) { if (*p == '/' && *(p+1)) { myname = p + 1; } } /* ----- set default options and parse arguments ----- */ maxSyms = 2000; maxVc = 8; init_ops (1); retcode = parse_args (argc, argv); if (retcode) { V2 "%s: Exit with status %d.\n",mypath,retcode V; exit (1); } if (interactive || (do_mode == DO_OUTPUT)) { // V2 "This is jcabc2ps, version %s.%s (%s)\n", VERSION, REVISION, VDATE V; V2 "This is jcabc2ps, version %s\n", version V; } alloc_structs (); /* ----- set the page format ----- */ nfontnames = 0; if (!set_page_format()) exit (3); if (help_me == 2) { print_format(cfmt); exit (0); } /* ----- help printout ----- */ // if (argc <= 1) help_me = 1; if (help_me == 1) { write_help (); exit (0); } // Allocate runtime stuff if (!(tunebuf = (char*)malloc(tunebuffsz))) { V1 "Can't malloc tunebuffsz=%d for tunebuf.\n",tunebuffsz V; exit(1); } if (!(staffbuf = (char*)malloc(staffbufsz))) { V1 "Can't malloc staffbufsz=%d for staffbuf.\n",staffbufsz V; exit(1); } // if ((ninf == 0) && (!interactive)) rx ("No input file specified", ""); if ((ninf < 1) && (!interactive)) { V2 "No input file specified.\n" V; if (use_stdin) { V2 "Reading standard input.\n" V; psel[0] = 0; // What's this? strcpy(in_file[j=0],"[stdin]"); // Symbolic name of input file V2 "%s: in_file[%d]=\"%s\"\n",F,j,in_file[j] V; ninf = 1; // Number of input files file_open = 1; file_initialized = 1; } else { V2 "Can't determine input file.\n" V; } } else { file_open = file_initialized = 0; } // if (use_stdout) { // V2 "%s: Writing to stdout.\n",F V; // strcpy(in_file[j],"[stdout]"); // fout = stdout; // } isel = psel[ninf-1]; search_field0 = s_field[isel]; /* default for interactive mode */ if (epsf || outf) { V6 "epsf=%d outf=\"%s\" [before cutext]\n",epsf,outf V; cutext(outf); V6 "epsf=%d outf=\"%s\" [after cutext]\n",epsf,outf V; } /* ----- initialize ----- */ // zero_sym(); pagenum = 0; tunenum = tnum1 = tnum2 = 0; nepsf = 0; bposy = 0.0; posx = cfmt.leftmargin; posy = cfmt.pageheight-cfmt.topmargin; strcpy(page_init, ""); strcpy (bbb,""); for (j = 0;j errorLimit) { fprintf(stderr,"+++ TOO MANY ERRORS (%d) +++\n",syntaxErrors); exit(1); } V2 "%s: in_file[%d]=\"%s\"\n",F,j,in_file[j] V; getext (in_file[j],ext); V2 "%s: in_file[%d]=\"%s\" ext=\"%s\"\n",F,j,in_file[j],ext V; /* skip .ps and .eps files */ if ((!strcmp(ext,"ps"))||(!strcmp(ext,"eps"))) continue; if (use_stdin) { V2 "%s: Reading from stdin.\n",F V; fin = stdin; } else { V2 "%s: Reading from \"%s\".\n",F,in_file[j] V; if ((fin = fopen (in_file[j],"r")) == NULL) { if (!strcmp(ext,"")) strext (in_file[j],in_file[j],"abc",1); if ((fin = fopen (in_file[j],"r")) == NULL) { fprintf(stderr,"++++ Cannot open input file: %s\n", in_file[j]); continue; } } } isel = psel[j]; search_field = s_field[isel]; npat = rehash_selectors (sel_str[isel], xref_str, pat); dfmt = sfmt; strcpy(infostr, in_file[j]); if (do_mode == DO_INDEX) { if (verbose > 1) fprintf(stderr,"%s:\n", in_file[j]); do_index(fin,xref_str,npat,pat,select_all,search_field); } else { if (!epsf) { if (*outf) { V2 "%s: outf=\"%s\" [before strext]\n",F,outf V; strext(outf, outf, "ps", 1); if (choose_outname) { strext(outf, in_file[j], "ps", 1); V2 "%s: outf=\"%s\" [after strext]\n",F,outf V; } V2 "%s: outf=\"%s\"\n",F,outf V; } if (use_stdout) { V2 "%s: Writing to stdout.\n",F V; strcpy(in_file[j],"[stdout]"); fout = stdout; // Do setup for stdout stream pagenum = 0; tunenum = 0; tnum1 = 0; tnum2 = 0; file_initialized = 0; file_open = 1; } else { V2 "%s: open_output_file(\"%s\",\"%s\")\n",F,outf,in_file[j] V; open_output_file(outf,in_file[j]); } } V2 "%s: in_file[%d]=\"%s\"\n",F,j,in_file[j] V; if ((vb >= 3) || interactive) fprintf(stderr,"\n"); doFile(fin,fout,xref_str,npat,pat,select_all,search_field); if (verbose > 1) fprintf(stderr,"\n"); } } if (!interactive) break; } // if ((!interactive) && (do_mode == DO_INDEX)) // fprintf(stderr,"Selected %d title%s of %d\n", tnum1, tnum1 == 1?"":"s", tnum2); close_output_file (); if ((do_mode == DO_OUTPUT) && make_index) close_index_file (); if ((do_mode == DO_OUTPUT) && make_audio) close_audio_file (); exit(0); }