Annotation of coherent/b/STREAMS/conf_79/input.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Input stream abstraction.
                      3:  */
                      4: 
                      5: /*
                      6:  *-IMPORTS:
                      7:  *     <sys/compat.h>
                      8:  *             CONST
                      9:  *             USE_PROTO
                     10:  *             ARGS ()
                     11:  *             LOCAL
                     12:  *     <stddef.h>
                     13:  *             NULL
                     14:  *             offsetof ()
                     15:  *     <stdio.h>
                     16:  *             EOF
                     17:  *             FILE
                     18:  *             stderr
                     19:  *             fprintf ()
                     20:  *             fputs ()
                     21:  *             getc ()
                     22:  *             putc ()
                     23:  *     <stdlib.h>
                     24:  *             free ()
                     25:  *             malloc ()
                     26:  *     <string.h>
                     27:  *             memcpy ()
                     28:  *             strlen ()
                     29:  */
                     30: 
                     31: #include <sys/compat.h>
                     32: #include <stddef.h>
                     33: #include <stdio.h>
                     34: #include <stdlib.h>
                     35: #include <string.h>
                     36: 
                     37: #include "lex.h"
                     38: 
                     39: #include "input.h"
                     40: #include "mkinput.h"
                     41: 
                     42: 
                     43: /*
                     44:  * Structures for dealing with input from a file.
                     45:  */
                     46: 
                     47: typedef struct fileinput filein_t;
                     48: 
                     49: struct fileinput {
                     50:        input_t         fi_input;
                     51: 
                     52:        char          * fi_name;
                     53:        FILE          * fi_file;        /* input stream */
                     54:        int             fi_lineno;      /* line number in file */
                     55:        int             fi_colno;       /* current column number */
                     56:        int             fi_prevline;
                     57:        int             fi_prevcol;
                     58:        int             fi_comment;     /* comment character (maybe none) */
                     59:        int             fi_prevchar;    /* previous character */
                     60: 
                     61:        char            fi_line [64];   /* line buffer for errors */
                     62: };
                     63: 
                     64: #define        ARRAY_LEN(a)    (sizeof (a) / sizeof (* a))
                     65: 
                     66: 
                     67: /*
                     68:  * Structure for processing input from a string.
                     69:  */
                     70: 
                     71: typedef struct strinput        strin_t;
                     72: 
                     73: struct strinput {
                     74:        input_t         si_input;
                     75: 
                     76:        CONST unsigned char
                     77:                      * si_data;        /* data being read */
                     78:        size_t          si_pos;         /* position in input stream */
                     79:        size_t          si_len;         /* length of input stream */
                     80: };
                     81: 
                     82: 
                     83: /*
                     84:  * Read a character from a file.
                     85:  */
                     86: 
                     87: #ifdef USE_PROTO
                     88: LOCAL int fi_read (input_t * input)
                     89: #else
                     90: LOCAL int
                     91: fi_read (input)
                     92: input_t              * input;
                     93: #endif
                     94: {
                     95:        filein_t      * fi = (filein_t *) input;
                     96:        int             ch;
                     97: 
                     98:        /*
                     99:         * Get a character from the input file, recording the data for the
                    100:         * purpose of error reporting.
                    101:         */
                    102: 
                    103:        fi->fi_prevcol = fi->fi_colno;
                    104:        fi->fi_prevline = fi->fi_lineno;
                    105: 
                    106:        if ((ch = getc (fi->fi_file)) == EOF)
                    107:                return IN_EOF;
                    108: 
                    109:        fi->fi_line [fi->fi_colno ++ % ARRAY_LEN (fi->fi_line)] = ch;
                    110: 
                    111:        if (ch == fi->fi_comment) {
                    112:                /*
                    113:                 * Consume data to EOL, then return EOL.
                    114:                 */
                    115: 
                    116:                do {
                    117:                        if ((ch = getc (fi->fi_file)) == EOF)
                    118:                                return IN_EOF;
                    119:                } while (ch != '\n');
                    120:        }
                    121: 
                    122: 
                    123:        if (ch == '\n') {
                    124: 
                    125:                fi->fi_colno = 0;
                    126:                fi->fi_lineno ++;
                    127:        }
                    128: 
                    129:        fi->fi_prevchar = ch;
                    130:        return ch;
                    131: }
                    132: 
                    133: 
                    134: /*
                    135:  * Return the last read character to the input stream.
                    136:  */
                    137: 
                    138: #ifdef USE_PROTO
                    139: LOCAL void fi_unread (input_t * input)
                    140: #else
                    141: LOCAL void
                    142: fi_unread (input)
                    143: input_t              * input;
                    144: #endif
                    145: {
                    146:        filein_t      * fi = (filein_t *) input;
                    147: 
                    148:        if (fi->fi_prevchar != IN_EOF) {
                    149: 
                    150:                ungetc (fi->fi_prevchar, fi->fi_file);
                    151: 
                    152:                fi->fi_prevchar = IN_EOF;
                    153:                fi->fi_colno = fi->fi_prevcol;
                    154:                fi->fi_lineno = fi->fi_prevline;
                    155:        }
                    156: }
                    157: 
                    158: 
                    159: /*
                    160:  * Close the input file.
                    161:  */
                    162: 
                    163: #ifdef USE_PROTO
                    164: LOCAL void fi_close (input_t * input)
                    165: #else
                    166: LOCAL void
                    167: fi_close (input)
                    168: input_t              * input;
                    169: #endif
                    170: {
                    171:        filein_t      * fi = (filein_t *) input;
                    172: 
                    173:        (void) fclose (fi->fi_file);
                    174:        free (fi);
                    175: }
                    176: 
                    177: 
                    178: /*
                    179:  * Produce an error report for this input source.
                    180:  */
                    181: 
                    182: #ifdef USE_PROTO
                    183: LOCAL void fi_error (input_t * input)
                    184: #else
                    185: LOCAL void
                    186: fi_error (input)
                    187: input_t              * input;
                    188: #endif
                    189: {
                    190:        filein_t      * fi = (filein_t *) input;
                    191:        int             col;
                    192:        int             ch;
                    193:        int             end;
                    194: 
                    195:        (void) fprintf (stderr, "Error vicinity : file \"%s\", line %d, column %d\n",
                    196:                        fi->fi_name, fi->fi_prevline, fi->fi_prevcol);
                    197: 
                    198:        col = fi->fi_prevcol < 40 ? 0 : fi->fi_prevcol - 40;
                    199: 
                    200:        if (fi->fi_colno > (end = fi->fi_prevcol))
                    201:                end ++;
                    202: 
                    203:        while (col < end) {
                    204:                /*
                    205:                 * Should think about escaping controls.
                    206:                 */
                    207: 
                    208:                ch = fi->fi_line [col ++ % ARRAY_LEN (fi->fi_line)];
                    209:                (void) putc (ch, stderr);
                    210:        }
                    211: 
                    212: 
                    213:        fputs (" <---\n", stderr);
                    214: }
                    215: 
                    216: 
                    217: /*
                    218:  * Create a source of input from a file.
                    219:  */
                    220: 
                    221: #ifdef USE_PROTO
                    222: input_t * (make_file_input) (FILE * file, CONST char * name, int comment)
                    223: #else
                    224: input_t *
                    225: make_file_input ARGS ((file, name, comment))
                    226: FILE         * file;
                    227: CONST char    *        name;
                    228: int            comment;
                    229: #endif
                    230: {
                    231:        filein_t      * fi;
                    232:        size_t          namelen;
                    233: 
                    234:        /* ASSERT that fi_input is the first member of the structure */
                    235: 
                    236:        if (offsetof (filein_t, fi_input) != 0)
                    237:                return NULL;
                    238: 
                    239:        if (name == NULL)
                    240:                name = "no name";
                    241: 
                    242:        namelen = strlen (name) + 1;
                    243: 
                    244:        if ((fi = (filein_t *) malloc (sizeof (* fi) + namelen)) == NULL)
                    245:                return NULL;
                    246: 
                    247:        fi->fi_lineno = 1;
                    248:        fi->fi_colno = 0;
                    249:        fi->fi_file = file;
                    250:        fi->fi_name = (char *) (fi + 1);
                    251: 
                    252:        fi->fi_comment = comment;
                    253:        fi->fi_prevchar = IN_EOF;
                    254: 
                    255:        if (namelen > 0)
                    256:                memcpy (fi->fi_name, name, namelen);
                    257: 
                    258:        fi->fi_input.in_read = fi_read;
                    259:        fi->fi_input.in_unread = fi_unread;
                    260:        fi->fi_input.in_readtok = NULL;
                    261:        fi->fi_input.in_close = fi_close;
                    262:        fi->fi_input.in_error = fi_error;
                    263: 
                    264:        return & fi->fi_input;
                    265: }
                    266: 
                    267: 
                    268: /*
                    269:  * Return a character from an input string, or EOF when the end-of-string is
                    270:  * reached.
                    271:  */
                    272: 
                    273: #ifdef USE_PROTO
                    274: LOCAL int si_read (input_t * input)
                    275: #else
                    276: LOCAL int
                    277: si_read (input)
                    278: input_t              * input;
                    279: #endif
                    280: {
                    281:        strin_t       * si = (strin_t *) input;
                    282: 
                    283:        if (si->si_pos >= si->si_len)
                    284:                return IN_EOF;
                    285: 
                    286:        return si->si_data [si->si_pos ++];
                    287: }
                    288: 
                    289: 
                    290: /*
                    291:  * Return a character to the input stream to be read again.
                    292:  */
                    293: 
                    294: #ifdef USE_PROTO
                    295: LOCAL void si_unread (input_t * input)
                    296: #else
                    297: LOCAL void
                    298: si_unread (input)
                    299: input_t              * input;
                    300: #endif
                    301: {
                    302:        strin_t       * si = (strin_t *) input;
                    303: 
                    304:        if (si->si_pos > 0)
                    305:                si->si_pos --;
                    306: }
                    307: 
                    308: 
                    309: /*
                    310:  * Reading a token, specialized to string input streams.
                    311:  */
                    312: 
                    313: #ifdef USE_PROTO
                    314: LOCAL CONST unsigned char * si_readtok (input_t * input, lex_t * lexp,
                    315:                                        size_t * lengthp)
                    316: #else
                    317: LOCAL CONST unsigned char *
                    318: si_readtok (input, lexp, lengthp)
                    319: input_t              * input;
                    320: lex_t        * lexp;
                    321: size_t       * lengthp;
                    322: #endif
                    323: {
                    324:        strin_t       * si = (strin_t *) input;
                    325:        int             start = -1;
                    326:        int             ch;
                    327: 
                    328:        for (;;) {
                    329:                if ((ch = si_read (input)) == IN_EOF)
                    330:                        break;
                    331: 
                    332:                switch (classify (lexp, ch, start == -1)) {
                    333: 
                    334:                case CLASS_FLUSH:
                    335:                        continue;
                    336: 
                    337:                case CLASS_SEP:
                    338:                        si_unread (input);
                    339:                        goto separator;
                    340: 
                    341:                default:
                    342:                        break;
                    343:                }
                    344: 
                    345:                if (start == -1)
                    346:                        start = si->si_pos - 1;
                    347:        }
                    348: 
                    349: separator:
                    350:        * lengthp = start == -1 ? 0 : si->si_pos - start;
                    351:        return start == -1 ? NULL : & si->si_data [start];
                    352: }
                    353: 
                    354: 
                    355: /*
                    356:  * Finish with a string input stream.
                    357:  */
                    358: 
                    359: #ifdef USE_PROTO
                    360: LOCAL void si_close (input_t * input)
                    361: #else
                    362: LOCAL void
                    363: si_close (input)
                    364: input_t              * input;
                    365: #endif
                    366: {
                    367:        free (input);
                    368: }
                    369: 
                    370: 
                    371: /*
                    372:  * Display an error locus in a string input stream.
                    373:  */
                    374: 
                    375: #ifdef USE_PROTO
                    376: LOCAL void si_error (input_t * input)
                    377: #else
                    378: LOCAL void
                    379: si_error (input)
                    380: input_t              * input;
                    381: #endif
                    382: {
                    383:        strin_t       * si = (strin_t *) input;
                    384:        int             col;
                    385: 
                    386:        col = si->si_pos < 40 ? 0 : si->si_pos - 40;
                    387: 
                    388:        (void) fprintf (stderr, "Error vicinity : %.*s <---\n",
                    389:                        si->si_pos - col, & si->si_data [col]);
                    390: }
                    391: 
                    392: 
                    393: /*
                    394:  * Create a source of input from a string. Depending on the "action" code,
                    395:  * the string may or may not be copied or left alone. If the user wants some
                    396:  * clean processing to be done at close time, then another version of this
                    397:  * code should be set in place which allows registration of a close-time
                    398:  * callback (which is messy, so it hasn't been done).
                    399:  */
                    400: 
                    401: #ifdef USE_PROTO
                    402: input_t * (make_string_input) (CONST unsigned char * str, int copy)
                    403: #else
                    404: input_t *
                    405: make_string_input ARGS ((str, copy))
                    406: CONST unsigned char
                    407:              * str;
                    408: int            copy;
                    409: #endif
                    410: {
                    411:        strin_t       * si;
                    412:        size_t          len;
                    413: 
                    414:        /* ASSERT that si_input is the first member of the structure */
                    415: 
                    416:        if (offsetof (strin_t, si_input) != 0)
                    417:                return NULL;
                    418: 
                    419:        len = strlen ((char *) str);
                    420: 
                    421:        if ((si = (strin_t *) malloc (sizeof (* si) +
                    422:                                      (copy ? len : 0))) == NULL)
                    423:                return NULL;
                    424: 
                    425:        si->si_pos = 0;
                    426:        si->si_len = len;
                    427: 
                    428:        if (copy) {
                    429: 
                    430:                si->si_data = (CONST unsigned char *) (si + 1);
                    431:                memcpy (si + 1, str, len);
                    432:        } else
                    433:                si->si_data = str;
                    434: 
                    435:        si->si_input.in_read = si_read;
                    436:        si->si_input.in_unread = si_unread;
                    437:        si->si_input.in_readtok = si_readtok;
                    438:        si->si_input.in_close = si_close;
                    439:        si->si_input.in_error = si_error;
                    440: 
                    441:        return & si->si_input;
                    442: }
                    443: 

unix.superglobalmegacorp.com

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