LCOV - code coverage report
Current view: top level - preproc/grn - hdb.cpp (source / functions) Hit Total Coverage
Test: GNU roff Lines: 122 176 69.3 %
Date: 2026-01-16 17:51:41 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             :  /* Last non-groff version: hdb.c  1.8 (Berkeley) 84/10/20
       2             :  *
       3             :  * Originally written by Barry Roitblat, 1982.
       4             :  * Adapted to GNU troff by Daniel Senderowicz 99/12/29.
       5             :  * Modified 2000-2024 by the Free Software Foundation, Inc.
       6             :  *
       7             :  * This file contains no AT&T code and is in the public domain.
       8             :  *
       9             :  * This file contains database routines for the hard copy programs of
      10             :  * the gremlin picture editor.
      11             :  */
      12             : 
      13             : #ifdef HAVE_CONFIG_H
      14             : #include <config.h>
      15             : #endif
      16             : 
      17             : #include <ctype.h> // isdigit()
      18             : #include <stdio.h> // FILE, feof(), fgets(), getc()
      19             : #include <stdlib.h> // atoi()
      20             : #include <string.h> // strcmp()
      21             : 
      22             : #include "errarg.h"
      23             : #include "error.h"
      24             : #include "gprint.h"
      25             : 
      26             : #define MAXSTRING 128
      27             : #define MAXSTRING_S "127"
      28             : 
      29             : /* imports from main.cpp */
      30             : 
      31             : extern char gremlinfile[];      /* name of file currently reading */
      32             : extern int SUNFILE;             /* TRUE if SUN gremlin file */
      33             : extern int compatibility_flag;  /* TRUE if in compatibility mode */
      34             : extern void *grnmalloc(size_t size, const char *what);
      35             : extern void savebounds(double x, double y);
      36             : 
      37             : /* imports from hpoint.cpp */
      38             : 
      39             : extern POINT *PTInit();
      40             : extern POINT *PTMakePoint(double x, double y, POINT ** pplist);
      41             : 
      42             : 
      43             : int DBGetType(char *s);
      44             : 
      45             : static long lineno = 0;         /* line number of gremlin file */
      46             : 
      47             : /*
      48             :  * This routine returns a pointer to an initialized database element
      49             :  * which would be the only element in an empty list.
      50             :  */
      51             : ELT *
      52           1 : DBInit()
      53             : {
      54           1 :   return ((ELT *) NULL);
      55             : }                               /* end DBInit */
      56             : 
      57             : 
      58             : /*
      59             :  * This routine creates a new element with the specified attributes and
      60             :  * links it into database.
      61             :  */
      62             : ELT *
      63         414 : DBCreateElt(int type,
      64             :             POINT * pointlist,
      65             :             int brush,
      66             :             int size,
      67             :             char *text,
      68             :             ELT **db)
      69             : {
      70         414 :   ELT *temp = 0;
      71             : 
      72         414 :   temp = (ELT *) grnmalloc(sizeof(ELT), "picture element");
      73         414 :   temp->nextelt = *db;
      74         414 :   temp->type = type;
      75         414 :   temp->ptlist = pointlist;
      76         414 :   temp->brushf = brush;
      77         414 :   temp->size = size;
      78         414 :   temp->textpt = text;
      79         414 :   *db = temp;
      80         414 :   return (temp);
      81             : }                               /* end CreateElt */
      82             : 
      83             : 
      84             : /*
      85             :  * This routine reads the specified file into a database and returns a
      86             :  * pointer to that database.
      87             :  */
      88             : ELT *
      89           1 : DBRead(FILE *file)
      90             : {
      91             :   int i;
      92             :   int done;             /* flag for input exhausted */
      93             :   double nx;            /* x holder so x is not set before orienting */
      94             :   int type;                     /* element type */
      95             :   ELT *elist;                   /* pointer to the file's elements */
      96             :   POINT *plist;                 /* pointer for reading in points */
      97             :   char string[MAXSTRING], *txt;
      98             :   double x, y;                  /* x and y are read in point coords */
      99             :   int len, brush, size;
     100             :   int lastpoint;
     101             : 
     102           1 :   SUNFILE = FALSE;
     103           1 :   elist = DBInit();
     104           1 :   int nitems = fscanf(file, "%" MAXSTRING_S "s%*[^\n]\n", string);
     105           1 :   if (nitems != 1) {
     106           0 :     error_with_file_and_line(gremlinfile, lineno,
     107             :                              "malformed input; giving up on this"
     108             :                              " picture");
     109           0 :     return (elist);
     110             :   }
     111           1 :   lineno++;
     112           1 :   if (strcmp(string, "gremlinfile")) {
     113           1 :     if (strcmp(string, "sungremlinfile")) {
     114           0 :       error_with_file_and_line(gremlinfile, lineno,
     115             :                                "not a gremlin file; giving up on this"
     116             :                                " picture");
     117           0 :       return (elist);
     118             :     }
     119           1 :     SUNFILE = TRUE;
     120             :   }
     121             : 
     122           1 :   nitems = fscanf(file, "%d%lf%lf\n", &size, &x, &y);
     123           1 :   if (nitems != 3) {
     124           0 :     error_with_file_and_line(gremlinfile, lineno,
     125             :                              "malformed input; giving up on this"
     126             :                              " picture");
     127           0 :     return (elist);
     128             :   }
     129           1 :   lineno++;
     130             :   /* ignore orientation and file positioning point */
     131             : 
     132           1 :   done = FALSE;
     133         416 :   while (!done) {
     134             :     /* if (fscanf(file,"%" MAXSTRING_S "s\n", string) == EOF) */
     135             :     /* I changed the scanf format because the element */
     136             :     /* can have two words (e.g. CURVE SPLINE)         */
     137         415 :     if (fscanf(file, "\n%"
     138             :                       MAXSTRING_S
     139         415 :                      "[^\n]%*[^\n]\n", string) == EOF) {
     140           0 :       lineno++;
     141           0 :       error_with_file_and_line(gremlinfile, lineno, "error in format;"
     142             :                                " giving up on this picture");
     143           0 :       return (elist);
     144             :     }
     145         415 :     lineno++;
     146             : 
     147         415 :     type = DBGetType(string);   /* interpret element type */
     148         415 :     if (type < 0) {          /* no more data */
     149           1 :       done = TRUE;
     150             :     } else {
     151             :       /* always one point */
     152             : #ifdef UW_FASTSCAN
     153             :       (void) xscanf(file, &x, &y);
     154             : #else
     155         414 :       nitems = fscanf(file, "%lf%lf\n", &x, &y);
     156         414 :       if (nitems != 2) {
     157           0 :         error_with_file_and_line(gremlinfile, lineno,
     158             :                                  "malformed input; giving up on this"
     159             :                                  " picture");
     160           0 :         return (elist);
     161             :       }
     162         414 :       lineno++;
     163             : #endif  /* UW_FASTSCAN */
     164         414 :       plist = PTInit();         /* NULL point list */
     165             : 
     166             :       /*
     167             :        * Files created on the SUN have point lists terminated by a line
     168             :        * containing only an asterisk ('*').  Files created on the AED
     169             :        * have point lists terminated by the coordinate pair (-1.00
     170             :        * -1.00).
     171             :        */
     172         414 :       if (TEXT(type)) { /* read only first point for TEXT elements */
     173          94 :         nx = xorn(x, y);
     174          94 :         y = yorn(x, y);
     175          94 :         (void) PTMakePoint(nx, y, &plist);
     176          94 :         savebounds(nx, y);
     177             : 
     178             : #ifdef UW_FASTSCAN
     179             :         while (xscanf(file, &x, &y));
     180             : #else
     181          94 :         lastpoint = FALSE;
     182         282 :         do {
     183         376 :           char *cp = fgets(string, MAXSTRING, file);
     184         376 :           if (0 /* nullptr */ == cp) {
     185           0 :             error_with_file_and_line(gremlinfile, lineno,
     186             :                                      "premature end-of-file or error"
     187             :                                      " reading input; giving up on this"
     188             :                                      " picture");
     189           0 :             return(elist);
     190             :           }
     191         376 :           lineno++;
     192         376 :           if (string[0] == '*') {       /* SUN gremlin file */
     193          94 :             lastpoint = TRUE;
     194             :           } else {
     195         282 :             if (!sscanf(string, "%lf%lf", &x, &y)) {
     196           0 :               error_with_file_and_line(gremlinfile, lineno,
     197             :                                        "expected coordinate pair, got"
     198             :                                        " '%1'; giving up on this"
     199           0 :                                        " picture", string);
     200           0 :               return(elist);
     201             :             }
     202         282 :             if ((x == -1.00 && y == -1.00) && (!SUNFILE))
     203           0 :               lastpoint = TRUE;
     204             :             else {
     205         282 :               if (compatibility_flag)
     206           0 :                 savebounds(xorn(x, y), yorn(x, y));
     207             :             }
     208             :           }
     209         376 :         } while (!lastpoint);
     210             : #endif  /* UW_FASTSCAN */
     211             :       } else {                  /* not TEXT element */
     212             : #ifdef UW_FASTSCAN
     213             :         do {
     214             :           nx = xorn(x, y);
     215             :           y = yorn(x, y);
     216             :           (void) PTMakePoint(nx, y, &plist);
     217             :           savebounds(nx, y);
     218             :         } while (xscanf(file, &x, &y));
     219             : #else
     220         320 :         lastpoint = FALSE;
     221        1535 :         while (!lastpoint) {
     222        1215 :           nx = xorn(x, y);
     223        1215 :           y = yorn(x, y);
     224        1215 :           (void) PTMakePoint(nx, y, &plist);
     225        1215 :           savebounds(nx, y);
     226             : 
     227        1215 :           char *cp = fgets(string, MAXSTRING, file);
     228        1215 :           if (0 /* nullptr */ == cp) {
     229           0 :             error_with_file_and_line(gremlinfile, lineno,
     230             :                                      "premature end-of-file or error"
     231             :                                      " reading input; giving up on this"
     232             :                                      " picture");
     233           0 :             return(elist);
     234             :           }
     235        1215 :           lineno++;
     236        1215 :           if (string[0] == '*') {       /* SUN gremlin file */
     237         320 :             lastpoint = TRUE;
     238             :           } else {
     239         895 :             (void) sscanf(string, "%lf%lf", &x, &y);
     240         895 :             if ((x == -1.00 && y == -1.00) && (!SUNFILE))
     241           0 :               lastpoint = TRUE;
     242             :           }
     243             :         }
     244             : #endif  /* UW_FASTSCAN */
     245             :       }
     246         414 :       nitems = fscanf(file, "%d%d\n", &brush, &size);
     247         414 :       if (nitems != 2) {
     248           0 :         error_with_file_and_line(gremlinfile, lineno,
     249             :                                  "malformed input; giving up on this"
     250             :                                  " picture");
     251           0 :         return (elist);
     252             :       }
     253         414 :       lineno++;
     254         414 :       nitems = fscanf(file, "%d", &len);  /* text length */
     255         414 :       if (nitems != 1) {
     256           0 :         error_with_file_and_line(gremlinfile, lineno,
     257             :                                  "malformed input; giving up on this"
     258             :                                  " picture");
     259           0 :         return (elist);
     260             :       }
     261         414 :       (void) getc(file);                /* eat blank */
     262         414 :       lineno++;                         /* advance line counter early */
     263         414 :       if (len < 0) {
     264           0 :         error_with_file_and_line(gremlinfile, lineno,
     265             :                                  "length claimed for text is nonsense:"
     266             :                                  " '%1'; giving up on this picture",
     267           0 :                                  len);
     268           0 :         return (elist);
     269             :       }
     270         414 :       txt = (char *) grnmalloc((unsigned) len + 1, "element text");
     271        1033 :       for (i = 0; i < len; ++i) {    /* read text */
     272         619 :         int c = getc(file);
     273         619 :         if (c == EOF)
     274           0 :           break;
     275         619 :         txt[i] = c;
     276             :       }
     277         414 :       if (feof(file)) {
     278           0 :         error_with_file_and_line(gremlinfile, lineno,
     279             :                                  "end of file while reading text of"
     280             :                                  " length %1; giving up on this"
     281           0 :                                  " picture", len);
     282           0 :         return (elist);
     283             :       }
     284         414 :       txt[len] = '\0';
     285         414 :       (void) DBCreateElt(type, plist, brush, size, txt, &elist);
     286             :     }                           /* end else */
     287             :   } /* end while not done */ ;
     288           1 :   return (elist);
     289             : }                               /* end DBRead */
     290             : 
     291             : 
     292             : /*
     293             :  * Interpret element type in string s.
     294             :  * Old file format consisted of integer element types.
     295             :  * New file format has literal names for element types.
     296             :  */
     297             : int
     298         415 : DBGetType(char *s)
     299             : {
     300         415 :   if (isdigit(s[0]) || (s[0] == '-'))   /* old element format or EOF */
     301           1 :     return (atoi(s));
     302             : 
     303         414 :   switch (s[0]) {
     304          36 :   case 'P':
     305          36 :     return (POLYGON);
     306         181 :   case 'V':
     307         181 :     return (VECTOR);
     308          99 :   case 'A':
     309          99 :     return (ARC);
     310          52 :   case 'C':
     311          52 :     if (s[1] == 'U') {
     312           4 :       if (s[5] == '\n')
     313           0 :         return (CURVE);
     314           4 :       switch (s[7]) {
     315           4 :       case 'S':
     316           4 :         return(BSPLINE);
     317           0 :       case 'E':
     318           0 :         warning_with_file_and_line(gremlinfile, lineno,
     319             :                                    "using B-spline for Bezier curve");
     320           0 :         return(BSPLINE);
     321           0 :       default:
     322           0 :         return(CURVE);
     323             :       }
     324             :     }
     325          48 :     switch (s[4]) {
     326          17 :     case 'L':
     327          17 :       return (CENTLEFT);
     328           2 :     case 'C':
     329           2 :       return (CENTCENT);
     330          29 :     case 'R':
     331          29 :       return (CENTRIGHT);
     332           0 :     default:
     333           0 :       error_with_file_and_line(gremlinfile, lineno,
     334           0 :                                "unknown element type '%1'", s);
     335           0 :       return -1;
     336             :     }
     337          29 :   case 'B':
     338          29 :     switch (s[3]) {
     339           3 :     case 'L':
     340           3 :       return (BOTLEFT);
     341          10 :     case 'C':
     342          10 :       return (BOTCENT);
     343          16 :     case 'R':
     344          16 :       return (BOTRIGHT);
     345           0 :     default:
     346           0 :       error_with_file_and_line(gremlinfile, lineno,
     347           0 :                                "unknown element type '%1'", s);
     348           0 :       return -1;
     349             :     }
     350          17 :   case 'T':
     351          17 :     switch (s[3]) {
     352           2 :     case 'L':
     353           2 :       return (TOPLEFT);
     354           9 :     case 'C':
     355           9 :       return (TOPCENT);
     356           6 :     case 'R':
     357           6 :       return (TOPRIGHT);
     358           0 :     default:
     359           0 :       error_with_file_and_line(gremlinfile, lineno,
     360           0 :                                "unknown element type '%1'", s);
     361           0 :       return -1;
     362             :     }
     363           0 :   default:
     364           0 :     error_with_file_and_line(gremlinfile, lineno,
     365           0 :                              "unknown element type '%1'", s);
     366           0 :     return -1;
     367             :   }
     368             : }
     369             : 
     370             : #ifdef UW_FASTSCAN
     371             : /*
     372             :  * Optimization hack added by solomon@crys.wisc.edu, 12/2/86.
     373             :  * A huge fraction of the time was spent reading floating point numbers
     374             :  * from the input file, but the numbers always have the format 'ddd.dd'.
     375             :  * Thus the following special-purpose version of fscanf.
     376             :  *
     377             :  * xscanf(f,xp,yp) does roughly what fscanf(f,"%f%f",xp,yp) does except:
     378             :  *   -the next piece of input must be of the form
     379             :  *      <space>* <digit>*'.'<digit>* <space>* <digit>*'.'<digit>*
     380             :  *   -xscanf eats the character following the second number
     381             :  *   -xscanf returns 0 for "end-of-data" indication, 1 otherwise, where
     382             :  *    end-of-data is signalled by a '*' [in which case the rest of the
     383             :  *    line is gobbled], or by '-1.00 -1.00' [but only if !SUNFILE].
     384             :  */
     385             : int
     386             : xscanf(FILE *f,
     387             :        double *xp,
     388             :        double *yp)
     389             : {
     390             :   int c, i, j, m, frac;
     391             :   int iscale = 1, jscale = 1;   /* x = i/scale, y=j/jscale */
     392             : 
     393             :   while ((c = getc(f)) == ' ');
     394             :   if (c == '*') {
     395             :     while ((c = getc(f)) != '\n');
     396             :     return 0;
     397             :   }
     398             :   i = m = frac = 0;
     399             :   while (isdigit(c) || c == '.' || c == '-') {
     400             :     if (c == '-') {
     401             :       m++;
     402             :       c = getc(f);
     403             :       continue;
     404             :     }
     405             :     if (c == '.')
     406             :       frac = 1;
     407             :     else {
     408             :       if (frac)
     409             :         iscale *= 10;
     410             :       i = 10 * i + c - '0';
     411             :     }
     412             :     c = getc(f);
     413             :   }
     414             :   if (m)
     415             :     i = -i;
     416             :   *xp = (double) i / (double) iscale;
     417             : 
     418             :   while ((c = getc(f)) == ' ');
     419             :   j = m = frac = 0;
     420             :   while (isdigit(c) || c == '.' || c == '-') {
     421             :     if (c == '-') {
     422             :       m++;
     423             :       c = getc(f);
     424             :       continue;
     425             :     }
     426             :     if (c == '.')
     427             :       frac = 1;
     428             :     else {
     429             :       if (frac)
     430             :         jscale *= 10;
     431             :       j = 10 * j + c - '0';
     432             :     }
     433             :     c = getc(f);
     434             :   }
     435             :   if (m)
     436             :     j = -j;
     437             :   *yp = (double) j / (double) jscale;
     438             :   return (SUNFILE || i != -iscale || j != -jscale);
     439             : }
     440             : #endif  /* UW_FASTSCAN */
     441             : 
     442             : // Local Variables:
     443             : // fill-column: 72
     444             : // mode: C++
     445             : // End:
     446             : // vim: set cindent noexpandtab shiftwidth=2 textwidth=72:

Generated by: LCOV version 1.14