Date: Sat, 3 Jun 2006 10:40:57 GMT From: Shteryana Shopova <shteryana@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 98386 for review Message-ID: <200606031040.k53Aevpt014554@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=98386 Change 98386 by shteryana@prometheus on 2006/06/03 10:40:27 IFC Affected files ... .. //depot/projects/soc2005/bsnmp/contrib/bsnmp/NEWS#4 integrate .. //depot/projects/soc2005/bsnmp/contrib/bsnmp/gensnmpdef/gensnmpdef.1#3 integrate .. //depot/projects/soc2005/bsnmp/contrib/bsnmp/gensnmpdef/gensnmpdef.c#3 integrate .. //depot/projects/soc2005/bsnmp/contrib/bsnmp/gensnmptree/gensnmptree.1#4 integrate .. //depot/projects/soc2005/bsnmp/contrib/bsnmp/gensnmptree/gensnmptree.c#5 integrate Differences ... ==== //depot/projects/soc2005/bsnmp/contrib/bsnmp/NEWS#4 (text+ko) ==== @@ -1,3 +1,7 @@ +1.12a + Support for ENUM and BITS in gensnmp{tree,def}. Include directives + and typedefs. + 1.12 A couple of man page fixes from various submitters. ==== //depot/projects/soc2005/bsnmp/contrib/bsnmp/gensnmpdef/gensnmpdef.1#3 (text+ko) ==== @@ -1,5 +1,5 @@ .\" -.\" Copyright (C) 2004-2005 +.\" Copyright (C) 2004-2006 .\" Hartmut Brandt. .\" All rights reserved. .\" @@ -26,9 +26,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Begemot: bsnmp/gensnmpdef/gensnmpdef.1,v 1.5 2005/10/04 08:46:46 brandt_h Exp $ +.\" $Begemot: gensnmpdef.1 383 2006-05-30 07:40:49Z brandt_h $ .\" -.Dd June 14, 2005 +.Dd May 28, 2006 .Dt GENSNMPDEF 1 .Os .Sh NAME @@ -36,7 +36,7 @@ .Nd "generate a MIB description file from MIBs" .Sh SYNOPSIS .Nm -.Op Fl h +.Op Fl hEe .Op Fl c Ar cut .Ar name Op Ar ... .Sh DESCRIPTION @@ -48,13 +48,28 @@ for feeding it into .Xr gensnmptree 1 . .Pp -The -.Fl c -option specifies the number of initial sub-oids that should be omitted -from the tree. +The following options are available: +.Bl -tag -width indent +.It Fl c Ar cut +Specify the number of initial sub-oids that should be omitted +from the tree in the output. .Xr gensnmptree 1 automatically adds 1.3.6 in front of all OIDs so the default value of 3 is just correct in most cases. +.It Fl E +Generate typedefs for named enumerations. +These are enumerations defined via the TEXTUAL-CONVENTION macro. +The normal tree output is suppressed. +.It Fl e +Generate typedefs for unnamed enumerations. +These are enumerations defined in the SYNTAX clause of an OBJECT-TYPE macro. +The name of the enumeration is formed by appending the string +.Ql Type +to the name of the object. +The normal tree output is suppressed. +.It Fl h +Print a short help text and exit. +.El .Pp .Nm does no attempt on sorting the OID tree so in case of complex and ==== //depot/projects/soc2005/bsnmp/contrib/bsnmp/gensnmpdef/gensnmpdef.c#3 (text+ko) ==== @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 + * Copyright (C) 2004-2006 * Hartmut Brandt. * All rights reserved. * @@ -26,8 +26,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Begemot: bsnmp/gensnmpdef/gensnmpdef.c,v 1.3 2004/08/06 08:46:45 brandt Exp $ + * $Begemot: gensnmpdef.c 383 2006-05-30 07:40:49Z brandt_h $ */ +#include <sys/queue.h> + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -38,9 +40,13 @@ #include <smi.h> static const char usgtxt[] = -"Usage: gensnmpdef [-h] [-c <cut>] MIB [MIB ...]\n" +"Usage: gensnmpdef [-hEe] [-c <cut>] MIB [MIB ...]\n" "Options:\n" " -c specify the number of initial sub-oids to cut from the oids\n" +" -E extract named enum types. Print a typedef for all enums defined\n" +" in syntax clauses of normal objects. Suppress normal output.\n" +" -e extract unnamed enum types. Print a typedef for all enums defined\n" +" as textual conventions. Suppress normal output.\n" " -h print this help\n" "MIBs are searched according to the libsmi(3) search rules and can\n" "be specified either by path or module name\n"; @@ -48,6 +54,14 @@ static SmiNode *last_node; static u_int cut = 3; +struct tdef { + char *name; + SLIST_ENTRY(tdef) link; +}; + +static SLIST_HEAD(, tdef) tdefs = SLIST_HEAD_INITIALIZER(tdef); +static int do_typedef = 0; + static void print_node(SmiNode *n, u_int level); static void @@ -135,7 +149,7 @@ [SMI_BASETYPE_FLOAT32] = "FLOAT32", [SMI_BASETYPE_FLOAT64] = "FLOAT64", [SMI_BASETYPE_FLOAT128] = "FLOAT128", - [SMI_BASETYPE_ENUM] = "INTEGER", + [SMI_BASETYPE_ENUM] = "ENUM", [SMI_BASETYPE_BITS] = "BITS", }; @@ -152,6 +166,18 @@ }; static void +print_enum(SmiType *t) +{ + SmiNamedNumber *nnum; + + printf(" ("); + for (nnum = smiGetFirstNamedNumber(t); nnum != NULL; + nnum = smiGetNextNamedNumber(nnum)) + printf(" %ld %s", nnum->value.value.integer32, nnum->name); + printf(" )"); +} + +static void print_type(SmiNode *n) { SmiType *type; @@ -168,6 +194,14 @@ } } printf("%s", type_names[type->basetype]); + + if (type->basetype == SMI_BASETYPE_ENUM || + type->basetype == SMI_BASETYPE_BITS) + print_enum(type); + + else if (type->basetype == SMI_BASETYPE_OCTETSTRING && + type->name != NULL) + printf(" | %s", type->name); } static void @@ -359,6 +393,111 @@ printf(")\n"); } +static void +save_typdef(char *name) +{ + struct tdef *t; + t = malloc(sizeof(struct tdef)); + + if (t == NULL) + err(1, NULL); + + memset(t, 0 , sizeof(struct tdef)); + t->name = name; + SLIST_INSERT_HEAD(&tdefs, t, link); +} + +static void +tdefs_cleanup(void) +{ + struct tdef *t; + + while ((t = SLIST_FIRST(&tdefs)) != NULL) { + SLIST_REMOVE_HEAD(&tdefs, link); + free(t); + } +} + +static void +print_enum_typedef(SmiType *t) +{ + SmiNamedNumber *nnum; + + for (nnum = smiGetFirstNamedNumber(t); nnum != NULL; + nnum = smiGetNextNamedNumber(nnum)) { + printf("\t%ld %s\n" , nnum->value.value.integer32, nnum->name); + } +} + +static void +print_stype(SmiNode *n) +{ + SmiType *type; + struct tdef *t = NULL; + + type = smiGetNodeType(n); + assert(type != NULL); + + if (type->basetype == SMI_BASETYPE_ENUM) { + if (do_typedef == 'e' && type->name != NULL) { + SLIST_FOREACH(t, &tdefs, link) { + if (strcmp(t->name, type->name) == 0) + return; + } + save_typdef(type->name); + printf("typedef %s ENUM (\n", type->name); + } else if (do_typedef == 'E' && type->name == NULL) + printf("typedef %sType ENUM (\n", n->name); + else + return; + + print_enum_typedef(type); + printf(")\n\n"); + + } else if (type->basetype == SMI_BASETYPE_BITS) { + if (do_typedef == 'e' && type->name != NULL) { + SLIST_FOREACH(t, &tdefs, link) { + if (strcmp(t->name, type->name) == 0) + return; + } + save_typdef(type->name); + printf("typedef %s BITS (\n", type->name); + } else if (do_typedef == 'E' && type->name == NULL) + printf("typedef %sType BITS (\n", n->name); + else + return; + + print_enum_typedef(type); + printf(")\n\n"); + } +} + +static void +print_typdefs(SmiNode *n) +{ + SmiNode *p; + + p = n; + n = smiGetFirstChildNode(n); + while (n != NULL) { + switch (n->nodekind) { + case SMI_NODEKIND_SCALAR: + case SMI_NODEKIND_COLUMN: + print_stype(n); + break; + case SMI_NODEKIND_COMPLIANCE: + case SMI_NODEKIND_GROUP: + save_node(n); + return; + default: + break; + } + n = smiGetNextChildNode(n); + } + + save_node(p); +} + int main(int argc, char *argv[]) { @@ -371,14 +510,9 @@ long u; char *end; - if ( argc <= 1 ){ - fprintf(stderr, usgtxt); - exit(0); - } - smiInit(NULL); - while ((opt = getopt(argc, argv, "c:h")) != -1) + while ((opt = getopt(argc, argv, "c:Eeh")) != -1) switch (opt) { case 'c': @@ -393,6 +527,14 @@ cut = (u_int)u; break; + case 'E': + do_typedef = 'E'; + break; + + case 'e': + do_typedef = 'e'; + break; + case 'h': fprintf(stderr, usgtxt); exit(0); @@ -401,11 +543,6 @@ argc -= optind; argv += optind; - if( argc == 0 ){ - fprintf(stderr,"No MIB specified\n"); - exit(0); - } - flags = smiGetFlags(); flags |= SMI_FLAG_ERRORS; smiSetFlags(flags); @@ -424,9 +561,12 @@ for (opt = 0; opt < argc; opt++) { n = smiGetFirstNode(mods[opt], SMI_NODEKIND_ANY); for (;;) { - level = open_node(n, level, &last); - print_it(n, level); - last = n; + if (do_typedef == 0) { + level = open_node(n, level, &last); + print_it(n, level); + last = n; + } else + print_typdefs(n); if (last_node == NULL || (n = smiGetNextNode(last_node, SMI_NODEKIND_ANY)) @@ -434,10 +574,10 @@ break; } } - if( last != NULL ){ + if (last != NULL && do_typedef == 0) level = close_node(last->oidlen - 1, level - 1); - } - - free(mods); + else if (do_typedef != 0) + tdefs_cleanup(); + return (0); } ==== //depot/projects/soc2005/bsnmp/contrib/bsnmp/gensnmptree/gensnmptree.1#4 (text+ko) ==== @@ -2,6 +2,9 @@ .\" Copyright (c) 2001-2005 .\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). .\" All rights reserved. +.\" Copyright (c) 2006 +.\" Hartmut Brandt +.\" All rights reserved. .\" .\" Author: Harti Brandt <harti@freebsd.org> .\" @@ -26,9 +29,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Begemot: bsnmp/gensnmptree/gensnmptree.1,v 1.7 2006/02/27 09:52:08 brandt_h Exp $ +.\" $Begemot: gensnmptree.1 383 2006-05-30 07:40:49Z brandt_h $ .\" -.Dd February 27, 2006 +.Dd May 26, 2006 .Dt GENSNMPTREE 1 .Os .Sh NAME @@ -36,7 +39,9 @@ .Nd "generate C and header files from a MIB description file" .Sh SYNOPSIS .Nm -.Op Fl helt +.Op Fl dEehlt +.Op Fl I Ar directory +.Op Fl i Ar infile .Op Fl p Ar prefix .Op Ar name Ar ... .Sh DESCRIPTION @@ -49,9 +54,12 @@ daemon or for module writers. The second form may be used by SNMP client program writers. .Pp -If the -.Fl e -option is not used +If none of the options +.Fl e , +.Fl E +or +.FL t +are used .Nm reads a MIB description from its standard input and creates two files: a C-file @@ -61,12 +69,20 @@ during PDU processing and a header file .Ar prefix Ns tree.h -containing appropriate declarations of the callback functions used in this table -and the table itself. +containing appropriate declarations of the callback functions used in this +table, the table itself and definitions for all enums. .Pp -If the -.Fl e -option is specified +The following options are available: +.Bl -tag -width ".Fl E" +.It Fl d +Switch on debugging. +.It Fl E +Extract enumerations and bit constructs. +In this mode the tool emits +a header file that contains for each type given on the command line a +C-enum definition and a preprocessor define that may be used to map +values to strings. +.It Fl e .Nm expects MIB variable names (only the last component) on its command line. It reads a MIB specification from standard input and for each MIB variable @@ -83,13 +99,13 @@ .It Va OID_ Ns Ar name is the last component of the OID. .El -.Pp -The options are as follows: -.Bl -tag -width ".Fl d Ar argument" .It Fl h Print a short help page. -.It Fl e -Enter extract mode. +.It Fl I Ar directory +Add the named directory to the include path just before the standard include +directories. +.It Fl i Ar infile +Read from the named file instead of standard input. .It Fl l Generate local preprocessor includes. This is used for bootstrapping @@ -103,26 +119,44 @@ .Sh MIBS The syntax of the MIB description file can formally be specified as follows: .Bd -unfilled -offset indent -file := tree | tree file + file := top | top file + + top := tree | typedef | include + + tree := head elements ')' + + entry := head ':' index STRING elements ')' + + leaf := head type STRING ACCESS ')' + + column := head type ACCESS ')' + + type := BASETYPE | BASETYPE '|' subtype | enum | bits + + subtype := STRING + + enum := ENUM '(' value ')' + + bits := BITS '(' value ')' -tree := head elements ')' + value := INT STRING | INT STRING value -entry := head ':' index STRING elements ')' + head := '(' INT STRING -leaf := head TYPE STRING ACCESS ')' + elements := EMPTY | elements element -column := head TYPE ACCESS ')' + element := tree | leaf | column -head := '(' INT STRING + index := type | index type -elements := EMPTY | elements element + typedef := 'typedef' STRING type -element := tree | leaf + include := 'include' filespec -index := TYPE | index TYPE + filespec := '"' STRING '"' | '<' STRING '>' .Ed .Pp -.Ar TYPE +.Ar BASETYPE specifies a SNMP data type and may be one of .Bl -bullet -offset indent -compact .It @@ -163,10 +197,25 @@ is a decimal integer and .Ar STRING is any string starting with a letter or underscore and consisting of -letters, digits and underscores, that is not one of the keywords. +letters, digits, underscores and minuses, that is not one of the keywords. +.Pp +The +.Ar typedef +directive associates a type with a single name. +.Pp +The +.Ar include +directive is replaced by the contents of the named file. .Sh EXAMPLES The following MIB description describes the system group: .Bd -literal -offset indent +include "tc.def" + +typedef AdminStatus ENUM ( + 1 up + 2 down +) + (1 internet (2 mgmt (1 mibII ==== //depot/projects/soc2005/bsnmp/contrib/bsnmp/gensnmptree/gensnmptree.c#5 (text+ko) ==== @@ -3,7 +3,7 @@ * Fraunhofer Institute for Open Communication Systems (FhG Fokus). * All rights reserved. * - * Copyright (c) 2004 + * Copyright (c) 2004-2006 * Hartmut Brandt. * All rights reserved. * @@ -30,21 +30,35 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Begemot: bsnmp/gensnmptree/gensnmptree.c,v 1.44 2006/02/14 09:04:17 brandt_h Exp $ + * $Begemot: gensnmptree.c 383 2006-05-30 07:40:49Z brandt_h $ * * Generate OID table from table description. * * Syntax is: * --------- - * file := tree | tree file + * file := top | top file + * + * top := tree | typedef | include * * tree := head elements ')' * * entry := head ':' index STRING elements ')' * - * leaf := head TYPE STRING ACCESS ')' + * leaf := head type STRING ACCESS ')' + * + * column := head type ACCESS ')' + * + * type := BASETYPE | BASETYPE '|' subtype | enum | bits + * + * subtype := STRING + * + * enum := ENUM '(' value ')' + * + * bits := BITS '(' value ')' + * + * value := optminus INT STRING | optminus INT STRING value * - * column := head TYPE ACCESS ')' + * optminus := '-' | EMPTY * * head := '(' INT STRING * @@ -52,8 +66,13 @@ * * element := tree | leaf | column * - * index := TYPE | index TYPE + * index := type | index type + * + * typedef := 'typedef' STRING type + * + * include := 'include' filespec * + * filespec := '"' STRING '"' | '<' STRING '>' */ #include <sys/types.h> #include <sys/param.h> @@ -82,20 +101,27 @@ u_int tree_size; static const char *file_prefix = ""; -static FILE *fp; /* if true generate local include paths */ static int localincs = 0; +/* if true print tokens */ +static int debug; + static const char usgtxt[] = "\ -Generate SNMP tables. Copyright (c) 2001-2002 Fraunhofer Institute for\n\ -Open Communication Systems (FhG Fokus). All rights reserved.\n\ -usage: gensnmptree [-hel] [-p prefix] [name]...\n\ +Generate SNMP tables.\n\ +usage: gensnmptree [-dEehlt] [-I directory] [-i infile] [-p prefix]\n\ + [name]...\n\ options:\n\ + -d debug mode\n\ + -E extract the named enums and bits only\n\ + -e extract the named oids or enums\n\ -h print this info\n\ - -e extrace the named oids\n\ + -I directory add directory to include path\n\ + -i ifile read from the named file instead of stdin\n\ -l generate local include directives\n\ -p prefix prepend prefix to file and variable names\n\ + -t generated a .def file\n\ "; /* @@ -153,6 +179,29 @@ static LIST_HEAD(, func) funcs = LIST_HEAD_INITIALIZER(funcs); +struct enums { + const char *name; + long value; + TAILQ_ENTRY(enums) link; +}; + +struct type { + const char *name; + const char *from_fname; + u_int from_lno; + u_int syntax; + int is_enum; + int is_bits; + TAILQ_HEAD(, enums) enums; + LIST_ENTRY(type) link; +}; + +static LIST_HEAD(, type) types = LIST_HEAD_INITIALIZER(types); + +static void report(const char *, ...) __dead2 __printflike(1, 2); +static void report_node(const struct node *, const char *, ...) + __dead2 __printflike(2, 3); + /************************************************************ * * Allocate memory and panic just in the case... @@ -168,6 +217,164 @@ return (ptr); } +static char * +savestr(const char *s) +{ + + if (s == NULL) + return (NULL); + return (strcpy(xalloc(strlen(s) + 1), s)); +} + +/************************************************************ + * + * Input stack + */ +struct input { + FILE *fp; + u_int lno; + char *fname; + char *path; + LIST_ENTRY(input) link; +}; +static LIST_HEAD(, input) inputs = LIST_HEAD_INITIALIZER(inputs); +static struct input *input = NULL; + +#define MAX_PATHS 100 +static u_int npaths = 2; +static u_int stdpaths = 2; +static const char *paths[MAX_PATHS + 1] = { + "/usr/share/snmp/defs", + "/usr/local/share/snmp/defs", + NULL +}; + +static int pbchar = -1; + +static void +path_new(const char *path) +{ + if (npaths >= MAX_PATHS) + report("too many -I directives"); + memmove(&paths[npaths - stdpaths + 1], &paths[npaths - stdpaths], + sizeof(path[0]) * stdpaths); + paths[npaths - stdpaths] = savestr(path); + npaths++; +} + +static void +input_new(FILE *fp, const char *path, const char *fname) +{ + struct input *ip; + + ip = xalloc(sizeof(*ip)); + ip->fp = fp; + ip->lno = 1; + ip->fname = savestr(fname); + ip->path = savestr(path); + LIST_INSERT_HEAD(&inputs, ip, link); + + input = ip; +} + +static void +input_close(void) +{ + + if (input == NULL) + return; + fclose(input->fp); + free(input->fname); + free(input->path); + LIST_REMOVE(input, link); + free(input); + + input = LIST_FIRST(&inputs); +} + +static FILE * +tryopen(const char *path, const char *fname) +{ + char *fn; + FILE *fp; + + if (path == NULL) + fn = savestr(fname); + else { + fn = xalloc(strlen(path) + strlen(fname) + 2); + sprintf(fn, "%s/%s", path, fname); + } + fp = fopen(fn, "r"); + free(fn); + return (fp); +} + +static void +input_fopen(const char *fname, int loc) +{ + FILE *fp; + char *path; + u_int p; + + if (fname[0] == '/') { + if ((fp = tryopen(NULL, fname)) != NULL) { + input_new(fp, NULL, fname); + return; + } + + } else { + if (loc) { + if (input == NULL) + path = NULL; + else + path = input->path; + + if ((fp = tryopen(path, fname)) != NULL) { + input_new(fp, NULL, fname); + return; + } + } + + for (p = 0; paths[p] != NULL; p++) + if ((fp = tryopen(paths[p], fname)) != NULL) { + input_new(fp, paths[p], fname); + return; + } + } + report("cannot open '%s'", fname); +} + +static int +tgetc(void) +{ + int c; + + if (pbchar != -1) { + c = pbchar; + pbchar = -1; + return (c); + } + + for (;;) { + if (input == NULL) + return (EOF); + + if ((c = getc(input->fp)) != EOF) + return (c); + + input_close(); + } +} + +static void +tungetc(int c) +{ + + if (pbchar != -1) + abort(); + pbchar = c; +} + /************************************************************ * * Parsing input @@ -178,6 +385,12 @@ TOK_STR, /* string */ TOK_ACCESS, /* access operator */ TOK_TYPE, /* type operator */ + TOK_ENUM, /* enum token (kind of a type) */ + TOK_TYPEDEF, /* typedef directive */ + TOK_DEFTYPE, /* defined type */ + TOK_INCLUDE, /* include directive */ + TOK_FILENAME, /* filename ("foo.bar" or <foo.bar>) */ + TOK_BITS, /* bits token (kind of a type) */ }; static const struct { @@ -198,6 +411,10 @@ { "COUNTER", TOK_TYPE, SNMP_SYNTAX_COUNTER }, { "GAUGE", TOK_TYPE, SNMP_SYNTAX_GAUGE }, { "COUNTER64", TOK_TYPE, SNMP_SYNTAX_COUNTER64 }, + { "ENUM", TOK_ENUM, SNMP_SYNTAX_INTEGER }, + { "BITS", TOK_BITS, SNMP_SYNTAX_OCTETSTRING }, + { "typedef", TOK_TYPEDEF, 0 }, + { "include", TOK_INCLUDE, 0 }, { NULL, 0, 0 } }; @@ -205,13 +422,9 @@ #define MAXSTR 1000 char str[MAXSTR]; u_long val; /* integer values */ -u_int lno = 1; /* current line number */ int all_cond; /* all conditions are true */ +int saved_token = -1; -static void report(const char *, ...) __dead2 __printflike(1, 2); -static void report_node(const struct node *, const char *, ...) - __dead2 __printflike(2, 3); - /* * Report an error and exit. */ @@ -222,11 +435,11 @@ int c; va_start(ap, fmt); - fprintf(stderr, "line %u: ", lno); + fprintf(stderr, "line %u: ", input->lno); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); fprintf(stderr, "context: \""); - while ((c = getchar()) != EOF && c != '\n') + while ((c = tgetc()) != EOF && c != '\n') fprintf(stderr, "%c", c); fprintf(stderr, "\n"); va_end(ap); @@ -251,24 +464,31 @@ static char * savetok(void) { - return (strcpy(xalloc(strlen(str)+1), str)); + return (savestr(str)); } /* * Get the next token from input. */ static int -gettoken(void) +gettoken_internal(void) { int c; + struct type *t; + + if (saved_token != -1) { + c = saved_token; + saved_token = -1; + return (c); + } again: /* * Skip any whitespace before the next token */ - while ((c = getchar()) != EOF) { + while ((c = tgetc()) != EOF) { if (c == '\n') - lno++; + input->lno++; if (!isspace(c)) break; } @@ -281,9 +501,9 @@ * Skip comments */ if (c == '#') { - while ((c = getchar()) != EOF) { + while ((c = tgetc()) != EOF) { if (c == '\n') { - lno++; + input->lno++; goto again; } } @@ -293,15 +513,51 @@ /* * Single character tokens */ - if (c == ')' || c == '(' || c == ':') + if (strchr("():|-", c) != NULL) return (c); + if (c == '"' || c == '<') { + int end = c; + size_t n = 0; + + val = 1; + if (c == '<') { + val = 0; + end = '>'; + } + + while ((c = tgetc()) != EOF) { + if (c == end) + break; + if (n == sizeof(str) - 1) { + str[n++] = '\0'; + report("filename too long '%s...'", str); + } + str[n++] = c; + } + str[n++] = '\0'; + return (TOK_FILENAME); + } + /* * Sort out numbers */ if (isdigit(c)) { - ungetc(c, stdin); - scanf("%lu", &val); + size_t n = 0; + str[n++] = c; + while ((c = tgetc()) != EOF) { + if (!isdigit(c)) { + tungetc(c); + break; + } + if (n == sizeof(str) - 1) { + str[n++] = '\0'; + report("number too long '%s...'", str); + } + str[n++] = c; + } + str[n++] = '\0'; + sscanf(str, "%lu", &val); return (TOK_NUM); } @@ -311,9 +567,9 @@ >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606031040.k53Aevpt014554>