home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume6 / yahp2ps / part05 / io.c next >
C/C++ Source or Header  |  1989-02-03  |  13KB  |  726 lines

  1. /*
  2.         HPGL to PostScript converter
  3.    Copyright (C) 1988 (and following) Federico Heinz
  4.  
  5. yahp2ps is distributed in the hope that it will be useful, but WITHOUT ANY
  6. WARRANTY.  No author or distributor accepts responsibility to anyone
  7. for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.
  9. Refer to the Free Software Foundation's General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute yahp2ps,
  12. but only under the conditions described in the GNU General Public
  13. License.  A copy of this license is supposed to have been given to you
  14. along with yahp2ps so you can know your rights and responsibilities.  It
  15. should be in a file named COPYING.  Among other things, the copyright
  16. notice and this notice must be preserved on all copies.
  17.  
  18. In other words, go ahead and share yahp2ps, but don't try to stop
  19. anyone else from sharing it farther.  Help stamp out software hoarding!
  20.  
  21. yahp2ps is TOTALLY unrelated to GNU or the Free Software Foundation,
  22. it is only released under the same conditions.
  23.  
  24.     For bug reports, wishes, etc. send e-mail to
  25.  
  26.     ...!mcvax!unido!tub!actisb!federico  (from Europe)
  27.     ...!uunet!pyramid!actisb!federico    (from anywhere else)
  28.  
  29.     For Physical mail:
  30.  
  31.     Federico Heinz
  32.     Beusselstr. 21
  33.     1000 Berlin 21
  34.  
  35.     Tel. (+49 30) 396 77 92
  36.  
  37. */
  38. /**************************************************************************
  39.  
  40.   Input/Output functions.
  41.  
  42. **************************************************************************/
  43.  
  44. #include <stdio.h>
  45. #include <ctype.h>
  46. #include "defs.h"
  47. #include "dispatch.h"
  48. #include "io.h"
  49.  
  50. int LookAhead = 0;    /* Lookahead feature buffer */
  51.  
  52. /*************************************************************************
  53.  
  54.     Error handling
  55.  
  56. *************************************************************************/
  57.  
  58.  
  59.  
  60. /*
  61.  
  62.   Put a non-fatal warning trough stderr.
  63.  
  64. */
  65.  
  66. void warning(text)
  67.  
  68. char *text;
  69.  
  70. { fprintf(stderr, "hpgl2ps WARNING: %s\n", text);
  71. }
  72.  
  73.  
  74.  
  75. /*
  76.  
  77.   Report a fatal error trough stderr.
  78.  
  79. */
  80.  
  81. void error(text)
  82.  
  83. char *text;
  84.  
  85. { fprintf(stderr, "hpgl2ps ERROR: %s\n", text);
  86.   exit(1);
  87. }
  88.  
  89.  
  90. /**************************************************************************
  91.  
  92.     Basic file I/O
  93.  
  94. **************************************************************************/
  95.  
  96.  
  97. static FILE *input = stdin;
  98.  
  99. static FILE *output = stdout;
  100.  
  101.  
  102. /*
  103.  
  104.   Get the next usable char from the file, skipping escape sequences.
  105.  
  106. */
  107.  
  108. static int getNextC()
  109.  
  110. { int c;
  111.  
  112.   c = getc(input);
  113.   while (c == '\033')
  114.   { (void)getc(input); /* Ignore dot */
  115.     switch (getc(input))
  116.     { case '@':
  117.       case 'H':
  118.       case 'I':
  119.       case 'M':
  120.       case 'N': while (getc(input) != ':') ;
  121.       case '(':
  122.       case 'Y':
  123.       case ')':
  124.       case 'Z':
  125.       case 'B':
  126.       case 'E':
  127.       case 'J':
  128.       case 'K':
  129.       case 'L':
  130.       case 'O':
  131.       case 'R': break;
  132.       default: warning("Illegal escape sequence.");
  133.     }
  134.     c = getc(input);
  135.     while(isTerminator(c)) c = getc(input);
  136.   }
  137.   return(c);
  138. }
  139.  
  140.           
  141.  
  142. /*
  143.  
  144.   Get the next char from the input stream with lookahead
  145.  
  146. */
  147.  
  148. int getChar()
  149.  
  150. { int   aChar;
  151.  
  152.   if (!LookAhead) LookAhead = getNextC();
  153.   aChar = LookAhead;
  154.   if (LookAhead != EOF) LookAhead = getNextC();
  155.   return(aChar);
  156. }
  157.  
  158.  
  159.  
  160.  
  161. /*
  162.  
  163.   Put a char to the output stream.
  164.  
  165. */
  166.  
  167. void putChar(c)
  168.  
  169. char c;
  170.  
  171. { putc(c, output); }
  172.  
  173.  
  174.  
  175. /*************************************************************************
  176.  
  177.    HPGL syntax sensitive stuff
  178.  
  179. *************************************************************************/
  180.  
  181.  
  182.  
  183. /*
  184.  
  185.   Skip over optional separator.
  186.  
  187. */
  188.  
  189. void skipSeparator()
  190.  
  191. { while (isSeparator(LookAhead)) (void)getChar(); }
  192.  
  193.  
  194.  
  195. /*
  196.  
  197.   Skip over statement terminator.
  198.  
  199. */
  200.  
  201. void skipTerminator()
  202.  
  203. { while (isTerminator(LookAhead))
  204.   { (void)getChar();
  205.     skipSeparator();
  206.   }
  207. }
  208.  
  209.  
  210. /*************************************************************************
  211.  
  212.   Number input
  213.  
  214. *************************************************************************/
  215.  
  216.  
  217. /* Powers of ten */
  218.  
  219. static  long int TenToThe[] = { 1L, 10L, 100L, 1000L, 10000L };
  220.  
  221.  
  222.  
  223. /*
  224.  
  225.   Read a Number from the input stream.
  226.  
  227. */
  228.  
  229.  
  230. Boolean getNumber(target)
  231.  
  232. Number *target;
  233.  
  234. { Number result;
  235.   int    placesLeft, decimalsLeft;
  236.   Boolean negative;
  237.  
  238.   if (LookAhead == '+')
  239.   { negative = False;
  240.     getChar();
  241.   }
  242.   else if (LookAhead == '-')
  243.   { negative = True;
  244.     getChar();
  245.   }
  246.   if (!isdigit(LookAhead) && (LookAhead != '.'))
  247.   { warning("Number expected.");
  248.     return(False);
  249.   }
  250.   result = 0; placesLeft = IntPlaces;
  251.   while (isdigit(LookAhead) && placesLeft)
  252.   { result = result * 10L + (Number)(getChar() - '0');
  253.     placesLeft--;
  254.   }
  255.   if (isdigit(LookAhead)) 
  256.   { warning("Number out of range.");
  257.     return(False);
  258.   }
  259.   decimalsLeft = DecPlaces;
  260.   if (LookAhead == '.')
  261.   { (void)getChar();
  262.     while(isdigit(LookAhead) && decimalsLeft)
  263.     { result = result * 10L + (Number)(getChar() - '0');
  264.       decimalsLeft--;
  265.     }
  266.     if (isdigit(LookAhead))
  267.     { warning("Extra decimal places skipped.");
  268.       while(isdigit(LookAhead)) (void)getChar();
  269.     }
  270.   }
  271.   skipSeparator();
  272.   *target = (negative ? -result : result) * TenToThe[decimalsLeft];
  273.   return(True);
  274. }
  275.  
  276.  
  277. /*
  278.  
  279.   Convert from ASCII to Number.
  280.  
  281. */
  282.  
  283. Boolean ASCIIToNumber(target, source)
  284.  
  285. Number *target;
  286. char **source;
  287.  
  288. { Number result;
  289.   int    placesLeft, decimalsLeft;
  290.  
  291.   result = 0; placesLeft = IntPlaces;
  292.   while (isdigit(**source) && placesLeft)
  293.   { result = result * 10L + (Number)((*((*source)++)) - '0');
  294.     placesLeft--;
  295.   }
  296.   if (isdigit(**source))
  297.     return(False);
  298.   decimalsLeft = DecPlaces;
  299.   if (**source == '.')
  300.   { (*source)++;
  301.     while(isdigit(**source) && decimalsLeft)
  302.     { result = result * 10L + (Number)((*((*source)++)) - '0');
  303.       decimalsLeft--;
  304.     }
  305.     while(isdigit(**source)) (*source)++;
  306.   }
  307.   *target = result * TenToThe[decimalsLeft];
  308.   return(True);
  309. }
  310.  
  311.  
  312.  
  313. /*
  314.  
  315.   Read an Integer
  316.  
  317. */
  318.  
  319. Boolean getInteger(target)
  320.  
  321. Number *target;
  322.  
  323. { Number result;
  324.  
  325.   if (getNumber(&result))
  326.   { *target = trunc(result);
  327.     return(True);
  328.   }
  329.   else
  330.     return(False);
  331. }
  332.  
  333.  
  334.  
  335. /*
  336.  
  337.   Read a CoordinatePair.
  338.  
  339. */
  340.  
  341. Boolean getCoordinatePair(target)
  342.  
  343. CoordinatePair target;
  344.  
  345. { if (!getNumber(&target[X])) return(False);
  346.   skipSeparator();
  347.   if (!isNumeric(LookAhead))
  348.   { warning("Uneven number of coordinates.");
  349.     return(False);
  350.   }
  351.   return(getNumber(&target[Y]));
  352. }
  353.  
  354.  
  355. /***************************************************************************
  356.  
  357.    Number output
  358.  
  359. **************************************************************************/
  360.  
  361.    
  362.  
  363.  
  364. /*
  365.  
  366.   Private routine to put a positive integer to the output stream. A zero
  367.   produces no output at all. No space is appended at the end.
  368.  
  369. */
  370.  
  371. static void putInt(n)
  372.  
  373. int n;
  374.  
  375. { if (n)
  376.   { putInt(n / 10);
  377.     putChar((n % 10) + '0');
  378.   }
  379. }
  380.  
  381.  
  382.  
  383. /*
  384.  
  385.   Write a Number to the output stream.
  386.  
  387. */
  388.  
  389. void writeNumber(n)
  390.  
  391. Number n;
  392.  
  393. { int integerPart, fractionalPart;
  394.  
  395.   if (n == Zero)
  396.     putChar('0');
  397.   else
  398.   { if (n < Zero)
  399.     { putChar('-');
  400.       n = -n;
  401.     }
  402.     integerPart = (int)(n / One);
  403.     fractionalPart = (int)(n % One);
  404.     putInt(integerPart);
  405.     if (fractionalPart)
  406.     { putChar('.');
  407.       while (!(fractionalPart % 10)) fractionalPart /= 10;
  408.       putInt(fractionalPart);
  409.     }
  410.   }
  411.   putChar(' ');
  412. }
  413.  
  414.  
  415.  
  416. /*
  417.  
  418.   Write a CoordinatePair to the output stream.
  419.  
  420. */
  421.  
  422. void writeCoordinatePair(source)
  423.  
  424. CoordinatePair  source;
  425.  
  426. { writeNumber(source[X]);
  427.   writeNumber(source[Y]);
  428. }
  429.  
  430.  
  431.  
  432. /*
  433.  
  434.   Write an integer to the output string.
  435.  
  436. */
  437.  
  438. void writeInt(n)
  439.  
  440. int n;
  441.  
  442. { if (n = 0)
  443.     putChar('0');
  444.   else
  445.     if (n < 0)
  446.     { putChar('-');
  447.       n = -n;
  448.     }
  449.     putInt(n);
  450.   putChar(' ');
  451. }
  452.  
  453.  
  454. /**************************************************************************
  455.  
  456.   String output.
  457.  
  458. **************************************************************************/
  459.  
  460.  
  461.  
  462. /*
  463.  
  464.   Write a string to the output stream.
  465.  
  466. */
  467.  
  468. void writeString(x)
  469.  
  470. char *x;
  471.  
  472. { while (*x) putChar(*(x++)); }
  473.  
  474.  
  475. /*************************************************************************
  476.  
  477.    Command input
  478.  
  479. *************************************************************************/
  480.  
  481.  
  482.  
  483. /*
  484.  
  485.   Get and decode a command from the input stream.
  486.  
  487. */
  488.  
  489. static struct CommandItem
  490. { int           key;
  491.   Command       code;
  492. } ACommands[] =
  493.   { {'A', ArcAbsolute },
  494.     {'R', ArcRelative },
  495.     { 0, 0 }
  496.   },
  497.  
  498.   CCommands[] =
  499.   { {'A', SetAlternateChar },
  500.     {'I', Circle },
  501.     {'P', CharacterPlot },
  502.     {'S', SetStandardChar },
  503.     { 0, 0 }
  504.   },
  505.  
  506.   DCommands[] =
  507.   { {'C', NotImplemented },             /* Digitize Clear */
  508.     {'F', SetDefaults },
  509.     {'I', SetAbsoluteDirection },
  510.     {'P', NotImplemented },             /* Digitize Point */
  511.     {'R', SetRelativeDirection },
  512.     {'T', SetLabelTerminator },
  513.     { 0, 0 }
  514.   },
  515.  
  516.   ECommands[] =
  517.   { {'A', RectangleAbsolute },
  518.     {'R', RectangleRelative },
  519.     {'W', Wedge },
  520.     { 0, 0 }
  521.   },
  522.  
  523.   FCommands[] =
  524.   { {'T', SetFillType },
  525.     { 0, 0 }
  526.   },
  527.  
  528.   ICommands[] =
  529.   { {'M', NotImplemented },             /* Input Mask */
  530.     {'N', Initialize },
  531.     {'P', InputP1P2 },
  532.     {'W', InputWindow },
  533.     { 0, 0 }
  534.   },
  535.  
  536.   LCommands[] =
  537.   { {'B', PutASCIILabel },
  538.     {'T', SetLineType },
  539.     { 0, 0 }
  540.   },
  541.  
  542.   OCommands[] =
  543.   { {'A', Interactive },                /* Output Position  */
  544.     {'C', Interactive },                /* Output Commanded */
  545.     {'D', Interactive },                /* Output Point     */
  546.     {'E', Interactive },                /* Output Error     */
  547.     {'F', Interactive },                /* Output Factors   */
  548.     {'H', Interactive },                /* Output Hard Clip */
  549.     {'I', Interactive },                /* Output Ident     */
  550.     {'O', Interactive },                /* Output Options   */
  551.     {'P', Interactive },                /* Output P1 and P2 */
  552.     {'S', Interactive },                /* Output Status    */
  553.     {'W', Interactive },                /* Output Window    */
  554.     { 0, 0 }
  555.   },
  556.  
  557.   PCommands[] =
  558.   { {'A', SetAbsolutePlot },
  559.     {'D', PenDown },
  560.     {'R', SetRelativePlot },
  561.     {'S', SetPaperSize },
  562.     {'T', PenThickness },             /* Pen Thickness */
  563.     {'U', PenUp },
  564.     { 0, 0 }
  565.   },
  566.  
  567.   RCommands[] =
  568.   { {'A', ShadeRectAbsolute },
  569.     {'O', RotateCoordSys },
  570.     {'R', ShadeRectRelative },
  571.     { 0, 0 }
  572.   },
  573.  
  574.   SCommands[] =
  575.   { {'A', SelectAlternate },
  576.     {'C', SetScale },
  577.     {'I', SetAbsoluteCharSize },
  578.     {'L', SetAbsoluteCharSlant },
  579.     {'M', SetSymbolMode },
  580.     {'P', SelectPen },
  581.     {'R', SetRelativeCharSize },
  582.     {'S', SelectStandard },
  583.     { 0, 0 }
  584.   },
  585.  
  586.   TCommands[] =
  587.   { {'L', SetTickLength },
  588.     { 0, 0 }
  589.   },
  590.  
  591.   UCommands[] =
  592.   { {'C', UserChar },
  593.     { 0, 0 }
  594.   },
  595.  
  596.   VCommands[] =
  597.   { {'S', NotImplemented },             /* Set Velocity */
  598.     { 0, 0 }
  599.   },
  600.  
  601.   WCommands[] =
  602.   { {'G', ShadeWedge },
  603.     { 0, 0 }
  604.   },
  605.  
  606.   XCommands[] =
  607.   { {'T', XTick },
  608.     { 0, 0 }
  609.   },
  610.  
  611.   YCommands[] =
  612.   { {'T', YTick },
  613.     { 0, 0 }
  614.   },
  615.  
  616.   *CommandIndex[] =
  617.     {   ACommands,
  618.         NULL, 
  619.         CCommands, 
  620.         DCommands, 
  621.         ECommands,
  622.         FCommands, 
  623.         NULL, 
  624.         NULL, 
  625.         ICommands, 
  626.         NULL, 
  627.         NULL, 
  628.         LCommands,
  629.         NULL, 
  630.         NULL, 
  631.         OCommands, 
  632.         PCommands, 
  633.         NULL, 
  634.         RCommands,
  635.         SCommands, 
  636.         TCommands, 
  637.         UCommands, 
  638.         VCommands,
  639.         WCommands, 
  640.         XCommands, 
  641.         YCommands, 
  642.         NULL
  643.     };
  644.  
  645.  
  646.  
  647. Command getCommand()
  648.  
  649. { int                   c;
  650.   struct CommandItem    *tablePointer;
  651.  
  652.   c = getChar();
  653.   if (isalpha(c) &&
  654.      ((tablePointer = CommandIndex[islower(c) ? (c - 'a') : (c - 'A')]) != NULL))
  655.   { skipSeparator();
  656.     c = getChar();
  657.     if (isalpha(c))
  658.     { if (islower(c)) c = toupper(c);
  659.       while (tablePointer->key)
  660.         if (tablePointer->key == c)
  661.         { skipSeparator();
  662.           return(tablePointer->code);
  663.         }
  664.         else
  665.           tablePointer++;
  666.     }
  667.   }
  668.   error("Illegal HPGL command.");
  669. }
  670.  
  671.  
  672.  
  673. /*
  674.  
  675.   Handle extra parameters to a command.
  676.  
  677. */
  678.  
  679. void endCommand()
  680.  
  681. { Number dummy;
  682.  
  683.   if (!isTerminator(LookAhead))
  684.   { warning("Extra parameters ignored");
  685.     while (!isTerminator(LookAhead))
  686.       (void)getChar();
  687.   }
  688.   skipTerminator();
  689. }
  690.  
  691.  
  692.  
  693. /*************************************************************************
  694.  
  695.   Internal I/O redirection
  696.  
  697. *************************************************************************/
  698.  
  699.  
  700. /*
  701.  
  702.   Get input chars from specified file.
  703.  
  704. */
  705.  
  706. Boolean setInput(fileName)
  707.  
  708. char *fileName;
  709.  
  710. { return((input = fopen(fileName,"r")) != NULL); }
  711.  
  712.  
  713.  
  714. /*
  715.  
  716.   Put output chars to specified file.
  717.  
  718. */
  719.  
  720. Boolean setOutput(fileName)
  721.  
  722. char *fileName;
  723.  
  724. { return((output = fopen(fileName,"w")) != NULL); }
  725.  
  726.