~ubuntu-branches/ubuntu/dapper/groff/dapper

« back to all changes in this revision

Viewing changes to src/libs/libdriver/input.cc

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2002-03-17 04:11:50 UTC
  • Revision ID: james.westby@ubuntu.com-20020317041150-wkgfawjc3gxlk0o5
Tags: upstream-1.17.2
ImportĀ upstreamĀ versionĀ 1.17.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- C++ -*-
 
2
/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
 
3
     Written by James Clark (jjc@jclark.com)
 
4
 
 
5
This file is part of groff.
 
6
 
 
7
groff is free software; you can redistribute it and/or modify it under
 
8
the terms of the GNU General Public License as published by the Free
 
9
Software Foundation; either version 2, or (at your option) any later
 
10
version.
 
11
 
 
12
groff is distributed in the hope that it will be useful, but WITHOUT ANY
 
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
14
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
15
for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License along
 
18
with groff; see the file COPYING.  If not, write to the Free Software
 
19
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
20
 
 
21
#include "driver.h"
 
22
#include "device.h"
 
23
#include "cset.h"
 
24
 
 
25
const char *current_filename=0;
 
26
int current_lineno;
 
27
const char *device = 0;
 
28
FILE *current_file;
 
29
 
 
30
int get_integer();              // don't read the newline
 
31
int possibly_get_integer(int *);
 
32
char *get_string(int is_long = 0);
 
33
void skip_line();
 
34
 
 
35
struct environment_list {
 
36
  environment env;
 
37
  environment_list *next;
 
38
 
 
39
  environment_list(const environment &, environment_list *);
 
40
};
 
41
 
 
42
environment_list::environment_list(const environment &e, environment_list *p)
 
43
: env(e), next(p)
 
44
{
 
45
}
 
46
 
 
47
inline int get_char()
 
48
{
 
49
  return getc(current_file);
 
50
}
 
51
 
 
52
/*
 
53
 *  remember_filename - is needed as get_string might overwrite the
 
54
 *                      filename eventually.
 
55
 */
 
56
 
 
57
void remember_filename(const char *filename)
 
58
{
 
59
  if (current_filename != 0) {
 
60
    free((char *)current_filename);
 
61
  }
 
62
  if (strcmp(filename, "-") == 0) {
 
63
    filename = "<standard input>";
 
64
  }
 
65
  current_filename = (const char *)malloc(strlen(filename) + 1);
 
66
  if (current_filename == 0) {
 
67
    fatal("can't malloc space for filename");
 
68
  }
 
69
  strcpy((char *)current_filename, (char *)filename);
 
70
}
 
71
 
 
72
void do_file(const char *filename)
 
73
{
 
74
  int npages = 0;
 
75
  if (filename[0] == '-' && filename[1] == '\0') {
 
76
    remember_filename(filename);
 
77
    current_file = stdin;
 
78
  }
 
79
  else {
 
80
    errno = 0;
 
81
    current_file = fopen(filename, "r");
 
82
    if (current_file == 0) {
 
83
      error("can't open `%1'", filename);
 
84
      return;
 
85
    }
 
86
    remember_filename(filename);
 
87
  }
 
88
  environment env;
 
89
  env.vpos = -1;
 
90
  env.hpos = -1;
 
91
  env.fontno = -1;
 
92
  env.height = 0;
 
93
  env.slant = 0;
 
94
  environment_list *env_list = 0;
 
95
  current_lineno = 1;
 
96
  int command;
 
97
  char *s;
 
98
  command = get_char();
 
99
  if (command == EOF)
 
100
    return;
 
101
  if (command != 'x')
 
102
    fatal("the first command must be `x T'");
 
103
  s = get_string();
 
104
  if (s[0] != 'T')
 
105
    fatal("the first command must be `x T'");
 
106
  char *dev = get_string();
 
107
  if (pr == 0) {
 
108
    device = strsave(dev);
 
109
    if (!font::load_desc())
 
110
      fatal("sorry, I can't continue");
 
111
  }
 
112
  else {
 
113
    if (device == 0 || strcmp(device, dev) != 0)
 
114
      fatal("all files must use the same device");
 
115
  }
 
116
  skip_line();
 
117
  env.size = 10*font::sizescale;
 
118
  command = get_char();
 
119
  if (command != 'x')
 
120
    fatal("the second command must be `x res'");
 
121
  s = get_string();
 
122
  if (s[0] != 'r')
 
123
    fatal("the second command must be `x res'");
 
124
  int n = get_integer();
 
125
  if (n != font::res)
 
126
    fatal("resolution does not match");
 
127
  n = get_integer();
 
128
  if (n != font::hor)
 
129
    fatal("horizontal resolution does not match");
 
130
  n = get_integer();
 
131
  if (n != font::vert)
 
132
    fatal("vertical resolution does not match");
 
133
  skip_line();
 
134
  command = get_char();
 
135
  if (command != 'x')
 
136
    fatal("the third command must be `x init'");
 
137
  s = get_string();
 
138
  if (s[0] != 'i')
 
139
    fatal("the third command must be `x init'");
 
140
  skip_line();
 
141
  if (pr == 0)
 
142
    pr = make_printer();
 
143
  while ((command = get_char()) != EOF) {
 
144
    switch (command) {
 
145
    case 's':
 
146
      env.size = get_integer();
 
147
      if (env.height == env.size)
 
148
        env.height = 0;
 
149
      break;
 
150
    case 'f':
 
151
      env.fontno = get_integer();
 
152
      break;
 
153
    case 'F':
 
154
      remember_filename(get_string());
 
155
      break;
 
156
    case 'C':
 
157
      {
 
158
        if (npages == 0)
 
159
          fatal("`C' command illegal before first `p' command");
 
160
        char *s = get_string();
 
161
        pr->set_special_char(s, &env);
 
162
      }
 
163
      break;
 
164
    case 'N':
 
165
      {
 
166
        if (npages == 0)
 
167
          fatal("`N' command illegal before first `p' command");
 
168
        pr->set_numbered_char(get_integer(), &env);
 
169
      }
 
170
      break;
 
171
    case 'H':
 
172
      env.hpos = get_integer();
 
173
      break;
 
174
    case 'h':
 
175
      env.hpos += get_integer();
 
176
      break;
 
177
    case 'V':
 
178
      env.vpos = get_integer();
 
179
      break;
 
180
    case 'v':
 
181
      env.vpos += get_integer();
 
182
      break;
 
183
    case '0':
 
184
    case '1':
 
185
    case '2':
 
186
    case '3':
 
187
    case '4':
 
188
    case '5':
 
189
    case '6':
 
190
    case '7':
 
191
    case '8':
 
192
    case '9':
 
193
      {
 
194
        int c = get_char();
 
195
        if (!csdigit(c))
 
196
          fatal("digit expected");
 
197
        env.hpos += (command - '0')*10 + (c - '0');
 
198
      }
 
199
      // fall through
 
200
    case 'c':
 
201
      {
 
202
        if (npages == 0)
 
203
          fatal("`c' command illegal before first `p' command");
 
204
        int c = get_char();
 
205
        if (c == EOF)
 
206
          fatal("missing argument to `c' command");
 
207
        pr->set_ascii_char(c, &env);
 
208
      }
 
209
      break;
 
210
    case 'n':
 
211
      if (npages == 0)
 
212
        fatal("`n' command illegal before first `p' command");
 
213
      pr->end_of_line();
 
214
      (void)get_integer();
 
215
      (void)get_integer();
 
216
      break;
 
217
    case 'w':
 
218
    case ' ':
 
219
      break;
 
220
    case '\n':
 
221
      current_lineno++;
 
222
      break;
 
223
    case 'p':
 
224
      if (npages)
 
225
        pr->end_page(env.vpos);
 
226
      npages++;
 
227
      pr->begin_page(get_integer());
 
228
      env.vpos = 0;
 
229
      break;
 
230
    case '{':
 
231
      env_list = new environment_list(env, env_list);
 
232
      break;
 
233
    case '}':
 
234
      if (!env_list) {
 
235
        fatal("can't pop");
 
236
      }
 
237
      else {
 
238
        env = env_list->env;
 
239
        environment_list *tem = env_list;
 
240
        env_list = env_list->next;
 
241
        delete tem;
 
242
      }
 
243
      break;
 
244
    case 'u':
 
245
      {
 
246
        if (npages == 0)
 
247
          fatal("`u' command illegal before first `p' command");
 
248
        int kern = get_integer();
 
249
        int c = get_char();
 
250
        while (c == ' ')
 
251
          c = get_char();
 
252
        while (c != EOF) {
 
253
          if (c == '\n') {
 
254
            current_lineno++;
 
255
            break;
 
256
          }
 
257
          int w;
 
258
          pr->set_ascii_char(c, &env, &w);
 
259
          env.hpos += w + kern;
 
260
          c = get_char();
 
261
          if (c == ' ')
 
262
            break;
 
263
        }
 
264
      }
 
265
      break;
 
266
    case 't':
 
267
      {
 
268
        if (npages == 0)
 
269
          fatal("`t' command illegal before first `p' command");
 
270
        int c;
 
271
        while ((c = get_char()) != EOF && c != ' ') {
 
272
          if (c == '\n') {
 
273
            current_lineno++;
 
274
            break;
 
275
          }
 
276
          int w;
 
277
          pr->set_ascii_char(c, &env, &w);
 
278
          env.hpos += w;
 
279
        }
 
280
      }
 
281
      break;
 
282
    case '#':
 
283
      skip_line();
 
284
      break;
 
285
    case 'D':
 
286
      {
 
287
        if (npages == 0)
 
288
          fatal("`D' command illegal before first `p' command");
 
289
        int c;
 
290
        while ((c = get_char()) == ' ')
 
291
          ;
 
292
        int n;
 
293
        int *p = 0;
 
294
        int szp = 0;
 
295
        int np;
 
296
        for (np = 0; possibly_get_integer(&n); np++) {
 
297
          if (np >= szp) {
 
298
            if (szp == 0) {
 
299
              szp = 16;
 
300
              p = new int[szp];
 
301
            }
 
302
            else {
 
303
              int *oldp = p;
 
304
              p = new int[szp*2];
 
305
              memcpy(p, oldp, szp*sizeof(int));
 
306
              szp *= 2;
 
307
              a_delete oldp;
 
308
            }
 
309
          }
 
310
          p[np] = n;
 
311
        }
 
312
        pr->draw(c, p, np, &env);
 
313
        if (c == 'e') {
 
314
          if (np > 0)
 
315
            env.hpos += p[0];
 
316
        }
 
317
        else if (c == 'f' || c == 't')
 
318
          ;
 
319
        else { 
 
320
          int i;
 
321
          for (i = 0; i < np/2; i++) {
 
322
            env.hpos += p[i*2];
 
323
            env.vpos += p[i*2 + 1];
 
324
          }
 
325
          // there might be an odd number of characters
 
326
          if (i*2 < np)
 
327
            env.hpos += p[i*2];
 
328
        }
 
329
        a_delete p;
 
330
        skip_line();
 
331
      }
 
332
      break;
 
333
    case 'x':
 
334
      {
 
335
        char *s = get_string();
 
336
        int suppress_skip = 0;
 
337
        switch (s[0]) {
 
338
        case 'i':
 
339
          error("duplicate `x init' command");
 
340
          break;
 
341
        case 'T':
 
342
          error("duplicate `x T' command");
 
343
          break;
 
344
        case 'r':
 
345
          error("duplicate `x res' command");
 
346
          break;
 
347
        case 'p':
 
348
          break;
 
349
        case 's':
 
350
          break;
 
351
        case 't':
 
352
          break;
 
353
        case 'f':
 
354
          {
 
355
            int n = get_integer();
 
356
            char *name = get_string();
 
357
            pr->load_font(n, name);
 
358
          }
 
359
          break;
 
360
        case 'H':
 
361
          env.height = get_integer();
 
362
          if (env.height == env.size)
 
363
            env.height = 0;
 
364
          break;
 
365
        case 'S':
 
366
          env.slant = get_integer();
 
367
          break;
 
368
        case 'X':
 
369
          if (npages == 0)
 
370
            fatal("`x X' command illegal before first `p' command");
 
371
          pr->special(get_string(1), &env);
 
372
          suppress_skip = 1;
 
373
          break;
 
374
        case 'u':
 
375
          // .cu
 
376
          pr->special(get_string(), &env, 'u');
 
377
          break;
 
378
        default:
 
379
          error("unrecognised x command `%1'", s);
 
380
        }
 
381
        if (!suppress_skip)
 
382
          skip_line();
 
383
      }
 
384
      break;
 
385
    default:
 
386
      error("unrecognised command code %1", int(command));
 
387
      skip_line();
 
388
      break;
 
389
    }
 
390
  }
 
391
  if (npages)
 
392
    pr->end_page(env.vpos);
 
393
}
 
394
 
 
395
int get_integer()
 
396
{
 
397
  int c = get_char();
 
398
  while (c == ' ')
 
399
    c = get_char();
 
400
  int neg = 0;
 
401
  if (c == '-') {
 
402
    neg = 1;
 
403
    c = get_char();
 
404
  }
 
405
  if (!csdigit(c))
 
406
    fatal("integer expected");
 
407
  int total = 0;
 
408
  do {
 
409
    total = total*10;
 
410
    if (neg)
 
411
      total -= c - '0';
 
412
    else
 
413
      total += c - '0';
 
414
    c = get_char();
 
415
  }  while (csdigit(c));
 
416
  if (c != EOF)
 
417
    ungetc(c, current_file);
 
418
  return total;
 
419
}
 
420
 
 
421
int possibly_get_integer(int *res)
 
422
{
 
423
  int c = get_char();
 
424
  while (c == ' ')
 
425
    c = get_char();
 
426
  int neg = 0;
 
427
  if (c == '-') {
 
428
    neg = 1;
 
429
    c = get_char();
 
430
  }
 
431
  if (!csdigit(c)) {
 
432
    if (c != EOF)
 
433
      ungetc(c, current_file);
 
434
    return 0;
 
435
  }
 
436
  int total = 0;
 
437
  do {
 
438
    total = total*10;
 
439
    if (neg)
 
440
      total -= c - '0';
 
441
    else
 
442
      total += c - '0';
 
443
    c = get_char();
 
444
  }  while (csdigit(c));
 
445
  if (c != EOF)
 
446
    ungetc(c, current_file);
 
447
  *res = total;
 
448
  return 1;
 
449
}
 
450
 
 
451
 
 
452
char *get_string(int is_long)
 
453
{
 
454
  static char *buf;
 
455
  static int buf_size;
 
456
  int c = get_char();
 
457
  while (c == ' ')
 
458
    c = get_char();
 
459
  for (int i = 0;; i++) {
 
460
    if (i >= buf_size) {
 
461
      if (buf_size == 0) {
 
462
        buf_size = 16;
 
463
        buf = new char[buf_size];
 
464
      }
 
465
      else {
 
466
        char *old_buf = buf;
 
467
        int old_size = buf_size;
 
468
        buf_size *= 2;
 
469
        buf = new char[buf_size];
 
470
        memcpy(buf, old_buf, old_size);
 
471
        a_delete old_buf;
 
472
      }
 
473
    }
 
474
    if ((!is_long && (c == ' ' || c == '\n')) || c == EOF) {
 
475
      buf[i] = '\0';
 
476
      break;
 
477
    }
 
478
    if (is_long && c == '\n') {
 
479
      current_lineno++;
 
480
      c = get_char();
 
481
      if (c == '+')
 
482
        c = '\n';
 
483
      else {
 
484
        buf[i] = '\0';
 
485
        break;
 
486
      }
 
487
    }  
 
488
    buf[i] = c;
 
489
    c = get_char();
 
490
  }
 
491
  if (c != EOF)
 
492
    ungetc(c, current_file);
 
493
  return buf;
 
494
}
 
495
 
 
496
void skip_line()
 
497
{
 
498
  int c;
 
499
  while ((c = get_char()) != EOF)
 
500
    if (c == '\n') {
 
501
      current_lineno++;
 
502
      break;
 
503
    }
 
504
}