X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fascii.c;h=738526f388e2b4ba3241471faeac348133374d29;hb=d594340cb1ae007a92d094ae67116f9f622f2b5d;hp=9c0103e0c5e2b044a97f200d5a2acbd1254da62a;hpb=97d6c6f6b1922621ca013668eba9a9a9f71d60fe;p=pspp-builds.git diff --git a/src/ascii.c b/src/ascii.c index 9c0103e0..738526f3 100644 --- a/src/ascii.c +++ b/src/ascii.c @@ -14,8 +14,8 @@ 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., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ #include #include "error.h" @@ -26,12 +26,16 @@ #include "alloc.h" #include "error.h" #include "filename.h" +#include "glob.h" #include "main.h" #include "misc.h" #include "output.h" #include "pool.h" #include "version.h" +#include "gettext.h" +#define _(msgid) gettext (msgid) + /* ASCII driver options: (defaults listed first) output-file="pspp.list" @@ -141,6 +145,14 @@ enum FSTY_COUNT = 6 /* Number of font styles. */ }; +/* A line of text. */ +struct line + { + unsigned short *chars; /* Characters and attributes. */ + int char_cnt; /* Length. */ + int char_cap; /* Allocated bytes. */ + }; + /* ASCII output driver extension record. */ struct ascii_driver_ext { @@ -157,9 +169,9 @@ struct ascii_driver_ext int bottom_margin; /* Bottom margin in lines. */ int paginate; /* 1=insert formfeeds. */ int tab_width; /* Width of a tab; 0 not to use tabs. */ - struct len_string ops[OPS_COUNT]; /* Basic output strings. */ - struct len_string box[LNS_COUNT]; /* Line & box drawing characters. */ - struct len_string fonts[FSTY_COUNT]; /* Font styles; NULL=overstrike. */ + struct fixed_string ops[OPS_COUNT]; /* Basic output strings. */ + struct fixed_string box[LNS_COUNT]; /* Line & box drawing characters. */ + struct fixed_string fonts[FSTY_COUNT]; /* Font styles; NULL=overstrike. */ int overstrike_style; /* OVS_SINGLE or OVS_LINE. */ int carriage_return_style; /* Carriage return style. */ int squeeze_blank_lines; /* 1=squeeze multiple blank lines into one. */ @@ -167,34 +179,38 @@ struct ascii_driver_ext /* Internal state. */ struct file_ext file; /* Output file. */ int page_number; /* Current page number. */ - unsigned short *page; /* Page content. */ - int page_size; /* Number of bytes allocated for page, attr. */ - int *line_len; /* Length of each line in page, attr. */ - int line_len_size; /* Number of ints allocated for line_len. */ + struct line *lines; /* Page content. */ + int lines_cap; /* Number of lines allocated. */ int w, l; /* Actual width & length w/o margins, etc. */ - int n_output; /* Number of lines output so far. */ int cur_font; /* Current font by OUTP_F_*. */ #if GLOBAL_DEBUGGING int debug; /* Set by som_text_draw(). */ #endif }; -static struct pool *ascii_pool; - static int postopen (struct file_ext *); static int preclose (struct file_ext *); +static struct outp_option_info *option_info; + static int ascii_open_global (struct outp_class *this UNUSED) { - ascii_pool = pool_create (); + option_info = xmalloc (sizeof *option_info); + option_info->initial = 0; + option_info->options = 0; return 1; } + +static char *s; static int ascii_close_global (struct outp_class *this UNUSED) { - pool_destroy (ascii_pool); + free(option_info->initial); + free(option_info->options); + free(option_info); + free(s); return 1; } @@ -216,7 +232,7 @@ ascii_preopen_driver (struct outp_driver *this) assert (this->driver_open == 0); msg (VM (1), _("ASCII driver initializing as `%s'..."), this->name); - this->ext = x = xmalloc (sizeof (struct ascii_driver_ext)); + this->ext = x = xmalloc (sizeof *x); x->char_set = CHS_ASCII; x->headers = 1; x->page_length = 66; @@ -246,11 +262,8 @@ ascii_preopen_driver (struct outp_driver *this) x->file.postopen = postopen; x->file.preclose = preclose; x->page_number = 0; - x->page = NULL; - x->page_size = 0; - x->line_len = NULL; - x->line_len_size = 0; - x->n_output = 0; + x->lines = NULL; + x->lines_cap = 0; x->cur_font = OUTP_F_R; #if GLOBAL_DEBUGGING x->debug = 0; @@ -286,11 +299,11 @@ ascii_postopen_driver (struct outp_driver *this) this->length = x->l * this->vert; if (ls_null_p (&x->ops[OPS_FORMFEED])) - ls_create (ascii_pool, &x->ops[OPS_FORMFEED], "\f"); + ls_create (&x->ops[OPS_FORMFEED], "\f"); if (ls_null_p (&x->ops[OPS_NEWLINE]) - || !strcmp (ls_value (&x->ops[OPS_NEWLINE]), "default")) + || !strcmp (ls_c_str (&x->ops[OPS_NEWLINE]), "default")) { - ls_create (ascii_pool, &x->ops[OPS_NEWLINE], "\n"); + ls_create (&x->ops[OPS_NEWLINE], "\n"); x->file.mode = "wt"; } @@ -349,7 +362,7 @@ ascii_postopen_driver (struct outp_driver *this) c[0] = '+'; break; } - ls_create (ascii_pool, &x->box[i], c); + ls_create (&x->box[i], c); } } @@ -387,13 +400,26 @@ static int ascii_close_driver (struct outp_driver *this) { struct ascii_driver_ext *x = this->ext; + int i; assert (this->driver_open == 1); msg (VM (2), _("%s: Beginning closing..."), this->name); x = this->ext; - free (x->page); - free (x->line_len); + for (i = 0; i < OPS_COUNT; i++) + ls_destroy (&x->ops[i]); + for (i = 0; i < LNS_COUNT; i++) + ls_destroy (&x->box[i]); + for (i = 0; i < FSTY_COUNT; i++) + ls_destroy (&x->fonts[i]); + if (x->lines != NULL) + { + int line; + + for (line = 0; line < x->lines_cap; line++) + free (x->lines[line].chars); + free (x->lines); + } fn_close_ext (&x->file); free (x->file.filename); free (x); @@ -444,7 +470,6 @@ static struct outp_option option_tab[] = {"squeeze", boolean_arg, 2}, {"", 0, 0}, }; -static struct outp_option_info option_info; static void ascii_option (struct outp_driver *this, const char *key, @@ -454,7 +479,7 @@ ascii_option (struct outp_driver *this, const char *key, int cat, subcat; const char *value; - value = ds_value (val); + value = ds_c_str (val); if (!strncmp (key, "box[", 4)) { char *tail; @@ -468,11 +493,11 @@ ascii_option (struct outp_driver *this, const char *key, } if (!ls_null_p (&x->box[indx])) msg (SW, _("Duplicate value for key `%s'."), key); - ls_create (ascii_pool, &x->box[indx], value); + ls_create (&x->box[indx], value); return; } - cat = outp_match_keyword (key, option_tab, &option_info, &subcat); + cat = outp_match_keyword (key, option_tab, option_info, &subcat); switch (cat) { case 0: @@ -578,7 +603,7 @@ ascii_option (struct outp_driver *this, const char *key, break; case string_arg: { - struct len_string *s; + struct fixed_string *s; switch (subcat) { case 0: @@ -597,17 +622,17 @@ ascii_option (struct outp_driver *this, const char *key, assert (0); abort (); } - ls_create (ascii_pool, s, value); + ls_create (s, value); } break; case font_string_arg: { if (!strcmp (value, "overstrike")) { - ls_destroy (ascii_pool, &x->fonts[subcat]); + ls_destroy (&x->fonts[subcat]); return; } - ls_create (ascii_pool, &x->fonts[subcat], value); + ls_create (&x->fonts[subcat], value); } break; case boolean_arg: @@ -649,9 +674,9 @@ int postopen (struct file_ext *f) { struct ascii_driver_ext *x = f->param; - struct len_string *s = &x->ops[OPS_INIT]; + struct fixed_string *s = &x->ops[OPS_INIT]; - if (!ls_empty_p (s) && fwrite (ls_value (s), ls_length (s), 1, f->file) < 1) + if (!ls_empty_p (s) && fwrite (ls_c_str (s), ls_length (s), 1, f->file) < 1) { msg (ME, _("ASCII output driver: %s: %s"), f->filename, strerror (errno)); @@ -664,9 +689,9 @@ int preclose (struct file_ext *f) { struct ascii_driver_ext *x = f->param; - struct len_string *d = &x->ops[OPS_DONE]; + struct fixed_string *d = &x->ops[OPS_DONE]; - if (!ls_empty_p (d) && fwrite (ls_value (d), ls_length (d), 1, f->file) < 1) + if (!ls_empty_p (d) && fwrite (ls_c_str (d), ls_length (d), 1, f->file) < 1) { msg (ME, _("ASCII output driver: %s: %s"), f->filename, strerror (errno)); @@ -679,7 +704,7 @@ static int ascii_open_page (struct outp_driver *this) { struct ascii_driver_ext *x = this->ext; - int req_page_size; + int i; assert (this->driver_open && !this->page_open); x->page_number++; @@ -690,21 +715,20 @@ ascii_open_page (struct outp_driver *this) return 0; } - req_page_size = x->w * x->l; - if (req_page_size > x->page_size || req_page_size / 2 < x->page_size) - { - x->page_size = req_page_size; - x->page = xrealloc (x->page, sizeof *x->page * req_page_size); - } - - if (x->l > x->line_len_size) + if (x->l > x->lines_cap) { - x->line_len_size = x->l; - x->line_len = xrealloc (x->line_len, - sizeof *x->line_len * x->line_len_size); + x->lines = xnrealloc (x->lines, x->l, sizeof *x->lines); + for (i = x->lines_cap; i < x->l; i++) + { + struct line *line = &x->lines[i]; + line->chars = NULL; + line->char_cap = 0; + } + x->lines_cap = x->l; } - memset (x->line_len, 0, sizeof *x->line_len * x->l); + for (i = 0; i < x->l; i++) + x->lines[i].char_cnt = 0; this->page_open = 1; return 1; @@ -715,18 +739,26 @@ ascii_open_page (struct outp_driver *this) static inline void expand_line (struct ascii_driver_ext *x, int i, int l) { - int limit = i * x->w + l; + struct line *line; int j; - for (j = i * x->w + x->line_len[i]; j < limit; j++) - x->page[j] = ' '; - x->line_len[i] = l; + assert (i < x->lines_cap); + line = &x->lines[i]; + if (l > line->char_cap) + { + line->char_cap = l * 2; + line->chars = xnrealloc (line->chars, + line->char_cap, sizeof *line->chars); + } + for (j = line->char_cnt; j < l; j++) + line->chars[j] = ' '; + line->char_cnt = l; } /* Puts line L at (H,K) in the current output page. Assumes struct ascii_driver_ext named `ext'. */ #define draw_line(H, K, L) \ - ext->page[ext->w * (K) + (H)] = (L) | 0x800 + ext->lines[K].chars[H] = (L) | 0x800 /* Line styles for each position. */ #define T(STYLE) (STYLE<line_len[y1] < x2) + if (ext->lines[y1].char_cnt < x2) expand_line (ext, y1, x2); for (x = x1; x < x2; x++) @@ -796,7 +828,7 @@ ascii_line_vert (struct outp_driver *this, const struct rect *r, #endif for (y = y1; y < y2; y++) - if (ext->line_len[y] <= x1) + if (ext->lines[y].char_cnt <= x1) expand_line (ext, y, x1 + 1); for (y = y1; y < y2; y++) @@ -828,7 +860,7 @@ ascii_line_intersection (struct outp_driver *this, const struct rect *r, l = ((style->l << LNS_LEFT) | (style->r << LNS_RIGHT) | (style->t << LNS_TOP) | (style->b << LNS_BOTTOM)); - if (ext->line_len[y] <= x) + if (ext->lines[y].char_cnt <= x) expand_line (ext, y, x + 1); draw_line (x, y, l); } @@ -956,7 +988,7 @@ delineate (struct outp_driver *this, struct outp_text *t, int draw) int max_y; /* Current position in string, character following end of string. */ - const char *s = ls_value (&t->s); + const char *s = ls_c_str (&t->s); const char *end = ls_end (&t->s); /* Temporary struct outp_text to pass to low-level function. */ @@ -1086,9 +1118,9 @@ text_draw (struct outp_driver *this, struct outp_text *t) unsigned attr = ext->cur_font << 8; int x = t->x; - int y = t->y * ext->w; + int y = t->y; - char *s = ls_value (&t->s); + char *s = ls_c_str (&t->s); /* Expand the line with the assumption that S takes up LEN character spaces (sometimes it takes up less). */ @@ -1111,7 +1143,7 @@ text_draw (struct outp_driver *this, struct outp_text *t) if (!(t->y < ext->l && x < ext->w)) return; min_len = min (x + ls_length (&t->s), ext->w); - if (ext->line_len[t->y] < min_len) + if (ext->lines[t->y].char_cnt < min_len) expand_line (ext, t->y, min_len); { @@ -1120,15 +1152,15 @@ text_draw (struct outp_driver *this, struct outp_text *t) if (len + x > ext->w) len = ext->w - x; while (len--) - ext->page[y + x++] = *s++ | attr; + ext->lines[y].chars[x++] = *s++ | attr; } } /* ascii_close_page () and support routines. */ #define LINE_BUF_SIZE 1024 -static unsigned char *line_buf; -static unsigned char *line_p; +static char *line_buf; +static char *line_p; static inline int commit_line_buf (struct outp_driver *this) @@ -1181,12 +1213,12 @@ output_shorts (struct outp_driver *this, { if (*bp & 0x800) { - struct len_string *box = &ext->box[*bp & 0xff]; + struct fixed_string *box = &ext->box[*bp & 0xff]; size_t len = ls_length (box); if (remaining >= len) { - memcpy (line_p, ls_value (box), len); + memcpy (line_p, ls_c_str (box), len); line_p += len; remaining -= len; } @@ -1194,13 +1226,13 @@ output_shorts (struct outp_driver *this, { if (!commit_line_buf (this)) return 0; - output_string (this, ls_value (box), ls_end (box)); + output_string (this, ls_c_str (box), ls_end (box)); remaining = LINE_BUF_SIZE - (line_p - line_buf); } } else if (*bp & 0x0300) { - struct len_string *on; + struct fixed_string *on; char buf[5]; int len; @@ -1281,7 +1313,7 @@ output_shorts (struct outp_driver *this, /* Writes CH into line_buf N times, or to THIS->output if line_buf overflows. */ static inline void -output_char (struct outp_driver *this, int n, int ch) +output_char (struct outp_driver *this, int n, char ch) { if (LINE_BUF_SIZE - (line_p - line_buf) >= n) { @@ -1345,7 +1377,7 @@ output_lines (struct outp_driver *this, int first, int count) struct ascii_driver_ext *ext = this->ext; int line_num; - struct len_string *newline = &ext->ops[OPS_NEWLINE]; + struct fixed_string *newline = &ext->ops[OPS_NEWLINE]; int n_chars; int n_passes; @@ -1356,8 +1388,9 @@ output_lines (struct outp_driver *this, int first, int count) /* Iterate over all the lines to be output. */ for (line_num = first; line_num < first + count; line_num++) { - unsigned short *p = &ext->page[ext->w * line_num]; - unsigned short *end_p = p + ext->line_len[line_num]; + struct line *line = &ext->lines[line_num]; + unsigned short *p = line->chars; + unsigned short *end_p = p + line->char_cnt; unsigned short *bp, *ep; unsigned short attr = 0; @@ -1367,8 +1400,8 @@ output_lines (struct outp_driver *this, int first, int count) requested. */ if (ext->squeeze_blank_lines && line_num > first - && ext->line_len[line_num] == 0 - && ext->line_len[line_num - 1] == 0) + && ext->lines[line_num].char_cnt == 0 + && ext->lines[line_num - 1].char_cnt == 0) continue; /* Output every character in the line in the appropriate @@ -1392,7 +1425,7 @@ output_lines (struct outp_driver *this, int first, int count) /* Turn off old font. */ if (attr != (OUTP_F_R << 8)) { - struct len_string *off; + struct fixed_string *off; switch (attr) { @@ -1410,14 +1443,14 @@ output_lines (struct outp_driver *this, int first, int count) abort (); } if (off) - output_string (this, ls_value (off), ls_end (off)); + output_string (this, ls_c_str (off), ls_end (off)); } /* Turn on new font. */ attr = (*bp & 0x0300); if (attr != (OUTP_F_R << 8)) { - struct len_string *on; + struct fixed_string *on; switch (attr) { @@ -1435,14 +1468,14 @@ output_lines (struct outp_driver *this, int first, int count) abort (); } if (on) - output_string (this, ls_value (on), ls_end (on)); + output_string (this, ls_c_str (on), ls_end (on)); } ep = bp + 1; } if (n_passes > 1) { - unsigned char ch; + char ch; return_carriage (this, n_chars); n_chars = 0; @@ -1494,19 +1527,19 @@ output_lines (struct outp_driver *this, int first, int count) } } - output_string (this, ls_value (newline), ls_end (newline)); + output_string (this, ls_c_str (newline), ls_end (newline)); } } + static int ascii_close_page (struct outp_driver *this) { - static unsigned char *s; static int s_len; struct ascii_driver_ext *x = this->ext; int nl_len, ff_len, total_len; - unsigned char *cp; + char *cp; int i; assert (this->driver_open && this->page_open); @@ -1526,7 +1559,7 @@ ascii_close_page (struct outp_driver *this) } for (cp = s, i = 0; i < x->top_margin; i++) { - memcpy (cp, ls_value (&x->ops[OPS_NEWLINE]), nl_len); + memcpy (cp, ls_c_str (&x->ops[OPS_NEWLINE]), nl_len); cp += nl_len; } output_string (this, s, &s[total_len]); @@ -1547,7 +1580,8 @@ ascii_close_page (struct outp_driver *this) { char temp[40]; - snprintf (temp, 80, _("%s - Page %d"), curdate, x->page_number); + snprintf (temp, 80, _("%s - Page %d"), get_start_date (), + x->page_number); memcpy (&s[x->w - strlen (temp)], temp, strlen (temp)); } @@ -1556,7 +1590,7 @@ ascii_close_page (struct outp_driver *this) len = min ((int) strlen (outp_title), x->w); memcpy (s, outp_title, len); } - memcpy (&s[x->w], ls_value (&x->ops[OPS_NEWLINE]), nl_len); + memcpy (&s[x->w], ls_c_str (&x->ops[OPS_NEWLINE]), nl_len); output_string (this, s, &s[total_len]); memset (s, ' ', x->w); @@ -1569,14 +1603,14 @@ ascii_close_page (struct outp_driver *this) len = min ((int) strlen (string), x->w); memcpy (s, string, len); } - memcpy (&s[x->w], ls_value (&x->ops[OPS_NEWLINE]), nl_len); + memcpy (&s[x->w], ls_c_str (&x->ops[OPS_NEWLINE]), nl_len); output_string (this, s, &s[total_len]); output_string (this, &s[x->w], &s[total_len]); } if (line_p != line_buf && !commit_line_buf (this)) return 0; - output_lines (this, x->n_output, x->l - x->n_output); + output_lines (this, 0, x->l); ff_len = ls_length (&x->ops[OPS_FORMFEED]); total_len = x->bottom_margin * nl_len + ff_len; @@ -1584,21 +1618,35 @@ ascii_close_page (struct outp_driver *this) s = xrealloc (s, total_len); for (cp = s, i = 0; i < x->bottom_margin; i++) { - memcpy (cp, ls_value (&x->ops[OPS_NEWLINE]), nl_len); + memcpy (cp, ls_c_str (&x->ops[OPS_NEWLINE]), nl_len); cp += nl_len; } - memcpy (cp, ls_value (&x->ops[OPS_FORMFEED]), ff_len); + memcpy (cp, ls_c_str (&x->ops[OPS_FORMFEED]), ff_len); if ( x->paginate ) output_string (this, s, &s[total_len]); + if (line_p != line_buf && !commit_line_buf (this)) return 0; - x->n_output = 0; - this->page_open = 0; return 1; } + + +static void +ascii_chart_initialise(struct outp_driver *d UNUSED, struct chart *ch ) +{ + msg(MW, _("Charts are unsupported with ascii drivers.")); + ch->lp = 0; +} + +static void +ascii_chart_finalise(struct outp_driver *d UNUSED, struct chart *ch UNUSED) +{ + +} + struct outp_class ascii_class = { "ascii", @@ -1637,4 +1685,7 @@ struct outp_class ascii_class = ascii_text_get_size, ascii_text_metrics, ascii_text_draw, + + ascii_chart_initialise, + ascii_chart_finalise };