summaryrefslogtreecommitdiffstats
path: root/src/misc/espresso/cvrin.c
blob: 993a9841fb636fb60c5e7c22cff2b0ac0f9b14a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#include "spinlock.h"

int atomic_read(const atomic_t *v){
    return v->val;
}

int atomic_dec_and_test(atomic_t *v){
    if(v->val > 0){
        v->val--;
        return v->val == 0;
    }
    return 0;
}

void atomic_inc(atomic_t *v){
    v->val++;
}

void atomic_set(atomic_t *v, int x){
    v->val = x;
}

void spin_lock_init(spinlock_t *lock){
    *lock = (spinlock_t){};
}

unsigned long _spin_lock_irqsave(spinlock_t *lock){
    lock->val++;
    return 0;
}

void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags){
    lock->val--;
}

unsigned long _read_lock_irqsave(rwlock_t *lock){
    lock->val++;
    return 0;
}

void read_unlock_irqrestore(rwlock_t *lock, unsigned long flags){
    lock->val--;
}

unsigned long _write_lock_irqsave(rwlock_t *lock){
    lock->val++;
    return 0;
}

void write_unlock_irqrestore(rwlock_t *lock, unsigned long flags){
    lock->val--;
}

void init_MUTEX(struct semaphore *sem){
    *sem = (struct semaphore){ .count = 1 };
}

void down(struct semaphore *sem){
    sem->count--;
}

void up(struct semaphore *sem){
    sem->count++;
}
36 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
/*
 * Revision Control Information
 *
 * $Source$
 * $Author$
 * $Revision$
 * $Date$
 *
 */
/*
    module: cvrin.c
    purpose: cube and cover input routines
*/

#include <ctype.h>
#include "espresso.h"

ABC_NAMESPACE_IMPL_START


static bool line_length_error;
static int lineno;

void skip_line(fpin, fpout, echo)
register FILE *fpin, *fpout;
register bool echo;
{
    register int ch;
    while ((ch=getc(fpin)) != EOF && ch != '\n')
    if (echo)
        putc(ch, fpout);
    if (echo)
    putc('\n', fpout);
    lineno++;
}

char *get_word(fp, word)
register FILE *fp;
register char *word;
{
    register int ch, i = 0;
    while ((ch = getc(fp)) != EOF && isspace(ch))
    ;
    word[i++] = ch;
    while ((ch = getc(fp)) != EOF && ! isspace(ch))
    word[i++] = ch;
    word[i++] = '\0';
    return word;
}

/*
 *  Yes, I know this routine is a mess
 */
void read_cube(fp, PLA)
register FILE *fp;
pPLA PLA;
{
    register int var, i;
    pcube cf = cube.temp[0], cr = cube.temp[1], cd = cube.temp[2];
    bool savef = FALSE, saved = FALSE, saver = FALSE;
    char token[256];             /* for kiss read hack */
    int varx, first, last, offset;    /* for kiss read hack */

    set_clear(cf, cube.size);

    /* Loop and read binary variables */
    for(var = 0; var < cube.num_binary_vars; var++)
    switch(getc(fp)) {
        case EOF:
        goto bad_char;
        case '\n':
        if (! line_length_error)
            (void) fprintf(stderr, "product term(s) %s\n",
            "span more than one line (warning only)");
        line_length_error = TRUE;
        lineno++;
        var--;
        break;
        case ' ': case '|': case '\t':
        var--;
        break;
        case '2': case '-':
        set_insert(cf, var*2+1);
        case '0':
        set_insert(cf, var*2);
        break;
        case '1':
        set_insert(cf, var*2+1);
        break;
        case '?':
        break;
        default:
        goto bad_char;
    }


    /* Loop for the all but one of the multiple-valued variables */    
    for(var = cube.num_binary_vars; var < cube.num_vars-1; var++)

    /* Read a symbolic multiple-valued variable */
    if (cube.part_size[var] < 0) {
        (void) fscanf(fp, "%s", token);
        if (equal(token, "-") || equal(token, "ANY")) {
        if (kiss && var == cube.num_vars - 2) {
            /* leave it empty */
        } else {
            /* make it full */
            set_or(cf, cf, cube.var_mask[var]);
        }
        } else if (equal(token, "~")) {
        ;
        /* leave it empty ... (?) */
        } else {
        if (kiss && var == cube.num_vars - 2)
            varx = var - 1, offset = ABS(cube.part_size[var-1]);
        else
            varx = var, offset = 0;
        /* Find the symbolic label in the label table */
        first = cube.first_part[varx];
        last = cube.last_part[varx];
        for(i = first; i <= last; i++)
            if (PLA->label[i] == (char *) NULL) {
            PLA->label[i] = util_strsav(token);    /* add new label */
            set_insert(cf, i+offset);
            break;
            } else if (equal(PLA->label[i], token)) {
            set_insert(cf, i+offset);    /* use column i */
            break;
            }
        if (i > last) {
            (void) fprintf(stderr,
"declared size of variable %d (counting from variable 0) is too small\n", var);
            exit(-1);
        }
        }
    
    } else for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
        switch (getc(fp)) {
        case EOF:
            goto bad_char;
        case '\n':
            if (! line_length_error)
            (void) fprintf(stderr, "product term(s) %s\n",
                "span more than one line (warning only)");
            line_length_error = TRUE;
            lineno++;
            i--;
            break;
        case ' ': case '|': case '\t':
            i--;
            break;
        case '1':
            set_insert(cf, i);
        case '0':
            break;
        default:
            goto bad_char;
        }

    /* Loop for last multiple-valued variable */
    if (kiss) {
    saver = savef = TRUE;
    (void) set_xor(cr, cf, cube.var_mask[cube.num_vars - 2]);
    } else
    set_copy(cr, cf);
    set_copy(cd, cf);
    for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
    switch (getc(fp)) {
        case EOF:
        goto bad_char;
        case '\n':
        if (! line_length_error)
            (void) fprintf(stderr, "product term(s) %s\n",
            "span more than one line (warning only)");
        line_length_error = TRUE;
        lineno++;
        i--;
        break;
        case ' ': case '|': case '\t':
        i--;
        break;
        case '4': case '1':
        if (PLA->pla_type & F_type)
            set_insert(cf, i), savef = TRUE;
        break;
        case '3': case '0':
        if (PLA->pla_type & R_type)
            set_insert(cr, i), saver = TRUE;
        break;
        case '2': case '-':
        if (PLA->pla_type & D_type)
            set_insert(cd, i), saved = TRUE;
        case '~':
        break;
        default:
        goto bad_char;
    }
    if (savef) PLA->F = sf_addset(PLA->F, cf);
    if (saved) PLA->D = sf_addset(PLA->D, cd);
    if (saver) PLA->R = sf_addset(PLA->R, cr);
    return;

bad_char:
    (void) fprintf(stderr, "(warning): input line #%d ignored\n", lineno);
    skip_line(fp, stdout, TRUE);
    return;
}
void parse_pla(fp, PLA)
IN FILE *fp;
INOUT pPLA PLA;
{
    int i, var, ch, np, last;
    char word[256];

    lineno = 1;
    line_length_error = FALSE;

loop:
    switch(ch = getc(fp)) {
    case EOF:
        return;

    case '\n':
        lineno++;

    case ' ': case '\t': case '\f': case '\r':
        break;

    case '#':
        (void) ungetc(ch, fp);
        skip_line(fp, stdout, echo_comments);
        break;

    case '.':
        /* .i gives the cube input size (binary-functions only) */
        if (equal(get_word(fp, word), "i")) {
        if (cube.fullset != NULL) {
            (void) fprintf(stderr, "extra .i ignored\n");
            skip_line(fp, stdout, /* echo */ FALSE);
        } else {
            if (fscanf(fp, "%d", &cube.num_binary_vars) != 1)
            fatal("error reading .i");
            cube.num_vars = cube.num_binary_vars + 1;
            cube.part_size = ALLOC(int, cube.num_vars);
        }

        /* .o gives the cube output size (binary-functions only) */
        } else if (equal(word, "o")) {
        if (cube.fullset != NULL) {
            (void) fprintf(stderr, "extra .o ignored\n");
            skip_line(fp, stdout, /* echo */ FALSE);
        } else {
            if (cube.part_size == NULL)
            fatal(".o cannot appear before .i");
            if (fscanf(fp, "%d", &(cube.part_size[cube.num_vars-1]))!=1)
            fatal("error reading .o");
            cube_setup();
            PLA_labels(PLA);
        }

        /* .mv gives the cube size for a multiple-valued function */
        } else if (equal(word, "mv")) {
        if (cube.fullset != NULL) {
            (void) fprintf(stderr, "extra .mv ignored\n");
            skip_line(fp, stdout, /* echo */ FALSE);
        } else {
            if (cube.part_size != NULL)
            fatal("cannot mix .i and .mv");
            if (fscanf(fp,"%d %d",
            &cube.num_vars,&cube.num_binary_vars) != 2)
             fatal("error reading .mv");
            if (cube.num_binary_vars < 0)
fatal("num_binary_vars (second field of .mv) cannot be negative");
            if (cube.num_vars < cube.num_binary_vars)
            fatal(
"num_vars (1st field of .mv) must exceed num_binary_vars (2nd field of .mv)");
            cube.part_size = ALLOC(int, cube.num_vars);
            for(var=cube.num_binary_vars; var < cube.num_vars; var++)
            if (fscanf(fp, "%d", &(cube.part_size[var])) != 1)
                fatal("error reading .mv");
            cube_setup();
            PLA_labels(PLA);
        }

        /* .p gives the number of product terms -- we ignore it */
        } else if (equal(word, "p"))
        (void) fscanf(fp, "%d", &np);
        /* .e and .end specify the end of the file */
        else if (equal(word, "e") || equal(word,"end")) {
        if (cube.fullset == NULL) {
            /* fatal("unknown PLA size, need .i/.o or .mv");*/
                } else if (PLA->F == NULL) {
                    PLA->F = new_cover(10);
                    PLA->D = new_cover(10);
                    PLA->R = new_cover(10);
                }
        return;
        }
        /* .kiss turns on the kiss-hack option */
        else if (equal(word, "kiss"))
        kiss = TRUE;

        /* .type specifies a logical type for the PLA */
        else if (equal(word, "type")) {
        (void) get_word(fp, word);
        for(i = 0; pla_types[i].key != 0; i++)
            if (equal(pla_types[i].key + 1, word)) {
            PLA->pla_type = pla_types[i].value;
            break;
            }
        if (pla_types[i].key == 0)
            fatal("unknown type in .type command");

        /* parse the labels */
        } else if (equal(word, "ilb")) {
        if (cube.fullset == NULL)
            fatal("PLA size must be declared before .ilb or .ob");
        if (PLA->label == NULL)
            PLA_labels(PLA);
        for(var = 0; var < cube.num_binary_vars; var++) {
            (void) get_word(fp, word);
            i = cube.first_part[var];
            PLA->label[i+1] = util_strsav(word);
            PLA->label[i] = ALLOC(char, strlen(word) + 6);
            (void) sprintf(PLA->label[i], "%s.bar", word);
        }
        } else if (equal(word, "ob")) {
        if (cube.fullset == NULL)
            fatal("PLA size must be declared before .ilb or .ob");
        if (PLA->label == NULL)
            PLA_labels(PLA);
        var = cube.num_vars - 1;
        for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
            (void) get_word(fp, word);
            PLA->label[i] = util_strsav(word);
        }
        /* .label assigns labels to multiple-valued variables */
        } else if (equal(word, "label")) {
        if (cube.fullset == NULL)
            fatal("PLA size must be declared before .label");
        if (PLA->label == NULL)
            PLA_labels(PLA);
        if (fscanf(fp, "var=%d", &var) != 1)
            fatal("Error reading labels");
        for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
            (void) get_word(fp, word);
            PLA->label[i] = util_strsav(word);
        }

        } else if (equal(word, "symbolic")) {
        symbolic_t *newlist, *p1;
        if (read_symbolic(fp, PLA, word, &newlist)) {
            if (PLA->symbolic == NIL(symbolic_t)) {
            PLA->symbolic = newlist;
            } else {
            for(p1=PLA->symbolic;p1->next!=NIL(symbolic_t);
                p1=p1->next){
            }
            p1->next = newlist;
            }
        } else {
            fatal("error reading .symbolic");
        }

        } else if (equal(word, "symbolic-output")) {
        symbolic_t *newlist, *p1;
        if (read_symbolic(fp, PLA, word, &newlist)) {
            if (PLA->symbolic_output == NIL(symbolic_t)) {
            PLA->symbolic_output = newlist;
            } else {
            for(p1=PLA->symbolic_output;p1->next!=NIL(symbolic_t);
                p1=p1->next){
            }
            p1->next = newlist;
            }
        } else {
            fatal("error reading .symbolic-output");
        }
        
        /* .phase allows a choice of output phases */
        } else if (equal(word, "phase")) {
        if (cube.fullset == NULL)
            fatal("PLA size must be declared before .phase");
        if (PLA->phase != NULL) {
            (void) fprintf(stderr, "extra .phase ignored\n");
            skip_line(fp, stdout, /* echo */ FALSE);
        } else {
            do ch = getc(fp); while (ch == ' ' || ch == '\t');
            (void) ungetc(ch, fp);
            PLA->phase = set_save(cube.fullset);
            last = cube.last_part[cube.num_vars - 1];
            for(i=cube.first_part[cube.num_vars - 1]; i <= last; i++)
            if ((ch = getc(fp)) == '0')
                set_remove(PLA->phase, i);
            else if (ch != '1')
                fatal("only 0 or 1 allowed in phase description");
        }

        /* .pair allows for bit-pairing input variables */
        } else if (equal(word, "pair")) {
        int j;
        if (PLA->pair != NULL) {
            (void) fprintf(stderr, "extra .pair ignored\n");
        } else {
            ppair pair;
            PLA->pair = pair = ALLOC(pair_t, 1);
            if (fscanf(fp, "%d", &(pair->cnt)) != 1)
            fatal("syntax error in .pair");
            pair->var1 = ALLOC(int, pair->cnt);
            pair->var2 = ALLOC(int, pair->cnt);
            for(i = 0; i < pair->cnt; i++) {
            (void) get_word(fp, word);
            if (word[0] == '(') (void) strcpy(word, word+1);
            if (label_index(PLA, word, &var, &j)) {
                pair->var1[i] = var+1;
            } else {
                fatal("syntax error in .pair");
            }

            (void) get_word(fp, word);
            if (word[strlen(word)-1] == ')') {
                word[strlen(word)-1]='\0';
            }
            if (label_index(PLA, word, &var, &j)) {
                pair->var2[i] = var+1;
            } else {
                fatal("syntax error in .pair");
            }
            }
        }
        
        } else {
        if (echo_unknown_commands)
            printf("%c%s ", ch, word);
        skip_line(fp, stdout, echo_unknown_commands);
        }
        break;
    default:
        (void) ungetc(ch, fp);
        if (cube.fullset == NULL) {
/*        fatal("unknown PLA size, need .i/.o or .mv");*/
        if (echo_comments)
            putchar('#');
        skip_line(fp, stdout, echo_comments);
        break;
        }
        if (PLA->F == NULL) {
        PLA->F = new_cover(10);
        PLA->D = new_cover(10);
        PLA->R = new_cover(10);
        }
        read_cube(fp, PLA);
    }
    goto loop;
}
/*
    read_pla -- read a PLA from a file

    Input stops when ".e" is encountered in the input file, or upon reaching
    end of file.

    Returns the PLA in the variable PLA after massaging the "symbolic"
    representation into a positional cube notation of the ON-set, OFF-set,
    and the DC-set.

    needs_dcset and needs_offset control the computation of the OFF-set
    and DC-set (i.e., if either needs to be computed, then it will be
    computed via complement only if the corresponding option is TRUE.)
    pla_type specifies the interpretation to be used when reading the
    PLA.

    The phase of the output functions is adjusted according to the
    global option "pos" or according to an imbedded .phase option in
    the input file.  Note that either phase option implies that the
    OFF-set be computed regardless of whether the caller needs it
    explicitly or not.

    Bit pairing of the binary variables is performed according to an
    imbedded .pair option in the input file.

    The global cube structure also reflects the sizes of the PLA which
    was just read.  If these fields have already been set, then any
    subsequent PLA must conform to these sizes.

    The global flags trace and summary control the output produced
    during the read.

    Returns a status code as a result:
    EOF (-1) : End of file reached before any data was read
    > 0     : Operation successful
*/

int read_pla(fp, needs_dcset, needs_offset, pla_type, PLA_return)
IN FILE *fp;
IN bool needs_dcset, needs_offset;
IN int pla_type;
OUT pPLA *PLA_return;
{
    pPLA PLA;
    int i, second, third;
    long time;
    cost_t cost;

    /* Allocate and initialize the PLA structure */
    PLA = *PLA_return = new_PLA();
    PLA->pla_type = pla_type;

    /* Read the pla */
    time = ptime();
    parse_pla(fp, PLA);

    /* Check for nothing on the file -- implies reached EOF */
    if (PLA->F == NULL) {
    return EOF;
    }

    /* This hack merges the next-state field with the outputs */
    for(i = 0; i < cube.num_vars; i++) {
    cube.part_size[i] = ABS(cube.part_size[i]);
    }
    if (kiss) {
    third = cube.num_vars - 3;
    second = cube.num_vars - 2;
    if (cube.part_size[third] != cube.part_size[second]) {
        (void) fprintf(stderr," with .kiss option, third to last and second\n");
        (void) fprintf(stderr, "to last variables must be the same size.\n");
        return EOF;
    }
    for(i = 0; i < cube.part_size[second]; i++) {
        PLA->label[i + cube.first_part[second]] =
        util_strsav(PLA->label[i + cube.first_part[third]]);
    }
    cube.part_size[second] += cube.part_size[cube.num_vars-1];
    cube.num_vars--;
    setdown_cube();
    cube_setup();
    }

    if (trace) {
    totals(time, READ_TIME, PLA->F, &cost);
    }

    /* Decide how to break PLA into ON-set, OFF-set and DC-set */
    time = ptime();
    if (pos || PLA->phase != NULL || PLA->symbolic_output != NIL(symbolic_t)) {
    needs_offset = TRUE;
    }
    if (needs_offset && (PLA->pla_type==F_type || PLA->pla_type==FD_type)) {
    free_cover(PLA->R);
    PLA->R = complement(cube2list(PLA->F, PLA->D));
    } else if (needs_dcset && PLA->pla_type == FR_type) {
    pcover X;
    free_cover(PLA->D);
    /* hack, why not? */
    X = d1merge(sf_join(PLA->F, PLA->R), cube.num_vars - 1);
    PLA->D = complement(cube1list(X));
    free_cover(X);
    } else if (PLA->pla_type == R_type || PLA->pla_type == DR_type) {
    free_cover(PLA->F);
    PLA->F = complement(cube2list(PLA->D, PLA->R));
    }

    if (trace) {
    totals(time, COMPL_TIME, PLA->R, &cost);
    }

    /* Check for phase rearrangement of the functions */
    if (pos) {
    pcover onset = PLA->F;
    PLA->F = PLA->R;
    PLA->R = onset;
    PLA->phase = new_cube();
    set_diff(PLA->phase, cube.fullset, cube.var_mask[cube.num_vars-1]);
    } else if (PLA->phase != NULL) {
    (void) set_phase(PLA);
    }

    /* Setup minimization for two-bit decoders */
    if (PLA->pair != (ppair) NULL) {
    set_pair(PLA);
    }

    if (PLA->symbolic != NIL(symbolic_t)) {
    EXEC(map_symbolic(PLA), "MAP-INPUT  ", PLA->F);
    }
    if (PLA->symbolic_output != NIL(symbolic_t)) {
    EXEC(map_output_symbolic(PLA), "MAP-OUTPUT ", PLA->F);
    if (needs_offset) {
        free_cover(PLA->R);
EXECUTE(PLA->R=complement(cube2list(PLA->F,PLA->D)), COMPL_TIME, PLA->R, cost);
    }
    }

    return 1;
}

void PLA_summary(PLA)
pPLA PLA;
{
    int var, i;
    symbolic_list_t *p2;
    symbolic_t *p1;

    printf("# PLA is %s", PLA->filename);
    if (cube.num_binary_vars == cube.num_vars - 1)
    printf(" with %d inputs and %d outputs\n",
        cube.num_binary_vars, cube.part_size[cube.num_vars - 1]);
    else {
    printf(" with %d variables (%d binary, mv sizes",
        cube.num_vars, cube.num_binary_vars);
    for(var = cube.num_binary_vars; var < cube.num_vars; var++)
        printf(" %d", cube.part_size[var]);
    printf(")\n");
    }
    printf("# ON-set cost is  %s\n", print_cost(PLA->F));
    printf("# OFF-set cost is %s\n", print_cost(PLA->R));
    printf("# DC-set cost is  %s\n", print_cost(PLA->D));
    if (PLA->phase != NULL)
    printf("# phase is %s\n", pc1(PLA->phase));
    if (PLA->pair != NULL) {
    printf("# two-bit decoders:");
    for(i = 0; i < PLA->pair->cnt; i++)
        printf(" (%d %d)", PLA->pair->var1[i], PLA->pair->var2[i]);
    printf("\n");
    }
    if (PLA->symbolic != NIL(symbolic_t)) {
    for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
        printf("# symbolic: ");
        for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
        printf(" %d", p2->variable);
        }
        printf("\n");
    }
    }
    if (PLA->symbolic_output != NIL(symbolic_t)) {
    for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1->next) {
        printf("# output symbolic: ");
        for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
        printf(" %d", p2->pos);
        }
        printf("\n");
    }
    }
    (void) fflush(stdout);
}


pPLA new_PLA()
{
    pPLA PLA;

    PLA = ALLOC(PLA_t, 1);
    PLA->F = PLA->D = PLA->R = (pcover) NULL;
    PLA->phase = (pcube) NULL;
    PLA->pair = (ppair) NULL;
    PLA->label = (char **) NULL;
    PLA->filename = (char *) NULL;
    PLA->pla_type = 0;
    PLA->symbolic = NIL(symbolic_t);
    PLA->symbolic_output = NIL(symbolic_t);
    return PLA;
}


void PLA_labels(PLA)
pPLA PLA;
{
    int i;

    PLA->label = ALLOC(char *, cube.size);
    for(i = 0; i < cube.size; i++)
    PLA->label[i] = (char *) NULL;
}


void free_PLA(PLA)
pPLA PLA;
{
    symbolic_list_t *p2, *p2next;
    symbolic_t *p1, *p1next;
    int i;

    if (PLA->F != (pcover) NULL)
    free_cover(PLA->F);
    if (PLA->R != (pcover) NULL)
    free_cover(PLA->R);
    if (PLA->D != (pcover) NULL)
    free_cover(PLA->D);
    if (PLA->phase != (pcube) NULL)
    free_cube(PLA->phase);
    if (PLA->pair != (ppair) NULL) {
    FREE(PLA->pair->var1);
    FREE(PLA->pair->var2);
    FREE(PLA->pair);
    }
    if (PLA->label != NULL) {
    for(i = 0; i < cube.size; i++)
        if (PLA->label[i] != NULL)
        FREE(PLA->label[i]);
    FREE(PLA->label);
    }
    if (PLA->filename != NULL) {
    FREE(PLA->filename);
    }
    for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1next) {
    for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) {
        p2next = p2->next;
        FREE(p2);
    }
    p1next = p1->next;
    FREE(p1);
    }
    PLA->symbolic = NIL(symbolic_t);
    for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1next) {
    for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) {
        p2next = p2->next;
        FREE(p2);
    }
    p1next = p1->next;
    FREE(p1);
    }
    PLA->symbolic_output = NIL(symbolic_t);
    FREE(PLA);
}


int read_symbolic(fp, PLA, word, retval)
FILE *fp;
pPLA PLA;
char *word;        /* scratch string for words */
symbolic_t **retval;
{
    symbolic_list_t *listp, *prev_listp;
    symbolic_label_t *labelp, *prev_labelp;
    symbolic_t *newlist;
    int i, var;

    newlist = ALLOC(symbolic_t, 1);
    newlist->next = NIL(symbolic_t);
    newlist->symbolic_list = NIL(symbolic_list_t);
    newlist->symbolic_list_length = 0;
    newlist->symbolic_label = NIL(symbolic_label_t);
    newlist->symbolic_label_length = 0;
    prev_listp = NIL(symbolic_list_t);
    prev_labelp = NIL(symbolic_label_t);

    for(;;) {
    (void) get_word(fp, word);
    if (equal(word, ";"))
        break;
    if (label_index(PLA, word, &var, &i)) {
        listp = ALLOC(symbolic_list_t, 1);
        listp->variable = var;
        listp->pos = i;
        listp->next = NIL(symbolic_list_t);
        if (prev_listp == NIL(symbolic_list_t)) {
        newlist->symbolic_list = listp;
        } else {
        prev_listp->next = listp;
        }
        prev_listp = listp;
        newlist->symbolic_list_length++;
    } else {
        return FALSE;
    }
    }

    for(;;) {
    (void) get_word(fp, word);
    if (equal(word, ";"))
        break;
    labelp = ALLOC(symbolic_label_t, 1);
    labelp->label = util_strsav(word);
    labelp->next = NIL(symbolic_label_t);
    if (prev_labelp == NIL(symbolic_label_t)) {
        newlist->symbolic_label = labelp;
    } else {
        prev_labelp->next = labelp;
    }
    prev_labelp = labelp;
    newlist->symbolic_label_length++;
    }

    *retval = newlist;
    return TRUE;
}


int label_index(PLA, word, varp, ip)
pPLA PLA;
char *word;
int *varp;
int *ip;
{
    int var, i;

    if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) {
    if (sscanf(word, "%d", varp) == 1) {
        *ip = *varp;
        return TRUE;
    }
    } else {
    for(var = 0; var < cube.num_vars; var++) {
        for(i = 0; i < cube.part_size[var]; i++) {
        if (equal(PLA->label[cube.first_part[var]+i], word)) {
            *varp = var;
            *ip = i;
            return TRUE;
        }
        }
    }
    }
    return FALSE;
}
ABC_NAMESPACE_IMPL_END