Annotation of coherent/g/usr/bin/tic/comp_parse.c, revision 1.1

1.1     ! root        1: /*********************************************************************
        !             2: *                         COPYRIGHT NOTICE                           *
        !             3: **********************************************************************
        !             4: *        This software is copyright (C) 1982 by Pavel Curtis         *
        !             5: *                                                                    *
        !             6: *        Permission is granted to reproduce and distribute           *
        !             7: *        this file by any means so long as no fee is charged         *
        !             8: *        above a nominal handling fee and so long as this            *
        !             9: *        notice is always included in the copies.                    *
        !            10: *                                                                    *
        !            11: *        Other rights are reserved except as explicitly granted      *
        !            12: *        by written permission of the author.                        *
        !            13: *                Pavel Curtis                                        *
        !            14: *                Computer Science Dept.                              *
        !            15: *                405 Upson Hall                                      *
        !            16: *                Cornell University                                  *
        !            17: *                Ithaca, NY 14853                                    *
        !            18: *                                                                    *
        !            19: *                Ph- (607) 256-4934                                  *
        !            20: *                                                                    *
        !            21: *                Pavel.Cornell@Udel-Relay   (ARPAnet)                *
        !            22: *                decvax!cornell!pavel       (UUCPnet)                *
        !            23: *********************************************************************/
        !            24: 
        !            25: /*
        !            26:  *     comp_parse.c -- The high-level (ha!) parts of the compiler,
        !            27:  *                     that is, the routines which drive the scanner,
        !            28:  *                     etc.
        !            29:  *
        !            30:  *   $Log:     comp_parse.c,v $
        !            31:  * Revision 1.1  92/03/13  10:45:43  bin
        !            32:  * Initial revision
        !            33:  * 
        !            34:  * Revision 3.2  91/07/28  13:59:10  munk
        !            35:  * Made all the large arrays static
        !            36:  *
        !            37:  * Revision 3.1  84/12/13  11:19:32  john
        !            38:  * Revisions by Mark Horton
        !            39:  * 
        !            40:  * Revision 2.1  82/10/25  14:45:43  pavel
        !            41:  * Added Copyright Notice
        !            42:  * 
        !            43:  * Revision 2.0  82/10/24  15:16:39  pavel
        !            44:  * Beta-one Test Release
        !            45:  * 
        !            46:  * Revision 1.3  82/08/23  22:29:39  pavel
        !            47:  * The REAL Alpha-one Release Version
        !            48:  * 
        !            49:  * Revision 1.2  82/08/19  19:09:53  pavel
        !            50:  * Alpha Test Release One
        !            51:  * 
        !            52:  * Revision 1.1  82/08/12  18:37:12  pavel
        !            53:  * Initial revision
        !            54:  * 
        !            55:  *
        !            56:  */
        !            57: 
        !            58: #ifndef COHERENT
        !            59: static char RCSid[] =
        !            60:        "$Header: /src386/usr/bin/tic/RCS/comp_parse.c,v 1.1 92/03/13 10:45:43 bin Exp $";
        !            61: #endif
        !            62: 
        !            63: #include <sys/types.h>
        !            64: #include <sys/stat.h>
        !            65: #include <stdio.h>
        !            66: #include <ctype.h>
        !            67: #include "compiler.h"
        !            68: #include "term.h"
        !            69: #include "object.h"
        !            70: 
        !            71: 
        !            72: char   *string_table;
        !            73: int    next_free;      /* next free character in string_table */
        !            74: int    table_size = 0; /* current string_table size */
        !            75: short  term_names;     /* string table offset - current terminal */
        !            76: int    part2 = 0;      /* set to allow old compiled defns to be used */
        !            77: int    complete = 0;   /* 1 if entry done with no forward uses */
        !            78: 
        !            79: struct use_item
        !            80: {
        !            81:        long    offset;
        !            82:        struct use_item *fptr, *bptr;
        !            83: };
        !            84: 
        !            85: struct use_header
        !            86: {
        !            87:        struct use_item *head, *tail;
        !            88: };
        !            89: 
        !            90: struct use_header      use_list = {NULL, NULL};
        !            91: int                    use_count = 0;
        !            92: 
        !            93: /*
        !            94:  *  The use_list is a doubly-linked list with NULLs terminating the lists:
        !            95:  *
        !            96:  *        use_item    use_item    use_item
        !            97:  *       ---------   ---------   ---------
        !            98:  *       |       |   |       |   |       |   offset
        !            99:  *        |-------|   |-------|   |-------|
        !           100:  *       |   ----+-->|   ----+-->|  NULL |   fptr
        !           101:  *       |-------|   |-------|   |-------|
        !           102:  *       |  NULL |<--+----   |<--+----   |   bptr
        !           103:  *       ---------   ---------   ---------
        !           104:  *       ^                       ^
        !           105:  *       |  ------------------   |
        !           106:  *       |  |       |        |   |
        !           107:  *       +--+----   |    ----+---+
        !           108:  *          |       |        |
        !           109:  *          ------------------
        !           110:  *            head     tail
        !           111:  *               use_list
        !           112:  *
        !           113:  */
        !           114: 
        !           115: 
        !           116: /*
        !           117:  *     compile()
        !           118:  *
        !           119:  *     Main loop of the compiler.
        !           120:  *
        !           121:  *     get_token()
        !           122:  *     if curr_token != NAMES
        !           123:  *         err_abort()
        !           124:  *     while (not at end of file)
        !           125:  *         do an entry
        !           126:  *
        !           127:  */
        !           128: 
        !           129: compile()
        !           130: {
        !           131:        static char             line[1024];
        !           132:        int                     token_type;
        !           133:        struct use_item *ptr;
        !           134:        int                     old_use_count;
        !           135: 
        !           136:        token_type = get_token();
        !           137: 
        !           138:        if (token_type != NAMES)
        !           139:            err_abort("File does not start with terminal names in column one");
        !           140:        
        !           141:        while (token_type != EOF)
        !           142:            token_type = do_entry(NULL);
        !           143: 
        !           144:        DEBUG(2, "Starting handling of forward USE's\n", "");
        !           145: 
        !           146:        for (part2=0; part2<2; part2++) {
        !           147:            old_use_count = -1;
        !           148:        DEBUG(2, "\n\nPART %d\n\n", part2);
        !           149:            while (use_list.head != NULL  &&  old_use_count != use_count)
        !           150:            {
        !           151:                old_use_count = use_count;
        !           152:                for (ptr = use_list.tail; ptr != NULL; ptr = ptr->bptr)
        !           153:                {
        !           154:                    fseek(stdin, ptr->offset, 0);
        !           155:                    reset_input();
        !           156:                    if ((token_type = get_token()) != NAMES)
        !           157:                        syserr_abort("Token after a seek not NAMES");
        !           158:                    (void) do_entry(ptr);
        !           159:                    if (complete)
        !           160:                        dequeue(ptr);
        !           161:                }
        !           162: 
        !           163:                for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr)
        !           164:                {
        !           165:                    fseek(stdin, ptr->offset, 0);
        !           166:                    reset_input();
        !           167:                    if ((token_type = get_token()) != NAMES)
        !           168:                        syserr_abort("Token after a seek not NAMES");
        !           169:                    (void) do_entry(ptr);
        !           170:                    if (complete)
        !           171:                        dequeue(ptr);
        !           172:                }
        !           173:                
        !           174:                DEBUG(2, "Finished a pass through enqueued forward USE's\n", "");
        !           175:            }
        !           176:        }
        !           177: 
        !           178:        if (use_list.head != NULL)
        !           179:        {
        !           180:            fprintf(stderr, "\nError in following up use-links.  Either there is\n");
        !           181:            fprintf(stderr, "a loop in the links or they reference non-existant\n");
        !           182:            fprintf(stderr, "terminals.  The following is a list of the entries\n");
        !           183:            fprintf(stderr, "involved:\n\n");
        !           184: 
        !           185:            for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr)
        !           186:            {
        !           187:                fseek(stdin, ptr->offset, 0);
        !           188:                fgets(line, 1024, stdin);
        !           189:                fprintf(stderr, "%s", line);
        !           190:            }
        !           191: 
        !           192:            exit(1);
        !           193:        }
        !           194: }
        !           195: 
        !           196: dump_list(str)
        !           197: char *str;
        !           198: {
        !           199:        struct use_item *ptr;
        !           200:        static char line[512];
        !           201: 
        !           202:        fprintf(stderr, "dump_list %s\n", str);
        !           203:        for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr)
        !           204:        {
        !           205:                fseek(stdin, ptr->offset, 0);
        !           206:                fgets(line, 1024, stdin);
        !           207:                fprintf(stderr, "ptr %x off %d bptr %x fptr %x str %s",
        !           208:                ptr, ptr->offset, ptr->bptr, ptr->fptr, line);
        !           209:        }
        !           210:        fprintf(stderr, "\n");
        !           211: }
        !           212: 
        !           213: 
        !           214: 
        !           215: /*
        !           216:  *     int
        !           217:  *     do_entry(item_ptr)
        !           218:  *
        !           219:  *     Compile one entry.  During the first pass, item_ptr is NULL.  In pass
        !           220:  *     two, item_ptr points to the current entry in the use_list.
        !           221:  *
        !           222:  *     found-forward-use = FALSE
        !           223:  *     re-initialise internal arrays
        !           224:  *     save names in string_table
        !           225:  *     get_token()
        !           226:  *     while (not EOF and not NAMES)
        !           227:  *         if found-forward-use
        !           228:  *             do nothing
        !           229:  *         else if 'use'
        !           230:  *             if handle_use() < 0
        !           231:  *                 found-forward-use = TRUE
        !           232:  *          else
        !           233:  *             check for existance and type-correctness
        !           234:  *             enter cap into structure
        !           235:  *             if STRING
        !           236:  *                 save string in string_table
        !           237:  *         get_token()
        !           238:  *      if ! found-forward-use
        !           239:  *         clear CANCELS out of the structure
        !           240:  *         dump compiled entry into filesystem
        !           241:  *
        !           242:  */
        !           243: 
        !           244: int
        !           245: do_entry(item_ptr)
        !           246: struct use_item        *item_ptr;
        !           247: {
        !           248:        long                                    entry_offset;
        !           249:        int                                     i;
        !           250:        register int                            token_type;
        !           251:        register struct name_table_entry        *entry_ptr;
        !           252:        int                                     found_forward_use = FALSE;
        !           253:        static char                             Booleans[BOOLCOUNT];
        !           254:        static short                            Numbers[NUMCOUNT],
        !           255:                                                Strings[STRCOUNT];
        !           256: 
        !           257:        init_structure(Booleans, Numbers, Strings);
        !           258:        complete = 0;
        !           259:        term_names = save_str(curr_token.tk_name);
        !           260:        DEBUG(2, "Starting '%s'\n", curr_token.tk_name);
        !           261:        entry_offset = curr_file_pos;
        !           262: 
        !           263:        for (token_type = get_token();
        !           264:                token_type != EOF  &&  token_type != NAMES;
        !           265:                token_type = get_token())
        !           266:        {
        !           267:            if (found_forward_use)
        !           268:                /* do nothing */ ;
        !           269:            else if (strcmp(curr_token.tk_name, "use") == 0)
        !           270:            {
        !           271:                if (handle_use(item_ptr, entry_offset,
        !           272:                                        Booleans, Numbers, Strings) < 0)
        !           273:                    found_forward_use = TRUE;
        !           274:            }
        !           275:            else
        !           276:            {
        !           277:                entry_ptr = find_entry(curr_token.tk_name);
        !           278: 
        !           279:                if (entry_ptr == NOTFOUND) {
        !           280:                    warning("Unknown Capability - '%s'",
        !           281:                                                           curr_token.tk_name);
        !           282:                    continue;
        !           283:                }
        !           284: 
        !           285: 
        !           286:                if (token_type != CANCEL
        !           287:                                         &&  entry_ptr->nte_type != token_type)
        !           288:                    warning("Wrong type used for capability '%s'",
        !           289:                                                          curr_token.tk_name);
        !           290:                switch (token_type)
        !           291:                {
        !           292:                    case CANCEL:
        !           293:                        switch (entry_ptr->nte_type)
        !           294:                        {
        !           295:                            case BOOLEAN:
        !           296:                                Booleans[entry_ptr->nte_index] = -2;
        !           297:                                break;
        !           298: 
        !           299:                            case NUMBER:
        !           300:                                Numbers[entry_ptr->nte_index] = -2;
        !           301:                                break;
        !           302: 
        !           303:                            case STRING:
        !           304:                                Strings[entry_ptr->nte_index] = -2;
        !           305:                                break;
        !           306:                        }
        !           307:                        break;
        !           308:                
        !           309:                    case BOOLEAN:
        !           310:                        Booleans[entry_ptr->nte_index] = TRUE;
        !           311:                        break;
        !           312:                    
        !           313:                    case NUMBER:
        !           314:                        Numbers[entry_ptr->nte_index] =
        !           315:                                                       curr_token.tk_valnumber;
        !           316:                        break;
        !           317: 
        !           318:                    case STRING:
        !           319:                        Strings[entry_ptr->nte_index] =
        !           320:                                             save_str(curr_token.tk_valstring);
        !           321:                        break;
        !           322: 
        !           323:                    default:
        !           324:                        warning("Unknown token type");
        !           325:                        panic_mode(',');
        !           326:                        continue;
        !           327:                }
        !           328:            } /* end else cur_token.name != "use" */
        !           329: 
        !           330:        } /* endwhile (not EOF and not NAMES) */
        !           331: 
        !           332:        if (found_forward_use)
        !           333:            return(token_type);
        !           334: 
        !           335:        for (i=0; i < BOOLCOUNT; i++)
        !           336:        {
        !           337:            if (Booleans[i] == -2)
        !           338:                Booleans[i] = FALSE;
        !           339:        }
        !           340: 
        !           341:        for (i=0; i < NUMCOUNT; i++)
        !           342:        {
        !           343:            if (Numbers[i] == -2)
        !           344:                Numbers[i] = -1;
        !           345:        }
        !           346: 
        !           347:        for (i=0; i < STRCOUNT; i++)
        !           348:        {
        !           349:            if (Strings[i] == -2)
        !           350:                Strings[i] = -1;
        !           351:        }
        !           352: 
        !           353:        dump_structure(term_names, Booleans, Numbers, Strings);
        !           354: 
        !           355:        complete = 1;
        !           356:        return(token_type);
        !           357: }
        !           358: 
        !           359: 
        !           360: 
        !           361: 
        !           362: /*
        !           363:  *     enqueue(offset)
        !           364:  *
        !           365:  *      Put a record of the given offset onto the use-list.
        !           366:  *
        !           367:  */
        !           368: 
        !           369: enqueue(offset)
        !           370: long   offset;
        !           371: {
        !           372:        struct use_item *item;
        !           373:        char *malloc();
        !           374: 
        !           375:        item = (struct use_item *) malloc(sizeof(struct use_item));
        !           376: 
        !           377:        if (item == NULL)
        !           378:            syserr_abort("Not enough memory for use_list element");
        !           379: 
        !           380:        item->offset = offset;
        !           381: 
        !           382:        if (use_list.head != NULL)
        !           383:        {
        !           384:            item->bptr = use_list.tail;
        !           385:            use_list.tail->fptr = item;
        !           386:            item->fptr = NULL;
        !           387:            use_list.tail = item;
        !           388:        }
        !           389:        else
        !           390:        {
        !           391:            use_list.tail = use_list.head = item;
        !           392:            item->fptr = item->bptr = NULL;
        !           393:        }
        !           394: 
        !           395:        use_count ++;
        !           396: }
        !           397: 
        !           398: 
        !           399: 
        !           400: 
        !           401: /*
        !           402:  *     dequeue(ptr)
        !           403:  *
        !           404:  *     remove the pointed-to item from the use_list
        !           405:  *
        !           406:  */
        !           407: 
        !           408: dequeue(ptr)
        !           409: struct use_item        *ptr;
        !           410: {
        !           411:        if (ptr->fptr == NULL)
        !           412:            use_list.tail = ptr->bptr;
        !           413:        else
        !           414:            (ptr->fptr)->bptr = ptr->bptr;
        !           415: 
        !           416:        if (ptr->bptr == NULL)
        !           417:            use_list.head = ptr->fptr;
        !           418:        else
        !           419:            (ptr->bptr)->fptr = ptr->fptr;
        !           420:        
        !           421:        use_count --;
        !           422: }
        !           423: 
        !           424: 
        !           425: 
        !           426: /*
        !           427:  *     dump_structure()
        !           428:  *
        !           429:  *     Save the compiled version of a description in the filesystem.
        !           430:  *
        !           431:  *     make a copy of the name-list
        !           432:  *     break it up into first-name and all-but-last-name
        !           433:  *     creat(first-name)
        !           434:  *     write object information to first-name
        !           435:  *     close(first-name)
        !           436:  *      for each name in all-but-last-name
        !           437:  *         link to first-name
        !           438:  *
        !           439:  */
        !           440: 
        !           441: dump_structure(term_names, Booleans, Numbers, Strings)
        !           442: short  term_names;
        !           443: char   Booleans[];
        !           444: short  Numbers[];
        !           445: short  Strings[];
        !           446: {
        !           447:        struct stat     statbuf;
        !           448:        FILE            *fp;
        !           449:        static char     name_list[1024];
        !           450:        register char   *first_name, *other_names;
        !           451:        register char   *ptr;
        !           452:        static char     filename[50];
        !           453:        static char     linkname[50];
        !           454:        extern char check_only;
        !           455: 
        !           456:        strcpy(name_list, term_names + string_table);
        !           457:        DEBUG(7, "Name list = '%s'\n", name_list);
        !           458: 
        !           459:        first_name = name_list;
        !           460: 
        !           461:        ptr = &name_list[strlen(name_list) - 1];
        !           462:        other_names = ptr + 1;
        !           463: 
        !           464:        while (ptr > name_list  &&  *ptr != '|')
        !           465:            ptr--;
        !           466: 
        !           467:        if (ptr != name_list)
        !           468:        {
        !           469:            *ptr = '\0';
        !           470: 
        !           471:            for (ptr = name_list; *ptr != '\0'  &&  *ptr != '|'; ptr++)
        !           472:                ;
        !           473:            
        !           474:            if (*ptr == '\0')
        !           475:                other_names = ptr;
        !           476:            else
        !           477:            {
        !           478:                *ptr = '\0';
        !           479:                other_names = ptr + 1;
        !           480:            }
        !           481:        }
        !           482: 
        !           483:        if (check_only) {
        !           484:                DEBUG(1, "Checked %s\n", first_name);
        !           485:                return;
        !           486:        }
        !           487: 
        !           488:        DEBUG(7, "First name = '%s'\n", first_name);
        !           489:        DEBUG(7, "Other names = '%s'\n", other_names);
        !           490: 
        !           491:        if (strlen(first_name) > 100)
        !           492:            warning("'%s': terminal name too long.", first_name);
        !           493: 
        !           494:        check_name(first_name);
        !           495: 
        !           496:        sprintf(filename, "%c/%s", first_name[0], first_name);
        !           497: 
        !           498:        if (stat(filename, &statbuf) >= 0  &&  statbuf.st_mtime >= start_time)
        !           499:        {
        !           500:            warning("'%s' defined in more than one entry.", first_name);
        !           501:            fprintf(stderr, "Entry being used is '%s'.\n",
        !           502:                            (unsigned) term_names + string_table);
        !           503:        }
        !           504: 
        !           505:        unlink(filename);
        !           506:        fp = fopen(filename, "w");
        !           507:        if (fp == NULL)
        !           508:        {
        !           509:            perror(filename);
        !           510:            syserr_abort("Can't open %s/%s\n", destination, filename);
        !           511:        }
        !           512:        DEBUG(1, "Created %s\n", filename);
        !           513: 
        !           514:        if (write_object(fp, term_names, Booleans, Numbers, Strings) < 0)
        !           515:        {
        !           516:            syserr_abort("Error in writing %s/%s", destination, filename);
        !           517:        }
        !           518:        fclose(fp);
        !           519: 
        !           520:        while (*other_names != '\0')
        !           521:        {
        !           522:            ptr = other_names++;
        !           523:            while (*other_names != '|'  &&  *other_names != '\0')
        !           524:                other_names++;
        !           525: 
        !           526:            if (*other_names != '\0')
        !           527:                *(other_names++) = '\0';
        !           528: 
        !           529:            if (strlen(ptr) > 100)
        !           530:            {
        !           531:                warning("'%s': terminal name too long.", ptr);
        !           532:                continue;
        !           533:            }
        !           534: 
        !           535:            sprintf(linkname, "%c/%s", ptr[0], ptr);
        !           536: 
        !           537:            if (strcmp(filename, linkname) == 0)
        !           538:            {
        !           539:                warning("Terminal name '%s' synonym for itself", first_name);
        !           540:            }
        !           541:            else if (stat(linkname, &statbuf) >= 0  &&
        !           542:                                                statbuf.st_mtime >= start_time)
        !           543:            {
        !           544:                warning("'%s' defined in more than one entry.", ptr);
        !           545:                fprintf(stderr, "Entry being used is '%s'.\n",
        !           546:                            (unsigned) term_names + string_table);
        !           547:            }
        !           548:            else
        !           549:            {
        !           550:                unlink(linkname);
        !           551:                if (link(filename, linkname) < 0)
        !           552:                    syserr_abort("Can't link %s to %s", filename, linkname);
        !           553:                DEBUG(1, "Linked %s\n", linkname);
        !           554:            }
        !           555:        }
        !           556: }
        !           557: 
        !           558: 
        !           559: 
        !           560: 
        !           561: /*
        !           562:  *     int
        !           563:  *     write_object(fp, term_names, Booleans, Numbers, Strings)
        !           564:  *
        !           565:  *     Write out the compiled entry to the given file.
        !           566:  *     Return 0 if OK or -1 if not.
        !           567:  *
        !           568:  */
        !           569: 
        !           570: #define swap(x)                (((x >> 8) & 0377) + 256 * (x & 0377))
        !           571: 
        !           572: #define might_swap(x)  (must_swap()  ?  swap(x)  :  (x))
        !           573: 
        !           574: 
        !           575: int
        !           576: write_object(fp, term_names, Booleans, Numbers, Strings)
        !           577: FILE   *fp;
        !           578: short  term_names;
        !           579: char   Booleans[];
        !           580: short  Numbers[];
        !           581: short  Strings[];
        !           582: {
        !           583:        struct header   header;
        !           584:        char            *namelist;
        !           585:        short           namelen;
        !           586:        char            zero = '\0';
        !           587:        int             i;
        !           588: 
        !           589:        namelist = term_names + string_table;
        !           590:        namelen = strlen(namelist) + 1;
        !           591: 
        !           592:        if (must_swap())
        !           593:        {
        !           594:            header.magic = swap(MAGIC);
        !           595:            header.name_size = swap(namelen);
        !           596:            header.bool_count = swap(BOOLCOUNT);
        !           597:            header.num_count = swap(NUMCOUNT);
        !           598:            header.str_count = swap(STRCOUNT);
        !           599:            header.str_size = swap(next_free);
        !           600:        }
        !           601:        else
        !           602:        {
        !           603:            header.magic = MAGIC;
        !           604:            header.name_size = namelen;
        !           605:            header.bool_count = BOOLCOUNT;
        !           606:            header.num_count = NUMCOUNT;
        !           607:            header.str_count = STRCOUNT;
        !           608:            header.str_size = next_free;
        !           609:        }
        !           610: 
        !           611:        if (fwrite(&header, sizeof(header), 1, fp) != 1
        !           612:                ||  fwrite(namelist, sizeof(char), namelen, fp) != namelen
        !           613:                ||  fwrite(Booleans, sizeof(char), BOOLCOUNT, fp) != BOOLCOUNT)
        !           614:            return(-1);
        !           615:        
        !           616:        if ((namelen+BOOLCOUNT) % 2 != 0  &&  fwrite(&zero, sizeof(char), 1, fp) != 1)
        !           617:            return(-1);
        !           618: 
        !           619:        if (must_swap())
        !           620:        {
        !           621:            for (i=0; i < NUMCOUNT; i++)
        !           622:                Numbers[i] = swap(Numbers[i]);
        !           623:            for (i=0; i < STRCOUNT; i++)
        !           624:                Strings[i] = swap(Strings[i]);
        !           625:        }
        !           626: 
        !           627:        if (fwrite(Numbers, sizeof(short), NUMCOUNT, fp) != NUMCOUNT
        !           628:               ||  fwrite(Strings, sizeof(short), STRCOUNT, fp) != STRCOUNT
        !           629:               ||  fwrite(string_table, sizeof(char), next_free, fp)
        !           630:                                                                  != next_free)
        !           631:            return(-1);
        !           632: 
        !           633: }
        !           634: 
        !           635: 
        !           636: 
        !           637: /*
        !           638:  *     check_name(name)
        !           639:  *
        !           640:  *     Generate an error message if given name does not begin with a
        !           641:  *     digit or letter (should be lower-case letter, but SV likes capital)
        !           642:  *     Vlad 3-11-92
        !           643:  */
        !           644: 
        !           645: check_name(name)
        !           646: char   *name;
        !           647: {
        !           648:        if (!isalnum(name[0]))
        !           649:        {
        !           650:            fprintf(stderr, "tic: Line %d: Illegal terminal name - '%s'\n",
        !           651:                                                            curr_line, name);
        !           652:            fprintf(stderr,
        !           653:                        "Terminal names must start with letter or digit\n");
        !           654:            exit(1);
        !           655:        }
        !           656: }
        !           657: 
        !           658: 
        !           659: 
        !           660: /*
        !           661:  *     int
        !           662:  *     save_str(string)
        !           663:  *
        !           664:  *     copy string into next free part of string_table, doing a realloc()
        !           665:  *     if necessary.  return offset of beginning of string from start of
        !           666:  *     string_table.
        !           667:  *
        !           668:  */
        !           669: 
        !           670: int
        !           671: save_str(string)
        !           672: char   *string;
        !           673: {
        !           674:        char    *malloc(), *realloc();
        !           675:        int     old_next_free = next_free;
        !           676: 
        !           677:        if (table_size == 0)
        !           678:        {
        !           679:            if ((string_table = malloc(1024)) == NULL)
        !           680:                syserr_abort("Out of memory");
        !           681:            table_size = 1024;
        !           682:            DEBUG(5, "Made initial string table allocation.  Size is %d\n",
        !           683:                                                                    table_size);
        !           684:        }
        !           685: 
        !           686:        while (table_size < next_free + strlen(string))
        !           687:        {
        !           688:            if ((string_table = realloc(string_table, table_size + 1024))
        !           689:                                                                        == NULL)
        !           690:                syserr_abort("Out of memory");
        !           691:            table_size += 1024;
        !           692:            DEBUG(5, "Extended string table.  Size now %d\n", table_size);
        !           693:        }
        !           694: 
        !           695:        strcpy(&string_table[next_free], string);
        !           696:        DEBUG(7, "Saved string '%s' ", string);
        !           697:        DEBUG(7, "at location %d\n", next_free);
        !           698:        next_free += strlen(string) + 1;
        !           699: 
        !           700:        return(old_next_free);
        !           701: }
        !           702: 
        !           703: 
        !           704: 
        !           705: /*
        !           706:  *     init_structure(Booleans, Numbers, Strings)
        !           707:  *
        !           708:  *     Initialise the given arrays
        !           709:  *     Reset the next_free counter to zero.
        !           710:  *
        !           711:  */
        !           712: 
        !           713: init_structure(Booleans, Numbers, Strings)
        !           714: char   Booleans[];
        !           715: short  Numbers[], Strings[];
        !           716: {
        !           717:        int     i;
        !           718: 
        !           719:        for (i=0; i < BOOLCOUNT; i++)
        !           720:            Booleans[i] = FALSE;
        !           721:        
        !           722:        for (i=0; i < NUMCOUNT; i++)
        !           723:            Numbers[i] = -1;
        !           724: 
        !           725:        for (i=0; i < STRCOUNT; i++)
        !           726:            Strings[i] = -1;
        !           727: 
        !           728:        next_free = 0;
        !           729: }
        !           730: 
        !           731: 
        !           732: 
        !           733: /*
        !           734: **     int
        !           735: **     handle_use(item_ptr, entry_offset, Booleans, Numbers, Strings)
        !           736: **
        !           737: **     Merge the compiled file whose name is in cur_token.valstring
        !           738: **     with the current entry.
        !           739: **
        !           740: **             if it's a forward use-link
        !           741: **                 if item_ptr == NULL
        !           742: **                     queue it up for later handling
        !           743: **                 else
        !           744: **                     ignore it (we're already going through the queue)
        !           745: **             else it's a backward use-link
        !           746: **                 read in the object file for that terminal
        !           747: **                 merge contents with current structure
        !           748: **
        !           749: **     Returned value is 0 if it was a backward link and we
        !           750: **     successfully read it in, -1 if a forward link.
        !           751: */
        !           752: 
        !           753: int
        !           754: handle_use(item_ptr, entry_offset, Booleans, Numbers, Strings)
        !           755: long           entry_offset;
        !           756: struct use_item        *item_ptr;
        !           757: char           Booleans[];
        !           758: short          Numbers[];
        !           759: short          Strings[];
        !           760: {
        !           761:        struct term     use_term;
        !           762:        struct stat     statbuf;
        !           763:        static char     filename[50];
        !           764:         int             i;
        !           765: 
        !           766:        check_name(curr_token.tk_valstring);
        !           767: 
        !           768:        sprintf(filename, "%c/%s", curr_token.tk_valstring[0],
        !           769:                                                      curr_token.tk_valstring);
        !           770: 
        !           771:        if (stat(filename, &statbuf) < 0  ||  part2==0 && statbuf.st_mtime < start_time)
        !           772:        {
        !           773:            DEBUG(2, "Forward USE to %s", curr_token.tk_valstring);
        !           774: 
        !           775:            if (item_ptr == NULL)
        !           776:            {
        !           777:                DEBUG(2, " (enqueued)\n", "");
        !           778:                enqueue(entry_offset);
        !           779:            }
        !           780:            else 
        !           781:                DEBUG(2, " (skipped)\n", "");
        !           782:            
        !           783:            return(-1);
        !           784:        }
        !           785:        else
        !           786:        {
        !           787:            DEBUG(2, "Backward USE to %s\n", curr_token.tk_valstring);
        !           788:            if (read_entry(filename, &use_term) < 0)
        !           789:                syserr_abort("Error in re-reading compiled file %s", filename);
        !           790: 
        !           791:            for (i=0; i < BOOLCOUNT; i++)
        !           792:            {
        !           793:                if (Booleans[i] == FALSE  &&  use_term.Booleans[i] == TRUE)
        !           794:                    Booleans[i] = TRUE;
        !           795:            }
        !           796: 
        !           797:            for (i=0; i < NUMCOUNT; i++)
        !           798:            {
        !           799:                if (Numbers[i] == -1  &&  use_term.Numbers[i] != -1)
        !           800:                    Numbers[i] = use_term.Numbers[i];
        !           801:            }
        !           802: 
        !           803:            for (i=0; i < STRCOUNT; i++)
        !           804:            {
        !           805:                if (Strings[i] == -1  &&  use_term.Strings[i] != (char *) 0)
        !           806:                    Strings[i] = save_str(use_term.Strings[i]);
        !           807:            }
        !           808: 
        !           809:        }
        !           810: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.