lefty.c 12.1 KB
Newer Older
1
/* $Id$ $Revision$ */ 
2 3
/* vim:set shiftwidth=4 ts=8: */

ellson's avatar
ellson committed
4 5 6 7 8 9 10 11 12
/*************************************************************************
 * Copyright (c) 2011 AT&T Intellectual Property 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors: See CVS logs. Details at http://www.graphviz.org/
 *************************************************************************/
13

14
/* Lefteris Koutsofios - AT&T Labs Research */
15

16 17 18 19
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

20
#define LEFTYVERSION "10 Mar 2005"
21

22
#include "builddate.h"
23 24 25 26 27 28 29 30 31 32 33 34 35
#include "common.h"
#include "g.h"
#include "code.h"
#include "io.h"
#include "mem.h"
#include "tbl.h"
#include "parse.h"
#include "exec.h"
#include "str.h"
#include "display.h"
#include "internal.h"
#include "txtview.h"
#include "gfxview.h"
36

37 38 39 40
#ifdef FEATURE_GMAP
#include "gmap.h"
#include "gmap2l.h"
#endif
41

42 43
#ifndef FEATURE_MS
#include <sys/time.h>
44 45 46
#  ifdef STATS
#  include <sys/resource.h>
#  endif
47 48
#endif

49 50
#if HAVE_FILE_CNT
#define canread(f) ((f)->_cnt>0)
51
#else
52 53 54 55 56 57 58 59 60 61 62 63 64
#  if HAVE_FILE_NEXT
#  define canread(f) ((f)->_next<(f)->_endb)
#  else
#    if HAVE_FILE_IO_READ_END
#    define canread(f) ((f)->_IO_read_end>(f)->_IO_read_ptr)
#    else
#      if HAVE_R_IN_FILE
#      define canread(f) ((f)->_r>0)
#      else
#      define canread(f) (1)
#      endif
#    endif
#  endif
65 66 67 68 69 70 71
#endif

#ifdef FEATURE_GMAP
static int gmapon;
#endif

static Grect_t txtcoords = {
72
    { 1,  1 }, { 449, 599 },
73 74 75 76 77 78 79 80 81 82 83
};

#ifdef STATS
static time_t stime;
#endif

static int endflag = FALSE;

static char *exprstr;
static FILE *fp;

84 85 86 87
static int processinput (int);
static void processargs (int, char **);
static void processstr (char *);
static void printusage (void);
88

89
#if defined(FEATURE_X11) || defined(FEATURE_NONE)
90

91
int main (int argc, char **argv) {
92 93 94 95 96 97 98 99
    Tobj co;
    Psrc_t src;

#ifdef MTRACE
    extern int Mt_certify;
    Mt_certify = 1;
#endif
#ifdef STATS
100
    stime = time (NULL);
101 102 103 104 105
#endif

    idlerunmode = 0;
    exprstr = NULL;
    fp = NULL;
106 107 108 109
    init (argv[0]);
    Minit (GFXprune);
    Ginit ();
    FD_SET (Gxfd, &inputfds);
110 111 112 113 114 115

    Eerrlevel = 1;
    Estackdepth = 2;
    Eshowbody = 1;
    Eshowcalls = 1;

116
    processstr (leftyoptions);
117
    argv++, argc--;
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
    processargs (argc, argv);

    if (setjmp (exitljbuf))
        goto eop;

    Cinit ();
    IOinit ();
    Tinit ();
    Pinit ();
    Einit ();
    Sinit ();
    Dinit ();
    Iinit ();
    TXTinit (txtcoords);
    GFXinit ();
133
#ifdef FEATURE_GMAP
134
    gmapon = TRUE, G2Linit ();
135 136 137
#endif

    if (exprstr) {
138 139 140 141
        src.flag = CHARSRC, src.s = exprstr, src.fp = NULL;
        src.tok = -1, src.lnum = 1;
        while ((co = Punit (&src)))
            Eunit (co);
142 143
    }
    if (fp) {
144 145 146 147
        src.flag = FILESRC, src.s = NULL, src.fp = fp;
        src.tok = -1, src.lnum = 1;
        while ((co = Punit (&src)))
            Eunit (co);
148 149
    }
    if (endflag)
150
        goto eop;
151

152
    TXTupdate ();
153 154

    Gneedredraw = FALSE;
155 156 157 158 159 160 161 162 163 164 165 166 167 168
    for (;;) {
        if (Gneedredraw)
            GFXredraw (), Gneedredraw = FALSE;
        if (Gbuttonsdown > 0) {
            GFXmove (), Gprocessevents (FALSE, G_ONEEVENT);
            processinput (FALSE);
        } else {
            if (Mcouldgc) {
                if (!processinput (FALSE))
                    Mdogc (M_GCINCR);
            }
            if (idlerunmode) {
                if (!processinput (FALSE))
                    GFXidle ();
169
#ifdef FEATURE_GMAP
170 171
            } else if (GMAPneedupdate) {
                processinput (FALSE);
172
#endif
173 174 175
            } else
                processinput (TRUE);
        }
176
#ifdef FEATURE_GMAP
177 178
        if (gmapon)
            GMAPupdate ();
179
#endif
180 181
        if (Erun)
            TXTupdate (), Erun = FALSE;
182
    }
183
eop:
184 185 186
#ifdef PARANOID
#ifdef FEATURE_GMAP
    if (gmapon)
187
        G2Lterm ();
188
#endif
189 190 191 192 193 194 195 196 197 198 199 200 201 202
    GFXterm ();
    TXTterm ();
    Iterm ();
    Dterm ();
    Sterm ();
    Eterm ();
    Pterm ();
    Tterm ();
    IOterm ();
    Cterm ();
    Gterm ();
    Mterm ();
    FD_CLR (Gxfd, &inputfds);
    term ();
203
#endif
204
    printusage ();
205 206 207 208 209
    return 0;
}

#else

210
HINSTANCE hinstance, hprevinstance;
211

212 213
int APIENTRY WinMain (
    HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow
214
) {
215 216 217 218 219 220 221 222
    Tobj co;
    Psrc_t src;

    hinstance = hInstance;
    hprevinstance = hPrevInstance;
    idlerunmode = 0;
    exprstr = NULL;
    fp = NULL;
223 224
    init (NULL);
    Ginit ();
225
#ifndef FEATURE_MS
226
    FD_SET (Gxfd, &inputfds);
227 228 229 230 231 232 233
#endif

    Eerrlevel = 1;
    Estackdepth = 2;
    Eshowbody = 1;
    Eshowcalls = 1;

234
    processstr (leftyoptions);
235
    __argv++, __argc--;
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
    processargs (__argc, __argv);

    if (setjmp (exitljbuf))
        goto eop;

    Cinit ();
    IOinit ();
    Minit (GFXprune);
    Tinit ();
    Pinit ();
    Einit ();
    Sinit ();
    Dinit ();
    Iinit ();
    TXTinit (txtcoords);
    GFXinit ();
252 253

    if (exprstr) {
254 255 256 257
        src.flag = CHARSRC, src.s = exprstr, src.fp = NULL;
        src.tok = -1, src.lnum = 1;
        while ((co = Punit (&src)))
            Eunit (co);
258 259
    }
    if (fp) {
260 261 262 263
        src.flag = FILESRC, src.s = NULL, src.fp = fp;
        src.tok = -1, src.lnum = 1;
        while ((co = Punit (&src)))
            Eunit (co);
264 265
    }
    if (endflag)
266
        goto eop;
267

268
    TXTupdate ();
269 270 271

    Gneedredraw = FALSE;
    for (;;) {
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
        if (Gneedredraw)
            GFXredraw (), Gneedredraw = FALSE;
        if (Gbuttonsdown > 0)
            GFXmove (), Gprocessevents (FALSE, G_ONEEVENT);
        else {
            if (Mcouldgc) {
                if (!processinput (FALSE))
                    Mdogc (M_GCINCR);
            } else if (idlerunmode) {
                if (!processinput (FALSE))
                    GFXidle ();
            } else
                processinput (TRUE);
        }
        if (Erun)
            TXTupdate (), Erun = FALSE;
288 289
    }

290
eop:
291
#ifdef PARANOID
292 293 294 295 296 297 298 299 300 301 302 303 304
    GFXterm ();
    TXTterm ();
    Iterm ();
    Dterm ();
    Sterm ();
    Eterm ();
    Pterm ();
    Tterm ();
    Mterm ();
    IOterm ();
    Cterm ();
    Gterm ();
    term ();
305
#endif
306 307
    printusage ();
    exit (0);
308 309 310 311 312 313 314 315 316
}

#endif

#ifndef FEATURE_MS
static struct timeval longwait = { 1000, 0 };
static struct timeval zerowait = { 0, 0 };
#endif

317
static int processinput (int waitflag) {
318 319 320 321 322 323 324 325 326 327 328
    fd_set fdset;
#ifndef FEATURE_MS
    struct timeval tz, *tzp;
#else
    HANDLE evs[MAXIMUM_WAIT_OBJECTS];
    int evn;
#endif
    int n, rtn;
    int ioi;

    rtn = 0;
329 330
    while (Gprocessevents (FALSE, G_MANYEVENTS))
        rtn = 1;
331 332
#ifndef FEATURE_MS
    for (ioi = 0, n = 0; ioi < ion; ioi++)
333 334 335 336 337 338
        if (
            iop[ioi].inuse && iop[ioi].ismonitored &&
            FD_ISSET (fileno (iop[ioi].ifp), &inputfds) &&
            canread (iop[ioi].ifp)
        )
            GFXmonitorfile (ioi), n++;
339
    if (n || rtn)
340
        return 1;
341
    if (Gneedredraw)
342
        return 0;
343 344 345
    tz = (waitflag && !rtn) ? longwait : zerowait;
    tzp = &tz;
    fdset = inputfds;
346 347
    if ((n = select (FD_SETSIZE, &fdset, NULL, NULL, tzp)) <= 0)
        return rtn;
348
    rtn = 1;
349 350
    if (FD_ISSET (Gxfd, &fdset))
        Gprocessevents (TRUE, G_MANYEVENTS), n--;
351
    if (!n)
352 353
        return rtn;
    Gsync ();
354
    for (ioi = 0; n > 0 && ioi < ion; ioi++)
355 356 357 358 359
        if (
            iop[ioi].inuse && iop[ioi].ismonitored &&
            FD_ISSET (fileno (iop[ioi].ifp), &fdset)
        )
            GFXmonitorfile (ioi), n--;
360 361
#else
    for (ioi = 0, n = 0, evn = 0; ioi < ion; ioi++) {
erg's avatar
erg committed
362
        if (!iop[ioi].inuse || !IOismonitored (ioi))
363 364 365 366 367 368 369 370 371
            continue;
        if (
            (iop[ioi].type == IO_FILE && canread (iop[ioi].ifp)) ||
            (iop[ioi].type == IO_PIPE && iop[ioi].buf[0])
        )
            GFXmonitorfile (ioi), n++;
        if (iop[ioi].type != IO_PIPE)
            continue;
        evs[evn++] = iop[ioi].ifp;
372 373
    }
    if (n)
374
        return 1;
375
    if (Gneedredraw)
376 377 378 379
        return 0;
    n = MsgWaitForMultipleObjects (
        evn, evs, FALSE, (waitflag && !rtn) ? 1 : 0, QS_ALLINPUT
    );
380
    if (n == WAIT_TIMEOUT || n < WAIT_OBJECT_0 || n > WAIT_OBJECT_0 + evn)
381
        return rtn;
382
    if (n == WAIT_OBJECT_0 + evn)
383 384
        Gprocessevents (TRUE, G_MANYEVENTS);
    Gsync ();
385
    for (ioi = 0; ioi < ion; ioi++)
386 387 388 389 390 391
        if (
            iop[ioi].inuse && IOismonitored (ioi) &&
            (iop[ioi].type == IO_FILE || (iop[ioi].type == IO_PIPE &&
            evs[n - WAIT_OBJECT_0] == iop[ioi].ifp))
        )
            GFXmonitorfile (ioi);
392 393 394 395
#endif
    return rtn;
}

Emden R. Gansner's avatar
Emden R. Gansner committed
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
static char* usestr =
"    -x    - exit after processing the input file.\n\
    -e E  - parse and execute expression E.\n\
    -el N - set error reporting level. (0)\n\
    -sd N - how much of the stack to show if error is printed. (2)\n\
    -sb N - how much of each function in the stack show if error is printed. (2)\n\
    -df S - set default font.\n\
    -ps F - specify a default file name for postscript files.\n\
    -     - read input from stdin.\n\
    -?    - show help.\n\
    -V    - print version.\n";

static void usage(int eval)
{
    fprintf (stderr, "Usage: lefty [options] [file]\n");
    fputs (usestr, stderr);
    exit (eval);
}

415
static void processstr (char *buf) {
416 417 418 419 420
    char *words[100];
    char *s, *s1;
    int i;

    if (!(s = buf) || *s == 0)
421 422 423 424 425 426 427 428 429 430 431 432
        return;
    s = strdup (s);
    for (i = 0, s1 = s; *s1; ) {
        for (; *s1 && *s1 == ' '; s1++)
            ;
        if (!*s1)
            break;
        words[i++] = s1;
        for (; *s1 && *s1 != ' '; s1++)
            ;
        if (*s1)
            *s1 = '\000', s1++;
433 434
    }
    words[i] = NULL;
435 436
    processargs (i, words);
    free (s);
437 438
}

439
static void processargs (int argc, char *argv[]) {
440
    while (argc) {
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
        if (strcmp (argv[0], "-x") == 0)
            endflag = TRUE;
        else if (strcmp (argv[0], "-e") == 0)
            exprstr = argv[1], argv++, argc--;
        else if (strcmp (argv[0], "-el") == 0)
            Eerrlevel = atoi (argv[1]), argv++, argc--;
        else if (strcmp (argv[0], "-sd") == 0)
            Estackdepth = atoi (argv[1]), argv++, argc--;
        else if (strcmp (argv[0], "-sb") == 0)
            Eshowbody = atoi (argv[1]), argv++, argc--;
        else if (strcmp (argv[0], "-sc") == 0)
            Eshowcalls = atoi (argv[1]), argv++, argc--;
        else if (strcmp (argv[0], "-df") == 0)
            Gdefaultfont = argv[1], argv++, argc--;
        else if (strcmp (argv[0], "-w") == 0)
            warnflag = TRUE;
        else if (strcmp (argv[0], "-ps") == 0)
            Gpscanvasname = argv[1], argv++, argc--;
459
        else if (strcmp (argv[0], "-V") == 0) {
460
            fprintf (stderr, "lefty version %s\n", LEFTYVERSION);
461
            fprintf (stderr, "graphviz version %s (%s)\n", PACKAGE_VERSION, BUILDDATE);
462
	}
Emden R. Gansner's avatar
Emden R. Gansner committed
463 464
        else if (strcmp (argv[0], "-?") == 0)
            usage(0);
465 466
        else if (strcmp (argv[0], "-") == 0)
            fp = stdin;
Emden R. Gansner's avatar
Emden R. Gansner committed
467 468 469
        else if (argv[0][0] == '-') {
            fprintf (stderr, "option %s unrecognized - ignored\n", argv[0]);
        }
470
        else {
Emden R. Gansner's avatar
Emden R. Gansner committed
471 472 473 474
            if ((fp = fopen (argv[0], "r")) == NULL) {
                fprintf (stderr, "cannot open input file: %s\n", argv[0]);
                exit(2);
            }
475 476
        }
        argv++, argc--;
477 478
    }
    if (Eerrlevel > 1)
479
        Gerrflag = TRUE;
480 481
}

482
static void printusage (void) {
483 484 485
#ifdef STATS
    struct rusage ru;

486 487
    getrusage (RUSAGE_SELF, &ru);
    Mreport ();
488
#ifdef FEATURE_RUSAGE
489 490 491 492 493 494 495 496
    printf (
        "user   time %13.3lf\n",
        ru.ru_utime.tv_sec + ru.ru_utime.tv_nsec / 1000000000.0
    );
    printf (
        "system time %13.3lf\n",
        ru.ru_stime.tv_sec + ru.ru_stime.tv_nsec / 1000000000.0
    );
497
#else
498 499 500 501 502 503 504 505
    printf (
        "user   time %13.3lf\n",
        ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1000000.0
    );
    printf (
        "system time %13.3lf\n",
        ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1000000.0
    );
506
#endif
507 508 509 510 511 512 513
    printf ("resident size  %10d\n", ru.ru_maxrss * getpagesize ());
    printf ("input            %8d\n", ru.ru_inblock);
    printf ("output           %8d\n", ru.ru_oublock);
    printf ("socket msgs sent %8d\n", ru.ru_msgsnd);
    printf ("socket msgs rcvd %8d\n", ru.ru_msgrcv);
    printf ("real time        %8d\n", time (NULL) - stime);
    fflush (stdout);
514 515
#endif
}