freebsd-buildutils-10.0/0000755000000000000000000000000012265500006012104 5ustar freebsd-buildutils-10.0/src/0000755000000000000000000000000012265500217012677 5ustar freebsd-buildutils-10.0/src/usr.bin/0000755000000000000000000000000012265500204014253 5ustar freebsd-buildutils-10.0/src/usr.bin/brandelf/0000755000000000000000000000000012265500204016030 5ustar freebsd-buildutils-10.0/src/usr.bin/brandelf/brandelf.10000644000000000000000000000564612206721704017707 0ustar .\" Copyright 1997 John-Mark Gurney. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY John-Mark Gurney AND CONTRIBUTORS ``AS IS'' .\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" .Dd February 6, 1997 .Dt BRANDELF 1 .Os .Sh NAME .Nm brandelf .Nd mark an ELF binary for a specific ABI .Sh SYNOPSIS .Nm .Op Fl lv .Op Fl f Ar ELF_ABI_number .Op Fl t Ar string .Ar .Sh DESCRIPTION The .Nm utility marks an ELF binary to be run under a certain ABI for .Fx . .Pp The options are as follows: .Bl -tag -width indent .It Fl f Ar ELF_ABI_number Forces branding with the supplied ELF ABI number. Incompatible with the .Fl t option. These values are assigned by SCO/USL. .It Fl l Writes the list of all known ELF types to the standard error. .It Fl v Turns on verbose output. .It Fl t Ar string Brands the given ELF binaries to be of the .Ar string ABI type. Currently supported ABIs are .Dq Li FreeBSD , .Dq Li Linux , and .Dq Li SVR4 . .It Ar file If .Fl t Ar string is given it will brand .Ar file to be of type .Ar string , otherwise it will simply display the branding of .Ar file . .El .Sh EXIT STATUS Exit status is 0 on success, and 1 if the command fails if a file does not exist, is too short, fails to brand properly, or the brand requested is not one of the known types and the .Fl f option is not set. .Sh EXAMPLES The following is an example of a typical usage of the .Nm command: .Bd -literal -offset indent brandelf file brandelf -t Linux file .Ed .Sh SEE ALSO .Rs .%A The Santa Cruz Operation, Inc. .%T System V Application Binary Interface .%D April 29, 1998 (DRAFT) .%U http://www.sco.com/developer/devspecs/ .Re .Sh HISTORY The .Nm manual page first appeared in .Fx 2.2 . .Sh AUTHORS This manual page was written by .An John-Mark Gurney Aq gurney_j@efn.org . freebsd-buildutils-10.0/src/usr.bin/brandelf/Makefile0000644000000000000000000000006407672674144017515 0ustar # $FreeBSD$ PROG= brandelf .include freebsd-buildutils-10.0/src/usr.bin/brandelf/brandelf.c0000644000000000000000000001203011702724525017756 0ustar /*- * Copyright (c) 2000, 2001 David O'Brien * Copyright (c) 1996 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include static int elftype(const char *); static const char *iselftype(int); static void printelftypes(void); static void usage(void); struct ELFtypes { const char *str; int value; }; /* XXX - any more types? */ static struct ELFtypes elftypes[] = { { "FreeBSD", ELFOSABI_FREEBSD }, { "Linux", ELFOSABI_LINUX }, { "Solaris", ELFOSABI_SOLARIS }, { "SVR4", ELFOSABI_SYSV } }; int main(int argc, char **argv) { const char *strtype = "FreeBSD"; int type = ELFOSABI_FREEBSD; int retval = 0; int ch, change = 0, force = 0, listed = 0; while ((ch = getopt(argc, argv, "f:lt:v")) != -1) switch (ch) { case 'f': if (change) errx(1, "f option incompatible with t option"); force = 1; type = atoi(optarg); if (errno == ERANGE || type < 0 || type > 255) { warnx("invalid argument to option f: %s", optarg); usage(); } break; case 'l': printelftypes(); listed = 1; break; case 'v': /* does nothing */ break; case 't': if (force) errx(1, "t option incompatible with f option"); change = 1; strtype = optarg; break; default: usage(); } argc -= optind; argv += optind; if (!argc) { if (listed) exit(0); else { warnx("no file(s) specified"); usage(); } } if (!force && (type = elftype(strtype)) == -1) { warnx("invalid ELF type '%s'", strtype); printelftypes(); usage(); } while (argc) { int fd; char buffer[EI_NIDENT]; if ((fd = open(argv[0], change || force ? O_RDWR : O_RDONLY, 0)) < 0) { warn("error opening file %s", argv[0]); retval = 1; goto fail; } if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) { warnx("file '%s' too short", argv[0]); retval = 1; goto fail; } if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 || buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) { warnx("file '%s' is not ELF format", argv[0]); retval = 1; goto fail; } if (!change && !force) { fprintf(stdout, "File '%s' is of brand '%s' (%u).\n", argv[0], iselftype(buffer[EI_OSABI]), buffer[EI_OSABI]); if (!iselftype(type)) { warnx("ELF ABI Brand '%u' is unknown", type); printelftypes(); } } else { buffer[EI_OSABI] = type; lseek(fd, 0, SEEK_SET); if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) { warn("error writing %s %d", argv[0], fd); retval = 1; goto fail; } } fail: close(fd); argc--; argv++; } return retval; } static void usage(void) { (void)fprintf(stderr, "usage: brandelf [-lv] [-f ELF_ABI_number] [-t string] file ...\n"); exit(1); } static const char * iselftype(int etype) { size_t elfwalk; for (elfwalk = 0; elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); elfwalk++) if (etype == elftypes[elfwalk].value) return elftypes[elfwalk].str; return 0; } static int elftype(const char *elfstrtype) { size_t elfwalk; for (elfwalk = 0; elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); elfwalk++) if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0) return elftypes[elfwalk].value; return -1; } static void printelftypes(void) { size_t elfwalk; fprintf(stderr, "known ELF types are: "); for (elfwalk = 0; elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); elfwalk++) fprintf(stderr, "%s(%u) ", elftypes[elfwalk].str, elftypes[elfwalk].value); fprintf(stderr, "\n"); } freebsd-buildutils-10.0/src/usr.bin/elfdump/0000755000000000000000000000000012265500055015713 5ustar freebsd-buildutils-10.0/src/usr.bin/elfdump/elfdump.c0000644000000000000000000007336312040264206017523 0ustar /*- * Copyright (c) 2003 David O'Brien. All rights reserved. * Copyright (c) 2001 Jake Burkholder * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ED_DYN (1<<0) #define ED_EHDR (1<<1) #define ED_GOT (1<<2) #define ED_HASH (1<<3) #define ED_INTERP (1<<4) #define ED_NOTE (1<<5) #define ED_PHDR (1<<6) #define ED_REL (1<<7) #define ED_SHDR (1<<8) #define ED_SYMTAB (1<<9) #define ED_ALL ((1<<10)-1) #define elf_get_addr elf_get_quad #define elf_get_off elf_get_quad #define elf_get_size elf_get_quad enum elf_member { D_TAG = 1, D_PTR, D_VAL, E_CLASS, E_DATA, E_OSABI, E_TYPE, E_MACHINE, E_VERSION, E_ENTRY, E_PHOFF, E_SHOFF, E_FLAGS, E_EHSIZE, E_PHENTSIZE, E_PHNUM, E_SHENTSIZE, E_SHNUM, E_SHSTRNDX, N_NAMESZ, N_DESCSZ, N_TYPE, P_TYPE, P_OFFSET, P_VADDR, P_PADDR, P_FILESZ, P_MEMSZ, P_FLAGS, P_ALIGN, SH_NAME, SH_TYPE, SH_FLAGS, SH_ADDR, SH_OFFSET, SH_SIZE, SH_LINK, SH_INFO, SH_ADDRALIGN, SH_ENTSIZE, ST_NAME, ST_VALUE, ST_SIZE, ST_INFO, ST_SHNDX, R_OFFSET, R_INFO, RA_OFFSET, RA_INFO, RA_ADDEND }; typedef enum elf_member elf_member_t; static int elf32_offsets[] = { 0, offsetof(Elf32_Dyn, d_tag), offsetof(Elf32_Dyn, d_un.d_ptr), offsetof(Elf32_Dyn, d_un.d_val), offsetof(Elf32_Ehdr, e_ident[EI_CLASS]), offsetof(Elf32_Ehdr, e_ident[EI_DATA]), offsetof(Elf32_Ehdr, e_ident[EI_OSABI]), offsetof(Elf32_Ehdr, e_type), offsetof(Elf32_Ehdr, e_machine), offsetof(Elf32_Ehdr, e_version), offsetof(Elf32_Ehdr, e_entry), offsetof(Elf32_Ehdr, e_phoff), offsetof(Elf32_Ehdr, e_shoff), offsetof(Elf32_Ehdr, e_flags), offsetof(Elf32_Ehdr, e_ehsize), offsetof(Elf32_Ehdr, e_phentsize), offsetof(Elf32_Ehdr, e_phnum), offsetof(Elf32_Ehdr, e_shentsize), offsetof(Elf32_Ehdr, e_shnum), offsetof(Elf32_Ehdr, e_shstrndx), offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz), offsetof(Elf_Note, n_type), offsetof(Elf32_Phdr, p_type), offsetof(Elf32_Phdr, p_offset), offsetof(Elf32_Phdr, p_vaddr), offsetof(Elf32_Phdr, p_paddr), offsetof(Elf32_Phdr, p_filesz), offsetof(Elf32_Phdr, p_memsz), offsetof(Elf32_Phdr, p_flags), offsetof(Elf32_Phdr, p_align), offsetof(Elf32_Shdr, sh_name), offsetof(Elf32_Shdr, sh_type), offsetof(Elf32_Shdr, sh_flags), offsetof(Elf32_Shdr, sh_addr), offsetof(Elf32_Shdr, sh_offset), offsetof(Elf32_Shdr, sh_size), offsetof(Elf32_Shdr, sh_link), offsetof(Elf32_Shdr, sh_info), offsetof(Elf32_Shdr, sh_addralign), offsetof(Elf32_Shdr, sh_entsize), offsetof(Elf32_Sym, st_name), offsetof(Elf32_Sym, st_value), offsetof(Elf32_Sym, st_size), offsetof(Elf32_Sym, st_info), offsetof(Elf32_Sym, st_shndx), offsetof(Elf32_Rel, r_offset), offsetof(Elf32_Rel, r_info), offsetof(Elf32_Rela, r_offset), offsetof(Elf32_Rela, r_info), offsetof(Elf32_Rela, r_addend) }; static int elf64_offsets[] = { 0, offsetof(Elf64_Dyn, d_tag), offsetof(Elf64_Dyn, d_un.d_ptr), offsetof(Elf64_Dyn, d_un.d_val), offsetof(Elf32_Ehdr, e_ident[EI_CLASS]), offsetof(Elf32_Ehdr, e_ident[EI_DATA]), offsetof(Elf32_Ehdr, e_ident[EI_OSABI]), offsetof(Elf64_Ehdr, e_type), offsetof(Elf64_Ehdr, e_machine), offsetof(Elf64_Ehdr, e_version), offsetof(Elf64_Ehdr, e_entry), offsetof(Elf64_Ehdr, e_phoff), offsetof(Elf64_Ehdr, e_shoff), offsetof(Elf64_Ehdr, e_flags), offsetof(Elf64_Ehdr, e_ehsize), offsetof(Elf64_Ehdr, e_phentsize), offsetof(Elf64_Ehdr, e_phnum), offsetof(Elf64_Ehdr, e_shentsize), offsetof(Elf64_Ehdr, e_shnum), offsetof(Elf64_Ehdr, e_shstrndx), offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz), offsetof(Elf_Note, n_type), offsetof(Elf64_Phdr, p_type), offsetof(Elf64_Phdr, p_offset), offsetof(Elf64_Phdr, p_vaddr), offsetof(Elf64_Phdr, p_paddr), offsetof(Elf64_Phdr, p_filesz), offsetof(Elf64_Phdr, p_memsz), offsetof(Elf64_Phdr, p_flags), offsetof(Elf64_Phdr, p_align), offsetof(Elf64_Shdr, sh_name), offsetof(Elf64_Shdr, sh_type), offsetof(Elf64_Shdr, sh_flags), offsetof(Elf64_Shdr, sh_addr), offsetof(Elf64_Shdr, sh_offset), offsetof(Elf64_Shdr, sh_size), offsetof(Elf64_Shdr, sh_link), offsetof(Elf64_Shdr, sh_info), offsetof(Elf64_Shdr, sh_addralign), offsetof(Elf64_Shdr, sh_entsize), offsetof(Elf64_Sym, st_name), offsetof(Elf64_Sym, st_value), offsetof(Elf64_Sym, st_size), offsetof(Elf64_Sym, st_info), offsetof(Elf64_Sym, st_shndx), offsetof(Elf64_Rel, r_offset), offsetof(Elf64_Rel, r_info), offsetof(Elf64_Rela, r_offset), offsetof(Elf64_Rela, r_info), offsetof(Elf64_Rela, r_addend) }; /* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */ static const char * d_tags(u_int64_t tag) { switch (tag) { case 0: return "DT_NULL"; case 1: return "DT_NEEDED"; case 2: return "DT_PLTRELSZ"; case 3: return "DT_PLTGOT"; case 4: return "DT_HASH"; case 5: return "DT_STRTAB"; case 6: return "DT_SYMTAB"; case 7: return "DT_RELA"; case 8: return "DT_RELASZ"; case 9: return "DT_RELAENT"; case 10: return "DT_STRSZ"; case 11: return "DT_SYMENT"; case 12: return "DT_INIT"; case 13: return "DT_FINI"; case 14: return "DT_SONAME"; case 15: return "DT_RPATH"; case 16: return "DT_SYMBOLIC"; case 17: return "DT_REL"; case 18: return "DT_RELSZ"; case 19: return "DT_RELENT"; case 20: return "DT_PLTREL"; case 21: return "DT_DEBUG"; case 22: return "DT_TEXTREL"; case 23: return "DT_JMPREL"; case 24: return "DT_BIND_NOW"; case 25: return "DT_INIT_ARRAY"; case 26: return "DT_FINI_ARRAY"; case 27: return "DT_INIT_ARRAYSZ"; case 28: return "DT_FINI_ARRAYSZ"; case 29: return "DT_RUNPATH"; case 30: return "DT_FLAGS"; case 32: return "DT_PREINIT_ARRAY"; /* XXX: DT_ENCODING */ case 33: return "DT_PREINIT_ARRAYSZ"; /* 0x6000000D - 0x6ffff000 operating system-specific semantics */ case 0x6ffffdf5: return "DT_GNU_PRELINKED"; case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ"; case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ"; case 0x6ffffdf8: return "DT_SUNW_CHECKSUM"; case 0x6ffffdf9: return "DT_PLTPADSZ"; case 0x6ffffdfa: return "DT_MOVEENT"; case 0x6ffffdfb: return "DT_MOVESZ"; case 0x6ffffdfc: return "DT_FEATURE"; case 0x6ffffdfd: return "DT_POSFLAG_1"; case 0x6ffffdfe: return "DT_SYMINSZ"; case 0x6ffffdff: return "DT_SYMINENT (DT_VALRNGHI)"; case 0x6ffffe00: return "DT_ADDRRNGLO"; case 0x6ffffef8: return "DT_GNU_CONFLICT"; case 0x6ffffef9: return "DT_GNU_LIBLIST"; case 0x6ffffefa: return "DT_SUNW_CONFIG"; case 0x6ffffefb: return "DT_SUNW_DEPAUDIT"; case 0x6ffffefc: return "DT_SUNW_AUDIT"; case 0x6ffffefd: return "DT_SUNW_PLTPAD"; case 0x6ffffefe: return "DT_SUNW_MOVETAB"; case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)"; case 0x6ffffff9: return "DT_RELACOUNT"; case 0x6ffffffa: return "DT_RELCOUNT"; case 0x6ffffffb: return "DT_FLAGS_1"; case 0x6ffffffc: return "DT_VERDEF"; case 0x6ffffffd: return "DT_VERDEFNUM"; case 0x6ffffffe: return "DT_VERNEED"; case 0x6fffffff: return "DT_VERNEEDNUM"; case 0x6ffffff0: return "DT_GNU_VERSYM"; /* 0x70000000 - 0x7fffffff processor-specific semantics */ case 0x70000000: return "DT_IA_64_PLT_RESERVE"; case 0x7ffffffd: return "DT_SUNW_AUXILIARY"; case 0x7ffffffe: return "DT_SUNW_USED"; case 0x7fffffff: return "DT_SUNW_FILTER"; default: return "ERROR: TAG NOT DEFINED"; } } static const char * e_machines(u_int mach) { static char machdesc[64]; switch (mach) { case EM_NONE: return "EM_NONE"; case EM_M32: return "EM_M32"; case EM_SPARC: return "EM_SPARC"; case EM_386: return "EM_386"; case EM_68K: return "EM_68K"; case EM_88K: return "EM_88K"; case EM_860: return "EM_860"; case EM_MIPS: return "EM_MIPS"; case EM_PPC: return "EM_PPC"; case EM_ARM: return "EM_ARM"; case EM_ALPHA: return "EM_ALPHA (legacy)"; case EM_SPARCV9:return "EM_SPARCV9"; case EM_IA_64: return "EM_IA_64"; case EM_X86_64: return "EM_X86_64"; } snprintf(machdesc, sizeof(machdesc), "(unknown machine) -- type 0x%x", mach); return (machdesc); } static const char *e_types[] = { "ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE" }; static const char *ei_versions[] = { "EV_NONE", "EV_CURRENT" }; static const char *ei_classes[] = { "ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64" }; static const char *ei_data[] = { "ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB" }; static const char *ei_abis[256] = { "ELFOSABI_SYSV", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX", "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", "ELFOSABI_AIX", "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", "ELFOSABI_TRU64", "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD", [255] = "ELFOSABI_STANDALONE" }; static const char *p_types[] = { "PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE", "PT_SHLIB", "PT_PHDR", "PT_TLS" }; static const char *p_flags[] = { "", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R", "PF_X|PF_W|PF_R" }; /* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */ static const char * sh_types(u_int64_t sht) { switch (sht) { case 0: return "SHT_NULL"; case 1: return "SHT_PROGBITS"; case 2: return "SHT_SYMTAB"; case 3: return "SHT_STRTAB"; case 4: return "SHT_RELA"; case 5: return "SHT_HASH"; case 6: return "SHT_DYNAMIC"; case 7: return "SHT_NOTE"; case 8: return "SHT_NOBITS"; case 9: return "SHT_REL"; case 10: return "SHT_SHLIB"; case 11: return "SHT_DYNSYM"; case 14: return "SHT_INIT_ARRAY"; case 15: return "SHT_FINI_ARRAY"; case 16: return "SHT_PREINIT_ARRAY"; case 17: return "SHT_GROUP"; case 18: return "SHT_SYMTAB_SHNDX"; /* 0x60000000 - 0x6fffffff operating system-specific semantics */ case 0x6ffffff0: return "XXX:VERSYM"; case 0x6ffffff4: return "SHT_SUNW_dof"; case 0x6ffffff7: return "SHT_GNU_LIBLIST"; case 0x6ffffffc: return "XXX:VERDEF"; case 0x6ffffffd: return "SHT_SUNW(GNU)_verdef"; case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed"; case 0x6fffffff: return "SHT_SUNW(GNU)_versym"; /* 0x70000000 - 0x7fffffff processor-specific semantics */ case 0x70000000: return "SHT_IA_64_EXT"; case 0x70000001: return "SHT_IA_64_UNWIND"; case 0x7ffffffd: return "XXX:AUXILIARY"; case 0x7fffffff: return "XXX:FILTER"; /* 0x80000000 - 0xffffffff application programs */ default: return "ERROR: SHT NOT DEFINED"; } } static const char *sh_flags[] = { "", "SHF_WRITE", "SHF_ALLOC", "SHF_WRITE|SHF_ALLOC", "SHF_EXECINSTR", "SHF_WRITE|SHF_EXECINSTR", "SHF_ALLOC|SHF_EXECINSTR", "SHF_WRITE|SHF_ALLOC|SHF_EXECINSTR" }; static const char *st_types[] = { "STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE" }; static const char *st_bindings[] = { "STB_LOCAL", "STB_GLOBAL", "STB_WEAK" }; static char *dynstr; static char *shstrtab; static char *strtab; static FILE *out; static u_int64_t elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member); static u_int64_t elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member); #if 0 static u_int64_t elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member); #endif static u_int64_t elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member); static u_int64_t elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member); static void elf_print_ehdr(Elf32_Ehdr *e); static void elf_print_phdr(Elf32_Ehdr *e, void *p); static void elf_print_shdr(Elf32_Ehdr *e, void *sh); static void elf_print_symtab(Elf32_Ehdr *e, void *sh, char *str); static void elf_print_dynamic(Elf32_Ehdr *e, void *sh); static void elf_print_rel(Elf32_Ehdr *e, void *r); static void elf_print_rela(Elf32_Ehdr *e, void *ra); static void elf_print_interp(Elf32_Ehdr *e, void *p); static void elf_print_got(Elf32_Ehdr *e, void *sh); static void elf_print_hash(Elf32_Ehdr *e, void *sh); static void elf_print_note(Elf32_Ehdr *e, void *sh); static void usage(void); int main(int ac, char **av) { u_int64_t phoff; u_int64_t shoff; u_int64_t phentsize; u_int64_t phnum; u_int64_t shentsize; u_int64_t shnum; u_int64_t shstrndx; u_int64_t offset; u_int64_t name; u_int64_t type; struct stat sb; u_int flags; Elf32_Ehdr *e; void *p; void *sh; void *v; int fd; int ch; int i; out = stdout; flags = 0; while ((ch = getopt(ac, av, "acdeiGhnprsw:")) != -1) switch (ch) { case 'a': flags = ED_ALL; break; case 'c': flags |= ED_SHDR; break; case 'd': flags |= ED_DYN; break; case 'e': flags |= ED_EHDR; break; case 'i': flags |= ED_INTERP; break; case 'G': flags |= ED_GOT; break; case 'h': flags |= ED_HASH; break; case 'n': flags |= ED_NOTE; break; case 'p': flags |= ED_PHDR; break; case 'r': flags |= ED_REL; break; case 's': flags |= ED_SYMTAB; break; case 'w': if ((out = fopen(optarg, "w")) == NULL) err(1, "%s", optarg); break; case '?': default: usage(); } ac -= optind; av += optind; if (ac == 0 || flags == 0) usage(); if ((fd = open(*av, O_RDONLY)) < 0 || fstat(fd, &sb) < 0) err(1, "%s", *av); e = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); if (e == MAP_FAILED) err(1, NULL); if (!IS_ELF(*(Elf32_Ehdr *)e)) errx(1, "not an elf file"); phoff = elf_get_off(e, e, E_PHOFF); shoff = elf_get_off(e, e, E_SHOFF); phentsize = elf_get_quarter(e, e, E_PHENTSIZE); phnum = elf_get_quarter(e, e, E_PHNUM); shentsize = elf_get_quarter(e, e, E_SHENTSIZE); shnum = elf_get_quarter(e, e, E_SHNUM); shstrndx = elf_get_quarter(e, e, E_SHSTRNDX); p = (char *)e + phoff; sh = (char *)e + shoff; offset = elf_get_off(e, (char *)sh + shstrndx * shentsize, SH_OFFSET); shstrtab = (char *)e + offset; for (i = 0; (u_int64_t)i < shnum; i++) { name = elf_get_word(e, (char *)sh + i * shentsize, SH_NAME); offset = elf_get_off(e, (char *)sh + i * shentsize, SH_OFFSET); if (strcmp(shstrtab + name, ".strtab") == 0) strtab = (char *)e + offset; if (strcmp(shstrtab + name, ".dynstr") == 0) dynstr = (char *)e + offset; } if (flags & ED_EHDR) elf_print_ehdr(e); if (flags & ED_PHDR) elf_print_phdr(e, p); if (flags & ED_SHDR) elf_print_shdr(e, sh); for (i = 0; (u_int64_t)i < phnum; i++) { v = (char *)p + i * phentsize; type = elf_get_word(e, v, P_TYPE); switch (type) { case PT_INTERP: if (flags & ED_INTERP) elf_print_interp(e, v); break; case PT_NULL: case PT_LOAD: case PT_DYNAMIC: case PT_NOTE: case PT_SHLIB: case PT_PHDR: break; } } for (i = 0; (u_int64_t)i < shnum; i++) { v = (char *)sh + i * shentsize; type = elf_get_word(e, v, SH_TYPE); switch (type) { case SHT_SYMTAB: if (flags & ED_SYMTAB) elf_print_symtab(e, v, strtab); break; case SHT_DYNAMIC: if (flags & ED_DYN) elf_print_dynamic(e, v); break; case SHT_RELA: if (flags & ED_REL) elf_print_rela(e, v); break; case SHT_REL: if (flags & ED_REL) elf_print_rel(e, v); break; case SHT_NOTE: name = elf_get_word(e, v, SH_NAME); if (flags & ED_NOTE && strcmp(shstrtab + name, ".note.ABI-tag") == 0) elf_print_note(e, v); break; case SHT_DYNSYM: if (flags & ED_SYMTAB) elf_print_symtab(e, v, dynstr); break; case SHT_PROGBITS: name = elf_get_word(e, v, SH_NAME); if (flags & ED_GOT && strcmp(shstrtab + name, ".got") == 0) elf_print_got(e, v); break; case SHT_HASH: if (flags & ED_HASH) elf_print_hash(e, v); break; case SHT_NULL: case SHT_STRTAB: case SHT_NOBITS: case SHT_SHLIB: break; } } return 0; } static void elf_print_ehdr(Elf32_Ehdr *e) { u_int64_t class; u_int64_t data; u_int64_t osabi; u_int64_t type; u_int64_t machine; u_int64_t version; u_int64_t entry; u_int64_t phoff; u_int64_t shoff; u_int64_t flags; u_int64_t ehsize; u_int64_t phentsize; u_int64_t phnum; u_int64_t shentsize; u_int64_t shnum; u_int64_t shstrndx; class = elf_get_byte(e, e, E_CLASS); data = elf_get_byte(e, e, E_DATA); osabi = elf_get_byte(e, e, E_OSABI); type = elf_get_quarter(e, e, E_TYPE); machine = elf_get_quarter(e, e, E_MACHINE); version = elf_get_word(e, e, E_VERSION); entry = elf_get_addr(e, e, E_ENTRY); phoff = elf_get_off(e, e, E_PHOFF); shoff = elf_get_off(e, e, E_SHOFF); flags = elf_get_word(e, e, E_FLAGS); ehsize = elf_get_quarter(e, e, E_EHSIZE); phentsize = elf_get_quarter(e, e, E_PHENTSIZE); phnum = elf_get_quarter(e, e, E_PHNUM); shentsize = elf_get_quarter(e, e, E_SHENTSIZE); shnum = elf_get_quarter(e, e, E_SHNUM); shstrndx = elf_get_quarter(e, e, E_SHSTRNDX); fprintf(out, "\nelf header:\n"); fprintf(out, "\n"); fprintf(out, "\te_ident: %s %s %s\n", ei_classes[class], ei_data[data], ei_abis[osabi]); fprintf(out, "\te_type: %s\n", e_types[type]); fprintf(out, "\te_machine: %s\n", e_machines(machine)); fprintf(out, "\te_version: %s\n", ei_versions[version]); fprintf(out, "\te_entry: %#jx\n", (intmax_t)entry); fprintf(out, "\te_phoff: %jd\n", (intmax_t)phoff); fprintf(out, "\te_shoff: %jd\n", (intmax_t)shoff); fprintf(out, "\te_flags: %jd\n", (intmax_t)flags); fprintf(out, "\te_ehsize: %jd\n", (intmax_t)ehsize); fprintf(out, "\te_phentsize: %jd\n", (intmax_t)phentsize); fprintf(out, "\te_phnum: %jd\n", (intmax_t)phnum); fprintf(out, "\te_shentsize: %jd\n", (intmax_t)shentsize); fprintf(out, "\te_shnum: %jd\n", (intmax_t)shnum); fprintf(out, "\te_shstrndx: %jd\n", (intmax_t)shstrndx); } static void elf_print_phdr(Elf32_Ehdr *e, void *p) { u_int64_t phentsize; u_int64_t phnum; u_int64_t type; u_int64_t offset; u_int64_t vaddr; u_int64_t paddr; u_int64_t filesz; u_int64_t memsz; u_int64_t flags; u_int64_t align; void *v; int i; phentsize = elf_get_quarter(e, e, E_PHENTSIZE); phnum = elf_get_quarter(e, e, E_PHNUM); fprintf(out, "\nprogram header:\n"); for (i = 0; (u_int64_t)i < phnum; i++) { v = (char *)p + i * phentsize; type = elf_get_word(e, v, P_TYPE); offset = elf_get_off(e, v, P_OFFSET); vaddr = elf_get_addr(e, v, P_VADDR); paddr = elf_get_addr(e, v, P_PADDR); filesz = elf_get_size(e, v, P_FILESZ); memsz = elf_get_size(e, v, P_MEMSZ); flags = elf_get_word(e, v, P_FLAGS); align = elf_get_size(e, v, P_ALIGN); fprintf(out, "\n"); fprintf(out, "entry: %d\n", i); fprintf(out, "\tp_type: %s\n", p_types[type & 0x7]); fprintf(out, "\tp_offset: %jd\n", (intmax_t)offset); fprintf(out, "\tp_vaddr: %#jx\n", (intmax_t)vaddr); fprintf(out, "\tp_paddr: %#jx\n", (intmax_t)paddr); fprintf(out, "\tp_filesz: %jd\n", (intmax_t)filesz); fprintf(out, "\tp_memsz: %jd\n", (intmax_t)memsz); fprintf(out, "\tp_flags: %s\n", p_flags[flags]); fprintf(out, "\tp_align: %jd\n", (intmax_t)align); } } static void elf_print_shdr(Elf32_Ehdr *e, void *sh) { u_int64_t shentsize; u_int64_t shnum; u_int64_t name; u_int64_t type; u_int64_t flags; u_int64_t addr; u_int64_t offset; u_int64_t size; u_int64_t shlink; u_int64_t info; u_int64_t addralign; u_int64_t entsize; void *v; int i; shentsize = elf_get_quarter(e, e, E_SHENTSIZE); shnum = elf_get_quarter(e, e, E_SHNUM); fprintf(out, "\nsection header:\n"); for (i = 0; (u_int64_t)i < shnum; i++) { v = (char *)sh + i * shentsize; name = elf_get_word(e, v, SH_NAME); type = elf_get_word(e, v, SH_TYPE); flags = elf_get_word(e, v, SH_FLAGS); addr = elf_get_addr(e, v, SH_ADDR); offset = elf_get_off(e, v, SH_OFFSET); size = elf_get_size(e, v, SH_SIZE); shlink = elf_get_word(e, v, SH_LINK); info = elf_get_word(e, v, SH_INFO); addralign = elf_get_size(e, v, SH_ADDRALIGN); entsize = elf_get_size(e, v, SH_ENTSIZE); fprintf(out, "\n"); fprintf(out, "entry: %d\n", i); fprintf(out, "\tsh_name: %s\n", shstrtab + name); fprintf(out, "\tsh_type: %s\n", sh_types(type)); fprintf(out, "\tsh_flags: %s\n", sh_flags[flags & 0x7]); fprintf(out, "\tsh_addr: %#jx\n", addr); fprintf(out, "\tsh_offset: %jd\n", (intmax_t)offset); fprintf(out, "\tsh_size: %jd\n", (intmax_t)size); fprintf(out, "\tsh_link: %jd\n", (intmax_t)shlink); fprintf(out, "\tsh_info: %jd\n", (intmax_t)info); fprintf(out, "\tsh_addralign: %jd\n", (intmax_t)addralign); fprintf(out, "\tsh_entsize: %jd\n", (intmax_t)entsize); } } static void elf_print_symtab(Elf32_Ehdr *e, void *sh, char *str) { u_int64_t offset; u_int64_t entsize; u_int64_t size; u_int64_t name; u_int64_t value; u_int64_t info; u_int64_t shndx; void *st; int len; int i; offset = elf_get_off(e, sh, SH_OFFSET); entsize = elf_get_size(e, sh, SH_ENTSIZE); size = elf_get_size(e, sh, SH_SIZE); name = elf_get_word(e, sh, SH_NAME); len = size / entsize; fprintf(out, "\nsymbol table (%s):\n", shstrtab + name); for (i = 0; i < len; i++) { st = (char *)e + offset + i * entsize; name = elf_get_word(e, st, ST_NAME); value = elf_get_addr(e, st, ST_VALUE); size = elf_get_size(e, st, ST_SIZE); info = elf_get_byte(e, st, ST_INFO); shndx = elf_get_quarter(e, st, ST_SHNDX); fprintf(out, "\n"); fprintf(out, "entry: %d\n", i); fprintf(out, "\tst_name: %s\n", str + name); fprintf(out, "\tst_value: %#jx\n", value); fprintf(out, "\tst_size: %jd\n", (intmax_t)size); fprintf(out, "\tst_info: %s %s\n", st_types[ELF32_ST_TYPE(info)], st_bindings[ELF32_ST_BIND(info)]); fprintf(out, "\tst_shndx: %jd\n", (intmax_t)shndx); } } static void elf_print_dynamic(Elf32_Ehdr *e, void *sh) { u_int64_t offset; u_int64_t entsize; u_int64_t size; int64_t tag; u_int64_t ptr; u_int64_t val; void *d; int i; offset = elf_get_off(e, sh, SH_OFFSET); entsize = elf_get_size(e, sh, SH_ENTSIZE); size = elf_get_size(e, sh, SH_SIZE); fprintf(out, "\ndynamic:\n"); for (i = 0; (u_int64_t)i < size / entsize; i++) { d = (char *)e + offset + i * entsize; tag = elf_get_size(e, d, D_TAG); ptr = elf_get_size(e, d, D_PTR); val = elf_get_addr(e, d, D_VAL); fprintf(out, "\n"); fprintf(out, "entry: %d\n", i); fprintf(out, "\td_tag: %s\n", d_tags(tag)); switch (tag) { case DT_NEEDED: case DT_SONAME: case DT_RPATH: fprintf(out, "\td_val: %s\n", dynstr + val); break; case DT_PLTRELSZ: case DT_RELA: case DT_RELASZ: case DT_RELAENT: case DT_STRSZ: case DT_SYMENT: case DT_RELSZ: case DT_RELENT: case DT_PLTREL: fprintf(out, "\td_val: %jd\n", (intmax_t)val); break; case DT_PLTGOT: case DT_HASH: case DT_STRTAB: case DT_SYMTAB: case DT_INIT: case DT_FINI: case DT_REL: case DT_JMPREL: fprintf(out, "\td_ptr: %#jx\n", ptr); break; case DT_NULL: case DT_SYMBOLIC: case DT_DEBUG: case DT_TEXTREL: break; } } } static void elf_print_rela(Elf32_Ehdr *e, void *sh) { u_int64_t offset; u_int64_t entsize; u_int64_t size; u_int64_t name; u_int64_t info; int64_t addend; void *ra; void *v; int i; offset = elf_get_off(e, sh, SH_OFFSET); entsize = elf_get_size(e, sh, SH_ENTSIZE); size = elf_get_size(e, sh, SH_SIZE); name = elf_get_word(e, sh, SH_NAME); v = (char *)e + offset; fprintf(out, "\nrelocation with addend (%s):\n", shstrtab + name); for (i = 0; (u_int64_t)i < size / entsize; i++) { ra = (char *)v + i * entsize; offset = elf_get_addr(e, ra, RA_OFFSET); info = elf_get_word(e, ra, RA_INFO); addend = elf_get_off(e, ra, RA_ADDEND); fprintf(out, "\n"); fprintf(out, "entry: %d\n", i); fprintf(out, "\tr_offset: %#jx\n", offset); fprintf(out, "\tr_info: %jd\n", (intmax_t)info); fprintf(out, "\tr_addend: %jd\n", (intmax_t)addend); } } static void elf_print_rel(Elf32_Ehdr *e, void *sh) { u_int64_t offset; u_int64_t entsize; u_int64_t size; u_int64_t name; u_int64_t info; void *r; void *v; int i; offset = elf_get_off(e, sh, SH_OFFSET); entsize = elf_get_size(e, sh, SH_ENTSIZE); size = elf_get_size(e, sh, SH_SIZE); name = elf_get_word(e, sh, SH_NAME); v = (char *)e + offset; fprintf(out, "\nrelocation (%s):\n", shstrtab + name); for (i = 0; (u_int64_t)i < size / entsize; i++) { r = (char *)v + i * entsize; offset = elf_get_addr(e, r, R_OFFSET); info = elf_get_word(e, r, R_INFO); fprintf(out, "\n"); fprintf(out, "entry: %d\n", i); fprintf(out, "\tr_offset: %#jx\n", offset); fprintf(out, "\tr_info: %jd\n", (intmax_t)info); } } static void elf_print_interp(Elf32_Ehdr *e, void *p) { u_int64_t offset; char *s; offset = elf_get_off(e, p, P_OFFSET); s = (char *)e + offset; fprintf(out, "\ninterp:\n"); fprintf(out, "\t%s\n", s); } static void elf_print_got(Elf32_Ehdr *e, void *sh) { u_int64_t offset; u_int64_t addralign; u_int64_t size; u_int64_t addr; void *v; int i; offset = elf_get_off(e, sh, SH_OFFSET); addralign = elf_get_size(e, sh, SH_ADDRALIGN); size = elf_get_size(e, sh, SH_SIZE); v = (char *)e + offset; fprintf(out, "\nglobal offset table:\n"); for (i = 0; (u_int64_t)i < size / addralign; i++) { addr = elf_get_addr(e, (char *)v + i * addralign, 0); fprintf(out, "\n"); fprintf(out, "entry: %d\n", i); fprintf(out, "\t%#jx\n", addr); } } static void elf_print_hash(Elf32_Ehdr *e __unused, void *sh __unused) { } static void elf_print_note(Elf32_Ehdr *e, void *sh) { u_int64_t offset; u_int64_t size; u_int64_t name; u_int32_t namesz; u_int32_t descsz; u_int32_t desc; char *n, *s; offset = elf_get_off(e, sh, SH_OFFSET); size = elf_get_size(e, sh, SH_SIZE); name = elf_get_word(e, sh, SH_NAME); n = (char *)e + offset; fprintf(out, "\nnote (%s):\n", shstrtab + name); while (n < ((char *)e + offset + size)) { namesz = elf_get_word(e, n, N_NAMESZ); descsz = elf_get_word(e, n, N_DESCSZ); s = n + sizeof(Elf_Note); desc = elf_get_word(e, n + sizeof(Elf_Note) + namesz, 0); fprintf(out, "\t%s %d\n", s, desc); n += sizeof(Elf_Note) + namesz + descsz; } } static u_int64_t elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member) { u_int64_t val; val = 0; switch (e->e_ident[EI_CLASS]) { case ELFCLASS32: val = ((uint8_t *)base)[elf32_offsets[member]]; break; case ELFCLASS64: val = ((uint8_t *)base)[elf64_offsets[member]]; break; case ELFCLASSNONE: errx(1, "invalid class"); } return val; } static u_int64_t elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member) { u_int64_t val; val = 0; switch (e->e_ident[EI_CLASS]) { case ELFCLASS32: base = (char *)base + elf32_offsets[member]; switch (e->e_ident[EI_DATA]) { case ELFDATA2MSB: val = be16dec(base); break; case ELFDATA2LSB: val = le16dec(base); break; case ELFDATANONE: errx(1, "invalid data format"); } break; case ELFCLASS64: base = (char *)base + elf64_offsets[member]; switch (e->e_ident[EI_DATA]) { case ELFDATA2MSB: val = be16dec(base); break; case ELFDATA2LSB: val = le16dec(base); break; case ELFDATANONE: errx(1, "invalid data format"); } break; case ELFCLASSNONE: errx(1, "invalid class"); } return val; } #if 0 static u_int64_t elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member) { u_int64_t val; val = 0; switch (e->e_ident[EI_CLASS]) { case ELFCLASS32: base = (char *)base + elf32_offsets[member]; switch (e->e_ident[EI_DATA]) { case ELFDATA2MSB: val = be16dec(base); break; case ELFDATA2LSB: val = le16dec(base); break; case ELFDATANONE: errx(1, "invalid data format"); } break; case ELFCLASS64: base = (char *)base + elf64_offsets[member]; switch (e->e_ident[EI_DATA]) { case ELFDATA2MSB: val = be32dec(base); break; case ELFDATA2LSB: val = le32dec(base); break; case ELFDATANONE: errx(1, "invalid data format"); } break; case ELFCLASSNONE: errx(1, "invalid class"); } return val; } #endif static u_int64_t elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member) { u_int64_t val; val = 0; switch (e->e_ident[EI_CLASS]) { case ELFCLASS32: base = (char *)base + elf32_offsets[member]; switch (e->e_ident[EI_DATA]) { case ELFDATA2MSB: val = be32dec(base); break; case ELFDATA2LSB: val = le32dec(base); break; case ELFDATANONE: errx(1, "invalid data format"); } break; case ELFCLASS64: base = (char *)base + elf64_offsets[member]; switch (e->e_ident[EI_DATA]) { case ELFDATA2MSB: val = be32dec(base); break; case ELFDATA2LSB: val = le32dec(base); break; case ELFDATANONE: errx(1, "invalid data format"); } break; case ELFCLASSNONE: errx(1, "invalid class"); } return val; } static u_int64_t elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member) { u_int64_t val; val = 0; switch (e->e_ident[EI_CLASS]) { case ELFCLASS32: base = (char *)base + elf32_offsets[member]; switch (e->e_ident[EI_DATA]) { case ELFDATA2MSB: val = be32dec(base); break; case ELFDATA2LSB: val = le32dec(base); break; case ELFDATANONE: errx(1, "invalid data format"); } break; case ELFCLASS64: base = (char *)base + elf64_offsets[member]; switch (e->e_ident[EI_DATA]) { case ELFDATA2MSB: val = be64dec(base); break; case ELFDATA2LSB: val = le64dec(base); break; case ELFDATANONE: errx(1, "invalid data format"); } break; case ELFCLASSNONE: errx(1, "invalid class"); } return val; } static void usage(void) { fprintf(stderr, "usage: elfdump -a | -cdeGhinprs [-w file] file\n"); exit(1); } freebsd-buildutils-10.0/src/usr.bin/elfdump/Makefile0000644000000000000000000000006311317617571017363 0ustar # $FreeBSD$ PROG= elfdump .include freebsd-buildutils-10.0/src/usr.bin/elfdump/elfdump.10000644000000000000000000000524211324110522017423 0ustar .\" Copyright (c) 2003 David O'Brien .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" .Dd January 15, 2003 .Dt ELFDUMP 1 .Os .Sh NAME .Nm elfdump .Nd "display information about" .Tn ELF files .Sh SYNOPSIS .Nm .Fl a | cdeGhinprs .Op Fl w Ar file .Ar file .Sh DESCRIPTION The .Nm utility dumps various information about the specified .Tn ELF .Ar file . .Pp The options are as follows: .Bl -tag -width ".Fl w Ar file" .It Fl a Dump all information. .It Fl c Dump shared headers. .It Fl d Dump dynamic symbols. .It Fl e Dump ELF header. .It Fl G Dump the GOT. .It Fl h Dump the hash values. .It Fl i Dump the dynamic interpreter. .It Fl n Dump note sections. .It Fl p Dump the program header. .It Fl r Dump relocations. .It Fl s Dump the symbol table. .It Fl w Ar file Write output to a .Ar file instead of the standard output. .El .Sh EXIT STATUS .Ex -std .Sh EXAMPLES The following is an example of a typical usage of the .Nm command: .Pp .Dl "elfdump -a -w output /bin/ls" .Sh SEE ALSO .Xr objdump 1 , .Xr readelf 1 .Rs .%A "AT&T Unix Systems Labs" .%T "System V Application Binary Interface" .%U http://www.sco.com/developers/gabi/ .Re .Sh HISTORY The .Nm utility first appeared in .Fx 5.0 . .Sh AUTHORS .An -nosplit The .Nm utility was written by .An Jake Burkholder Aq jake@FreeBSD.org . This manual page was written by .An David O'Brien Aq obrien@FreeBSD.org . .Sh BUGS Does not fully implement the .Tn ELF gABI. freebsd-buildutils-10.0/src/usr.bin/lex/0000755000000000000000000000000012265500112015041 5ustar freebsd-buildutils-10.0/src/usr.bin/lex/version.awk0000644000000000000000000000034312146745723017253 0ustar # $FreeBSD$ BEGIN { FS = "[ \t\.\"]+" } { if ($1 ~ /^#define$/ && $2 ~ /^VERSION$/) { printf("-DFLEX_MAJOR_VERSION=%s\n", $3); printf("-DFLEX_MINOR_VERSION=%s\n", $4); printf("-DFLEX_SUBMINOR_VERSION=%s\n", $5); } } freebsd-buildutils-10.0/src/usr.bin/lex/initskel.c0000644000000000000000000035010112146745723017050 0ustar /* $FreeBSD$ */ /* File created from flex.skl via mkskel.sh */ #include "flexdef.h" const char *skel[] = { "%# -*-C-*- vi: set ft=c:", "%# This file is processed in several stages.", "%# Here are the stages, as best as I can describe:", "%#", "%# 1. flex.skl is processed through GNU m4 during the", "%# pre-compilation stage of flex. Only macros starting", "%# with `m4_' are processed, and quoting is normal.", "%#", "%# 2. The preprocessed skeleton is translated verbatim into a", "%# C array, saved as \"skel.c\" and compiled into the flex binary.", "%#", "%# 3. At runtime, the skeleton is generated and filtered (again)", "%# through m4. Macros beginning with `m4_' will be processed.", "%# The quoting is \"[[\" and \"]]\" so we don't interfere with", "%# user code.", "%# ", "%# All generate macros for the m4 stage contain the text \"m4\" or \"M4\"", "%# in them. This is to distinguish them from CPP macros.", "%# The exception to this rule is YY_G, which is an m4 macro, ", "%# but it needs to be remain short because it is used everywhere.", "%#", "/* A lexical scanner generated by flex */", "", "%# Macros for preproc stage.", "", "", "%# Macros for runtime processing stage.", "m4_changecom", "m4_changequote", "m4_changequote([[, ]])", "", "%# ", "%# Lines in this skeleton starting with a \"%\" character are \"control lines\"", "%# and affect the generation of the scanner. The possible control codes are", "%# listed and processed in misc.c.", "%#", "%# %# - A comment. The current line is omitted from the generated scanner.", "%# %if-c++-only - The following lines are printed for C++ scanners ONLY.", "%# %if-c-only - The following lines are NOT printed for C++ scanners.", "%# %if-c-or-c++ - The following lines are printed in BOTH C and C++ scanners.", "%# %if-reentrant - Print for reentrant scanners.(push)", "%# %if-not-reentrant - Print for non-reentrant scanners. (push)", "%# %if-bison-bridge - Print for bison-bridge. (push)", "%# %if-not-bison-bridge - Print for non-bison-bridge. (push)", "%# %endif - pop from the previous if code.", "%# %% - A stop-point, where code is inserted by flex.", "%# Each stop-point is numbered here and also in the code generator.", "%# (See gen.c, etc. for details.)", "%# %not-for-header - Begin code that should NOT appear in a \".h\" file.", "%# %ok-for-header - %c and %e are used for building a header file.", "%# %if-tables-serialization", "%#", "%# All control-lines EXCEPT comment lines (\"%#\") will be inserted into", "%# the generated scanner as a C-style comment. This is to aid those who", "%# edit the skeleton.", "%#", "", "%not-for-header", "%if-c-only", "%if-not-reentrant", "m4_ifelse(M4_YY_PREFIX,yy,,", "#define yy_create_buffer M4_YY_PREFIX[[_create_buffer]]", "#define yy_delete_buffer M4_YY_PREFIX[[_delete_buffer]]", "#define yy_flex_debug M4_YY_PREFIX[[_flex_debug]]", "#define yy_init_buffer M4_YY_PREFIX[[_init_buffer]]", "#define yy_flush_buffer M4_YY_PREFIX[[_flush_buffer]]", "#define yy_load_buffer_state M4_YY_PREFIX[[_load_buffer_state]]", "#define yy_switch_to_buffer M4_YY_PREFIX[[_switch_to_buffer]]", "#define yyin M4_YY_PREFIX[[in]]", "#define yyleng M4_YY_PREFIX[[leng]]", "#define yylex M4_YY_PREFIX[[lex]]", "#define yylineno M4_YY_PREFIX[[lineno]]", "#define yyout M4_YY_PREFIX[[out]]", "#define yyrestart M4_YY_PREFIX[[restart]]", "#define yytext M4_YY_PREFIX[[text]]", "#define yywrap M4_YY_PREFIX[[wrap]]", "#define yyalloc M4_YY_PREFIX[[alloc]]", "#define yyrealloc M4_YY_PREFIX[[realloc]]", "#define yyfree M4_YY_PREFIX[[free]]", ")", "%endif", "%endif", "%ok-for-header", "", "#define FLEX_SCANNER", "#define YY_FLEX_MAJOR_VERSION 2", "#define YY_FLEX_MINOR_VERSION 5", "#define YY_FLEX_SUBMINOR_VERSION 37", "#if YY_FLEX_SUBMINOR_VERSION > 0", "#define FLEX_BETA", "#endif", "", "%# Some negated symbols", "m4_ifdef( [[M4_YY_IN_HEADER]], , [[m4_define([[M4_YY_NOT_IN_HEADER]], [[]])]])", "m4_ifdef( [[M4_YY_REENTRANT]], , [[m4_define([[M4_YY_NOT_REENTRANT]], [[]])]])", "", "%# This is the m4 way to say \"(stack_used || is_reentrant)", "m4_ifdef( [[M4_YY_STACK_USED]], [[m4_define([[M4_YY_HAS_START_STACK_VARS]])]])", "m4_ifdef( [[M4_YY_REENTRANT]], [[m4_define([[M4_YY_HAS_START_STACK_VARS]])]])", "", "%# Prefixes.", "%# The complexity here is necessary so that m4 preserves", "%# the argument lists to each C function.", "", "", "m4_ifdef( [[M4_YY_PREFIX]],, [[m4_define([[M4_YY_PREFIX]], [[yy]])]])", "", "", "", "%if-c++-only", " /* The c++ scanner is a mess. The FlexLexer.h header file relies on the", " * following macro. This is required in order to pass the c++-multiple-scanners", " * test in the regression suite. We get reports that it breaks inheritance.", " * We will address this in a future release of flex, or omit the C++ scanner", " * altogether.", " */", " #define yyFlexLexer M4_YY_PREFIX[[FlexLexer]]", "%endif", "", "%if-c-only", " m4_define(yy[[_create_buffer]], [[M4_YY_PREFIX[[_create_buffer]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[_delete_buffer]], [[M4_YY_PREFIX[[_delete_buffer]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[_scan_buffer]], [[M4_YY_PREFIX[[_scan_buffer]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[_scan_string]], [[M4_YY_PREFIX[[_scan_string]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[_scan_bytes]], [[M4_YY_PREFIX[[_scan_bytes]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[_init_buffer]], [[M4_YY_PREFIX[[_init_buffer]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[_flush_buffer]], [[M4_YY_PREFIX[[_flush_buffer]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[_load_buffer_state]], [[M4_YY_PREFIX[[_load_buffer_state]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[_switch_to_buffer]], [[M4_YY_PREFIX[[_switch_to_buffer]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[push_buffer_state]], [[M4_YY_PREFIX[[push_buffer_state]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[pop_buffer_state]], [[M4_YY_PREFIX[[pop_buffer_state]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[ensure_buffer_stack]], [[M4_YY_PREFIX[[ensure_buffer_stack]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[lex]], [[M4_YY_PREFIX[[lex]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[restart]], [[M4_YY_PREFIX[[restart]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[lex_init]], [[M4_YY_PREFIX[[lex_init]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[lex_init_extra]], [[M4_YY_PREFIX[[lex_init_extra]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[lex_destroy]], [[M4_YY_PREFIX[[lex_destroy]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[get_debug]], [[M4_YY_PREFIX[[get_debug]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[set_debug]], [[M4_YY_PREFIX[[set_debug]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[get_extra]], [[M4_YY_PREFIX[[get_extra]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[set_extra]], [[M4_YY_PREFIX[[set_extra]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[get_in]], [[M4_YY_PREFIX[[get_in]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[set_in]], [[M4_YY_PREFIX[[set_in]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[get_out]], [[M4_YY_PREFIX[[get_out]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[set_out]], [[M4_YY_PREFIX[[set_out]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[get_leng]], [[M4_YY_PREFIX[[get_leng]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[get_text]], [[M4_YY_PREFIX[[get_text]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[get_lineno]], [[M4_YY_PREFIX[[get_lineno]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[set_lineno]], [[M4_YY_PREFIX[[set_lineno]]m4_ifelse($#,0,,[[($@)]])]])", " m4_ifdef( [[M4_YY_REENTRANT]],", " [[", " m4_define(yy[[get_column]], [[M4_YY_PREFIX[[get_column]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[set_column]], [[M4_YY_PREFIX[[set_column]]m4_ifelse($#,0,,[[($@)]])]])", " ]])", " m4_define(yy[[wrap]], [[M4_YY_PREFIX[[wrap]]m4_ifelse($#,0,,[[($@)]])]])", "%endif", "", "m4_ifdef( [[M4_YY_BISON_LVAL]],", "[[", " m4_define(yy[[get_lval]], [[M4_YY_PREFIX[[get_lval]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[set_lval]], [[M4_YY_PREFIX[[set_lval]]m4_ifelse($#,0,,[[($@)]])]])", "]])", "", "m4_ifdef( [[]],", "[[", " m4_define(yy[[get_lloc]], [[M4_YY_PREFIX[[get_lloc]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[set_lloc]], [[M4_YY_PREFIX[[set_lloc]]m4_ifelse($#,0,,[[($@)]])]])", "]])", "", "", " m4_define(yy[[alloc]], [[M4_YY_PREFIX[[alloc]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[realloc]], [[M4_YY_PREFIX[[realloc]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[free]], [[M4_YY_PREFIX[[free]]m4_ifelse($#,0,,[[($@)]])]])", "", "%if-c-only", "m4_ifdef( [[M4_YY_NOT_REENTRANT]],", "[[", " m4_define(yy[[text]], [[M4_YY_PREFIX[[text]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[leng]], [[M4_YY_PREFIX[[leng]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[in]], [[M4_YY_PREFIX[[in]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[out]], [[M4_YY_PREFIX[[out]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[_flex_debug]], [[M4_YY_PREFIX[[_flex_debug]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[lineno]], [[M4_YY_PREFIX[[lineno]]m4_ifelse($#,0,,[[($@)]])]])", "]])", "%endif", "", "", "m4_ifdef( [[M4_YY_TABLES_EXTERNAL]],", "[[", " m4_define(yy[[tables_fload]], [[M4_YY_PREFIX[[tables_fload]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[tables_destroy]], [[M4_YY_PREFIX[[tables_destroy]]m4_ifelse($#,0,,[[($@)]])]])", " m4_define(yy[[TABLES_NAME]], [[M4_YY_PREFIX[[TABLES_NAME]]m4_ifelse($#,0,,[[($@)]])]])", "]])", "", "/* First, we deal with platform-specific or compiler-specific issues. */", "", "#if defined(__FreeBSD__)", "#ifndef __STDC_LIMIT_MACROS", "#define __STDC_LIMIT_MACROS", "#endif", "#include ", "#include ", "#else", "#define __dead2", "#endif", "", "/* begin standard C headers. */", "%if-c-only", "#include ", "#include ", "#include ", "#include ", "%endif", "", "%if-tables-serialization", "#include ", "#include ", "%endif", "/* end standard C headers. */", "", "%if-c-or-c++", "/* flex integer type definitions */", "", "#ifndef FLEXINT_H", "#define FLEXINT_H", "", "/* C99 systems have . Non-C99 systems may or may not. */", "", "#if defined(__FreeBSD__) || \\", " (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)", "", "/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,", " * if you want the limit (max/min) macros for int types. ", " */", "#ifndef __STDC_LIMIT_MACROS", "#define __STDC_LIMIT_MACROS 1", "#endif", "", "#include ", "typedef int8_t flex_int8_t;", "typedef uint8_t flex_uint8_t;", "typedef int16_t flex_int16_t;", "typedef uint16_t flex_uint16_t;", "typedef int32_t flex_int32_t;", "typedef uint32_t flex_uint32_t;", "#else", "typedef signed char flex_int8_t;", "typedef short int flex_int16_t;", "typedef int flex_int32_t;", "typedef unsigned char flex_uint8_t; ", "typedef unsigned short int flex_uint16_t;", "typedef unsigned int flex_uint32_t;", "", "/* Limits of integral types. */", "#ifndef INT8_MIN", "#define INT8_MIN (-128)", "#endif", "#ifndef INT16_MIN", "#define INT16_MIN (-32767-1)", "#endif", "#ifndef INT32_MIN", "#define INT32_MIN (-2147483647-1)", "#endif", "#ifndef INT8_MAX", "#define INT8_MAX (127)", "#endif", "#ifndef INT16_MAX", "#define INT16_MAX (32767)", "#endif", "#ifndef INT32_MAX", "#define INT32_MAX (2147483647)", "#endif", "#ifndef UINT8_MAX", "#define UINT8_MAX (255U)", "#endif", "#ifndef UINT16_MAX", "#define UINT16_MAX (65535U)", "#endif", "#ifndef UINT32_MAX", "#define UINT32_MAX (4294967295U)", "#endif", "", "#endif /* ! C99 */", "", "#endif /* ! FLEXINT_H */", "", "%endif", "", "%if-c++-only", "/* begin standard C++ headers. */", "#include ", "#include ", "#include ", "#include ", "#include ", "/* end standard C++ headers. */", "%endif", "", "#ifdef __cplusplus", "", "/* The \"const\" storage-class-modifier is valid. */", "#define YY_USE_CONST", "", "#else /* ! __cplusplus */", "", "/* C99 requires __STDC__ to be defined as 1. */", "#if defined (__STDC__)", "", "#define YY_USE_CONST", "", "#endif /* defined (__STDC__) */", "#endif /* ! __cplusplus */", "", "#ifdef YY_USE_CONST", "#define yyconst const", "#else", "#define yyconst", "#endif", "", "%# For compilers that can not handle prototypes.", "%# e.g.,", "%# The function prototype", "%# int foo(int x, char* y);", "%# ", "%# ...should be written as", "%# int foo M4_YY_PARAMS(int x, char* y);", "%# ", "%# ...which could possibly generate", "%# int foo ();", "%# ", "m4_ifdef( [[M4_YY_NO_ANSI_FUNC_PROTOS]],", "[[", " m4_define( [[M4_YY_PARAMS]], [[()]])", "]],", "[[", " m4_define( [[M4_YY_PARAMS]], [[($*)]])", "]])", "", "%not-for-header", "/* Returned upon end-of-file. */", "#define YY_NULL 0", "%ok-for-header", "", "%not-for-header", "/* Promotes a possibly negative, possibly signed char to an unsigned", " * integer for use as an array index. If the signed char is negative,", " * we want to instead treat it as an 8-bit unsigned char, hence the", " * double cast.", " */", "#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)", "%ok-for-header", "", "", "", "%if-reentrant", "", "/* An opaque pointer. */", "#ifndef YY_TYPEDEF_YY_SCANNER_T", "#define YY_TYPEDEF_YY_SCANNER_T", "typedef void* yyscan_t;", "#endif", "", "%# Declare yyguts variable", "m4_define( [[M4_YY_DECL_GUTS_VAR]], [[struct yyguts_t * yyg = (struct yyguts_t*)yyscanner]])", "%# Perform a noop access on yyguts to prevent unused variable complains", "m4_define( [[M4_YY_NOOP_GUTS_VAR]], [[(void)yyg]])", "%# For use wherever a Global is accessed or assigned.", "m4_define( [[YY_G]], [[yyg->$1]])", "", "%# For use in function prototypes to append the additional argument.", "m4_define( [[M4_YY_PROTO_LAST_ARG]], [[, yyscan_t yyscanner]])", "m4_define( [[M4_YY_PROTO_ONLY_ARG]], [[yyscan_t yyscanner]])", "", "%# For use in function definitions to append the additional argument.", "m4_ifdef( [[M4_YY_NO_ANSI_FUNC_DEFS]],", "[[", " m4_define( [[M4_YY_DEF_LAST_ARG]], [[, yyscanner]])", " m4_define( [[M4_YY_DEF_ONLY_ARG]], [[yyscanner]])", "]],", "[[", " m4_define( [[M4_YY_DEF_LAST_ARG]], [[, yyscan_t yyscanner]])", " m4_define( [[M4_YY_DEF_ONLY_ARG]], [[yyscan_t yyscanner]])", "]])", "m4_define( [[M4_YY_DECL_LAST_ARG]], [[yyscan_t yyscanner;]])", "", "%# For use in function calls to pass the additional argument.", "m4_define( [[M4_YY_CALL_LAST_ARG]], [[, yyscanner]])", "m4_define( [[M4_YY_CALL_ONLY_ARG]], [[yyscanner]])", "", "%# For use in function documentation to adjust for additional argument.", "m4_define( [[M4_YY_DOC_PARAM]], [[@param yyscanner The scanner object.]])", "", "/* For convenience, these vars (plus the bison vars far below)", " are macros in the reentrant scanner. */", "#define yyin YY_G(yyin_r)", "#define yyout YY_G(yyout_r)", "#define yyextra YY_G(yyextra_r)", "#define yyleng YY_G(yyleng_r)", "#define yytext YY_G(yytext_r)", "#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)", "#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)", "#define yy_flex_debug YY_G(yy_flex_debug_r)", "", "m4_define( [[M4_YY_INCR_LINENO]],", "[[ ", " do{ yylineno++;", " yycolumn=0;", " }while(0)", "]])", "", "%endif", "", "", "", "%if-not-reentrant", "", "m4_define( [[M4_YY_INCR_LINENO]],", "[[ ", " yylineno++;", "]])", "", "%# Define these macros to be no-ops.", "m4_define( [[M4_YY_DECL_GUTS_VAR]], [[m4_dnl]])", "m4_define( [[M4_YY_NOOP_GUTS_VAR]], [[m4_dnl]])", "m4_define( [[YY_G]], [[($1)]])", "m4_define( [[M4_YY_PROTO_LAST_ARG]])", "m4_define( [[M4_YY_PROTO_ONLY_ARG]], [[void]])", "m4_define( [[M4_YY_DEF_LAST_ARG]])", "", "m4_ifdef( [[M4_YY_NO_ANSI_FUNC_DEFS]],", "[[", " m4_define( [[M4_YY_DEF_ONLY_ARG]])", "]],", "[[", " m4_define( [[M4_YY_DEF_ONLY_ARG]], [[void]])", "]])", "m4_define([[M4_YY_DECL_LAST_ARG]])", "m4_define([[M4_YY_CALL_LAST_ARG]])", "m4_define([[M4_YY_CALL_ONLY_ARG]])", "m4_define( [[M4_YY_DOC_PARAM]], [[]])", "", "%endif", "", "", "m4_ifdef( [[M4_YY_NO_ANSI_FUNC_DEFS]],", "[[", "%# For compilers that need traditional function definitions.", "%# e.g.,", "%# The function prototype taking 2 arguments", "%# int foo (int x, char* y)", "%#", "%# ...should be written as", "%# int foo YYFARGS2(int,x, char*,y)", "%#", "%# ...which could possibly generate", "%# int foo (x,y,yyscanner)", "%# int x;", "%# char * y;", "%# yyscan_t yyscanner;", "%#", "%# Generate traditional function defs", " m4_define( [[YYFARGS0]], [[(M4_YY_DEF_ONLY_ARG) [[\\]]", " M4_YY_DECL_LAST_ARG]])", " m4_define( [[YYFARGS1]], [[($2 M4_YY_DEF_LAST_ARG) [[\\]]", " $1 $2; [[\\]]", " M4_YY_DECL_LAST_ARG]])", " m4_define( [[YYFARGS2]], [[($2,$4 M4_YY_DEF_LAST_ARG) [[\\]]", " $1 $2; [[\\]]", " $3 $4; [[\\]]", " M4_YY_DECL_LAST_ARG]])", " m4_define( [[YYFARGS3]], [[($2,$4,$6 M4_YY_DEF_LAST_ARG) [[\\]]", " $1 $2; [[\\]]", " $3 $4; [[\\]]", " $5 $6; [[\\]]", " M4_YY_DECL_LAST_ARG]])", "]],", "[[", "%# Generate C99 function defs.", " m4_define( [[YYFARGS0]], [[(M4_YY_DEF_ONLY_ARG)]])", " m4_define( [[YYFARGS1]], [[($1 $2 M4_YY_DEF_LAST_ARG)]])", " m4_define( [[YYFARGS2]], [[($1 $2, $3 $4 M4_YY_DEF_LAST_ARG)]])", " m4_define( [[YYFARGS3]], [[($1 $2, $3 $4, $5 $6 M4_YY_DEF_LAST_ARG)]])", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* Enter a start condition. This macro really ought to take a parameter,", " * but we do it the disgusting crufty way forced on us by the ()-less", " * definition of BEGIN.", " */", "#define BEGIN YY_G(yy_start) = 1 + 2 *", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* Translate the current start state into a value that can be later handed", " * to BEGIN to return to the state. The YYSTATE alias is for lex", " * compatibility.", " */", "#define YY_START ((YY_G(yy_start) - 1) / 2)", "#define YYSTATE YY_START", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* Action number for EOF rule of a given start state. */", "#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* Special action meaning \"start processing a new file\". */", "#define YY_NEW_FILE yyrestart( yyin M4_YY_CALL_LAST_ARG )", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "#define YY_END_OF_BUFFER_CHAR 0", "]])", "", "/* Size of default input buffer. */", "#ifndef YY_BUF_SIZE", "#define YY_BUF_SIZE 16384", "#endif", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* The state buf must be large enough to hold one state per character in the main buffer.", " */", "#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))", "]])", "", "", "#ifndef YY_TYPEDEF_YY_BUFFER_STATE", "#define YY_TYPEDEF_YY_BUFFER_STATE", "typedef struct yy_buffer_state *YY_BUFFER_STATE;", "#endif", "", "#ifndef YY_TYPEDEF_YY_SIZE_T", "#define YY_TYPEDEF_YY_SIZE_T", "typedef size_t yy_size_t;", "#endif", "", "%if-not-reentrant", "extern yy_size_t yyleng;", "%endif", "", "%if-c-only", "%if-not-reentrant", "extern FILE *yyin, *yyout;", "%endif", "%endif", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "#define EOB_ACT_CONTINUE_SCAN 0", "#define EOB_ACT_END_OF_FILE 1", "#define EOB_ACT_LAST_MATCH 2", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", " m4_ifdef( [[M4_YY_USE_LINENO]],", " [[", " /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires", " * access to the local variable yy_act. Since yyless() is a macro, it would break", " * existing scanners that call yyless() from OUTSIDE yylex. ", " * One obvious solution it to make yy_act a global. I tried that, and saw", " * a 5% performance hit in a non-yylineno scanner, because yy_act is", " * normally declared as a register variable-- so it is not worth it.", " */", " #define YY_LESS_LINENO(n) \\", " do { \\", " int yyl;\\", " for ( yyl = n; yyl < yyleng; ++yyl )\\", " if ( yytext[yyl] == '\\n' )\\", " --yylineno;\\", " }while(0)", " ]],", " [[", " #define YY_LESS_LINENO(n)", " ]])", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* Return all but the first \"n\" matched characters back to the input stream. */", "#define yyless(n) \\", " do \\", " { \\", " /* Undo effects of setting up yytext. */ \\", " int yyless_macro_arg = (n); \\", " YY_LESS_LINENO(yyless_macro_arg);\\", " *yy_cp = YY_G(yy_hold_char); \\", " YY_RESTORE_YY_MORE_OFFSET \\", " YY_G(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \\", " YY_DO_BEFORE_ACTION; /* set up yytext again */ \\", " } \\", " while ( 0 )", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "#define unput(c) yyunput( c, YY_G(yytext_ptr) M4_YY_CALL_LAST_ARG )", "]])", "", "#ifndef YY_STRUCT_YY_BUFFER_STATE", "#define YY_STRUCT_YY_BUFFER_STATE", "struct yy_buffer_state", " {", "%if-c-only", " FILE *yy_input_file;", "%endif", "", "%if-c++-only", " std::istream* yy_input_file;", "%endif", "", "", " char *yy_ch_buf; /* input buffer */", " char *yy_buf_pos; /* current position in input buffer */", "", " /* Size of input buffer in bytes, not including room for EOB", " * characters.", " */", " yy_size_t yy_buf_size;", "", " /* Number of characters read into yy_ch_buf, not including EOB", " * characters.", " */", " yy_size_t yy_n_chars;", "", " /* Whether we \"own\" the buffer - i.e., we know we created it,", " * and can realloc() it to grow it, and should free() it to", " * delete it.", " */", " int yy_is_our_buffer;", "", " /* Whether this is an \"interactive\" input source; if so, and", " * if we're using stdio for input, then we want to use getc()", " * instead of fread(), to make sure we stop fetching input after", " * each newline.", " */", " int yy_is_interactive;", "", " /* Whether we're considered to be at the beginning of a line.", " * If so, '^' rules will be active on the next match, otherwise", " * not.", " */", " int yy_at_bol;", "", " int yy_bs_lineno; /**< The line count. */", " int yy_bs_column; /**< The column count. */", " ", "", " /* Whether to try to fill the input buffer when we reach the", " * end of it.", " */", " int yy_fill_buffer;", "", " int yy_buffer_status;", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "#define YY_BUFFER_NEW 0", "#define YY_BUFFER_NORMAL 1", " /* When an EOF's been seen but there's still some text to process", " * then we mark the buffer as YY_EOF_PENDING, to indicate that we", " * shouldn't try reading from the input source any more. We might", " * still have a bunch of tokens to match, though, because of", " * possible backing-up.", " *", " * When we actually see the EOF, we change the status to \"new\"", " * (via yyrestart()), so that the user can continue scanning by", " * just pointing yyin at a new input file.", " */", "#define YY_BUFFER_EOF_PENDING 2", "]])", " };", "#endif /* !YY_STRUCT_YY_BUFFER_STATE */", "", "%if-c-only Standard (non-C++) definition", "%not-for-header", "%if-not-reentrant", "", "/* Stack of input buffers. */", "static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */", "static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */", "static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */", "%endif", "%ok-for-header", "%endif", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* We provide macros for accessing buffer states in case in the", " * future we want to put the buffer states in a more general", " * \"scanner state\".", " *", " * Returns the top of the stack, or NULL.", " */", "#define YY_CURRENT_BUFFER ( YY_G(yy_buffer_stack) \\", " ? YY_G(yy_buffer_stack)[YY_G(yy_buffer_stack_top)] \\", " : NULL)", "#define yy_current_buffer YY_CURRENT_BUFFER", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* Same as previous macro, but useful when we know that the buffer stack is not", " * NULL or when we need an lvalue. For internal use only.", " */", "#define YY_CURRENT_BUFFER_LVALUE YY_G(yy_buffer_stack)[YY_G(yy_buffer_stack_top)]", "]])", "", "%if-c-only Standard (non-C++) definition", "", "%if-not-reentrant", "%not-for-header", "/* yy_hold_char holds the character lost when yytext is formed. */", "static char yy_hold_char;", "static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */", "yy_size_t yyleng;", "", "/* Points to current character in buffer. */", "static char *yy_c_buf_p = (char *) 0;", "static int yy_init = 0; /* whether we need to initialize */", "static int yy_start = 0; /* start state number */", "", "/* Flag which is used to allow yywrap()'s to do buffer switches", " * instead of setting up a fresh yyin. A bit of a hack ...", " */", "static int yy_did_buffer_switch_on_eof;", "%ok-for-header", "%endif", "", "void yyrestart M4_YY_PARAMS( FILE *input_file M4_YY_PROTO_LAST_ARG );", "void yy_switch_to_buffer M4_YY_PARAMS( YY_BUFFER_STATE new_buffer M4_YY_PROTO_LAST_ARG );", "YY_BUFFER_STATE yy_create_buffer M4_YY_PARAMS( FILE *file, int size M4_YY_PROTO_LAST_ARG );", "void yy_delete_buffer M4_YY_PARAMS( YY_BUFFER_STATE b M4_YY_PROTO_LAST_ARG );", "void yy_flush_buffer M4_YY_PARAMS( YY_BUFFER_STATE b M4_YY_PROTO_LAST_ARG );", "void yypush_buffer_state M4_YY_PARAMS( YY_BUFFER_STATE new_buffer M4_YY_PROTO_LAST_ARG );", "void yypop_buffer_state M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "static void yyensure_buffer_stack M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "static void yy_load_buffer_state M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "static void yy_init_buffer M4_YY_PARAMS( YY_BUFFER_STATE b, FILE *file M4_YY_PROTO_LAST_ARG );", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG)", "]])", "", "YY_BUFFER_STATE yy_scan_buffer M4_YY_PARAMS( char *base, yy_size_t size M4_YY_PROTO_LAST_ARG );", "YY_BUFFER_STATE yy_scan_string M4_YY_PARAMS( yyconst char *yy_str M4_YY_PROTO_LAST_ARG );", "YY_BUFFER_STATE yy_scan_bytes M4_YY_PARAMS( yyconst char *bytes, yy_size_t len M4_YY_PROTO_LAST_ARG );", "", "%endif", "", "void *yyalloc M4_YY_PARAMS( yy_size_t M4_YY_PROTO_LAST_ARG );", "void *yyrealloc M4_YY_PARAMS( void *, yy_size_t M4_YY_PROTO_LAST_ARG );", "void yyfree M4_YY_PARAMS( void * M4_YY_PROTO_LAST_ARG );", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "#define yy_new_buffer yy_create_buffer", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "#define yy_set_interactive(is_interactive) \\", " { \\", " if ( ! YY_CURRENT_BUFFER ){ \\", " yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG); \\", " YY_CURRENT_BUFFER_LVALUE = \\", " yy_create_buffer( yyin, YY_BUF_SIZE M4_YY_CALL_LAST_ARG); \\", " } \\", " YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \\", " }", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "#define yy_set_bol(at_bol) \\", " { \\", " if ( ! YY_CURRENT_BUFFER ){\\", " yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG); \\", " YY_CURRENT_BUFFER_LVALUE = \\", " yy_create_buffer( yyin, YY_BUF_SIZE M4_YY_CALL_LAST_ARG); \\", " } \\", " YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \\", " }", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)", "]])", "", "%% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "%% [1.5] DFA", "]])", "", "%if-c-only Standard (non-C++) definition", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "static yy_state_type yy_get_previous_state M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "static yy_state_type yy_try_NUL_trans M4_YY_PARAMS( yy_state_type current_state M4_YY_PROTO_LAST_ARG);", "static int yy_get_next_buffer M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "static void yy_fatal_error M4_YY_PARAMS( yyconst char msg[] M4_YY_PROTO_LAST_ARG ) __dead2;", "]])", "", "%endif", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* Done after the current pattern has been matched and before the", " * corresponding action - sets up yytext.", " */", "#define YY_DO_BEFORE_ACTION \\", " YY_G(yytext_ptr) = yy_bp; \\", "%% [2.0] code to fiddle yytext and yyleng for yymore() goes here \\", " YY_G(yy_hold_char) = *yy_cp; \\", " *yy_cp = '\\0'; \\", "%% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \\", " YY_G(yy_c_buf_p) = yy_cp;", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "%% [4.0] data tables for the DFA and the user's section 1 definitions go here", "]])", "", "m4_ifdef( [[M4_YY_IN_HEADER]], [[#ifdef YY_HEADER_EXPORT_START_CONDITIONS]])", "M4_YY_SC_DEFS", "m4_ifdef( [[M4_YY_IN_HEADER]], [[#endif]])", "", "m4_ifdef( [[M4_YY_NO_UNISTD_H]],,", "[[", "#ifndef YY_NO_UNISTD_H", "/* Special case for \"unistd.h\", since it is non-ANSI. We include it way", " * down here because we want the user's section 1 to have been scanned first.", " * The user has a chance to override it with an option.", " */", "%if-c-only", "#include ", "%endif", "%if-c++-only", "#include ", "%endif", "#endif", "]])", "", "m4_ifdef( [[M4_EXTRA_TYPE_DEFS]],", "[[", "#define YY_EXTRA_TYPE M4_EXTRA_TYPE_DEFS", "]],", "[[", "#ifndef YY_EXTRA_TYPE", "#define YY_EXTRA_TYPE void *", "#endif", "]]", ")", "", "%if-c-only Reentrant structure and macros (non-C++).", "%if-reentrant", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* Holds the entire state of the reentrant scanner. */", "struct yyguts_t", " {", "", " /* User-defined. Not touched by flex. */", " YY_EXTRA_TYPE yyextra_r;", "", " /* The rest are the same as the globals declared in the non-reentrant scanner. */", " FILE *yyin_r, *yyout_r;", " size_t yy_buffer_stack_top; /**< index of top of stack. */", " size_t yy_buffer_stack_max; /**< capacity of stack. */", " YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */", " char yy_hold_char;", " yy_size_t yy_n_chars;", " yy_size_t yyleng_r;", " char *yy_c_buf_p;", " int yy_init;", " int yy_start;", " int yy_did_buffer_switch_on_eof;", " int yy_start_stack_ptr;", " int yy_start_stack_depth;", " int *yy_start_stack;", " yy_state_type yy_last_accepting_state;", " char* yy_last_accepting_cpos;", "", " int yylineno_r;", " int yy_flex_debug_r;", "", "m4_ifdef( [[M4_YY_USES_REJECT]],", "[[", " yy_state_type *yy_state_buf;", " yy_state_type *yy_state_ptr;", " char *yy_full_match;", " int yy_lp;", "", " /* These are only needed for trailing context rules,", " * but there's no conditional variable for that yet. */", " int yy_looking_for_trail_begin;", " int yy_full_lp;", " int *yy_full_state;", "]])", "", "m4_ifdef( [[M4_YY_TEXT_IS_ARRAY]],", "[[", " char yytext_r[YYLMAX];", " char *yytext_ptr;", " int yy_more_offset;", " int yy_prev_more_offset;", "]],", "[[", " char *yytext_r;", " int yy_more_flag;", " int yy_more_len;", "]])", "", "m4_ifdef( [[M4_YY_BISON_LVAL]],", "[[", " YYSTYPE * yylval_r;", "]])", "", "m4_ifdef( [[]],", "[[", " YYLTYPE * yylloc_r;", "]])", "", " }; /* end struct yyguts_t */", "]])", "", "", "%if-c-only", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "static int yy_init_globals M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "]])", "%endif", "", "%if-reentrant", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", " m4_ifdef( [[M4_YY_BISON_LVAL]],", " [[", " /* This must go here because YYSTYPE and YYLTYPE are included", " * from bison output in section 1.*/", " # define yylval YY_G(yylval_r)", " ]])", "", " m4_ifdef( [[]],", " [[", " # define yylloc YY_G(yylloc_r)", " ]])", "]])", "", "int yylex_init M4_YY_PARAMS(yyscan_t* scanner);", "", "int yylex_init_extra M4_YY_PARAMS( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);", "", "%endif", "", "%endif End reentrant structures and macros.", "", "/* Accessor methods to globals.", " These are made visible to non-reentrant scanners for convenience. */", "", "m4_ifdef( [[M4_YY_NO_DESTROY]],,", "[[", "int yylex_destroy M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "]])", "", "m4_ifdef( [[M4_YY_NO_GET_DEBUG]],,", "[[", "int yyget_debug M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "]])", "", "m4_ifdef( [[M4_YY_NO_SET_DEBUG]],,", "[[", "void yyset_debug M4_YY_PARAMS( int debug_flag M4_YY_PROTO_LAST_ARG );", "]])", "", "m4_ifdef( [[M4_YY_NO_GET_EXTRA]],,", "[[", "YY_EXTRA_TYPE yyget_extra M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "]])", "", "m4_ifdef( [[M4_YY_NO_SET_EXTRA]],,", "[[", "void yyset_extra M4_YY_PARAMS( YY_EXTRA_TYPE user_defined M4_YY_PROTO_LAST_ARG );", "]])", "", "m4_ifdef( [[M4_YY_NO_GET_IN]],,", "[[", "FILE *yyget_in M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "]])", "", "m4_ifdef( [[M4_YY_NO_SET_IN]],,", "[[", "void yyset_in M4_YY_PARAMS( FILE * in_str M4_YY_PROTO_LAST_ARG );", "]])", "", "m4_ifdef( [[M4_YY_NO_GET_OUT]],,", "[[", "FILE *yyget_out M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "]])", "", "m4_ifdef( [[M4_YY_NO_SET_OUT]],,", "[[", "void yyset_out M4_YY_PARAMS( FILE * out_str M4_YY_PROTO_LAST_ARG );", "]])", "", "m4_ifdef( [[M4_YY_NO_GET_LENG]],,", "[[", "yy_size_t yyget_leng M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "]])", "", "m4_ifdef( [[M4_YY_NO_GET_TEXT]],,", "[[", "char *yyget_text M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "]])", "", "m4_ifdef( [[M4_YY_NO_GET_LINENO]],,", "[[", "int yyget_lineno M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "]])", "", "m4_ifdef( [[M4_YY_NO_SET_LINENO]],,", "[[", "void yyset_lineno M4_YY_PARAMS( int line_number M4_YY_PROTO_LAST_ARG );", "]])", "", "m4_ifdef( [[M4_YY_REENTRANT]],", "[[", "m4_ifdef( [[M4_YY_NO_GET_COLUMN]],,", "[[", "int yyget_column M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "]])", "]])", "", "m4_ifdef( [[M4_YY_REENTRANT]],", "[[", "m4_ifdef( [[M4_YY_NO_SET_COLUMN]],,", "[[", "void yyset_column M4_YY_PARAMS( int column_no M4_YY_PROTO_LAST_ARG );", "]])", "]])", "", "%if-bison-bridge", "m4_ifdef( [[M4_YY_NO_GET_LVAL]],,", "[[", "YYSTYPE * yyget_lval M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "]])", "", "void yyset_lval M4_YY_PARAMS( YYSTYPE * yylval_param M4_YY_PROTO_LAST_ARG );", "", "m4_ifdef( [[]],", "[[", " m4_ifdef( [[M4_YY_NO_GET_LLOC]],,", " [[", " YYLTYPE *yyget_lloc M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", " ]])", "", " m4_ifdef( [[M4_YY_NO_SET_LLOC]],,", " [[", " void yyset_lloc M4_YY_PARAMS( YYLTYPE * yylloc_param M4_YY_PROTO_LAST_ARG );", " ]])", "]])", "%endif", "", "/* Macros after this point can all be overridden by user definitions in", " * section 1.", " */", "", "#ifndef YY_SKIP_YYWRAP", "#ifdef __cplusplus", "extern \"C\" int yywrap M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "#else", "extern int yywrap M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "#endif", "#endif", "", "%not-for-header", " m4_ifdef( [[M4_YY_NO_UNPUT]],,", " [[", "#ifndef YY_NO_UNPUT", " static void yyunput M4_YY_PARAMS( int c, char *buf_ptr M4_YY_PROTO_LAST_ARG);", "#endif", " ]])", "%ok-for-header", "%endif", "", "#ifndef yytext_ptr", "static void yy_flex_strncpy M4_YY_PARAMS( char *, yyconst char *, int M4_YY_PROTO_LAST_ARG);", "#endif", "", "#ifdef YY_NEED_STRLEN", "static int yy_flex_strlen M4_YY_PARAMS( yyconst char * M4_YY_PROTO_LAST_ARG);", "#endif", "", "#ifndef YY_NO_INPUT", "%if-c-only Standard (non-C++) definition", "%not-for-header", "#ifdef __cplusplus", "static int yyinput M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "#else", "static int input M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", "#endif", "%ok-for-header", "%endif", "#endif", "", "", "%if-c-only", "%# TODO: This is messy.", "m4_ifdef( [[M4_YY_STACK_USED]],", "[[", "", "m4_ifdef( [[M4_YY_NOT_REENTRANT]],", "[[", " m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", " [[", " static int yy_start_stack_ptr = 0;", " static int yy_start_stack_depth = 0;", " static int *yy_start_stack = NULL;", " ]])", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", " m4_ifdef( [[M4_YY_NO_PUSH_STATE]],,", " [[", " static void yy_push_state M4_YY_PARAMS( int new_state M4_YY_PROTO_LAST_ARG);", " ]])", " m4_ifdef( [[M4_YY_NO_POP_STATE]],,", " [[", " static void yy_pop_state M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", " ]])", " m4_ifdef( [[M4_YY_NO_TOP_STATE]],,", " [[", " static int yy_top_state M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG );", " ]])", "]])", "", "]],", "[[", "m4_define( [[M4_YY_NO_PUSH_STATE]])", "m4_define( [[M4_YY_NO_POP_STATE]])", "m4_define( [[M4_YY_NO_TOP_STATE]])", "]])", "%endif", "", "/* Amount of stuff to slurp up with each read. */", "#ifndef YY_READ_BUF_SIZE", "#define YY_READ_BUF_SIZE 8192", "#endif", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* Copy whatever the last rule matched to the standard output. */", "#ifndef ECHO", "%if-c-only Standard (non-C++) definition", "/* This used to be an fputs(), but since the string might contain NUL's,", " * we now use fwrite().", " */", "#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)", "%endif", "%if-c++-only C++ definition", "#define ECHO LexerOutput( yytext, yyleng )", "%endif", "#endif", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* Gets input and stuffs it into \"buf\". number of characters read, or YY_NULL,", " * is returned in \"result\".", " */", "#ifndef YY_INPUT", "#define YY_INPUT(buf,result,max_size) \\", "%% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \\", "\\", "%if-c++-only C++ definition \\", " if ( (result = LexerInput( (char *) buf, max_size )) < 0 ) \\", " YY_FATAL_ERROR( \"input in flex scanner failed\" );", "%endif", "", "#endif", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* No semi-colon after return; correct usage is to write \"yyterminate();\" -", " * we don't want an extra ';' after the \"return\" because that will cause", " * some compilers to complain about unreachable statements.", " */", "#ifndef yyterminate", "#define yyterminate() return YY_NULL", "#endif", "]])", "", "/* Number of entries by which start-condition stack grows. */", "#ifndef YY_START_STACK_INCR", "#define YY_START_STACK_INCR 25", "#endif", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* Report a fatal error. */", "#ifndef YY_FATAL_ERROR", "%if-c-only", "#define YY_FATAL_ERROR(msg) yy_fatal_error( msg M4_YY_CALL_LAST_ARG)", "%endif", "%if-c++-only", "#define YY_FATAL_ERROR(msg) LexerError( msg )", "%endif", "#endif", "]])", "", "%if-tables-serialization structures and prototypes", "#ifdef FLEX_SCANNER", "/*", "dnl tables_shared.h - tables serialization header", "dnl", "dnl Copyright (c) 1990 The Regents of the University of California.", "dnl All rights reserved.", "dnl", "dnl This code is derived from software contributed to Berkeley by", "dnl Vern Paxson.", "dnl", "dnl The United States Government has rights in this work pursuant", "dnl to contract no. DE-AC03-76SF00098 between the United States", "dnl Department of Energy and the University of California.", "dnl", "dnl This file is part of flex.", "dnl", "dnl Redistribution and use in source and binary forms, with or without", "dnl modification, are permitted provided that the following conditions", "dnl are met:", "dnl", "dnl 1. Redistributions of source code must retain the above copyright", "dnl notice, this list of conditions and the following disclaimer.", "dnl 2. Redistributions in binary form must reproduce the above copyright", "dnl notice, this list of conditions and the following disclaimer in the", "dnl documentation and/or other materials provided with the distribution.", "dnl", "dnl Neither the name of the University nor the names of its contributors", "dnl may be used to endorse or promote products derived from this software", "dnl without specific prior written permission.", "dnl", "dnl THIS SOFTWARE IS PROVIDED `AS IS' AND WITHOUT ANY EXPRESS OR", "dnl IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED", "dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR", "dnl PURPOSE.", " ", "dnl", "dnl This file is meant to be included in both the skeleton and the actual", "dnl flex code (hence the name \"_shared\").", "*/", "#ifndef yyskel_static", "#define yyskel_static static", "#endif", "#else", "#ifndef yyskel_static", "#define yyskel_static", "#endif", "#endif", "", "/* Structures and prototypes for serializing flex tables. The", " * binary format is documented in the manual.", " *", " * Design considerations:", " *", " * - The format allows many tables per file.", " * - The tables can be streamed.", " * - All data is stored in network byte order.", " * - We do not hinder future unicode support.", " * - We can lookup tables by name.", " */", "", "/** Magic number for serialized format. */", "#ifndef YYTBL_MAGIC", "#define YYTBL_MAGIC 0xF13C57B1", "#endif", "", "/** Calculate (0-7) = number bytes needed to pad n to next 64-bit boundary. */", "#ifndef yypad64", "#define yypad64(n) ((8-((n)%8))%8)", "#endif", "", "", "#ifndef YYTABLES_TYPES", "#define YYTABLES_TYPES", "/** Possible values for td_id field. Each one corresponds to a", " * scanner table of the same name.", " */", "enum yytbl_id {", " YYTD_ID_ACCEPT = 0x01, /**< 1-dim ints */", " YYTD_ID_BASE = 0x02, /**< 1-dim ints */", " YYTD_ID_CHK = 0x03, /**< 1-dim ints */", " YYTD_ID_DEF = 0x04, /**< 1-dim ints */", " YYTD_ID_EC = 0x05, /**< 1-dim ints */", " YYTD_ID_META = 0x06, /**< 1-dim ints */", " YYTD_ID_NUL_TRANS = 0x07, /**< 1-dim ints, maybe indices */", " YYTD_ID_NXT = 0x08, /**< may be 2 dimensional ints */", " YYTD_ID_RULE_CAN_MATCH_EOL = 0x09, /**< 1-dim ints */", " YYTD_ID_START_STATE_LIST = 0x0A, /**< 1-dim indices into trans tbl */", " YYTD_ID_TRANSITION = 0x0B, /**< structs */", " YYTD_ID_ACCLIST = 0x0C /**< 1-dim ints */", "};", "", "/** bit flags for t_flags field of struct yytbl_data */", "enum yytbl_flags {", " /* These first three are mutually exclusive */", " YYTD_DATA8 = 0x01, /**< data is an array of type flex_int8_t */", " YYTD_DATA16 = 0x02, /**< data is an array of type flex_int16_t */", " YYTD_DATA32 = 0x04, /**< data is an array of type flex_int32_t */", "", " /* These two are mutually exclusive. */", " YYTD_PTRANS = 0x08, /**< data is a list of indexes of entries", " into the expanded yy_transition", " array. See notes in manual. */", " YYTD_STRUCT = 0x10 /**< data consists of yy_trans_info structs */", "};", "", "/* The serialized tables header. */", "struct yytbl_hdr {", " flex_uint32_t th_magic; /**< Must be 0xF13C57B1 (comes from \"Flex Table\") */", " flex_uint32_t th_hsize; /**< Size of this header in bytes. */", " flex_uint32_t th_ssize; /**< Size of this dataset, in bytes, including header. */", " flex_uint16_t th_flags; /**< Currently unused, must be 0 */", " char *th_version; /**< Flex version string. NUL terminated. */", " char *th_name; /**< The name of this table set. NUL terminated. */", "};", "", "/** A single serialized table */", "struct yytbl_data {", " flex_uint16_t td_id; /**< enum yytbl_id table identifier */", " flex_uint16_t td_flags; /**< how to interpret this data */", " flex_uint32_t td_hilen; /**< num elements in highest dimension array */", " flex_uint32_t td_lolen; /**< num elements in lowest dimension array */", " void *td_data; /**< table data */", "};", "#endif", "", "/** Extract corresponding data size_t from td_flags */", "#ifndef YYTDFLAGS2BYTES", "#define YYTDFLAGS2BYTES(td_flags)\\", " (((td_flags) & YYTD_DATA8)\\", " ? sizeof(flex_int8_t)\\", " :(((td_flags) & YYTD_DATA16)\\", " ? sizeof(flex_int16_t)\\", " :sizeof(flex_int32_t)))", "#endif", "", "#ifdef FLEX_SCANNER", "%not-for-header", "#endif", "yyskel_static flex_int32_t yytbl_calc_total_len (const struct yytbl_data *tbl);", "#ifdef FLEX_SCANNER", "%ok-for-header", "#endif", "", "/* vim:set noexpandtab cindent tabstop=8 softtabstop=0 shiftwidth=8 textwidth=0: */", "", "", "/* Load the DFA tables from the given stream. */", "int yytables_fload M4_YY_PARAMS(FILE * fp M4_YY_PROTO_LAST_ARG);", "", "/* Unload the tables from memory. */", "int yytables_destroy M4_YY_PARAMS(M4_YY_PROTO_ONLY_ARG);", "%not-for-header", "", "/** Describes a mapping from a serialized table id to its deserialized state in", " * this scanner. This is the bridge between our \"generic\" deserialization code", " * and the specifics of this scanner. ", " */", "struct yytbl_dmap {", " enum yytbl_id dm_id;/**< table identifier */", " void **dm_arr; /**< address of pointer to store the deserialized table. */", " size_t dm_sz; /**< local sizeof() each element in table. */", "};", "", "/** A {0,0,0}-terminated list of structs, forming the map */", "static struct yytbl_dmap yydmap[] =", "{", "%tables-yydmap generated elements", " {0,0,0}", "};", "", "/** A tables-reader object to maintain some state in the read. */", "struct yytbl_reader {", " FILE * fp; /**< input stream */", " flex_uint32_t bread; /**< bytes read since beginning of current tableset */", "};", "", "%endif", "/* end tables serialization structures and prototypes */", "", "%ok-for-header", "", "/* Default declaration of generated scanner - a define so the user can", " * easily add parameters.", " */", "#ifndef YY_DECL", "#define YY_DECL_IS_OURS 1", "%if-c-only Standard (non-C++) definition", "", "", "m4_define( [[M4_YY_LEX_PROTO]], [[M4_YY_PARAMS(M4_YY_PROTO_ONLY_ARG)]])", "m4_define( [[M4_YY_LEX_DECLARATION]], [[YYFARGS0(void)]])", "", "m4_ifdef( [[M4_YY_BISON_LVAL]],", "[[", " m4_dnl The bison pure parser is used. Redefine yylex to", " m4_dnl accept the lval parameter.", "", " m4_define( [[M4_YY_LEX_PROTO]], [[\\]]", " [[M4_YY_PARAMS(YYSTYPE * yylval_param M4_YY_PROTO_LAST_ARG)]])", " m4_define( [[M4_YY_LEX_DECLARATION]], [[\\]]", " [[YYFARGS1(YYSTYPE *,yylval_param)]])", "]])", "", "m4_ifdef( [[]],", "[[", " m4_dnl Locations are used. yylex should also accept the ylloc parameter.", "", " m4_define( [[M4_YY_LEX_PROTO]], [[\\]]", " [[M4_YY_PARAMS(YYSTYPE * yylval_param, YYLTYPE * yylloc_param M4_YY_PROTO_LAST_ARG)]])", " m4_define( [[M4_YY_LEX_DECLARATION]], [[\\]]", " [[YYFARGS2(YYSTYPE *,yylval_param, YYLTYPE *,yylloc_param)]])", "]])", "", "extern int yylex M4_YY_LEX_PROTO;", "", "#define YY_DECL int yylex M4_YY_LEX_DECLARATION", "%endif", "%if-c++-only C++ definition", "#define YY_DECL int yyFlexLexer::yylex()", "%endif", "#endif /* !YY_DECL */", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* Code executed at the beginning of each rule, after yytext and yyleng", " * have been set up.", " */", "#ifndef YY_USER_ACTION", "#define YY_USER_ACTION", "#endif", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* Code executed at the end of each rule. */", "#ifndef YY_BREAK", "#define YY_BREAK break;", "#endif", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "%% [6.0] YY_RULE_SETUP definition goes here", "]])", "", "%not-for-header", "/** The main scanner function which does all the work.", " */", "YY_DECL", "{", " yy_state_type yy_current_state;", " char *yy_cp, *yy_bp;", " int yy_act;", " M4_YY_DECL_GUTS_VAR();", "", "m4_ifdef( [[M4_YY_NOT_REENTRANT]],", "[[", " m4_ifdef( [[M4_YY_BISON_LVAL]],", " [[", " YYSTYPE * yylval;", " ]])", " m4_ifdef( [[]],", " [[", " YYLTYPE * yylloc;", " ]])", "]])", "", "%% [7.0] user's declarations go here", "", "m4_ifdef( [[M4_YY_BISON_LVAL]],", "[[", " yylval = yylval_param;", "]])", "", "m4_ifdef( [[]],", "[[", " yylloc = yylloc_param;", "]])", "", " if ( !YY_G(yy_init) )", " {", " YY_G(yy_init) = 1;", "", "#ifdef YY_USER_INIT", " YY_USER_INIT;", "#endif", "", "m4_ifdef( [[M4_YY_USES_REJECT]],", "[[", " /* Create the reject buffer large enough to save one state per allowed character. */", " if ( ! YY_G(yy_state_buf) )", " YY_G(yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE M4_YY_CALL_LAST_ARG);", " if ( ! YY_G(yy_state_buf) )", " YY_FATAL_ERROR( \"out of dynamic memory in yylex()\" );", "]])", "", " if ( ! YY_G(yy_start) )", " YY_G(yy_start) = 1; /* first start state */", "", " if ( ! yyin )", "%if-c-only", " yyin = stdin;", "%endif", "%if-c++-only", " yyin = & std::cin;", "%endif", "", " if ( ! yyout )", "%if-c-only", " yyout = stdout;", "%endif", "%if-c++-only", " yyout = & std::cout;", "%endif", "", " if ( ! YY_CURRENT_BUFFER ) {", " yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG);", " YY_CURRENT_BUFFER_LVALUE =", " yy_create_buffer( yyin, YY_BUF_SIZE M4_YY_CALL_LAST_ARG);", " }", "", " yy_load_buffer_state( M4_YY_CALL_ONLY_ARG );", " }", "", " while ( 1 ) /* loops until end-of-file is reached */", " {", "%% [8.0] yymore()-related code goes here", " yy_cp = YY_G(yy_c_buf_p);", "", " /* Support of yytext. */", " *yy_cp = YY_G(yy_hold_char);", "", " /* yy_bp points to the position in yy_ch_buf of the start of", " * the current run.", " */", " yy_bp = yy_cp;", "", "%% [9.0] code to set up and find next match goes here", "", "yy_find_action:", "%% [10.0] code to find the action number goes here", "", " YY_DO_BEFORE_ACTION;", "", "%% [11.0] code for yylineno update goes here", "", "do_action: /* This label is used only to access EOF actions. */", "", "%% [12.0] debug code goes here", "", " switch ( yy_act )", " { /* beginning of action switch */", "%% [13.0] actions go here", "", " case YY_END_OF_BUFFER:", " {", " /* Amount of text matched not including the EOB char. */", " int yy_amount_of_matched_text = (int) (yy_cp - YY_G(yytext_ptr)) - 1;", "", " /* Undo the effects of YY_DO_BEFORE_ACTION. */", " *yy_cp = YY_G(yy_hold_char);", " YY_RESTORE_YY_MORE_OFFSET", "", " if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )", " {", " /* We're scanning a new file or input source. It's", " * possible that this happened because the user", " * just pointed yyin at a new source and called", " * yylex(). If so, then we have to assure", " * consistency between YY_CURRENT_BUFFER and our", " * globals. Here is the right place to do so, because", " * this is the first action (other than possibly a", " * back-up) that will match for the new input source.", " */", " YY_G(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;", " YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;", " YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;", " }", "", " /* Note that here we test for yy_c_buf_p \"<=\" to the position", " * of the first EOB in the buffer, since yy_c_buf_p will", " * already have been incremented past the NUL character", " * (since all states make transitions on EOB to the", " * end-of-buffer state). Contrast this with the test", " * in input().", " */", " if ( YY_G(yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars)] )", " { /* This was really a NUL. */", " yy_state_type yy_next_state;", "", " YY_G(yy_c_buf_p) = YY_G(yytext_ptr) + yy_amount_of_matched_text;", "", " yy_current_state = yy_get_previous_state( M4_YY_CALL_ONLY_ARG );", "", " /* Okay, we're now positioned to make the NUL", " * transition. We couldn't have", " * yy_get_previous_state() go ahead and do it", " * for us because it doesn't know how to deal", " * with the possibility of jamming (and we don't", " * want to build jamming into it because then it", " * will run more slowly).", " */", "", " yy_next_state = yy_try_NUL_trans( yy_current_state M4_YY_CALL_LAST_ARG);", "", " yy_bp = YY_G(yytext_ptr) + YY_MORE_ADJ;", "", " if ( yy_next_state )", " {", " /* Consume the NUL. */", " yy_cp = ++YY_G(yy_c_buf_p);", " yy_current_state = yy_next_state;", " goto yy_match;", " }", "", " else", " {", "%% [14.0] code to do back-up for compressed tables and set up yy_cp goes here", " goto yy_find_action;", " }", " }", "", " else switch ( yy_get_next_buffer( M4_YY_CALL_ONLY_ARG ) )", " {", " case EOB_ACT_END_OF_FILE:", " {", " YY_G(yy_did_buffer_switch_on_eof) = 0;", "", " if ( yywrap( M4_YY_CALL_ONLY_ARG ) )", " {", " /* Note: because we've taken care in", " * yy_get_next_buffer() to have set up", " * yytext, we can now set up", " * yy_c_buf_p so that if some total", " * hoser (like flex itself) wants to", " * call the scanner after we return the", " * YY_NULL, it'll still work - another", " * YY_NULL will get returned.", " */", " YY_G(yy_c_buf_p) = YY_G(yytext_ptr) + YY_MORE_ADJ;", "", " yy_act = YY_STATE_EOF(YY_START);", " goto do_action;", " }", "", " else", " {", " if ( ! YY_G(yy_did_buffer_switch_on_eof) )", " YY_NEW_FILE;", " }", " break;", " }", "", " case EOB_ACT_CONTINUE_SCAN:", " YY_G(yy_c_buf_p) =", " YY_G(yytext_ptr) + yy_amount_of_matched_text;", "", " yy_current_state = yy_get_previous_state( M4_YY_CALL_ONLY_ARG );", "", " yy_cp = YY_G(yy_c_buf_p);", " yy_bp = YY_G(yytext_ptr) + YY_MORE_ADJ;", " goto yy_match;", "", " case EOB_ACT_LAST_MATCH:", " YY_G(yy_c_buf_p) =", " &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars)];", "", " yy_current_state = yy_get_previous_state( M4_YY_CALL_ONLY_ARG );", "", " yy_cp = YY_G(yy_c_buf_p);", " yy_bp = YY_G(yytext_ptr) + YY_MORE_ADJ;", " goto yy_find_action;", " }", " break;", " }", "", " default:", " YY_FATAL_ERROR(", " \"fatal flex scanner internal error--no action found\" );", " } /* end of action switch */", " } /* end of scanning one token */", "} /* end of yylex */", "%ok-for-header", "", "%if-c++-only", "%not-for-header", "/* The contents of this function are C++ specific, so the YY_G macro is not used.", " */", "yyFlexLexer::yyFlexLexer( std::istream* arg_yyin, std::ostream* arg_yyout )", "{", " yyin = arg_yyin;", " yyout = arg_yyout;", " yy_c_buf_p = 0;", " yy_init = 0;", " yy_start = 0;", " yy_flex_debug = 0;", " yylineno = 1; // this will only get updated if %option yylineno", "", " yy_did_buffer_switch_on_eof = 0;", "", " yy_looking_for_trail_begin = 0;", " yy_more_flag = 0;", " yy_more_len = 0;", " yy_more_offset = yy_prev_more_offset = 0;", "", " yy_start_stack_ptr = yy_start_stack_depth = 0;", " yy_start_stack = NULL;", "", " yy_buffer_stack = 0;", " yy_buffer_stack_top = 0;", " yy_buffer_stack_max = 0;", "", "", "m4_ifdef( [[M4_YY_USES_REJECT]],", "[[", " yy_state_buf = new yy_state_type[YY_STATE_BUF_SIZE];", "]],", "[[", " yy_state_buf = 0;", "]])", "}", "", "/* The contents of this function are C++ specific, so the YY_G macro is not used.", " */", "yyFlexLexer::~yyFlexLexer()", "{", " delete [] yy_state_buf;", " yyfree( yy_start_stack M4_YY_CALL_LAST_ARG );", " yy_delete_buffer( YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG);", " yyfree( yy_buffer_stack M4_YY_CALL_LAST_ARG );", "}", "", "/* The contents of this function are C++ specific, so the YY_G macro is not used.", " */", "void yyFlexLexer::switch_streams( std::istream* new_in, std::ostream* new_out )", "{", " if ( new_in )", " {", " yy_delete_buffer( YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG);", " yy_switch_to_buffer( yy_create_buffer( new_in, YY_BUF_SIZE M4_YY_CALL_LAST_ARG) M4_YY_CALL_LAST_ARG);", " }", "", " if ( new_out )", " yyout = new_out;", "}", "", "#ifdef YY_INTERACTIVE", "int yyFlexLexer::LexerInput( char* buf, int /* max_size */ )", "#else", "int yyFlexLexer::LexerInput( char* buf, int max_size )", "#endif", "{", " if ( yyin->eof() || yyin->fail() )", " return 0;", "", "#ifdef YY_INTERACTIVE", " yyin->get( buf[0] );", "", " if ( yyin->eof() )", " return 0;", "", " if ( yyin->bad() )", " return -1;", "", " return 1;", "", "#else", " (void) yyin->read( buf, max_size );", "", " if ( yyin->bad() )", " return -1;", " else", " return yyin->gcount();", "#endif", "}", "", "void yyFlexLexer::LexerOutput( const char* buf, int size )", "{", " (void) yyout->write( buf, size );", "}", "%ok-for-header", "%endif", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/* yy_get_next_buffer - try to read in a new buffer", " *", " * Returns a code representing an action:", " * EOB_ACT_LAST_MATCH -", " * EOB_ACT_CONTINUE_SCAN - continue scanning from current position", " * EOB_ACT_END_OF_FILE - end of file", " */", "%if-c-only", "static int yy_get_next_buffer YYFARGS0(void)", "%endif", "%if-c++-only", "int yyFlexLexer::yy_get_next_buffer()", "%endif", "{", " M4_YY_DECL_GUTS_VAR();", " char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;", " char *source = YY_G(yytext_ptr);", " int number_to_move, i;", " int ret_val;", "", " if ( YY_G(yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars) + 1] )", " YY_FATAL_ERROR(", " \"fatal flex scanner internal error--end of buffer missed\" );", "", " if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )", " { /* Don't try to fill the buffer, so this is an EOF. */", " if ( YY_G(yy_c_buf_p) - YY_G(yytext_ptr) - YY_MORE_ADJ == 1 )", " {", " /* We matched a single character, the EOB, so", " * treat this as a final EOF.", " */", " return EOB_ACT_END_OF_FILE;", " }", "", " else", " {", " /* We matched some text prior to the EOB, first", " * process it.", " */", " return EOB_ACT_LAST_MATCH;", " }", " }", "", " /* Try to read more data. */", "", " /* First move last chars to start of buffer. */", " number_to_move = (int) (YY_G(yy_c_buf_p) - YY_G(yytext_ptr)) - 1;", "", " for ( i = 0; i < number_to_move; ++i )", " *(dest++) = *(source++);", "", " if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )", " /* don't do the read, it's not guaranteed to return an EOF,", " * just force an EOF", " */", " YY_CURRENT_BUFFER_LVALUE->yy_n_chars = YY_G(yy_n_chars) = 0;", "", " else", " {", " yy_size_t num_to_read =", " YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;", "", " while ( num_to_read <= 0 )", " { /* Not enough room in the buffer - grow it. */", "m4_ifdef( [[M4_YY_USES_REJECT]],", "[[", " YY_FATAL_ERROR(", "\"input buffer overflow, can't enlarge buffer because scanner uses REJECT\" );", "]],", "[[", " /* just a shorter name for the current buffer */", " YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;", "", " int yy_c_buf_p_offset =", " (int) (YY_G(yy_c_buf_p) - b->yy_ch_buf);", "", " if ( b->yy_is_our_buffer )", " {", " yy_size_t new_size = b->yy_buf_size * 2;", "", " if ( new_size <= 0 )", " b->yy_buf_size += b->yy_buf_size / 8;", " else", " b->yy_buf_size *= 2;", "", " b->yy_ch_buf = (char *)", " /* Include room in for 2 EOB chars. */", " yyrealloc( (void *) b->yy_ch_buf,", " b->yy_buf_size + 2 M4_YY_CALL_LAST_ARG );", " }", " else", " /* Can't grow it, we don't own it. */", " b->yy_ch_buf = 0;", "", " if ( ! b->yy_ch_buf )", " YY_FATAL_ERROR(", " \"fatal error - scanner input buffer overflow\" );", "", " YY_G(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];", "", " num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -", " number_to_move - 1;", "]])", " }", "", " if ( num_to_read > YY_READ_BUF_SIZE )", " num_to_read = YY_READ_BUF_SIZE;", "", " /* Read in more data. */", " YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),", " YY_G(yy_n_chars), num_to_read );", "", " YY_CURRENT_BUFFER_LVALUE->yy_n_chars = YY_G(yy_n_chars);", " }", "", " if ( YY_G(yy_n_chars) == 0 )", " {", " if ( number_to_move == YY_MORE_ADJ )", " {", " ret_val = EOB_ACT_END_OF_FILE;", " yyrestart( yyin M4_YY_CALL_LAST_ARG);", " }", "", " else", " {", " ret_val = EOB_ACT_LAST_MATCH;", " YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =", " YY_BUFFER_EOF_PENDING;", " }", " }", "", " else", " ret_val = EOB_ACT_CONTINUE_SCAN;", "", " if ((yy_size_t) (YY_G(yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {", " /* Extend the array by 50%, plus the number we really need. */", " yy_size_t new_size = YY_G(yy_n_chars) + number_to_move + (YY_G(yy_n_chars) >> 1);", " YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(", " (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, new_size M4_YY_CALL_LAST_ARG );", " if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )", " YY_FATAL_ERROR( \"out of dynamic memory in yy_get_next_buffer()\" );", " }", "", " YY_G(yy_n_chars) += number_to_move;", " YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;", " YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;", "", " YY_G(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];", "", " return ret_val;", "}", "]])", "", "/* yy_get_previous_state - get the state just before the EOB char was reached */", "", "%if-c-only", "%not-for-header", " static yy_state_type yy_get_previous_state YYFARGS0(void)", "%endif", "%if-c++-only", " yy_state_type yyFlexLexer::yy_get_previous_state()", "%endif", "{", " yy_state_type yy_current_state;", " char *yy_cp;", " M4_YY_DECL_GUTS_VAR();", "", "%% [15.0] code to get the start state into yy_current_state goes here", "", " for ( yy_cp = YY_G(yytext_ptr) + YY_MORE_ADJ; yy_cp < YY_G(yy_c_buf_p); ++yy_cp )", " {", "%% [16.0] code to find the next state goes here", " }", "", " return yy_current_state;", "}", "", "", "/* yy_try_NUL_trans - try to make a transition on the NUL character", " *", " * synopsis", " * next_state = yy_try_NUL_trans( current_state );", " */", "%if-c-only", " static yy_state_type yy_try_NUL_trans YYFARGS1( yy_state_type, yy_current_state)", "%endif", "%if-c++-only", " yy_state_type yyFlexLexer::yy_try_NUL_trans( yy_state_type yy_current_state )", "%endif", "{", " int yy_is_jam;", " M4_YY_DECL_GUTS_VAR(); /* This var may be unused depending upon options. */", "%% [17.0] code to find the next state, and perhaps do backing up, goes here", "", " M4_YY_NOOP_GUTS_VAR();", " return yy_is_jam ? 0 : yy_current_state;", "}", "", "", "%if-c-only", "m4_ifdef( [[M4_YY_NO_UNPUT]],,", "[[", "#ifndef YY_NO_UNPUT", " static void yyunput YYFARGS2( int,c, char *,yy_bp)", "%endif", "%if-c++-only", "#ifndef YY_NO_UNPUT", " void yyFlexLexer::yyunput( int c, char* yy_bp)", "%endif", "{", " char *yy_cp;", " M4_YY_DECL_GUTS_VAR();", "", " yy_cp = YY_G(yy_c_buf_p);", "", " /* undo effects of setting up yytext */", " *yy_cp = YY_G(yy_hold_char);", "", " if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )", " { /* need to shift things up to make room */", " /* +2 for EOB chars. */", " yy_size_t number_to_move = YY_G(yy_n_chars) + 2;", " char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[", " YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];", " char *source =", " &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];", "", " while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )", " *--dest = *--source;", "", " yy_cp += (int) (dest - source);", " yy_bp += (int) (dest - source);", " YY_CURRENT_BUFFER_LVALUE->yy_n_chars =", " YY_G(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;", "", " if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )", " YY_FATAL_ERROR( \"flex scanner push-back overflow\" );", " }", "", " *--yy_cp = (char) c;", "", "%% [18.0] update yylineno here", "m4_ifdef( [[M4_YY_USE_LINENO]],", "[[", " if ( c == '\\n' ){", " --yylineno;", " }", "]])", "", " YY_G(yytext_ptr) = yy_bp;", " YY_G(yy_hold_char) = *yy_cp;", " YY_G(yy_c_buf_p) = yy_cp;", "}", "#endif /* ifndef YY_NO_UNPUT */", "%if-c-only", "]])", "%endif", "", "%if-c-only", "#ifndef YY_NO_INPUT", "#ifdef __cplusplus", " static int yyinput YYFARGS0(void)", "#else", " static int input YYFARGS0(void)", "#endif", "", "%endif", "%if-c++-only", " int yyFlexLexer::yyinput()", "%endif", "{", " int c;", " M4_YY_DECL_GUTS_VAR();", "", " *YY_G(yy_c_buf_p) = YY_G(yy_hold_char);", "", " if ( *YY_G(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )", " {", " /* yy_c_buf_p now points to the character we want to return.", " * If this occurs *before* the EOB characters, then it's a", " * valid NUL; if not, then we've hit the end of the buffer.", " */", " if ( YY_G(yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars)] )", " /* This was really a NUL. */", " *YY_G(yy_c_buf_p) = '\\0';", "", " else", " { /* need more input */", " yy_size_t offset = YY_G(yy_c_buf_p) - YY_G(yytext_ptr);", " ++YY_G(yy_c_buf_p);", "", " switch ( yy_get_next_buffer( M4_YY_CALL_ONLY_ARG ) )", " {", " case EOB_ACT_LAST_MATCH:", " /* This happens because yy_g_n_b()", " * sees that we've accumulated a", " * token and flags that we need to", " * try matching the token before", " * proceeding. But for input(),", " * there's no matching to consider.", " * So convert the EOB_ACT_LAST_MATCH", " * to EOB_ACT_END_OF_FILE.", " */", "", " /* Reset buffer status. */", " yyrestart( yyin M4_YY_CALL_LAST_ARG);", "", " /*FALLTHROUGH*/", "", " case EOB_ACT_END_OF_FILE:", " {", " if ( yywrap( M4_YY_CALL_ONLY_ARG ) )", " return EOF;", "", " if ( ! YY_G(yy_did_buffer_switch_on_eof) )", " YY_NEW_FILE;", "#ifdef __cplusplus", " return yyinput(M4_YY_CALL_ONLY_ARG);", "#else", " return input(M4_YY_CALL_ONLY_ARG);", "#endif", " }", "", " case EOB_ACT_CONTINUE_SCAN:", " YY_G(yy_c_buf_p) = YY_G(yytext_ptr) + offset;", " break;", " }", " }", " }", "", " c = *(unsigned char *) YY_G(yy_c_buf_p); /* cast for 8-bit char's */", " *YY_G(yy_c_buf_p) = '\\0'; /* preserve yytext */", " YY_G(yy_hold_char) = *++YY_G(yy_c_buf_p);", "", "%% [19.0] update BOL and yylineno", "", " return c;", "}", "%if-c-only", "#endif /* ifndef YY_NO_INPUT */", "%endif", "", "/** Immediately switch to a different input stream.", " * @param input_file A readable stream.", " * M4_YY_DOC_PARAM", " * @note This function does not reset the start condition to @c INITIAL .", " */", "%if-c-only", " void yyrestart YYFARGS1( FILE *,input_file)", "%endif", "%if-c++-only", " void yyFlexLexer::yyrestart( std::istream* input_file )", "%endif", "{", " M4_YY_DECL_GUTS_VAR();", "", " if ( ! YY_CURRENT_BUFFER ){", " yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG);", " YY_CURRENT_BUFFER_LVALUE =", " yy_create_buffer( yyin, YY_BUF_SIZE M4_YY_CALL_LAST_ARG);", " }", "", " yy_init_buffer( YY_CURRENT_BUFFER, input_file M4_YY_CALL_LAST_ARG);", " yy_load_buffer_state( M4_YY_CALL_ONLY_ARG );", "}", "", "/** Switch to a different input buffer.", " * @param new_buffer The new input buffer.", " * M4_YY_DOC_PARAM", " */", "%if-c-only", " void yy_switch_to_buffer YYFARGS1( YY_BUFFER_STATE ,new_buffer)", "%endif", "%if-c++-only", " void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )", "%endif", "{", " M4_YY_DECL_GUTS_VAR();", "", " /* TODO. We should be able to replace this entire function body", " * with", " * yypop_buffer_state();", " * yypush_buffer_state(new_buffer);", " */", " yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG);", " if ( YY_CURRENT_BUFFER == new_buffer )", " return;", "", " if ( YY_CURRENT_BUFFER )", " {", " /* Flush out information for old buffer. */", " *YY_G(yy_c_buf_p) = YY_G(yy_hold_char);", " YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = YY_G(yy_c_buf_p);", " YY_CURRENT_BUFFER_LVALUE->yy_n_chars = YY_G(yy_n_chars);", " }", "", " YY_CURRENT_BUFFER_LVALUE = new_buffer;", " yy_load_buffer_state( M4_YY_CALL_ONLY_ARG );", "", " /* We don't actually know whether we did this switch during", " * EOF (yywrap()) processing, but the only time this flag", " * is looked at is after yywrap() is called, so it's safe", " * to go ahead and always set it.", " */", " YY_G(yy_did_buffer_switch_on_eof) = 1;", "}", "", "", "%if-c-only", "static void yy_load_buffer_state YYFARGS0(void)", "%endif", "%if-c++-only", " void yyFlexLexer::yy_load_buffer_state()", "%endif", "{", " M4_YY_DECL_GUTS_VAR();", " YY_G(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;", " YY_G(yytext_ptr) = YY_G(yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;", " yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;", " YY_G(yy_hold_char) = *YY_G(yy_c_buf_p);", "}", "", "/** Allocate and initialize an input buffer state.", " * @param file A readable stream.", " * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.", " * M4_YY_DOC_PARAM", " * @return the allocated buffer state.", " */", "%if-c-only", " YY_BUFFER_STATE yy_create_buffer YYFARGS2( FILE *,file, int ,size)", "%endif", "%if-c++-only", " YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( std::istream* file, int size )", "%endif", "{", " YY_BUFFER_STATE b;", " m4_dnl M4_YY_DECL_GUTS_VAR();", "", " b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) M4_YY_CALL_LAST_ARG );", " if ( ! b )", " YY_FATAL_ERROR( \"out of dynamic memory in yy_create_buffer()\" );", "", " b->yy_buf_size = size;", "", " /* yy_ch_buf has to be 2 characters longer than the size given because", " * we need to put in 2 end-of-buffer characters.", " */", " b->yy_ch_buf = (char *) yyalloc( b->yy_buf_size + 2 M4_YY_CALL_LAST_ARG );", " if ( ! b->yy_ch_buf )", " YY_FATAL_ERROR( \"out of dynamic memory in yy_create_buffer()\" );", "", " b->yy_is_our_buffer = 1;", "", " yy_init_buffer( b, file M4_YY_CALL_LAST_ARG);", "", " return b;", "}", "", "/** Destroy the buffer.", " * @param b a buffer created with yy_create_buffer()", " * M4_YY_DOC_PARAM", " */", "%if-c-only", " void yy_delete_buffer YYFARGS1( YY_BUFFER_STATE ,b)", "%endif", "%if-c++-only", " void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b )", "%endif", "{", " M4_YY_DECL_GUTS_VAR();", "", " if ( ! b )", " return;", "", " if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */", " YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;", "", " if ( b->yy_is_our_buffer )", " yyfree( (void *) b->yy_ch_buf M4_YY_CALL_LAST_ARG );", "", " yyfree( (void *) b M4_YY_CALL_LAST_ARG );", "}", "", "", "/* Initializes or reinitializes a buffer.", " * This function is sometimes called more than once on the same buffer,", " * such as during a yyrestart() or at EOF.", " */", "%if-c-only", " static void yy_init_buffer YYFARGS2( YY_BUFFER_STATE ,b, FILE *,file)", "%endif", "%if-c++-only", " void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, std::istream* file )", "%endif", "", "{", " int oerrno = errno;", " M4_YY_DECL_GUTS_VAR();", "", " yy_flush_buffer( b M4_YY_CALL_LAST_ARG);", "", " b->yy_input_file = file;", " b->yy_fill_buffer = 1;", "", " /* If b is the current buffer, then yy_init_buffer was _probably_", " * called from yyrestart() or through yy_get_next_buffer.", " * In that case, we don't want to reset the lineno or column.", " */", " if (b != YY_CURRENT_BUFFER){", " b->yy_bs_lineno = 1;", " b->yy_bs_column = 0;", " }", "", "%if-c-only", "m4_ifdef( [[M4_YY_ALWAYS_INTERACTIVE]],", "[[", " b->yy_is_interactive = 1;", "]],", "[[", " m4_ifdef( [[M4_YY_NEVER_INTERACTIVE]],", " [[", " b->yy_is_interactive = 0;", " ]],", " [[", " b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;", " ]])", "]])", "%endif", "%if-c++-only", " b->yy_is_interactive = 0;", "%endif", " errno = oerrno;", "}", "", "/** Discard all buffered characters. On the next scan, YY_INPUT will be called.", " * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.", " * M4_YY_DOC_PARAM", " */", "%if-c-only", " void yy_flush_buffer YYFARGS1( YY_BUFFER_STATE ,b)", "%endif", "%if-c++-only", " void yyFlexLexer::yy_flush_buffer( YY_BUFFER_STATE b )", "%endif", "{", " M4_YY_DECL_GUTS_VAR();", " if ( ! b )", " return;", "", " b->yy_n_chars = 0;", "", " /* We always need two end-of-buffer characters. The first causes", " * a transition to the end-of-buffer state. The second causes", " * a jam in that state.", " */", " b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;", " b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;", "", " b->yy_buf_pos = &b->yy_ch_buf[0];", "", " b->yy_at_bol = 1;", " b->yy_buffer_status = YY_BUFFER_NEW;", "", " if ( b == YY_CURRENT_BUFFER )", " yy_load_buffer_state( M4_YY_CALL_ONLY_ARG );", "}", "", "%if-c-or-c++", "/** Pushes the new state onto the stack. The new state becomes", " * the current state. This function will allocate the stack", " * if necessary.", " * @param new_buffer The new state.", " * M4_YY_DOC_PARAM", " */", "%if-c-only", "void yypush_buffer_state YYFARGS1(YY_BUFFER_STATE,new_buffer)", "%endif", "%if-c++-only", "void yyFlexLexer::yypush_buffer_state (YY_BUFFER_STATE new_buffer)", "%endif", "{", " M4_YY_DECL_GUTS_VAR();", " if (new_buffer == NULL)", " return;", "", " yyensure_buffer_stack(M4_YY_CALL_ONLY_ARG);", "", " /* This block is copied from yy_switch_to_buffer. */", " if ( YY_CURRENT_BUFFER )", " {", " /* Flush out information for old buffer. */", " *YY_G(yy_c_buf_p) = YY_G(yy_hold_char);", " YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = YY_G(yy_c_buf_p);", " YY_CURRENT_BUFFER_LVALUE->yy_n_chars = YY_G(yy_n_chars);", " }", "", " /* Only push if top exists. Otherwise, replace top. */", " if (YY_CURRENT_BUFFER)", " YY_G(yy_buffer_stack_top)++;", " YY_CURRENT_BUFFER_LVALUE = new_buffer;", "", " /* copied from yy_switch_to_buffer. */", " yy_load_buffer_state( M4_YY_CALL_ONLY_ARG );", " YY_G(yy_did_buffer_switch_on_eof) = 1;", "}", "%endif", "", "", "%if-c-or-c++", "/** Removes and deletes the top of the stack, if present.", " * The next element becomes the new top.", " * M4_YY_DOC_PARAM", " */", "%if-c-only", "void yypop_buffer_state YYFARGS0(void)", "%endif", "%if-c++-only", "void yyFlexLexer::yypop_buffer_state (void)", "%endif", "{", " M4_YY_DECL_GUTS_VAR();", " if (!YY_CURRENT_BUFFER)", " return;", "", " yy_delete_buffer(YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG);", " YY_CURRENT_BUFFER_LVALUE = NULL;", " if (YY_G(yy_buffer_stack_top) > 0)", " --YY_G(yy_buffer_stack_top);", "", " if (YY_CURRENT_BUFFER) {", " yy_load_buffer_state( M4_YY_CALL_ONLY_ARG );", " YY_G(yy_did_buffer_switch_on_eof) = 1;", " }", "}", "%endif", "", "", "%if-c-or-c++", "/* Allocates the stack if it does not exist.", " * Guarantees space for at least one push.", " */", "%if-c-only", "static void yyensure_buffer_stack YYFARGS0(void)", "%endif", "%if-c++-only", "void yyFlexLexer::yyensure_buffer_stack(void)", "%endif", "{", " yy_size_t num_to_alloc;", " M4_YY_DECL_GUTS_VAR();", "", " if (!YY_G(yy_buffer_stack)) {", "", " /* First allocation is just for 2 elements, since we don't know if this", " * scanner will even need a stack. We use 2 instead of 1 to avoid an", " * immediate realloc on the next call.", " */", " num_to_alloc = 1;", " YY_G(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc", " (num_to_alloc * sizeof(struct yy_buffer_state*)", " M4_YY_CALL_LAST_ARG);", " if ( ! YY_G(yy_buffer_stack) )", " YY_FATAL_ERROR( \"out of dynamic memory in yyensure_buffer_stack()\" );", " ", " ", " memset(YY_G(yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));", " ", " YY_G(yy_buffer_stack_max) = num_to_alloc;", " YY_G(yy_buffer_stack_top) = 0;", " return;", " }", "", " if (YY_G(yy_buffer_stack_top) >= (YY_G(yy_buffer_stack_max)) - 1){", "", " /* Increase the buffer to prepare for a possible push. */", " int grow_size = 8 /* arbitrary grow size */;", "", " num_to_alloc = YY_G(yy_buffer_stack_max) + grow_size;", " YY_G(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc", " (YY_G(yy_buffer_stack),", " num_to_alloc * sizeof(struct yy_buffer_state*)", " M4_YY_CALL_LAST_ARG);", " if ( ! YY_G(yy_buffer_stack) )", " YY_FATAL_ERROR( \"out of dynamic memory in yyensure_buffer_stack()\" );", "", " /* zero only the new slots.*/", " memset(YY_G(yy_buffer_stack) + YY_G(yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));", " YY_G(yy_buffer_stack_max) = num_to_alloc;", " }", "}", "%endif", "", "", "", "", "m4_ifdef( [[M4_YY_NO_SCAN_BUFFER]],,", "[[", "%if-c-only", "/** Setup the input buffer state to scan directly from a user-specified character buffer.", " * @param base the character buffer", " * @param size the size in bytes of the character buffer", " * M4_YY_DOC_PARAM", " * @return the newly allocated buffer state object. ", " */", "YY_BUFFER_STATE yy_scan_buffer YYFARGS2( char *,base, yy_size_t ,size)", "{", " YY_BUFFER_STATE b;", " m4_dnl M4_YY_DECL_GUTS_VAR();", "", " if ( size < 2 ||", " base[size-2] != YY_END_OF_BUFFER_CHAR ||", " base[size-1] != YY_END_OF_BUFFER_CHAR )", " /* They forgot to leave room for the EOB's. */", " return 0;", "", " b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) M4_YY_CALL_LAST_ARG );", " if ( ! b )", " YY_FATAL_ERROR( \"out of dynamic memory in yy_scan_buffer()\" );", "", " b->yy_buf_size = size - 2; /* \"- 2\" to take care of EOB's */", " b->yy_buf_pos = b->yy_ch_buf = base;", " b->yy_is_our_buffer = 0;", " b->yy_input_file = 0;", " b->yy_n_chars = b->yy_buf_size;", " b->yy_is_interactive = 0;", " b->yy_at_bol = 1;", " b->yy_fill_buffer = 0;", " b->yy_buffer_status = YY_BUFFER_NEW;", "", " yy_switch_to_buffer( b M4_YY_CALL_LAST_ARG );", "", " return b;", "}", "%endif", "]])", "", "", "m4_ifdef( [[M4_YY_NO_SCAN_STRING]],,", "[[", "%if-c-only", "/** Setup the input buffer state to scan a string. The next call to yylex() will", " * scan from a @e copy of @a str.", " * @param yystr a NUL-terminated string to scan", " * M4_YY_DOC_PARAM", " * @return the newly allocated buffer state object.", " * @note If you want to scan bytes that may contain NUL values, then use", " * yy_scan_bytes() instead.", " */", "YY_BUFFER_STATE yy_scan_string YYFARGS1( yyconst char *, yystr)", "{", " m4_dnl M4_YY_DECL_GUTS_VAR();", "", " return yy_scan_bytes( yystr, strlen(yystr) M4_YY_CALL_LAST_ARG);", "}", "%endif", "]])", "", "", "m4_ifdef( [[M4_YY_NO_SCAN_BYTES]],,", "[[", "%if-c-only", "/** Setup the input buffer state to scan the given bytes. The next call to yylex() will", " * scan from a @e copy of @a bytes.", " * @param yybytes the byte buffer to scan", " * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.", " * M4_YY_DOC_PARAM", " * @return the newly allocated buffer state object.", " */", "YY_BUFFER_STATE yy_scan_bytes YYFARGS2( yyconst char *,yybytes, yy_size_t ,_yybytes_len)", "{", " YY_BUFFER_STATE b;", " char *buf;", " yy_size_t n;", " yy_size_t i;", " m4_dnl M4_YY_DECL_GUTS_VAR();", "", " /* Get memory for full buffer, including space for trailing EOB's. */", " n = _yybytes_len + 2;", " buf = (char *) yyalloc( n M4_YY_CALL_LAST_ARG );", " if ( ! buf )", " YY_FATAL_ERROR( \"out of dynamic memory in yy_scan_bytes()\" );", "", " for ( i = 0; i < _yybytes_len; ++i )", " buf[i] = yybytes[i];", "", " buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;", "", " b = yy_scan_buffer( buf, n M4_YY_CALL_LAST_ARG);", " if ( ! b )", " YY_FATAL_ERROR( \"bad buffer in yy_scan_bytes()\" );", "", " /* It's okay to grow etc. this buffer, and we should throw it", " * away when we're done.", " */", " b->yy_is_our_buffer = 1;", "", " return b;", "}", "%endif", "]])", "", "", "m4_ifdef( [[M4_YY_NO_PUSH_STATE]],,", "[[", "%if-c-only", " static void yy_push_state YYFARGS1( int ,new_state)", "%endif", "%if-c++-only", " void yyFlexLexer::yy_push_state( int new_state )", "%endif", "{", " M4_YY_DECL_GUTS_VAR();", " if ( YY_G(yy_start_stack_ptr) >= YY_G(yy_start_stack_depth) )", " {", " yy_size_t new_size;", "", " YY_G(yy_start_stack_depth) += YY_START_STACK_INCR;", " new_size = YY_G(yy_start_stack_depth) * sizeof( int );", "", " if ( ! YY_G(yy_start_stack) )", " YY_G(yy_start_stack) = (int *) yyalloc( new_size M4_YY_CALL_LAST_ARG );", "", " else", " YY_G(yy_start_stack) = (int *) yyrealloc(", " (void *) YY_G(yy_start_stack), new_size M4_YY_CALL_LAST_ARG );", "", " if ( ! YY_G(yy_start_stack) )", " YY_FATAL_ERROR( \"out of memory expanding start-condition stack\" );", " }", "", " YY_G(yy_start_stack)[YY_G(yy_start_stack_ptr)++] = YY_START;", "", " BEGIN(new_state);", "}", "]])", "", "", "m4_ifdef( [[M4_YY_NO_POP_STATE]],,", "[[", "%if-c-only", " static void yy_pop_state YYFARGS0(void)", "%endif", "%if-c++-only", " void yyFlexLexer::yy_pop_state()", "%endif", "{", " M4_YY_DECL_GUTS_VAR();", " if ( --YY_G(yy_start_stack_ptr) < 0 )", " YY_FATAL_ERROR( \"start-condition stack underflow\" );", "", " BEGIN(YY_G(yy_start_stack)[YY_G(yy_start_stack_ptr)]);", "}", "]])", "", "", "m4_ifdef( [[M4_YY_NO_TOP_STATE]],,", "[[", "%if-c-only", " static int yy_top_state YYFARGS0(void)", "%endif", "%if-c++-only", " int yyFlexLexer::yy_top_state()", "%endif", "{", " M4_YY_DECL_GUTS_VAR();", " return YY_G(yy_start_stack)[YY_G(yy_start_stack_ptr) - 1];", "}", "]])", "", "#ifndef YY_EXIT_FAILURE", "#define YY_EXIT_FAILURE 2", "#endif", "", "%if-c-only", "static void yy_fatal_error YYFARGS1(yyconst char*, msg)", "{", " m4_dnl M4_YY_DECL_GUTS_VAR();", " (void) fprintf( stderr, \"%s\\n\", msg );", " exit( YY_EXIT_FAILURE );", "}", "%endif", "%if-c++-only", "void yyFlexLexer::LexerError( yyconst char msg[] )", "{", " M4_YY_DECL_GUTS_VAR();", " std::cerr << msg << std::endl;", " exit( YY_EXIT_FAILURE );", "}", "%endif", "", "/* Redefine yyless() so it works in section 3 code. */", "", "#undef yyless", "#define yyless(n) \\", " do \\", " { \\", " /* Undo effects of setting up yytext. */ \\", " int yyless_macro_arg = (n); \\", " YY_LESS_LINENO(yyless_macro_arg);\\", " yytext[yyleng] = YY_G(yy_hold_char); \\", " YY_G(yy_c_buf_p) = yytext + yyless_macro_arg; \\", " YY_G(yy_hold_char) = *YY_G(yy_c_buf_p); \\", " *YY_G(yy_c_buf_p) = '\\0'; \\", " yyleng = yyless_macro_arg; \\", " } \\", " while ( 0 )", "", "", "", "/* Accessor methods (get/set functions) to struct members. */", "", "%if-c-only", "%if-reentrant", "m4_ifdef( [[M4_YY_NO_GET_EXTRA]],,", "[[", "/** Get the user-defined data for this scanner.", " * M4_YY_DOC_PARAM", " */", "YY_EXTRA_TYPE yyget_extra YYFARGS0(void)", "{", " M4_YY_DECL_GUTS_VAR();", " return yyextra;", "}", "]])", "%endif", "", "m4_ifdef( [[M4_YY_NO_GET_LINENO]],,", "[[", "/** Get the current line number.", " * M4_YY_DOC_PARAM", " */", "int yyget_lineno YYFARGS0(void)", "{", " M4_YY_DECL_GUTS_VAR();", " ", " m4_ifdef( [[M4_YY_REENTRANT]],", " [[", " if (! YY_CURRENT_BUFFER)", " return 0;", " ]])", " return yylineno;", "}", "]])", "", "m4_ifdef( [[M4_YY_REENTRANT]],", "[[", "m4_ifdef( [[M4_YY_NO_GET_COLUMN]],,", "[[", "/** Get the current column number.", " * M4_YY_DOC_PARAM", " */", "int yyget_column YYFARGS0(void)", "{", " M4_YY_DECL_GUTS_VAR();", " ", " m4_ifdef( [[M4_YY_REENTRANT]],", " [[", " if (! YY_CURRENT_BUFFER)", " return 0;", " ]])", " return yycolumn;", "}", "]])", "]])", "", "m4_ifdef( [[M4_YY_NO_GET_IN]],,", "[[", "/** Get the input stream.", " * M4_YY_DOC_PARAM", " */", "FILE *yyget_in YYFARGS0(void)", "{", " M4_YY_DECL_GUTS_VAR();", " return yyin;", "}", "]])", "", "m4_ifdef( [[M4_YY_NO_GET_OUT]],,", "[[", "/** Get the output stream.", " * M4_YY_DOC_PARAM", " */", "FILE *yyget_out YYFARGS0(void)", "{", " M4_YY_DECL_GUTS_VAR();", " return yyout;", "}", "]])", "", "m4_ifdef( [[M4_YY_NO_GET_LENG]],,", "[[", "/** Get the length of the current token.", " * M4_YY_DOC_PARAM", " */", "yy_size_t yyget_leng YYFARGS0(void)", "{", " M4_YY_DECL_GUTS_VAR();", " return yyleng;", "}", "]])", "", "/** Get the current token.", " * M4_YY_DOC_PARAM", " */", "m4_ifdef( [[M4_YY_NO_GET_TEXT]],,", "[[", "char *yyget_text YYFARGS0(void)", "{", " M4_YY_DECL_GUTS_VAR();", " return yytext;", "}", "]])", "", "%if-reentrant", "m4_ifdef( [[M4_YY_NO_SET_EXTRA]],,", "[[", "/** Set the user-defined data. This data is never touched by the scanner.", " * @param user_defined The data to be associated with this scanner.", " * M4_YY_DOC_PARAM", " */", "void yyset_extra YYFARGS1( YY_EXTRA_TYPE ,user_defined)", "{", " M4_YY_DECL_GUTS_VAR();", " yyextra = user_defined ;", "}", "]])", "%endif", "", "m4_ifdef( [[M4_YY_NO_SET_LINENO]],,", "[[", "/** Set the current line number.", " * @param line_number", " * M4_YY_DOC_PARAM", " */", "void yyset_lineno YYFARGS1( int ,line_number)", "{", " M4_YY_DECL_GUTS_VAR();", "", " m4_ifdef( [[M4_YY_REENTRANT]],", " [[", " /* lineno is only valid if an input buffer exists. */", " if (! YY_CURRENT_BUFFER )", " YY_FATAL_ERROR( \"yyset_lineno called with no buffer\" );", " ]])", " yylineno = line_number;", "}", "]])", "", "m4_ifdef( [[M4_YY_REENTRANT]],", "[[", "m4_ifdef( [[M4_YY_NO_SET_COLUMN]],,", "[[", "/** Set the current column.", " * @param line_number", " * M4_YY_DOC_PARAM", " */", "void yyset_column YYFARGS1( int , column_no)", "{", " M4_YY_DECL_GUTS_VAR();", "", " m4_ifdef( [[M4_YY_REENTRANT]],", " [[", " /* column is only valid if an input buffer exists. */", " if (! YY_CURRENT_BUFFER )", " YY_FATAL_ERROR( \"yyset_column called with no buffer\" );", " ]])", " yycolumn = column_no;", "}", "]])", "]])", "", "", "m4_ifdef( [[M4_YY_NO_SET_IN]],,", "[[", "/** Set the input stream. This does not discard the current", " * input buffer.", " * @param in_str A readable stream.", " * M4_YY_DOC_PARAM", " * @see yy_switch_to_buffer", " */", "void yyset_in YYFARGS1( FILE * ,in_str)", "{", " M4_YY_DECL_GUTS_VAR();", " yyin = in_str ;", "}", "]])", "", "m4_ifdef( [[M4_YY_NO_SET_OUT]],,", "[[", "void yyset_out YYFARGS1( FILE * ,out_str)", "{", " M4_YY_DECL_GUTS_VAR();", " yyout = out_str ;", "}", "]])", "", "", "m4_ifdef( [[M4_YY_NO_GET_DEBUG]],,", "[[", "int yyget_debug YYFARGS0(void)", "{", " M4_YY_DECL_GUTS_VAR();", " return yy_flex_debug;", "}", "]])", "", "m4_ifdef( [[M4_YY_NO_SET_DEBUG]],,", "[[", "void yyset_debug YYFARGS1( int ,bdebug)", "{", " M4_YY_DECL_GUTS_VAR();", " yy_flex_debug = bdebug ;", "}", "]])", "%endif", "", "%if-reentrant", "/* Accessor methods for yylval and yylloc */", "", "%if-bison-bridge", "m4_ifdef( [[M4_YY_NO_GET_LVAL]],,", "[[", "YYSTYPE * yyget_lval YYFARGS0(void)", "{", " M4_YY_DECL_GUTS_VAR();", " return yylval;", "}", "]])", "", "m4_ifdef( [[M4_YY_NO_SET_LVAL]],,", "[[", "void yyset_lval YYFARGS1( YYSTYPE * ,yylval_param)", "{", " M4_YY_DECL_GUTS_VAR();", " yylval = yylval_param;", "}", "]])", "", "m4_ifdef( [[]],", "[[", " m4_ifdef( [[M4_YY_NO_GET_LLOC]],,", " [[", "YYLTYPE *yyget_lloc YYFARGS0(void)", "{", " M4_YY_DECL_GUTS_VAR();", " return yylloc;", "}", " ]])", "", " m4_ifdef( [[M4_YY_NO_SET_LLOC]],,", " [[", "void yyset_lloc YYFARGS1( YYLTYPE * ,yylloc_param)", "{", " M4_YY_DECL_GUTS_VAR();", " yylloc = yylloc_param;", "}", " ]])", "]])", "", "%endif", "", "", "/* User-visible API */", "", "/* yylex_init is special because it creates the scanner itself, so it is", " * the ONLY reentrant function that doesn't take the scanner as the last argument.", " * That's why we explicitly handle the declaration, instead of using our macros.", " */", "m4_ifdef( [[M4_YY_NO_ANSI_FUNC_DEFS]],", "[[", "int yylex_init( ptr_yy_globals )", " yyscan_t* ptr_yy_globals;", "]],", "[[", "int yylex_init(yyscan_t* ptr_yy_globals)", "]])", "{", " if (ptr_yy_globals == NULL){", " errno = EINVAL;", " return 1;", " }", "", " *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );", "", " if (*ptr_yy_globals == NULL){", " errno = ENOMEM;", " return 1;", " }", "", " /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */", " memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));", "", " return yy_init_globals ( *ptr_yy_globals );", "}", "", "", "/* yylex_init_extra has the same functionality as yylex_init, but follows the", " * convention of taking the scanner as the last argument. Note however, that", " * this is a *pointer* to a scanner, as it will be allocated by this call (and", " * is the reason, too, why this function also must handle its own declaration).", " * The user defined value in the first argument will be available to yyalloc in", " * the yyextra field.", " */", "m4_ifdef( [[M4_YY_NO_ANSI_FUNC_DEFS]],", "[[", "int yylex_init_extra( yy_user_defined, ptr_yy_globals )", " YY_EXTRA_TYPE yy_user_defined;", " yyscan_t* ptr_yy_globals;", "]],", "[[", "int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals )", "]])", "{", " struct yyguts_t dummy_yyguts;", "", " yyset_extra (yy_user_defined, &dummy_yyguts);", "", " if (ptr_yy_globals == NULL){", " errno = EINVAL;", " return 1;", " }", " ", " *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );", " ", " if (*ptr_yy_globals == NULL){", " errno = ENOMEM;", " return 1;", " }", " ", " /* By setting to 0xAA, we expose bugs in", " yy_init_globals. Leave at 0x00 for releases. */", " memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));", " ", " yyset_extra (yy_user_defined, *ptr_yy_globals);", " ", " return yy_init_globals ( *ptr_yy_globals );", "}", "", "%endif if-c-only", "", "", "%if-c-only", "static int yy_init_globals YYFARGS0(void)", "{", " M4_YY_DECL_GUTS_VAR();", " /* Initialization is the same as for the non-reentrant scanner.", " * This function is called from yylex_destroy(), so don't allocate here.", " */", "", "m4_ifdef( [[M4_YY_USE_LINENO]],", "[[", " m4_ifdef( [[M4_YY_NOT_REENTRANT]],", " [[", " /* We do not touch yylineno unless the option is enabled. */", " yylineno = 1;", " ]])", "]])", " YY_G(yy_buffer_stack) = 0;", " YY_G(yy_buffer_stack_top) = 0;", " YY_G(yy_buffer_stack_max) = 0;", " YY_G(yy_c_buf_p) = (char *) 0;", " YY_G(yy_init) = 0;", " YY_G(yy_start) = 0;", "", "m4_ifdef( [[M4_YY_HAS_START_STACK_VARS]],", "[[", " YY_G(yy_start_stack_ptr) = 0;", " YY_G(yy_start_stack_depth) = 0;", " YY_G(yy_start_stack) = NULL;", "]])", "", "m4_ifdef( [[M4_YY_USES_REJECT]],", "[[", " YY_G(yy_state_buf) = 0;", " YY_G(yy_state_ptr) = 0;", " YY_G(yy_full_match) = 0;", " YY_G(yy_lp) = 0;", "]])", "", "m4_ifdef( [[M4_YY_TEXT_IS_ARRAY]],", "[[", " YY_G(yytext_ptr) = 0;", " YY_G(yy_more_offset) = 0;", " YY_G(yy_prev_more_offset) = 0;", "]])", "", "/* Defined in main.c */", "#ifdef YY_STDINIT", " yyin = stdin;", " yyout = stdout;", "#else", " yyin = (FILE *) 0;", " yyout = (FILE *) 0;", "#endif", "", " /* For future reference: Set errno on error, since we are called by", " * yylex_init()", " */", " return 0;", "}", "%endif", "", "", "%if-c-only SNIP! this currently causes conflicts with the c++ scanner", "/* yylex_destroy is for both reentrant and non-reentrant scanners. */", "int yylex_destroy YYFARGS0(void)", "{", " M4_YY_DECL_GUTS_VAR();", "", " /* Pop the buffer stack, destroying each element. */", " while(YY_CURRENT_BUFFER){", " yy_delete_buffer( YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG );", " YY_CURRENT_BUFFER_LVALUE = NULL;", " yypop_buffer_state(M4_YY_CALL_ONLY_ARG);", " }", "", " /* Destroy the stack itself. */", " yyfree(YY_G(yy_buffer_stack) M4_YY_CALL_LAST_ARG);", " YY_G(yy_buffer_stack) = NULL;", "", "m4_ifdef( [[M4_YY_HAS_START_STACK_VARS]],", "[[", " /* Destroy the start condition stack. */", " yyfree( YY_G(yy_start_stack) M4_YY_CALL_LAST_ARG );", " YY_G(yy_start_stack) = NULL;", "]])", "", "m4_ifdef( [[M4_YY_USES_REJECT]],", "[[", " yyfree ( YY_G(yy_state_buf) M4_YY_CALL_LAST_ARG);", " YY_G(yy_state_buf) = NULL;", "]])", "", " /* Reset the globals. This is important in a non-reentrant scanner so the next time", " * yylex() is called, initialization will occur. */", " yy_init_globals( M4_YY_CALL_ONLY_ARG);", "", "%if-reentrant", " /* Destroy the main struct (reentrant only). */", " yyfree ( yyscanner M4_YY_CALL_LAST_ARG );", " yyscanner = NULL;", "%endif", " return 0;", "}", "%endif", "", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "/*", " * Internal utility routines.", " */", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "#ifndef yytext_ptr", "static void yy_flex_strncpy YYFARGS3( char*,s1, yyconst char *,s2, int,n)", "{", " int i;", " for ( i = 0; i < n; ++i )", " s1[i] = s2[i];", "}", "#endif", "]])", "", "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],", "[[", "#ifdef YY_NEED_STRLEN", "static int yy_flex_strlen YYFARGS1( yyconst char *,s)", "{", " int n;", " for ( n = 0; s[n]; ++n )", " ;", "", " return n;", "}", "#endif", "]])", "", "m4_ifdef( [[M4_YY_NO_FLEX_ALLOC]],,", "[[", "void *yyalloc YYFARGS1( yy_size_t ,size)", "{", " return (void *) malloc( size );", "}", "]])", "", "m4_ifdef( [[M4_YY_NO_FLEX_REALLOC]],,", "[[", "void *yyrealloc YYFARGS2( void *,ptr, yy_size_t ,size)", "{", " /* The cast to (char *) in the following accommodates both", " * implementations that use char* generic pointers, and those", " * that use void* generic pointers. It works with the latter", " * because both ANSI C and C++ allow castless assignment from", " * any pointer type to void*, and deal with argument conversions", " * as though doing an assignment.", " */", " return (void *) realloc( (char *) ptr, size );", "}", "]])", "", "m4_ifdef( [[M4_YY_NO_FLEX_FREE]],,", "[[", "void yyfree YYFARGS1( void *,ptr)", "{", " free( (char *) ptr ); /* see yyrealloc() for (char *) cast */", "}", "]])", "", "%if-tables-serialization definitions", "#ifdef FLEX_SCANNER", "/*", "dnl tables_shared.c - tables serialization code", "dnl ", "dnl Copyright (c) 1990 The Regents of the University of California.", "dnl All rights reserved.", "dnl ", "dnl This code is derived from software contributed to Berkeley by", "dnl Vern Paxson.", "dnl ", "dnl The United States Government has rights in this work pursuant", "dnl to contract no. DE-AC03-76SF00098 between the United States", "dnl Department of Energy and the University of California.", "dnl ", "dnl This file is part of flex.", "dnl ", "dnl Redistribution and use in source and binary forms, with or without", "dnl modification, are permitted provided that the following conditions", "dnl are met:", "dnl ", "dnl 1. Redistributions of source code must retain the above copyright", "dnl notice, this list of conditions and the following disclaimer.", "dnl 2. Redistributions in binary form must reproduce the above copyright", "dnl notice, this list of conditions and the following disclaimer in the", "dnl documentation and/or other materials provided with the distribution.", "dnl ", "dnl Neither the name of the University nor the names of its contributors", "dnl may be used to endorse or promote products derived from this software", "dnl without specific prior written permission.", "dnl ", "dnl THIS SOFTWARE IS PROVIDED `AS IS' AND WITHOUT ANY EXPRESS OR", "dnl IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED", "dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR", "dnl PURPOSE.", "dnl ", "*/", " ", "/* This file is meant to be included in both the skeleton and the actual", " * flex code (hence the name \"_shared\"). ", " */", "#ifndef yyskel_static", "#define yyskel_static static", "#endif", "#else", "#include \"flexdef.h\"", "#include \"tables.h\"", "#ifndef yyskel_static", "#define yyskel_static", "#endif", "#endif", "", "", "/** Get the number of integers in this table. This is NOT the", " * same thing as the number of elements.", " * @param td the table ", " * @return the number of integers in the table", " */", "yyskel_static flex_int32_t yytbl_calc_total_len (const struct yytbl_data *tbl)", "{", " flex_int32_t n;", "", " /* total number of ints */", " n = tbl->td_lolen;", " if (tbl->td_hilen > 0)", " n *= tbl->td_hilen;", "", " if (tbl->td_id == YYTD_ID_TRANSITION)", " n *= 2;", " return n;", "}", "", "", "static int yytbl_read8 (void *v, struct yytbl_reader * rd)", "{", " errno = 0;", " if (fread (v, sizeof (flex_uint8_t), 1, rd->fp) != 1){", " errno = EIO;", " return -1;", " }", " rd->bread += sizeof(flex_uint8_t);", " return 0;", "}", "", "static int yytbl_read16 (void *v, struct yytbl_reader * rd)", "{", " errno = 0;", " if (fread (v, sizeof (flex_uint16_t), 1, rd->fp) != 1){", " errno = EIO;", " return -1;", " }", " *((flex_uint16_t *) v) = ntohs (*((flex_uint16_t *) v));", " rd->bread += sizeof(flex_uint16_t);", " return 0;", "}", "", "static int yytbl_read32 (void *v, struct yytbl_reader * rd)", "{", " errno = 0;", " if (fread (v, sizeof (flex_uint32_t), 1, rd->fp) != 1){", " errno = EIO;", " return -1;", " }", " *((flex_uint32_t *) v) = ntohl (*((flex_uint32_t *) v));", " rd->bread += sizeof(flex_uint32_t);", " return 0;", "}", "", "/** Read the header */", "static int yytbl_hdr_read YYFARGS2(struct yytbl_hdr *, th, struct yytbl_reader *, rd)", "{", " int bytes;", " memset (th, 0, sizeof (struct yytbl_hdr));", "", " if (yytbl_read32 (&(th->th_magic), rd) != 0)", " return -1;", "", " if (th->th_magic != YYTBL_MAGIC){", " YY_FATAL_ERROR( \"bad magic number\" ); /* TODO: not fatal. */", " return -1;", " }", "", " if (yytbl_read32 (&(th->th_hsize), rd) != 0", " || yytbl_read32 (&(th->th_ssize), rd) != 0", " || yytbl_read16 (&(th->th_flags), rd) != 0)", " return -1;", "", " /* Sanity check on header size. Greater than 1k suggests some funny business. */", " if (th->th_hsize < 16 || th->th_hsize > 1024){", " YY_FATAL_ERROR( \"insane header size detected\" ); /* TODO: not fatal. */", " return -1;", " }", "", " /* Allocate enough space for the version and name fields */", " bytes = th->th_hsize - 14;", " th->th_version = (char *) yyalloc (bytes M4_YY_CALL_LAST_ARG);", " if ( ! th->th_version )", " YY_FATAL_ERROR( \"out of dynamic memory in yytbl_hdr_read()\" );", "", " /* we read it all into th_version, and point th_name into that data */", " if (fread (th->th_version, 1, bytes, rd->fp) != bytes){", " errno = EIO;", " yyfree(th->th_version M4_YY_CALL_LAST_ARG);", " th->th_version = NULL;", " return -1;", " }", " else", " rd->bread += bytes;", "", " th->th_name = th->th_version + strlen (th->th_version) + 1;", " return 0;", "}", "", "/** lookup id in the dmap list.", " * @param dmap pointer to first element in list", " * @return NULL if not found.", " */", "static struct yytbl_dmap *yytbl_dmap_lookup YYFARGS2(struct yytbl_dmap *, dmap,", " int, id)", "{", " while (dmap->dm_id)", " if (dmap->dm_id == id)", " return dmap;", " else", " dmap++;", " return NULL;", "}", "", "/** Read a table while mapping its contents to the local array. ", " * @param dmap used to performing mapping", " * @return 0 on success", " */", "static int yytbl_data_load YYFARGS2(struct yytbl_dmap *, dmap, struct yytbl_reader*, rd)", "{", " struct yytbl_data td;", " struct yytbl_dmap *transdmap=0;", " int len, i, rv, inner_loop_count;", " void *p=0;", "", " memset (&td, 0, sizeof (struct yytbl_data));", "", " if (yytbl_read16 (&td.td_id, rd) != 0", " || yytbl_read16 (&td.td_flags, rd) != 0", " || yytbl_read32 (&td.td_hilen, rd) != 0", " || yytbl_read32 (&td.td_lolen, rd) != 0)", " return -1;", "", " /* Lookup the map for the transition table so we have it in case we need it", " * inside the loop below. This scanner might not even have a transition", " * table, which is ok.", " */", " transdmap = yytbl_dmap_lookup (dmap, YYTD_ID_TRANSITION M4_YY_CALL_LAST_ARG);", "", " if ((dmap = yytbl_dmap_lookup (dmap, td.td_id M4_YY_CALL_LAST_ARG)) == NULL){", " YY_FATAL_ERROR( \"table id not found in map.\" ); /* TODO: not fatal. */", " return -1;", " }", "", " /* Allocate space for table.", " * The --full yy_transition table is a special case, since we", " * need the dmap.dm_sz entry to tell us the sizeof the individual", " * struct members.", " */", " {", " size_t bytes;", "", " if ((td.td_flags & YYTD_STRUCT))", " bytes = sizeof(struct yy_trans_info) * td.td_lolen * (td.td_hilen ? td.td_hilen : 1);", " else", " bytes = td.td_lolen * (td.td_hilen ? td.td_hilen : 1) * dmap->dm_sz;", "", " if(M4_YY_TABLES_VERIFY)", " /* We point to the array itself */", " p = dmap->dm_arr; ", " else", " /* We point to the address of a pointer. */", " *dmap->dm_arr = p = (void *) yyalloc (bytes M4_YY_CALL_LAST_ARG);", " if ( ! p )", " YY_FATAL_ERROR( \"out of dynamic memory in yytbl_data_load()\" );", " }", "", " /* If it's a struct, we read 2 integers to get one element */", " if ((td.td_flags & YYTD_STRUCT) != 0)", " inner_loop_count = 2;", " else", " inner_loop_count = 1;", "", " /* read and map each element.", " * This loop iterates once for each element of the td_data array.", " * Notice that we increment 'i' in the inner loop.", " */", " len = yytbl_calc_total_len (&td);", " for (i = 0; i < len; ){", " int j;", "", "", " /* This loop really executes exactly 1 or 2 times.", " * The second time is to handle the second member of the", " * YYTD_STRUCT for the yy_transition array.", " */", " for (j = 0; j < inner_loop_count; j++, i++) {", " flex_int32_t t32;", "", " /* read into t32 no matter what the real size is. */", " {", " flex_int16_t t16;", " flex_int8_t t8;", "", " switch (YYTDFLAGS2BYTES (td.td_flags)) {", " case sizeof (flex_int32_t):", " rv = yytbl_read32 (&t32, rd);", " break;", " case sizeof (flex_int16_t):", " rv = yytbl_read16 (&t16, rd);", " t32 = t16;", " break;", " case sizeof (flex_int8_t):", " rv = yytbl_read8 (&t8, rd);", " t32 = t8;", " break;", " default: ", " YY_FATAL_ERROR( \"invalid td_flags\" ); /* TODO: not fatal. */", " return -1;", " }", " }", " if (rv != 0)", " return -1;", "", " /* copy into the deserialized array... */", "", " if ((td.td_flags & YYTD_STRUCT)) {", " /* t32 is the j'th member of a two-element struct. */", " void *v;", "", " v = j == 0 ? &(((struct yy_trans_info *) p)->yy_verify)", " : &(((struct yy_trans_info *) p)->yy_nxt);", "", " switch (dmap->dm_sz) {", " case sizeof (flex_int32_t):", " if (M4_YY_TABLES_VERIFY){", " if( ((flex_int32_t *) v)[0] != (flex_int32_t) t32)", " YY_FATAL_ERROR( \"tables verification failed at YYTD_STRUCT flex_int32_t\" );", " }else", " ((flex_int32_t *) v)[0] = (flex_int32_t) t32;", " break;", " case sizeof (flex_int16_t):", " if (M4_YY_TABLES_VERIFY ){", " if(((flex_int16_t *) v)[0] != (flex_int16_t) t32)", " YY_FATAL_ERROR( \"tables verification failed at YYTD_STRUCT flex_int16_t\" );", " }else", " ((flex_int16_t *) v)[0] = (flex_int16_t) t32;", " break;", " case sizeof(flex_int8_t):", " if (M4_YY_TABLES_VERIFY ){", " if( ((flex_int8_t *) v)[0] != (flex_int8_t) t32)", " YY_FATAL_ERROR( \"tables verification failed at YYTD_STRUCT flex_int8_t\" );", " }else", " ((flex_int8_t *) v)[0] = (flex_int8_t) t32;", " break;", " default:", " YY_FATAL_ERROR( \"invalid dmap->dm_sz for struct\" ); /* TODO: not fatal. */", " return -1;", " }", "", " /* if we're done with j, increment p */", " if (j == 1)", " p = (struct yy_trans_info *) p + 1;", " }", " else if ((td.td_flags & YYTD_PTRANS)) {", " /* t32 is an index into the transition array. */", " struct yy_trans_info *v;", "", "", " if (!transdmap){", " YY_FATAL_ERROR( \"transition table not found\" ); /* TODO: not fatal. */", " return -1;", " }", " ", " if( M4_YY_TABLES_VERIFY)", " v = &(((struct yy_trans_info *) (transdmap->dm_arr))[t32]);", " else", " v = &((*((struct yy_trans_info **) (transdmap->dm_arr)))[t32]);", "", " if(M4_YY_TABLES_VERIFY ){", " if( ((struct yy_trans_info **) p)[0] != v)", " YY_FATAL_ERROR( \"tables verification failed at YYTD_PTRANS\" );", " }else", " ((struct yy_trans_info **) p)[0] = v;", " ", " /* increment p */", " p = (struct yy_trans_info **) p + 1;", " }", " else {", " /* t32 is a plain int. copy data, then incrememnt p. */", " switch (dmap->dm_sz) {", " case sizeof (flex_int32_t):", " if(M4_YY_TABLES_VERIFY ){", " if( ((flex_int32_t *) p)[0] != (flex_int32_t) t32)", " YY_FATAL_ERROR( \"tables verification failed at flex_int32_t\" );", " }else", " ((flex_int32_t *) p)[0] = (flex_int32_t) t32;", " p = ((flex_int32_t *) p) + 1;", " break;", " case sizeof (flex_int16_t):", " if(M4_YY_TABLES_VERIFY ){", " if( ((flex_int16_t *) p)[0] != (flex_int16_t) t32)", " YY_FATAL_ERROR( \"tables verification failed at flex_int16_t\" );", " }else", " ((flex_int16_t *) p)[0] = (flex_int16_t) t32;", " p = ((flex_int16_t *) p) + 1;", " break;", " case sizeof (flex_int8_t):", " if(M4_YY_TABLES_VERIFY ){", " if( ((flex_int8_t *) p)[0] != (flex_int8_t) t32)", " YY_FATAL_ERROR( \"tables verification failed at flex_int8_t\" );", " }else", " ((flex_int8_t *) p)[0] = (flex_int8_t) t32;", " p = ((flex_int8_t *) p) + 1;", " break;", " default:", " YY_FATAL_ERROR( \"invalid dmap->dm_sz for plain int\" ); /* TODO: not fatal. */", " return -1;", " }", " }", " }", "", " }", "", " /* Now eat padding. */", " {", " int pad;", " pad = yypad64(rd->bread);", " while(--pad >= 0){", " flex_int8_t t8;", " if(yytbl_read8(&t8,rd) != 0)", " return -1;", " }", " }", "", " return 0;", "}", "", "%define-yytables The name for this specific scanner's tables.", "", "/* Find the key and load the DFA tables from the given stream. */", "static int yytbl_fload YYFARGS2(FILE *, fp, const char *, key)", "{", " int rv=0;", " struct yytbl_hdr th;", " struct yytbl_reader rd;", "", " rd.fp = fp;", " th.th_version = NULL;", "", " /* Keep trying until we find the right set of tables or end of file. */", " while (!feof(rd.fp)) {", " rd.bread = 0;", " if (yytbl_hdr_read (&th, &rd M4_YY_CALL_LAST_ARG) != 0){", " rv = -1;", " goto return_rv;", " }", "", " /* A NULL key means choose the first set of tables. */", " if (key == NULL)", " break;", "", " if (strcmp(th.th_name,key) != 0){", " /* Skip ahead to next set */", " fseek(rd.fp, th.th_ssize - th.th_hsize, SEEK_CUR);", " yyfree(th.th_version M4_YY_CALL_LAST_ARG);", " th.th_version = NULL;", " }", " else", " break;", " }", "", " while (rd.bread < th.th_ssize){", " /* Load the data tables */", " if(yytbl_data_load (yydmap,&rd M4_YY_CALL_LAST_ARG) != 0){", " rv = -1;", " goto return_rv;", " }", " }", "", "return_rv:", " if(th.th_version){", " yyfree(th.th_version M4_YY_CALL_LAST_ARG);", " th.th_version = NULL;", " }", "", " return rv;", "}", "", "/** Load the DFA tables for this scanner from the given stream. */", "int yytables_fload YYFARGS1(FILE *, fp)", "{", "", " if( yytbl_fload(fp, YYTABLES_NAME M4_YY_CALL_LAST_ARG) != 0)", " return -1;", " return 0;", "}", "", "/** Destroy the loaded tables, freeing memory, etc.. */", "int yytables_destroy YYFARGS0(void)", "{ ", " struct yytbl_dmap *dmap=0;", "", " if(!M4_YY_TABLES_VERIFY){", " /* Walk the dmap, freeing the pointers */", " for(dmap=yydmap; dmap->dm_id; dmap++) {", " void * v;", " v = dmap->dm_arr;", " if(v && *(char**)v){", " yyfree(*(char**)v M4_YY_CALL_LAST_ARG);", " *(char**)v = NULL;", " }", " }", " }", "", " return 0;", "}", "", "/* end table serialization code definitions */", "%endif", "", "", "m4_ifdef([[M4_YY_MAIN]], [[", "int main M4_YY_PARAMS(void);", "", "int main ()", "{", "", "%if-reentrant", " yyscan_t lexer;", " yylex_init(&lexer);", " yylex( lexer );", " yylex_destroy( lexer);", "", "%endif", "%if-not-reentrant", " yylex();", "%endif", "", " return 0;", "}", "]])", "", "%ok-for-header", "m4_ifdef( [[M4_YY_IN_HEADER]],", "[[", "#undef YY_NEW_FILE", "#undef YY_FLUSH_BUFFER", "#undef yy_set_bol", "#undef yy_new_buffer", "#undef yy_set_interactive", "#undef YY_DO_BEFORE_ACTION", "", "#ifdef YY_DECL_IS_OURS", "#undef YY_DECL_IS_OURS", "#undef YY_DECL", "#endif", "]])", 0 }; freebsd-buildutils-10.0/src/usr.bin/lex/initscan.c0000644000000000000000000050647212146745723017054 0ustar /* $FreeBSD$ */ #line 3 "" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 37 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ #if defined(__FreeBSD__) #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS #endif #include #include #else #define __dead2 #endif /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined(__FreeBSD__) || \ (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart(yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif extern yy_size_t yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ yy_size_t yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) #define yy_current_buffer YY_CURRENT_BUFFER /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ yy_size_t yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart (FILE *input_file ); void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); void yy_delete_buffer (YY_BUFFER_STATE b ); void yy_flush_buffer (YY_BUFFER_STATE b ); void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); void yypop_buffer_state (void ); static void yyensure_buffer_stack (void ); static void yy_load_buffer_state (void ); static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ); void *yyalloc (yy_size_t ); void *yyrealloc (void *,yy_size_t ); void yyfree (void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern int yylineno; int yylineno = 1; extern char *yytext; #define yytext_ptr yytext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); static void yy_fatal_error (yyconst char msg[] ) __dead2; /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ (yytext_ptr) -= (yy_more_len); \ yyleng = (size_t) (yy_cp - (yytext_ptr)); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 251 #define YY_END_OF_BUFFER 252 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_acclist[1223] = { 0, 248, 248, 252, 250, 251, 9, 250, 251, 20, 250, 251, 250, 251, 18, 250, 251, 1, 9, 250, 251, 19, 20, 250, 251, 250, 251, 250, 251, 250, 251, 250, 251, 17, 18, 250, 251, 164, 250, 251, 149, 164, 250, 251, 150, 250, 251, 164, 250, 251, 142, 164, 250, 251, 164, 250, 251, 161, 163, 164, 250, 251, 162, 163, 164, 250, 251, 163, 164, 250, 251, 163, 164, 250, 251, 164, 250, 251, 164, 250, 251, 164, 250, 251, 163, 164, 250, 251, 148, 149, 164, 250, 251, 138, 150, 250, 251, 164, 250, 251, 164, 250, 251, 140, 164, 250, 251, 141, 164, 250, 251, 136, 250, 251, 137, 250, 251, 136, 250, 251, 135, 136, 250, 251, 134, 136, 250, 251, 135, 136, 250, 251, 248, 249, 250, 251, 248, 249, 250, 251, 249, 250, 251, 249, 250, 251, 41, 250, 251, 42, 250, 251, 41, 250, 251, 41, 250, 251, 41, 250, 251, 41, 250, 251, 41, 250, 251, 41, 250, 251, 50, 250, 251, 49, 250, 251, 51, 250, 251, 250, 251, 170, 250, 251, 170, 250, 251, 165, 250, 251, 170, 250, 251, 166, 170, 250, 251, 167, 170, 250, 251, 169, 170, 250, 251, 171, 250, 251, 219, 250, 251, 220, 250, 251, 219, 250, 251, 217, 219, 250, 251, 216, 219, 250, 251, 218, 219, 250, 251, 172, 250, 251, 174, 250, 251, 172, 250, 251, 173, 250, 251, 172, 250, 251, 186, 250, 251, 186, 250, 251, 186, 250, 251, 186, 250, 251, 188, 190, 250, 251, 190, 250, 251, 188, 190, 250, 251, 188, 190, 250, 251, 188, 190, 250, 251, 188, 190, 250, 251, 189, 190, 250, 251, 233, 239, 250, 251, 238, 250, 251, 233, 239, 250, 251, 237, 239, 250, 251, 239, 250, 251, 239, 250, 251, 235, 239, 250, 251, 235, 239, 250, 251, 235, 239, 250, 251, 234, 239, 250, 251, 234, 239, 250, 251, 229, 239, 250, 251, 230, 239, 250, 251, 250, 251, 131, 250, 251, 250, 251, 25, 250, 251, 26, 250, 251, 25, 250, 251, 22, 250, 251, 25, 250, 251, 25, 250, 251, 240, 244, 250, 251, 242, 250, 251, 240, 244, 250, 251, 243, 244, 250, 251, 244, 250, 251, 227, 250, 251, 227, 250, 251, 228, 250, 251, 227, 250, 251, 227, 250, 251, 227, 250, 251, 227, 250, 251, 227, 250, 251, 227, 250, 251, 227, 250, 251, 130, 250, 251, 53, 130, 250, 251, 52, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 54, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 130, 250, 251, 37, 250, 251, 34, 250, 251, 37, 250, 251, 35, 37, 250, 251, 48, 250, 251, 45, 250, 251, 250, 251, 48, 250, 251, 48, 250, 251, 44, 250, 251, 43, 250, 251, 176, 250, 251, 175, 250, 251, 177, 250, 251, 178, 250, 251, 179, 250, 251, 180, 250, 251, 181, 250, 251, 182, 250, 251, 183, 250, 251, 32, 250, 251, 33, 250, 251, 32, 250, 251, 31, 250, 251, 29, 250, 251, 30, 250, 251, 29, 250, 251, 28, 250, 251, 9, 20, 18, 1, 9, 19, 20, 16, 10, 16, 4, 16, 5, 2, 17, 18, 149, 150, 144, 160, 158, 154, 154, 245, 245, 245, 143, 148, 149, 138, 150, 140, 141, 153, 139, 137, 135, 134, 134, 132, 135, 133, 135, 248, 248, 246, 247, 42, 39, 40, 50, 49, 51, 165, 165, 168, 169, 220, 216, 174, 184, 185, 190, 187, 233, 238, 236, 222, 235, 235, 235, 231, 232, 131, 26, 21, 23, 24, 240, 242, 241, 228, 221, 225, 226, 53, 52, 129, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 55, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 36, 35, 45, 46, 47, 32, 33, 30, 27, 16, 10, 16, 14, 4, 16, 5, 6, 145, 146, 159, 154, 154, 154, 154, 154, 245, 245, 156, 155, 157, 139, 145, 147, 153, 132, 135, 133, 135, 38, 235, 235, 221, 130, 130, 130, 130, 130, 130, 130, 67, 130, 130, 130, 130, 72, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 14, 15, 4, 8, 16, 5, 154, 154, 154, 154, 154, 154, 154, 245, 157, 235, 235, 56, 57, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 73, 130, 74, 130, 130, 130, 130, 130, 79, 130, 130, 130, 130, 130, 130, 130, 130, 84, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 93, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 15, 8, 16, 8, 16, 8, 16, 154, 154, 154, 154, 154, 154, 154, 215, 235, 235, 58, 130, 130, 130, 60, 130, 130, 64, 130, 130, 130, 130, 130, 70, 130, 130, 130, 130, 75, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 87, 130, 130, 130, 130, 130, 91, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 3, 8, 16, 7, 8, 16, 154, 154, 154, 223, 224, 223, 235, 224, 235, 130, 130, 130, 63, 130, 130, 130, 130, 130, 130, 130, 130, 126, 130, 130, 130, 130, 130, 130, 130, 130, 130, 124, 130, 130, 86, 130, 130, 89, 130, 130, 90, 130, 130, 130, 130, 105, 130, 130, 95, 130, 130, 96, 130, 12, 13, 152, 151, 152, 130, 130, 130, 130, 130, 130, 130, 68, 130, 130, 71, 130, 130, 130, 130, 130, 130, 130, 123, 130, 130, 83, 130, 130, 130, 88, 130, 130, 92, 130, 103, 130, 125, 130, 130, 130, 151, 130, 130, 130, 130, 130, 130, 130, 69, 130, 130, 130, 130, 130, 80, 130, 130, 130, 130, 130, 130, 130, 114, 94, 130, 130, 115, 11, 191, 215, 192, 215, 193, 215, 194, 215, 195, 215, 196, 215, 197, 215, 198, 215, 199, 215, 200, 215, 201, 215, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 85, 130, 130, 130, 116, 104, 130, 117, 202, 215, 203, 215, 204, 215, 205, 215, 206, 215, 207, 215, 208, 215, 209, 215, 210, 215, 211, 215, 212, 215, 213, 215, 130, 130, 130, 130, 130, 130, 130, 122, 130, 130, 130, 77, 130, 130, 130, 130, 130, 130, 110, 120, 118, 111, 121, 119, 214, 215, 130, 130, 130, 130, 130, 130, 130, 126, 130, 76, 130, 130, 82, 130, 130, 127, 130, 130, 106, 108, 107, 109, 130, 130, 130, 65, 130, 130, 130, 130, 130, 78, 130, 130, 112, 113, 98, 99, 130, 130, 130, 130, 130, 130, 130, 128, 130, 97, 101, 130, 130, 130, 130, 130, 68, 130, 130, 100, 102, 130, 130, 62, 130, 66, 130, 130, 130, 130, 61, 130, 69, 130, 130, 130, 81, 130, 59, 130 } ; static yyconst flex_int16_t yy_accept[1108] = { 0, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 6, 9, 12, 14, 17, 21, 25, 27, 29, 31, 33, 37, 40, 44, 47, 50, 54, 57, 62, 67, 71, 75, 78, 81, 84, 88, 93, 97, 100, 103, 107, 111, 114, 117, 120, 124, 128, 132, 136, 140, 143, 146, 149, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, 181, 184, 187, 190, 193, 197, 201, 205, 208, 211, 214, 217, 221, 225, 229, 232, 235, 238, 241, 244, 247, 250, 253, 256, 260, 263, 267, 271, 275, 279, 283, 287, 290, 294, 298, 301, 304, 308, 312, 316, 320, 324, 328, 332, 334, 337, 339, 342, 345, 348, 351, 354, 357, 361, 364, 368, 372, 375, 378, 381, 384, 387, 390, 393, 396, 399, 402, 405, 408, 412, 415, 418, 421, 424, 427, 431, 434, 437, 440, 443, 446, 449, 452, 455, 458, 461, 464, 467, 470, 473, 476, 479, 482, 485, 488, 491, 494, 497, 500, 503, 507, 510, 513, 515, 518, 521, 524, 527, 530, 533, 536, 539, 542, 545, 548, 551, 554, 557, 560, 563, 566, 569, 572, 575, 578, 579, 580, 580, 581, 583, 585, 585, 585, 585, 586, 588, 588, 588, 588, 588, 589, 590, 591, 591, 592, 594, 595, 596, 596, 596, 596, 597, 597, 598, 599, 599, 600, 601, 601, 602, 603, 604, 604, 604, 605, 605, 607, 609, 609, 609, 609, 610, 611, 612, 613, 613, 614, 615, 616, 617, 619, 621, 622, 623, 624, 625, 626, 626, 626, 627, 628, 628, 629, 630, 631, 631, 632, 632, 633, 634, 635, 636, 637, 638, 638, 639, 640, 641, 642, 643, 644, 644, 645, 645, 646, 647, 648, 649, 650, 651, 651, 652, 652, 653, 654, 655, 656, 657, 658, 659, 659, 659, 660, 661, 662, 663, 664, 665, 665, 666, 666, 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, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 707, 708, 710, 710, 711, 711, 711, 711, 711, 711, 712, 713, 714, 714, 715, 715, 716, 716, 717, 717, 718, 718, 719, 720, 720, 721, 722, 723, 724, 725, 726, 727, 727, 728, 730, 731, 731, 732, 732, 734, 736, 736, 736, 736, 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 738, 739, 740, 740, 740, 741, 742, 743, 744, 745, 746, 747, 749, 750, 751, 752, 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, 788, 788, 788, 788, 790, 790, 790, 790, 790, 790, 790, 791, 793, 794, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 820, 822, 823, 824, 825, 826, 828, 829, 830, 831, 832, 833, 834, 835, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 857, 857, 857, 857, 858, 858, 858, 858, 858, 858, 860, 862, 864, 864, 865, 866, 867, 868, 869, 870, 871, 871, 871, 871, 871, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 873, 874, 876, 877, 878, 880, 881, 883, 884, 885, 886, 887, 889, 890, 891, 892, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 907, 908, 909, 910, 911, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 923, 923, 923, 923, 924, 924, 924, 924, 926, 927, 929, 929, 930, 931, 932, 932, 932, 933, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 936, 938, 939, 940, 941, 943, 944, 945, 946, 947, 948, 949, 950, 952, 953, 954, 955, 956, 957, 958, 959, 960, 962, 963, 965, 966, 968, 969, 971, 972, 973, 974, 976, 976, 977, 979, 980, 980, 982, 982, 982, 982, 982, 982, 983, 983, 984, 984, 985, 985, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 988, 989, 990, 991, 992, 993, 994, 996, 997, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1007, 1008, 1010, 1011, 1012, 1014, 1015, 1017, 1019, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1022, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1033, 1034, 1035, 1036, 1037, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1045, 1045, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1048, 1049, 1049, 1049, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1051, 1051, 1053, 1055, 1057, 1059, 1061, 1063, 1065, 1067, 1069, 1071, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1089, 1090, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1092, 1092, 1094, 1094, 1094, 1094, 1094, 1094, 1095, 1095, 1095, 1095, 1095, 1095, 1097, 1099, 1101, 1103, 1105, 1107, 1109, 1111, 1113, 1115, 1117, 1119, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1128, 1129, 1130, 1132, 1133, 1134, 1135, 1136, 1137, 1137, 1137, 1138, 1138, 1139, 1140, 1141, 1141, 1141, 1141, 1142, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1154, 1156, 1157, 1159, 1160, 1162, 1163, 1164, 1165, 1165, 1166, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1168, 1169, 1170, 1172, 1173, 1174, 1175, 1176, 1178, 1179, 1180, 1181, 1182, 1182, 1182, 1182, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1192, 1193, 1193, 1194, 1194, 1195, 1196, 1197, 1198, 1199, 1201, 1202, 1203, 1204, 1205, 1206, 1208, 1210, 1211, 1212, 1213, 1215, 1217, 1218, 1219, 1221, 1223, 1223 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 4, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 6, 7, 8, 9, 1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19, 19, 19, 19, 19, 20, 21, 22, 23, 1, 24, 25, 26, 27, 1, 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, 44, 53, 54, 55, 56, 57, 1, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 44, 74, 75, 76, 77, 78, 79, 80, 81, 44, 82, 83, 84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int32_t yy_meta[85] = { 0, 1, 1, 2, 1, 3, 4, 1, 1, 1, 5, 1, 6, 1, 7, 1, 8, 1, 5, 9, 9, 9, 9, 10, 1, 1, 1, 1, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 14, 15, 1, 16, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 5, 1, 17 } ; static yyconst flex_int16_t yy_base[1201] = { 0, 0, 84, 167, 250, 171, 184, 174, 179, 192, 233, 196, 200, 334, 0, 3343, 3340, 203, 416, 206, 211, 187, 216, 276, 417, 500, 0, 210, 223, 421, 427, 436, 440, 583, 588, 669, 0, 277, 299, 584, 751, 579, 580, 576, 732, 279, 305, 310, 444, 3378, 3975, 228, 3975, 3371, 0, 322, 3975, 3358, 423, 827, 3328, 0, 3975, 755, 3975, 3337, 3975, 448, 3312, 3975, 3975, 3323, 3291, 222, 408, 444, 764, 3975, 3311, 230, 3289, 3975, 3975, 3975, 3306, 0, 3306, 164, 3304, 3975, 3236, 3217, 3975, 3975, 3266, 239, 119, 3215, 3212, 3180, 0, 3248, 3975, 3243, 3975, 476, 3227, 3222, 3975, 3168, 0, 3975, 3975, 3975, 3203, 3975, 464, 3975, 3975, 3975, 3186, 3975, 742, 3975, 3161, 751, 180, 3975, 3975, 3171, 0, 3149, 757, 3975, 0, 3975, 3149, 3975, 200, 3138, 0, 429, 241, 3097, 3092, 3975, 3975, 306, 3975, 323, 3975, 3975, 3126, 3108, 3072, 3069, 0, 3975, 3115, 3975, 0, 3975, 446, 3975, 3114, 3031, 3098, 435, 371, 3045, 3026, 3975, 3076, 3975, 3074, 3070, 439, 440, 3975, 578, 751, 586, 562, 735, 752, 0, 572, 577, 588, 786, 749, 396, 809, 727, 582, 747, 753, 764, 769, 580, 3975, 3975, 3067, 588, 3975, 3975, 3053, 3002, 2996, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 0, 3975, 3046, 3975, 3975, 3975, 3018, 2986, 837, 3975, 2998, 0, 847, 3975, 2997, 817, 777, 0, 0, 891, 903, 912, 924, 0, 774, 0, 451, 3975, 0, 858, 3975, 2996, 2914, 472, 3975, 2974, 2953, 3975, 791, 236, 822, 899, 3975, 275, 0, 2873, 2872, 3975, 2871, 949, 3975, 2949, 2850, 2918, 2906, 3975, 0, 3975, 796, 3975, 0, 0, 2925, 0, 0, 2597, 3975, 3975, 3975, 3975, 795, 794, 3975, 3975, 484, 0, 2597, 3975, 877, 2596, 2594, 2594, 3975, 0, 3975, 918, 3975, 1005, 3975, 3975, 3975, 3975, 0, 3975, 611, 3975, 0, 3975, 0, 853, 851, 3975, 3975, 490, 3975, 608, 3975, 3975, 3975, 3975, 0, 3975, 3975, 596, 2510, 3975, 0, 3975, 3975, 2588, 3975, 2581, 3975, 894, 906, 0, 911, 717, 727, 923, 728, 2571, 882, 930, 889, 902, 916, 917, 940, 928, 923, 940, 933, 0, 932, 3975, 935, 939, 951, 956, 1059, 964, 965, 1052, 955, 957, 1099, 2578, 3975, 1078, 3975, 3975, 3975, 0, 3975, 3975, 3975, 987, 0, 0, 1087, 3975, 2576, 1132, 985, 1046, 1058, 0, 1058, 0, 1009, 3975, 1016, 3975, 1057, 3975, 1099, 3975, 1068, 731, 1088, 1095, 1178, 1244, 1280, 988, 0, 3975, 3975, 2492, 1162, 3975, 3975, 1081, 0, 1086, 0, 0, 1098, 1105, 1100, 3975, 1167, 1245, 1246, 1247, 1250, 2539, 1248, 1249, 1258, 1244, 1251, 1259, 1321, 1233, 1224, 0, 1072, 1228, 1243, 1261, 1287, 1298, 1289, 1298, 1287, 0, 1299, 1228, 1308, 0, 1280, 1298, 1307, 1316, 1314, 1316, 2532, 1322, 1337, 1338, 1340, 1342, 1342, 1348, 1353, 1356, 1347, 1357, 1362, 1366, 1358, 1353, 1356, 1377, 1366, 1370, 1371, 1367, 1383, 1384, 1379, 1391, 1392, 1381, 1388, 1397, 1275, 1455, 3975, 1439, 1463, 1444, 1415, 1412, 1415, 0, 1409, 0, 1429, 1492, 1558, 1594, 1524, 2449, 1564, 1639, 3975, 3975, 1537, 1556, 1560, 1407, 2427, 1558, 1563, 1559, 1564, 1572, 1584, 1574, 1562, 1615, 1619, 1609, 1625, 1626, 1643, 1614, 1651, 1662, 1658, 1664, 1665, 1616, 1616, 1637, 3975, 3975, 1638, 1631, 2352, 1634, 1641, 1655, 1650, 1677, 1679, 1671, 1689, 0, 0, 1690, 1677, 1681, 1697, 0, 2348, 1684, 1694, 2274, 1686, 1685, 1695, 0, 1692, 1711, 1704, 1703, 1701, 1713, 1703, 1704, 1712, 0, 1717, 1731, 1731, 1719, 1723, 1722, 1741, 1726, 1742, 1734, 1747, 1741, 2241, 3975, 1464, 1485, 1729, 1743, 1740, 0, 1721, 1591, 2173, 1585, 2139, 1771, 1807, 1417, 962, 1426, 1755, 2049, 1745, 1769, 3975, 1774, 1782, 1789, 1775, 1796, 1791, 1810, 1800, 1820, 1822, 1821, 1823, 1832, 1831, 1838, 1840, 1853, 1856, 1854, 1855, 1863, 1865, 1861, 1846, 1862, 0, 1853, 1864, 0, 1857, 0, 2008, 1866, 1862, 1869, 0, 1874, 1893, 1870, 0, 1888, 1875, 1886, 1882, 1880, 1878, 1897, 1876, 1882, 1889, 1889, 0, 1904, 1895, 1899, 1919, 0, 1907, 1909, 1908, 1923, 1791, 1924, 1925, 1919, 1747, 1917, 1918, 1918, 1938, 1924, 1726, 1599, 1927, 1937, 1970, 3975, 1702, 1652, 1923, 1755, 1941, 1625, 1618, 3975, 3975, 1961, 1977, 1966, 1969, 1956, 1979, 1983, 1986, 1989, 1984, 1992, 1987, 1994, 1990, 1988, 1995, 2007, 2004, 2016, 2022, 1996, 2028, 2018, 2026, 0, 0, 1620, 1990, 2009, 0, 2035, 2020, 2035, 2029, 2024, 2025, 2029, 1589, 2049, 2041, 2052, 2048, 2053, 2054, 2044, 2057, 0, 2064, 0, 2048, 0, 1576, 0, 2064, 2070, 2056, 0, 2096, 2062, 0, 2067, 2108, 0, 1531, 2072, 2078, 1438, 1853, 3975, 2105, 3975, 2068, 3975, 1463, 3975, 1407, 1402, 1348, 1345, 1314, 1307, 1269, 1260, 1256, 1210, 1158, 2106, 2111, 2097, 2118, 2122, 2129, 2125, 2140, 2131, 2136, 2141, 2143, 2156, 2131, 2138, 2147, 2101, 2151, 2138, 2153, 0, 2141, 0, 2144, 2165, 2153, 2159, 2158, 2165, 0, 2165, 0, 2167, 2169, 0, 2178, 0, 0, 0, 2183, 2167, 2179, 2210, 2178, 2189, 2188, 2189, 2202, 2186, 2194, 2218, 2196, 2202, 1119, 1114, 2206, 2118, 3975, 1106, 1100, 1081, 1068, 1065, 1061, 1057, 972, 968, 965, 914, 925, 893, 881, 874, 869, 865, 861, 854, 843, 807, 802, 776, 2235, 2212, 2226, 2221, 2227, 2239, 2238, 2228, 0, 2228, 2239, 2242, 2252, 0, 2238, 2244, 2249, 2244, 2258, 2263, 2269, 2255, 3975, 2263, 2265, 2265, 2281, 2265, 2262, 0, 2285, 2288, 2274, 3975, 2277, 2280, 2295, 2279, 2280, 2283, 2303, 2283, 2330, 3975, 2335, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 735, 612, 608, 598, 441, 374, 261, 245, 202, 152, 149, 137, 165, 2296, 2303, 2304, 2320, 2326, 2316, 2324, 2329, 2324, 2316, 2319, 2335, 2324, 2327, 0, 2332, 2328, 2327, 2332, 2345, 2348, 2352, 2344, 3975, 2338, 0, 2338, 2343, 2357, 2362, 2357, 3975, 2371, 2356, 2359, 2358, 2380, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 3975, 128, 2384, 2382, 2373, 2387, 2376, 2378, 2378, 0, 2395, 2396, 0, 2385, 2384, 2405, 2403, 2401, 2405, 2413, 3975, 2401, 3975, 3975, 3975, 2409, 2416, 2404, 3975, 3975, 2400, 2422, 2422, 2414, 2417, 2417, 3975, 2421, 2421, 2418, 2424, 2441, 2442, 2443, 0, 0, 2453, 0, 2436, 0, 2451, 3975, 3975, 2445, 3975, 3975, 2446, 2457, 2445, 2461, 2464, 2462, 2468, 2473, 2466, 2460, 0, 2462, 2459, 2461, 2483, 0, 2463, 3975, 3975, 3975, 2484, 2488, 2476, 2482, 3975, 2495, 2485, 2497, 2495, 2501, 2506, 2493, 0, 3975, 2496, 3975, 2508, 2498, 2506, 2503, 2506, 2505, 0, 2520, 3975, 3975, 2522, 2514, 0, 0, 2529, 2514, 2515, 0, 0, 2533, 2539, 0, 0, 3975, 2601, 2618, 2635, 2652, 2669, 2686, 2703, 2720, 2737, 2754, 2771, 2788, 2805, 2822, 2839, 2856, 2873, 2890, 2907, 2917, 2933, 2942, 2958, 2975, 2986, 3002, 3019, 3036, 3053, 3063, 3079, 3096, 3113, 3127, 3137, 3153, 3170, 3187, 3204, 3215, 2009, 3227, 3244, 3254, 3270, 3287, 3294, 3300, 3316, 3326, 3342, 3359, 3376, 2564, 3386, 3403, 3420, 3437, 3454, 3471, 3488, 3505, 3522, 3532, 3548, 3562, 3572, 3588, 3605, 3622, 3639, 3650, 3662, 3679, 3696, 3713, 3730, 3740, 3749, 3765, 3782, 3799, 2571, 3809, 3826, 3843, 3860, 3877, 3885, 3890, 3906, 3923, 3940, 3957 } ; static yyconst flex_int16_t yy_def[1201] = { 0, 1106, 1106, 1107, 1107, 1108, 1109, 1110, 1110, 1111, 1111, 1112, 1112, 1106, 13, 1113, 1113, 1114, 1114, 1115, 1115, 1116, 1116, 1117, 1117, 1106, 25, 1118, 1118, 1119, 1119, 1120, 1120, 1121, 1121, 1106, 35, 1122, 1122, 1123, 1123, 1113, 1113, 1113, 1113, 1124, 1124, 1125, 1125, 1106, 1106, 1106, 1106, 1106, 1126, 1106, 1106, 1106, 1106, 1127, 1106, 1128, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1129, 1130, 1131, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1132, 1133, 1132, 1134, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1135, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1136, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1130, 1106, 1106, 1130, 1137, 1106, 1106, 1106, 1138, 1106, 1130, 1106, 1139, 1106, 1139, 1106, 1140, 1106, 1141, 1141, 1141, 1106, 1106, 1106, 1106, 1142, 1106, 1142, 1106, 1106, 1106, 1106, 1106, 1106, 1143, 1106, 1143, 1106, 1144, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1145, 1106, 1106, 1106, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1147, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1106, 1106, 1148, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1149, 1106, 1149, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1150, 1106, 1106, 1106, 1106, 1106, 1151, 1152, 1106, 1106, 1106, 1106, 1153, 1151, 1154, 1155, 1106, 1156, 1106, 1106, 1106, 1106, 1157, 1106, 1106, 1106, 1106, 1106, 1158, 1158, 1159, 1106, 1106, 1160, 1106, 1106, 1106, 1161, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1162, 1106, 1106, 1106, 1163, 1164, 1164, 1165, 1166, 1167, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1168, 1169, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1170, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1171, 1106, 1172, 1106, 1172, 1106, 1173, 1173, 1173, 1106, 1106, 1174, 1106, 1174, 1106, 1106, 1106, 1106, 1175, 1106, 1106, 1106, 1106, 1106, 1176, 1106, 1106, 1106, 1106, 1177, 1106, 1106, 1106, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1106, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1179, 1106, 1106, 1106, 1106, 1106, 1180, 1106, 1106, 1106, 1106, 1181, 1182, 1183, 1106, 1106, 1106, 1106, 1106, 1106, 1184, 1181, 1185, 1186, 1106, 1186, 1106, 1187, 1106, 1187, 1106, 1106, 1188, 1188, 1188, 1106, 1188, 1188, 1106, 1189, 1106, 1106, 1190, 1106, 1106, 1106, 1106, 1191, 1106, 1192, 1193, 1106, 1106, 1194, 1106, 1194, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1196, 1196, 1197, 1106, 1106, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1106, 1106, 1183, 1183, 1106, 1183, 1183, 1106, 1106, 1106, 1106, 1184, 1198, 1185, 1106, 1106, 1188, 414, 412, 412, 1188, 414, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1196, 1196, 1106, 1106, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1106, 1106, 1106, 1106, 1106, 1183, 1183, 1106, 1106, 1106, 1198, 1198, 1198, 1106, 511, 511, 1188, 414, 1188, 1188, 1188, 1106, 1106, 1106, 1106, 1106, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1196, 1196, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1106, 1106, 1106, 1106, 1106, 1199, 1106, 1106, 1198, 1106, 1198, 1106, 1188, 1188, 1188, 1106, 1106, 1106, 1106, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1196, 1196, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1106, 1178, 1178, 1178, 1106, 1178, 1106, 1106, 1106, 1106, 1199, 1106, 1199, 1106, 1106, 1106, 1106, 1106, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1106, 1106, 1106, 1106, 1106, 1106, 1178, 1178, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1200, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1178, 1178, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1200, 1106, 1200, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1195, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1178, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1106, 1106, 1106, 1106, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1106, 1106, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 0, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106 } ; static yyconst flex_int16_t yy_nxt[4060] = { 0, 50, 51, 52, 50, 53, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 50, 50, 50, 50, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 50, 50, 50, 50, 55, 56, 50, 57, 50, 58, 50, 59, 50, 50, 50, 50, 50, 50, 50, 50, 60, 50, 50, 50, 50, 50, 50, 50, 50, 50, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 50, 50, 50, 50, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 50, 50, 50, 63, 64, 291, 65, 66, 83, 67, 84, 89, 68, 69, 70, 70, 89, 1027, 70, 71, 86, 83, 992, 84, 50, 72, 991, 87, 70, 93, 309, 94, 101, 102, 291, 103, 101, 102, 990, 103, 113, 989, 114, 119, 315, 120, 121, 148, 119, 149, 120, 121, 115, 50, 73, 74, 116, 116, 116, 116, 148, 90, 149, 91, 228, 229, 90, 230, 91, 309, 93, 95, 94, 276, 124, 125, 99, 126, 96, 97, 283, 98, 284, 75, 70, 70, 76, 77, 316, 78, 66, 988, 67, 79, 122, 68, 69, 70, 70, 122, 95, 70, 71, 124, 125, 290, 126, 96, 80, 260, 261, 70, 95, 128, 201, 129, 221, 202, 222, 96, 97, 117, 98, 410, 411, 223, 130, 320, 415, 415, 203, 203, 203, 203, 987, 290, 201, 73, 74, 202, 81, 95, 221, 324, 222, 325, 277, 225, 96, 226, 986, 223, 203, 203, 203, 203, 320, 227, 232, 233, 324, 234, 325, 131, 132, 133, 75, 70, 70, 104, 105, 106, 104, 107, 104, 104, 104, 104, 104, 104, 104, 108, 104, 108, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 109, 104, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 104, 104, 104, 104, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 104, 104, 104, 113, 128, 114, 129, 291, 151, 235, 152, 263, 263, 985, 151, 115, 152, 130, 153, 116, 116, 116, 116, 157, 153, 158, 159, 157, 366, 158, 159, 225, 333, 226, 254, 254, 291, 255, 401, 334, 402, 227, 265, 264, 266, 319, 236, 267, 267, 267, 267, 290, 343, 344, 131, 132, 133, 366, 154, 405, 155, 406, 298, 299, 154, 300, 155, 305, 305, 305, 305, 431, 264, 432, 160, 319, 236, 324, 160, 325, 984, 290, 343, 344, 117, 134, 134, 135, 134, 136, 137, 134, 134, 134, 138, 134, 134, 134, 134, 134, 134, 134, 139, 134, 134, 134, 134, 134, 134, 134, 134, 134, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 141, 140, 140, 140, 140, 140, 140, 142, 143, 134, 144, 134, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 141, 140, 140, 140, 140, 140, 140, 142, 145, 134, 146, 162, 163, 205, 164, 206, 162, 163, 165, 164, 353, 211, 211, 165, 333, 216, 351, 166, 212, 212, 358, 334, 166, 379, 379, 379, 379, 324, 217, 325, 352, 213, 213, 346, 359, 347, 360, 315, 218, 348, 353, 214, 214, 219, 167, 371, 215, 215, 376, 167, 358, 168, 169, 207, 170, 208, 168, 169, 217, 170, 352, 213, 213, 346, 359, 347, 360, 218, 348, 983, 214, 214, 219, 167, 371, 215, 215, 376, 167, 982, 168, 316, 209, 981, 210, 168, 171, 172, 173, 171, 174, 175, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 176, 177, 171, 171, 171, 178, 171, 171, 179, 180, 181, 182, 183, 184, 185, 186, 187, 185, 185, 188, 189, 190, 191, 192, 185, 193, 194, 195, 196, 197, 198, 185, 199, 171, 171, 171, 171, 171, 179, 180, 181, 182, 183, 184, 185, 186, 187, 185, 185, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 185, 199, 171, 171, 171, 205, 216, 206, 249, 250, 370, 251, 263, 263, 452, 252, 354, 269, 270, 217, 271, 263, 263, 453, 272, 456, 372, 263, 263, 218, 349, 356, 364, 273, 219, 410, 411, 355, 350, 274, 370, 980, 365, 452, 264, 373, 354, 374, 375, 217, 941, 357, 453, 264, 456, 207, 372, 208, 218, 264, 349, 356, 364, 219, 387, 361, 355, 398, 350, 362, 235, 275, 365, 264, 408, 373, 940, 374, 375, 425, 357, 939, 264, 428, 209, 429, 210, 238, 264, 253, 228, 229, 367, 230, 387, 361, 412, 398, 253, 362, 232, 233, 368, 234, 408, 369, 239, 236, 240, 425, 240, 249, 250, 428, 251, 429, 240, 938, 252, 240, 241, 242, 367, 240, 243, 244, 410, 411, 937, 245, 298, 299, 368, 300, 369, 936, 239, 236, 240, 935, 240, 445, 446, 934, 390, 391, 240, 392, 933, 240, 241, 242, 240, 243, 244, 932, 390, 391, 245, 392, 246, 393, 393, 393, 393, 390, 391, 931, 392, 413, 413, 445, 446, 393, 393, 393, 393, 390, 391, 458, 392, 448, 393, 393, 393, 393, 461, 394, 305, 305, 305, 305, 253, 449, 393, 393, 393, 393, 450, 930, 462, 414, 269, 270, 454, 271, 395, 464, 458, 272, 459, 448, 451, 463, 460, 461, 394, 396, 273, 465, 929, 455, 466, 449, 274, 468, 467, 469, 450, 462, 414, 470, 471, 472, 454, 473, 395, 464, 474, 476, 459, 451, 463, 480, 460, 482, 481, 396, 475, 465, 455, 485, 466, 486, 468, 467, 275, 469, 262, 262, 470, 471, 472, 401, 473, 402, 410, 411, 474, 476, 401, 928, 402, 480, 927, 482, 481, 475, 926, 497, 485, 504, 486, 253, 433, 434, 435, 436, 437, 437, 438, 437, 437, 437, 437, 439, 437, 437, 437, 440, 437, 437, 441, 437, 442, 437, 437, 443, 437, 497, 504, 405, 444, 406, 433, 434, 435, 436, 437, 437, 438, 437, 437, 437, 437, 439, 437, 437, 437, 440, 437, 441, 437, 442, 437, 437, 443, 437, 477, 483, 499, 500, 478, 501, 505, 506, 484, 479, 379, 379, 379, 379, 508, 405, 431, 406, 432, 502, 502, 502, 502, 510, 511, 925, 520, 512, 512, 924, 477, 483, 548, 923, 478, 505, 922, 506, 484, 479, 487, 521, 488, 522, 508, 489, 490, 503, 391, 921, 392, 491, 492, 510, 410, 411, 520, 493, 494, 513, 523, 548, 495, 409, 393, 393, 393, 393, 920, 496, 487, 521, 488, 522, 919, 489, 490, 519, 519, 519, 519, 491, 492, 431, 914, 432, 493, 494, 513, 913, 523, 495, 409, 409, 861, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 410, 411, 860, 515, 409, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 409, 409, 409, 516, 516, 546, 547, 524, 524, 524, 524, 524, 524, 524, 524, 549, 558, 550, 599, 859, 600, 524, 524, 858, 525, 526, 528, 533, 527, 551, 535, 530, 857, 529, 534, 546, 547, 410, 411, 517, 517, 517, 517, 531, 549, 558, 532, 550, 517, 517, 517, 517, 517, 517, 525, 526, 528, 533, 527, 551, 535, 530, 529, 552, 534, 560, 553, 554, 555, 556, 856, 557, 531, 410, 411, 532, 559, 855, 517, 517, 517, 517, 517, 517, 1106, 561, 562, 563, 565, 536, 537, 538, 539, 552, 560, 540, 553, 554, 555, 556, 541, 557, 564, 567, 542, 568, 559, 543, 854, 544, 569, 853, 545, 570, 561, 571, 562, 563, 565, 536, 537, 538, 539, 572, 573, 540, 574, 575, 576, 577, 541, 564, 578, 567, 542, 568, 543, 581, 544, 582, 569, 545, 579, 570, 583, 571, 584, 585, 580, 586, 587, 606, 588, 572, 573, 589, 574, 575, 576, 577, 590, 591, 578, 592, 593, 852, 594, 581, 582, 598, 851, 595, 579, 583, 596, 597, 584, 585, 580, 586, 587, 588, 500, 602, 600, 589, 503, 391, 603, 392, 590, 591, 619, 592, 593, 594, 604, 499, 500, 598, 501, 595, 608, 596, 597, 601, 500, 599, 501, 600, 410, 411, 259, 602, 502, 502, 502, 502, 603, 410, 411, 619, 502, 502, 502, 502, 604, 601, 500, 850, 501, 607, 608, 409, 409, 848, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 410, 411, 613, 610, 409, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 409, 409, 409, 611, 611, 616, 409, 524, 524, 614, 614, 524, 524, 524, 845, 617, 618, 623, 828, 696, 697, 524, 698, 524, 625, 621, 626, 622, 775, 629, 776, 817, 624, 524, 700, 616, 628, 410, 411, 612, 612, 612, 612, 410, 411, 617, 618, 623, 612, 612, 612, 612, 612, 612, 625, 621, 626, 622, 524, 629, 627, 624, 806, 524, 524, 524, 628, 409, 524, 630, 781, 632, 644, 643, 524, 524, 636, 780, 612, 612, 612, 612, 612, 612, 615, 615, 615, 615, 631, 627, 633, 634, 524, 615, 615, 615, 615, 615, 615, 630, 524, 632, 644, 643, 779, 646, 636, 524, 645, 647, 635, 524, 649, 524, 524, 650, 651, 652, 631, 653, 633, 634, 637, 615, 615, 615, 615, 615, 615, 639, 638, 697, 640, 641, 642, 646, 654, 645, 647, 656, 635, 649, 655, 658, 650, 657, 651, 652, 659, 606, 660, 637, 661, 662, 692, 664, 665, 669, 639, 667, 638, 640, 668, 641, 642, 670, 654, 671, 672, 656, 673, 675, 655, 658, 657, 674, 676, 677, 659, 660, 678, 661, 679, 662, 664, 680, 665, 669, 667, 681, 683, 668, 682, 684, 670, 685, 687, 671, 672, 686, 673, 675, 688, 690, 674, 676, 677, 693, 689, 691, 678, 694, 679, 695, 703, 680, 701, 701, 705, 681, 683, 682, 684, 524, 524, 685, 687, 706, 686, 607, 768, 524, 688, 690, 410, 411, 693, 689, 524, 691, 524, 694, 695, 708, 703, 524, 710, 705, 707, 524, 410, 411, 702, 702, 702, 702, 709, 706, 711, 524, 712, 702, 702, 702, 702, 702, 702, 714, 713, 524, 524, 524, 524, 708, 764, 710, 715, 707, 716, 717, 524, 524, 775, 718, 776, 721, 709, 524, 711, 524, 712, 702, 702, 702, 702, 702, 702, 714, 713, 719, 723, 720, 524, 524, 524, 524, 715, 724, 716, 717, 524, 722, 524, 718, 524, 721, 726, 728, 752, 731, 732, 734, 727, 730, 748, 733, 736, 741, 738, 719, 723, 720, 725, 735, 729, 743, 740, 724, 739, 742, 722, 744, 745, 746, 747, 749, 726, 728, 731, 750, 732, 734, 727, 730, 733, 751, 736, 741, 738, 753, 754, 725, 755, 735, 729, 740, 756, 739, 757, 742, 744, 758, 745, 746, 747, 749, 759, 761, 750, 760, 762, 763, 765, 766, 767, 751, 769, 770, 753, 754, 771, 755, 772, 773, 777, 778, 756, 757, 696, 697, 758, 698, 410, 411, 409, 524, 759, 761, 760, 762, 524, 763, 765, 766, 767, 524, 769, 770, 524, 771, 410, 411, 772, 773, 777, 778, 524, 782, 524, 786, 784, 783, 524, 524, 785, 524, 524, 524, 524, 524, 787, 524, 791, 524, 524, 524, 363, 363, 807, 793, 737, 795, 802, 524, 788, 796, 524, 782, 786, 789, 784, 783, 790, 792, 785, 524, 797, 524, 794, 798, 787, 524, 791, 799, 800, 524, 804, 524, 807, 793, 808, 795, 802, 788, 803, 796, 805, 811, 789, 801, 809, 790, 792, 812, 813, 797, 814, 794, 815, 798, 810, 704, 816, 799, 800, 818, 804, 819, 820, 808, 821, 822, 823, 825, 803, 824, 805, 811, 826, 801, 809, 827, 829, 812, 813, 814, 830, 815, 831, 838, 810, 816, 839, 846, 775, 818, 776, 819, 820, 849, 821, 822, 823, 825, 824, 847, 524, 917, 826, 918, 827, 864, 829, 832, 833, 524, 830, 831, 834, 838, 524, 835, 839, 846, 836, 840, 841, 524, 849, 837, 842, 524, 878, 843, 524, 847, 844, 863, 524, 862, 524, 864, 865, 832, 833, 524, 868, 866, 834, 524, 524, 835, 524, 875, 836, 840, 841, 876, 837, 872, 842, 878, 867, 843, 870, 524, 844, 863, 862, 871, 880, 869, 865, 882, 873, 877, 868, 866, 874, 879, 881, 409, 883, 875, 884, 699, 885, 876, 886, 872, 887, 867, 888, 870, 889, 890, 891, 892, 871, 880, 869, 894, 882, 873, 895, 877, 896, 902, 874, 879, 881, 883, 901, 893, 884, 885, 903, 904, 886, 887, 905, 907, 888, 906, 889, 890, 891, 892, 897, 692, 911, 894, 898, 895, 912, 899, 896, 902, 915, 943, 908, 901, 893, 909, 524, 900, 903, 904, 944, 946, 905, 907, 906, 910, 945, 947, 948, 950, 897, 911, 949, 951, 898, 912, 952, 899, 953, 915, 942, 943, 908, 954, 955, 909, 900, 956, 666, 957, 944, 946, 958, 959, 910, 945, 960, 947, 948, 950, 961, 949, 962, 951, 963, 964, 952, 965, 953, 942, 966, 967, 954, 968, 955, 969, 971, 956, 957, 970, 972, 973, 958, 959, 974, 975, 960, 976, 979, 961, 977, 917, 962, 918, 963, 964, 917, 965, 918, 966, 967, 993, 994, 968, 995, 969, 971, 978, 970, 996, 972, 973, 997, 974, 975, 998, 976, 979, 999, 1000, 977, 1001, 663, 1002, 1003, 1004, 648, 1005, 1006, 1007, 993, 1008, 994, 1009, 995, 1010, 978, 1011, 1012, 996, 1013, 1014, 997, 1015, 1016, 998, 1017, 1018, 999, 1000, 1019, 1001, 1002, 1003, 1020, 1004, 1005, 1021, 1006, 1007, 1008, 1022, 1009, 1025, 1010, 1023, 1026, 1011, 1012, 1024, 1013, 1014, 1015, 1016, 1028, 1017, 1029, 1018, 1030, 1031, 1019, 1032, 1033, 1034, 1020, 1035, 1036, 1021, 1037, 1038, 1022, 1039, 1025, 1040, 1023, 1041, 1026, 1042, 1024, 1043, 1044, 1045, 1046, 1047, 1028, 1048, 1029, 1030, 1049, 1031, 1032, 1033, 1034, 1050, 1057, 1035, 1036, 1037, 1038, 1051, 1052, 1039, 1053, 1040, 1054, 1041, 1055, 1042, 1056, 1043, 1044, 1045, 1046, 1047, 1048, 1058, 1059, 1060, 1049, 1061, 620, 1062, 1063, 1050, 1057, 1064, 1065, 1066, 1051, 1052, 1067, 1053, 1068, 1054, 1069, 1055, 1070, 1056, 1071, 1072, 1073, 1074, 1075, 409, 1076, 1058, 1059, 1060, 1077, 1061, 1062, 1078, 1063, 1079, 1080, 1064, 1065, 1066, 1081, 1067, 1082, 1083, 1068, 1084, 1069, 1085, 1070, 1086, 1071, 1072, 1073, 1074, 1075, 1076, 1087, 1088, 1089, 1077, 1090, 1091, 1092, 1078, 1079, 1093, 1080, 1094, 566, 1095, 1081, 1082, 1096, 1083, 1097, 1084, 1098, 1085, 1099, 1086, 1100, 1101, 524, 1102, 1103, 1104, 1087, 1088, 1089, 1090, 1091, 1105, 1092, 416, 1093, 416, 420, 1094, 1095, 391, 518, 1096, 518, 1097, 378, 457, 1098, 342, 1099, 1100, 339, 1101, 1102, 1103, 336, 1104, 301, 299, 301, 296, 286, 1105, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 231, 231, 282, 231, 231, 423, 422, 421, 231, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 248, 248, 270, 248, 248, 420, 418, 417, 248, 259, 407, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 262, 254, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 268, 268, 268, 403, 268, 268, 250, 233, 229, 268, 280, 386, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 281, 385, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 384, 285, 382, 285, 285, 295, 381, 380, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 303, 303, 378, 303, 303, 342, 340, 339, 303, 308, 338, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 311, 337, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 317, 311, 311, 312, 336, 312, 335, 331, 312, 312, 312, 312, 312, 329, 328, 327, 312, 314, 326, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 318, 318, 322, 318, 318, 321, 317, 313, 318, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 330, 307, 330, 310, 330, 330, 330, 330, 330, 330, 330, 330, 330, 307, 330, 330, 330, 332, 306, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 341, 304, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 345, 345, 302, 299, 345, 345, 377, 301, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 383, 297, 383, 383, 383, 296, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 231, 231, 294, 231, 231, 293, 292, 289, 231, 388, 288, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 389, 287, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 397, 397, 286, 282, 279, 397, 399, 399, 278, 270, 258, 399, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 248, 248, 257, 248, 248, 256, 250, 247, 248, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 409, 233, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 229, 409, 409, 259, 1106, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 419, 419, 111, 419, 419, 111, 1106, 1106, 419, 419, 424, 1106, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 280, 1106, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 281, 1106, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 426, 1106, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 427, 1106, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 1106, 285, 1106, 285, 285, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 295, 1106, 1106, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 303, 303, 1106, 303, 303, 1106, 1106, 1106, 303, 312, 1106, 312, 1106, 1106, 312, 312, 312, 312, 312, 1106, 1106, 1106, 312, 314, 1106, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 318, 318, 1106, 318, 318, 1106, 1106, 1106, 318, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 330, 1106, 330, 1106, 330, 330, 330, 330, 330, 330, 330, 330, 330, 1106, 330, 330, 330, 447, 1106, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 341, 1106, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 345, 345, 1106, 1106, 345, 345, 377, 1106, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 383, 1106, 383, 383, 383, 1106, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 388, 1106, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 389, 1106, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 507, 507, 1106, 507, 507, 1106, 1106, 1106, 507, 509, 509, 1106, 509, 509, 1106, 1106, 1106, 509, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 409, 1106, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 1106, 409, 409, 419, 419, 1106, 419, 419, 1106, 1106, 1106, 419, 419, 424, 1106, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 426, 1106, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 427, 1106, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 437, 437, 437, 318, 318, 1106, 318, 318, 1106, 1106, 1106, 318, 447, 1106, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 605, 1106, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 49, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106 } ; static yyconst flex_int16_t yy_chk[4060] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 96, 3, 3, 5, 3, 5, 7, 3, 3, 3, 3, 8, 992, 3, 3, 6, 6, 942, 6, 21, 3, 941, 6, 3, 9, 126, 9, 11, 11, 96, 11, 12, 12, 940, 12, 17, 939, 17, 19, 138, 19, 19, 27, 20, 27, 20, 20, 17, 22, 3, 3, 17, 17, 17, 17, 28, 7, 28, 7, 51, 51, 8, 51, 8, 126, 10, 9, 10, 79, 21, 21, 10, 21, 9, 9, 87, 9, 87, 3, 3, 3, 4, 4, 138, 4, 4, 938, 4, 4, 19, 4, 4, 4, 4, 20, 9, 4, 4, 22, 22, 95, 22, 9, 4, 73, 73, 4, 10, 23, 37, 23, 45, 37, 45, 10, 10, 17, 10, 259, 259, 45, 23, 142, 263, 263, 37, 37, 37, 37, 937, 95, 38, 4, 4, 38, 4, 10, 46, 147, 46, 147, 79, 47, 10, 47, 936, 46, 38, 38, 38, 38, 142, 47, 55, 55, 149, 55, 149, 23, 23, 23, 4, 4, 4, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 18, 24, 18, 24, 168, 29, 58, 29, 74, 74, 935, 30, 18, 30, 24, 29, 18, 18, 18, 18, 31, 30, 31, 31, 32, 191, 32, 32, 48, 162, 48, 67, 67, 168, 67, 246, 162, 246, 48, 75, 74, 75, 141, 58, 75, 75, 75, 75, 167, 176, 177, 24, 24, 24, 191, 29, 253, 29, 253, 105, 105, 30, 105, 30, 116, 116, 116, 116, 294, 74, 294, 31, 141, 58, 323, 32, 323, 934, 167, 176, 177, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 33, 33, 39, 33, 39, 34, 34, 33, 34, 182, 41, 42, 34, 333, 43, 181, 33, 41, 42, 186, 333, 34, 203, 203, 203, 203, 325, 43, 325, 181, 41, 42, 179, 187, 179, 188, 314, 43, 179, 182, 41, 42, 43, 33, 194, 41, 42, 199, 34, 186, 33, 33, 39, 33, 39, 34, 34, 43, 34, 181, 41, 42, 179, 187, 179, 188, 43, 179, 933, 41, 42, 43, 33, 194, 41, 42, 199, 34, 932, 33, 314, 39, 931, 39, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 40, 44, 40, 63, 63, 193, 63, 122, 122, 347, 63, 183, 76, 76, 44, 76, 125, 125, 348, 76, 350, 195, 132, 132, 44, 180, 184, 190, 76, 44, 409, 409, 183, 180, 76, 193, 930, 190, 347, 122, 196, 183, 197, 198, 44, 873, 184, 348, 125, 350, 40, 195, 40, 44, 132, 180, 184, 190, 44, 236, 189, 183, 244, 180, 189, 235, 76, 190, 122, 258, 196, 872, 197, 198, 278, 184, 871, 125, 290, 40, 291, 40, 59, 132, 63, 228, 228, 192, 228, 236, 189, 260, 244, 76, 189, 232, 232, 192, 232, 258, 192, 59, 235, 59, 278, 59, 249, 249, 290, 249, 291, 59, 870, 249, 59, 59, 59, 192, 59, 59, 59, 260, 260, 869, 59, 298, 298, 192, 298, 192, 868, 59, 235, 59, 867, 59, 319, 320, 866, 239, 239, 59, 239, 865, 59, 59, 59, 59, 59, 59, 864, 240, 240, 59, 240, 59, 239, 239, 239, 239, 241, 241, 863, 241, 261, 261, 319, 320, 240, 240, 240, 240, 242, 242, 352, 242, 343, 241, 241, 241, 241, 354, 239, 305, 305, 305, 305, 249, 344, 242, 242, 242, 242, 346, 862, 355, 261, 269, 269, 349, 269, 241, 357, 352, 269, 353, 343, 346, 356, 353, 354, 239, 242, 269, 358, 861, 349, 359, 344, 269, 360, 359, 361, 346, 355, 261, 362, 364, 366, 349, 367, 241, 357, 368, 369, 353, 346, 356, 371, 353, 372, 371, 242, 368, 358, 349, 374, 359, 375, 360, 359, 269, 361, 415, 415, 362, 364, 366, 400, 367, 400, 614, 614, 368, 369, 402, 860, 402, 371, 859, 372, 371, 368, 858, 387, 374, 394, 375, 269, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 387, 394, 404, 307, 404, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 370, 373, 390, 390, 370, 390, 395, 396, 373, 370, 379, 379, 379, 379, 398, 406, 430, 406, 430, 390, 390, 390, 390, 408, 410, 857, 423, 411, 411, 856, 370, 373, 448, 855, 370, 395, 854, 396, 373, 370, 376, 425, 376, 428, 398, 376, 376, 393, 393, 853, 393, 376, 376, 408, 410, 410, 423, 376, 376, 411, 429, 448, 376, 411, 393, 393, 393, 393, 852, 376, 376, 425, 376, 428, 851, 376, 376, 420, 420, 420, 420, 376, 376, 432, 847, 432, 376, 376, 411, 846, 429, 376, 412, 412, 792, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 791, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 413, 413, 445, 446, 441, 433, 434, 435, 438, 439, 436, 442, 449, 459, 450, 498, 790, 498, 440, 443, 789, 433, 434, 436, 441, 435, 451, 443, 439, 788, 438, 442, 445, 446, 413, 413, 414, 414, 414, 414, 440, 449, 459, 440, 450, 414, 414, 414, 414, 414, 414, 433, 434, 436, 441, 435, 451, 443, 439, 438, 452, 442, 462, 453, 454, 455, 456, 787, 458, 440, 414, 414, 440, 460, 786, 414, 414, 414, 414, 414, 414, 444, 463, 464, 465, 467, 444, 444, 444, 444, 452, 462, 444, 453, 454, 455, 456, 444, 458, 466, 469, 444, 470, 460, 444, 785, 444, 471, 784, 444, 472, 463, 473, 464, 465, 467, 444, 444, 444, 444, 474, 475, 444, 476, 477, 478, 479, 444, 466, 480, 469, 444, 470, 444, 482, 444, 483, 471, 444, 481, 472, 484, 473, 485, 486, 481, 487, 488, 508, 489, 474, 475, 490, 476, 477, 478, 479, 491, 492, 480, 493, 494, 783, 495, 482, 483, 497, 782, 496, 481, 484, 496, 496, 485, 486, 481, 487, 488, 489, 501, 504, 501, 490, 503, 503, 505, 503, 491, 492, 523, 493, 494, 495, 506, 499, 499, 497, 499, 496, 510, 496, 496, 502, 502, 600, 502, 600, 613, 613, 613, 504, 499, 499, 499, 499, 505, 615, 615, 523, 502, 502, 502, 502, 506, 601, 601, 780, 601, 508, 510, 511, 511, 773, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 514, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 512, 512, 520, 514, 525, 527, 516, 516, 532, 526, 528, 770, 521, 522, 526, 758, 607, 607, 529, 607, 531, 528, 525, 529, 525, 693, 532, 693, 744, 527, 530, 609, 520, 531, 512, 512, 513, 513, 513, 513, 516, 516, 521, 522, 526, 513, 513, 513, 513, 513, 513, 528, 525, 529, 525, 535, 532, 530, 527, 733, 539, 533, 545, 531, 609, 534, 533, 704, 535, 546, 545, 536, 537, 539, 703, 513, 513, 513, 513, 513, 513, 517, 517, 517, 517, 534, 530, 536, 537, 538, 517, 517, 517, 517, 517, 517, 533, 540, 535, 546, 545, 699, 550, 539, 542, 547, 551, 538, 541, 553, 543, 544, 554, 555, 556, 534, 557, 536, 537, 540, 517, 517, 517, 517, 517, 517, 542, 541, 698, 542, 543, 544, 550, 557, 547, 551, 558, 538, 553, 557, 560, 554, 559, 555, 556, 563, 606, 564, 540, 565, 566, 692, 569, 570, 574, 542, 572, 541, 542, 573, 543, 544, 576, 557, 577, 578, 558, 579, 581, 557, 560, 559, 580, 582, 583, 563, 564, 584, 565, 586, 566, 569, 587, 570, 574, 572, 588, 590, 573, 589, 591, 576, 592, 594, 577, 578, 593, 579, 581, 595, 596, 580, 582, 583, 602, 595, 597, 584, 603, 586, 604, 616, 587, 611, 611, 618, 588, 590, 589, 591, 621, 624, 592, 594, 619, 593, 606, 686, 622, 595, 596, 701, 701, 602, 595, 623, 597, 626, 603, 604, 622, 616, 625, 624, 618, 621, 628, 611, 611, 612, 612, 612, 612, 623, 619, 625, 627, 626, 612, 612, 612, 612, 612, 612, 628, 627, 629, 631, 630, 632, 622, 682, 624, 629, 621, 630, 631, 634, 633, 774, 632, 774, 634, 623, 635, 625, 636, 626, 612, 612, 612, 612, 612, 612, 628, 627, 633, 636, 633, 637, 639, 640, 638, 629, 637, 630, 631, 643, 635, 641, 632, 642, 634, 639, 641, 668, 644, 645, 648, 640, 643, 664, 647, 650, 655, 653, 633, 636, 633, 638, 648, 642, 658, 654, 637, 653, 657, 635, 659, 661, 662, 663, 665, 639, 641, 644, 666, 645, 648, 640, 643, 647, 667, 650, 655, 653, 669, 670, 638, 671, 648, 642, 654, 673, 653, 674, 657, 659, 675, 661, 662, 663, 665, 676, 679, 666, 678, 680, 681, 683, 684, 685, 667, 687, 688, 669, 670, 689, 671, 690, 691, 694, 695, 673, 674, 696, 696, 675, 696, 700, 700, 700, 711, 676, 679, 678, 680, 707, 681, 683, 684, 685, 709, 687, 688, 710, 689, 702, 702, 690, 691, 694, 695, 708, 707, 712, 711, 709, 708, 713, 716, 710, 714, 718, 721, 715, 720, 712, 717, 716, 719, 722, 727, 1147, 1147, 734, 718, 652, 720, 727, 724, 713, 721, 723, 707, 711, 714, 709, 708, 715, 717, 710, 725, 722, 729, 719, 723, 712, 726, 716, 724, 725, 730, 729, 728, 734, 718, 735, 720, 727, 713, 728, 721, 730, 738, 714, 726, 737, 715, 717, 739, 740, 722, 741, 719, 742, 723, 737, 617, 743, 724, 725, 745, 729, 746, 747, 735, 748, 749, 750, 752, 728, 751, 730, 738, 754, 726, 737, 756, 760, 739, 740, 741, 761, 742, 762, 765, 737, 743, 767, 771, 776, 745, 776, 746, 747, 778, 748, 749, 750, 752, 751, 772, 795, 849, 754, 849, 756, 795, 760, 764, 764, 793, 761, 762, 764, 765, 794, 764, 767, 771, 764, 768, 768, 796, 778, 764, 768, 797, 809, 768, 799, 772, 768, 794, 798, 793, 801, 795, 796, 764, 764, 802, 799, 797, 764, 800, 803, 764, 804, 806, 764, 768, 768, 807, 764, 803, 768, 809, 798, 768, 801, 805, 768, 794, 793, 802, 811, 800, 796, 814, 804, 808, 799, 797, 805, 810, 812, 610, 816, 806, 817, 608, 818, 807, 819, 803, 820, 798, 821, 801, 823, 825, 826, 828, 802, 811, 800, 832, 814, 804, 833, 808, 834, 837, 805, 810, 812, 816, 836, 828, 817, 818, 838, 839, 819, 820, 840, 842, 821, 841, 823, 825, 826, 828, 835, 598, 844, 832, 835, 833, 845, 835, 834, 837, 848, 875, 843, 836, 828, 843, 874, 835, 838, 839, 876, 878, 840, 842, 841, 843, 877, 879, 880, 883, 835, 844, 881, 884, 835, 845, 885, 835, 886, 848, 874, 875, 843, 888, 889, 843, 835, 890, 571, 891, 876, 878, 892, 893, 843, 877, 894, 879, 880, 883, 895, 881, 897, 884, 898, 899, 885, 900, 886, 874, 901, 902, 888, 904, 889, 905, 908, 890, 891, 906, 909, 910, 892, 893, 911, 912, 894, 913, 915, 895, 914, 916, 897, 916, 898, 899, 918, 900, 918, 901, 902, 943, 944, 904, 945, 905, 908, 914, 906, 946, 909, 910, 947, 911, 912, 948, 913, 915, 949, 950, 914, 951, 568, 952, 953, 954, 552, 955, 956, 958, 943, 959, 944, 960, 945, 961, 914, 962, 963, 946, 964, 965, 947, 967, 969, 948, 970, 971, 949, 950, 972, 951, 952, 953, 973, 954, 955, 975, 956, 958, 959, 976, 960, 978, 961, 977, 979, 962, 963, 977, 964, 965, 967, 969, 993, 970, 994, 971, 995, 996, 972, 997, 998, 999, 973, 1001, 1002, 975, 1004, 1005, 976, 1006, 978, 1007, 977, 1008, 979, 1009, 977, 1010, 1012, 1016, 1017, 1018, 993, 1021, 994, 995, 1022, 996, 997, 998, 999, 1023, 1031, 1001, 1002, 1004, 1005, 1024, 1025, 1006, 1026, 1007, 1028, 1008, 1029, 1009, 1030, 1010, 1012, 1016, 1017, 1018, 1021, 1032, 1033, 1034, 1022, 1037, 524, 1039, 1041, 1023, 1031, 1044, 1047, 1048, 1024, 1025, 1049, 1026, 1050, 1028, 1051, 1029, 1052, 1030, 1053, 1054, 1055, 1056, 1058, 515, 1059, 1032, 1033, 1034, 1060, 1037, 1039, 1061, 1041, 1063, 1067, 1044, 1047, 1048, 1068, 1049, 1069, 1070, 1050, 1072, 1051, 1073, 1052, 1074, 1053, 1054, 1055, 1056, 1058, 1059, 1075, 1076, 1077, 1060, 1078, 1081, 1083, 1061, 1063, 1084, 1067, 1085, 468, 1086, 1068, 1069, 1087, 1070, 1088, 1072, 1090, 1073, 1093, 1074, 1094, 1097, 437, 1098, 1099, 1102, 1075, 1076, 1077, 1078, 1081, 1103, 1083, 1160, 1084, 1160, 419, 1085, 1086, 392, 1189, 1087, 1189, 1088, 377, 351, 1090, 341, 1093, 1094, 339, 1097, 1098, 1099, 334, 1102, 301, 300, 299, 296, 285, 1103, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1126, 1126, 282, 1126, 1126, 274, 273, 272, 1126, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1128, 1128, 271, 1128, 1128, 268, 266, 265, 1128, 1129, 256, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1130, 255, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1131, 1131, 1131, 252, 1131, 1131, 251, 234, 230, 1131, 1132, 227, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1133, 226, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 222, 1134, 208, 1134, 1134, 1135, 207, 206, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1136, 1136, 202, 1136, 1136, 175, 174, 172, 1136, 1137, 170, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1138, 169, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 166, 1138, 1138, 1139, 165, 1139, 164, 158, 1139, 1139, 1139, 1139, 1139, 155, 154, 153, 1139, 1140, 152, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1141, 1141, 144, 1141, 1141, 143, 139, 136, 1141, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1143, 131, 1143, 129, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 124, 1143, 1143, 1143, 1144, 120, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1145, 114, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1146, 1146, 109, 107, 1146, 1146, 1148, 106, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1149, 103, 1149, 1149, 1149, 101, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1150, 1150, 99, 1150, 1150, 98, 97, 94, 1150, 1151, 91, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1152, 90, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1153, 1153, 88, 86, 84, 1153, 1154, 1154, 80, 78, 72, 1154, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1156, 1156, 71, 1156, 1156, 68, 65, 60, 1156, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1158, 57, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 53, 1158, 1158, 1159, 49, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1161, 1161, 16, 1161, 1161, 15, 0, 0, 1161, 1161, 1162, 0, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1163, 0, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1164, 0, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1165, 0, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1166, 0, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 0, 1167, 0, 1167, 1167, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1169, 0, 0, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1170, 1170, 0, 1170, 1170, 0, 0, 0, 1170, 1171, 0, 1171, 0, 0, 1171, 1171, 1171, 1171, 1171, 0, 0, 0, 1171, 1172, 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1173, 1173, 0, 1173, 1173, 0, 0, 0, 1173, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1175, 0, 1175, 0, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 0, 1175, 1175, 1175, 1176, 0, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1177, 0, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1178, 1178, 0, 0, 1178, 1178, 1179, 0, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1180, 0, 1180, 1180, 1180, 0, 1180, 1180, 1180, 1180, 1180, 1180, 1180, 1180, 1180, 1180, 1180, 1181, 0, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1182, 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1184, 1184, 0, 1184, 1184, 0, 0, 0, 1184, 1185, 1185, 0, 1185, 1185, 0, 0, 0, 1185, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1188, 0, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 0, 1188, 1188, 1190, 1190, 0, 1190, 1190, 0, 0, 0, 1190, 1190, 1191, 0, 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1192, 0, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1193, 0, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1195, 1195, 1195, 1196, 1196, 0, 1196, 1196, 0, 0, 0, 1196, 1197, 0, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1198, 0, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106 } ; extern int yy_flex_debug; int yy_flex_debug = 0; static yy_state_type *yy_state_buf=0, *yy_state_ptr=0; static char *yy_full_match; static int yy_lp; #define REJECT \ { \ *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ \ yy_cp = (yy_full_match); /* restore poss. backed-over text */ \ ++(yy_lp); \ goto find_rule; \ } static int yy_more_flag = 0; static int yy_more_len = 0; #define yymore() ((yy_more_flag) = 1) #define YY_MORE_ADJ (yy_more_len) #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "scan.l" /* scan.l - scanner for flex input -*-C-*- */ #line 4 "scan.l" /* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */ /* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */ /* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #include "flexdef.h" #include "parse.h" extern bool tablesverify, tablesext; extern int trlcontxt; /* Set in parse.y for each rule. */ extern const char *escaped_qstart, *escaped_qend; #define ACTION_ECHO add_action( yytext ) #define ACTION_IFDEF(def, should_define) \ { \ if ( should_define ) \ action_define( def, 1 ); \ } #define ACTION_ECHO_QSTART add_action (escaped_qstart) #define ACTION_ECHO_QEND add_action (escaped_qend) #define ACTION_M4_IFDEF(def, should_define) \ do{ \ if ( should_define ) \ buf_m4_define( &m4defs_buf, def, NULL);\ else \ buf_m4_undefine( &m4defs_buf, def);\ } while(0) #define MARK_END_OF_PROLOG mark_prolog(); #define YY_DECL \ int flexscan() #define RETURNCHAR \ yylval = (unsigned char) yytext[0]; \ return CHAR; #define RETURNNAME \ if(yyleng < MAXLINE) \ { \ strcpy( nmstr, yytext ); \ } \ else \ { \ synerr(_("Input line too long\n")); \ FLEX_EXIT(EXIT_FAILURE); \ } \ return NAME; #define PUT_BACK_STRING(str, start) \ for ( i = strlen( str ) - 1; i >= start; --i ) \ unput((str)[i]) #define CHECK_REJECT(str) \ if ( all_upper( str ) ) \ reject = true; #define CHECK_YYMORE(str) \ if ( all_lower( str ) ) \ yymore_used = true; #define YY_USER_INIT \ if ( getenv("POSIXLY_CORRECT") ) \ posix_compat = true; #line 1990 "" #define INITIAL 0 #define SECT2 1 #define SECT2PROLOG 2 #define SECT3 3 #define CODEBLOCK 4 #define PICKUPDEF 5 #define SC 6 #define CARETISBOL 7 #define NUM 8 #define QUOTE 9 #define FIRSTCCL 10 #define CCL 11 #define ACTION 12 #define RECOVER 13 #define COMMENT 14 #define ACTION_STRING 15 #define PERCENT_BRACE_ACTION 16 #define OPTION 17 #define LINEDIR 18 #define CODEBLOCK_MATCH_BRACE 19 #define GROUP_WITH_PARAMS 20 #define GROUP_MINUS_PARAMS 21 #define EXTENDED_COMMENT 22 #define COMMENT_DISCARD 23 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int yylex_destroy (void ); int yyget_debug (void ); void yyset_debug (int debug_flag ); YY_EXTRA_TYPE yyget_extra (void ); void yyset_extra (YY_EXTRA_TYPE user_defined ); FILE *yyget_in (void ); void yyset_in (FILE * in_str ); FILE *yyget_out (void ); void yyset_out (FILE * out_str ); yy_size_t yyget_leng (void ); char *yyget_text (void ); int yyget_lineno (void ); void yyset_lineno (int line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap (void ); #else extern int yywrap (void ); #endif #endif #ifndef YY_NO_UNPUT static void yyunput (int c,char *buf_ptr ); #endif #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif static int yy_start_stack_ptr = 0; static int yy_start_stack_depth = 0; static int *yy_start_stack = NULL; static void yy_push_state (int new_state ); static void yy_pop_state (void ); /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int yylex (void); #define YY_DECL int yylex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ if ( yyleng > 0 ) \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \ (yytext[yyleng - 1] == '\n'); \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { yy_state_type yy_current_state; char *yy_cp, *yy_bp; int yy_act; #line 131 "scan.l" static int bracelevel, didadef, indented_code; static int doing_rule_action = false; static int option_sense; int doing_codeblock = false; int i, brace_depth=0, brace_start_line=0; Char nmdef[MAXLINE]; #line 2219 "" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif /* Create the reject buffer large enough to save one state per allowed character. */ if ( ! (yy_state_buf) ) (yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE ); if ( ! (yy_state_buf) ) YY_FATAL_ERROR( "out of dynamic memory in yylex()" ); if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { (yy_more_len) = 0; if ( (yy_more_flag) ) { (yy_more_len) = (yy_c_buf_p) - (yytext_ptr); (yy_more_flag) = 0; } yy_cp = (yy_c_buf_p); /* Support of yytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_current_state += YY_AT_BOL(); (yy_state_ptr) = (yy_state_buf); *(yy_state_ptr)++ = yy_current_state; yy_match: do { YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1107 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; *(yy_state_ptr)++ = yy_current_state; ++yy_cp; } while ( yy_base[yy_current_state] != 3975 ); yy_find_action: yy_current_state = *--(yy_state_ptr); (yy_lp) = yy_accept[yy_current_state]; goto find_rule; /* avoid `defined but not used' warning */ find_rule: /* we branch to this label when backing up */ for ( ; ; ) /* until we find what rule we matched */ { if ( (yy_lp) && (yy_lp) < yy_accept[yy_current_state + 1] ) { yy_act = yy_acclist[(yy_lp)]; { (yy_full_match) = yy_cp; break; } } --yy_cp; yy_current_state = *--(yy_state_ptr); (yy_lp) = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 1: YY_RULE_SETUP #line 142 "scan.l" indented_code = true; BEGIN(CODEBLOCK); YY_BREAK case 2: YY_RULE_SETUP #line 143 "scan.l" ACTION_ECHO; yy_push_state( COMMENT ); YY_BREAK case 3: YY_RULE_SETUP #line 144 "scan.l" yy_push_state( LINEDIR ); YY_BREAK case 4: YY_RULE_SETUP #line 145 "scan.l" return SCDECL; YY_BREAK case 5: YY_RULE_SETUP #line 146 "scan.l" return XSCDECL; YY_BREAK case 6: /* rule 6 can match eol */ YY_RULE_SETUP #line 147 "scan.l" { ++linenum; line_directive_out( (FILE *) 0, 1 ); indented_code = false; BEGIN(CODEBLOCK); } YY_BREAK case 7: /* rule 7 can match eol */ YY_RULE_SETUP #line 153 "scan.l" { brace_start_line = linenum; ++linenum; buf_linedir( &top_buf, infilename?infilename:"", linenum); brace_depth = 1; yy_push_state(CODEBLOCK_MATCH_BRACE); } YY_BREAK case 8: YY_RULE_SETUP #line 161 "scan.l" synerr( _("malformed '%top' directive") ); YY_BREAK case 9: YY_RULE_SETUP #line 163 "scan.l" /* discard */ YY_BREAK case 10: YY_RULE_SETUP #line 165 "scan.l" { sectnum = 2; bracelevel = 0; mark_defs1(); line_directive_out( (FILE *) 0, 1 ); BEGIN(SECT2PROLOG); return SECTEND; } YY_BREAK case 11: /* rule 11 can match eol */ YY_RULE_SETUP #line 174 "scan.l" yytext_is_array = false; ++linenum; YY_BREAK case 12: /* rule 12 can match eol */ YY_RULE_SETUP #line 175 "scan.l" yytext_is_array = true; ++linenum; YY_BREAK case 13: YY_RULE_SETUP #line 177 "scan.l" BEGIN(OPTION); return OPTION_OP; YY_BREAK case 14: /* rule 14 can match eol */ YY_RULE_SETUP #line 179 "scan.l" ++linenum; /* ignore */ YY_BREAK case 15: /* rule 15 can match eol */ YY_RULE_SETUP #line 180 "scan.l" ++linenum; /* ignore */ YY_BREAK /* xgettext: no-c-format */ case 16: /* rule 16 can match eol */ YY_RULE_SETUP #line 183 "scan.l" synerr( _( "unrecognized '%' directive" ) ); YY_BREAK case 17: YY_RULE_SETUP #line 185 "scan.l" { if(yyleng < MAXLINE) { strcpy( nmstr, yytext ); } else { synerr( _("Definition name too long\n")); FLEX_EXIT(EXIT_FAILURE); } didadef = false; BEGIN(PICKUPDEF); } YY_BREAK case 18: YY_RULE_SETUP #line 200 "scan.l" RETURNNAME; YY_BREAK case 19: /* rule 19 can match eol */ YY_RULE_SETUP #line 201 "scan.l" ++linenum; /* allows blank lines in section 1 */ YY_BREAK case 20: /* rule 20 can match eol */ YY_RULE_SETUP #line 202 "scan.l" ACTION_ECHO; ++linenum; /* maybe end of comment line */ YY_BREAK case 21: YY_RULE_SETUP #line 207 "scan.l" ACTION_ECHO; yy_pop_state(); YY_BREAK case 22: YY_RULE_SETUP #line 208 "scan.l" ACTION_ECHO; YY_BREAK case 23: YY_RULE_SETUP #line 209 "scan.l" ACTION_ECHO_QSTART; YY_BREAK case 24: YY_RULE_SETUP #line 210 "scan.l" ACTION_ECHO_QEND; YY_BREAK case 25: YY_RULE_SETUP #line 211 "scan.l" ACTION_ECHO; YY_BREAK case 26: /* rule 26 can match eol */ YY_RULE_SETUP #line 212 "scan.l" ++linenum; ACTION_ECHO; YY_BREAK /* This is the same as COMMENT, but is discarded rather than output. */ case 27: YY_RULE_SETUP #line 217 "scan.l" yy_pop_state(); YY_BREAK case 28: YY_RULE_SETUP #line 218 "scan.l" ; YY_BREAK case 29: YY_RULE_SETUP #line 219 "scan.l" ; YY_BREAK case 30: /* rule 30 can match eol */ YY_RULE_SETUP #line 220 "scan.l" ++linenum; YY_BREAK case 31: YY_RULE_SETUP #line 224 "scan.l" yy_pop_state(); YY_BREAK case 32: YY_RULE_SETUP #line 225 "scan.l" ; YY_BREAK case 33: /* rule 33 can match eol */ YY_RULE_SETUP #line 226 "scan.l" ++linenum; YY_BREAK case 34: /* rule 34 can match eol */ YY_RULE_SETUP #line 230 "scan.l" yy_pop_state(); YY_BREAK case 35: YY_RULE_SETUP #line 231 "scan.l" linenum = myctoi( yytext ); YY_BREAK case 36: YY_RULE_SETUP #line 233 "scan.l" { flex_free( (void *) infilename ); infilename = copy_string( yytext + 1 ); infilename[strlen( infilename ) - 1] = '\0'; } YY_BREAK case 37: YY_RULE_SETUP #line 238 "scan.l" /* ignore spurious characters */ YY_BREAK case 38: /* rule 38 can match eol */ YY_RULE_SETUP #line 242 "scan.l" ++linenum; BEGIN(INITIAL); YY_BREAK case 39: YY_RULE_SETUP #line 244 "scan.l" ACTION_ECHO_QSTART; YY_BREAK case 40: YY_RULE_SETUP #line 245 "scan.l" ACTION_ECHO_QEND; YY_BREAK case 41: YY_RULE_SETUP #line 246 "scan.l" ACTION_ECHO; YY_BREAK case 42: /* rule 42 can match eol */ YY_RULE_SETUP #line 248 "scan.l" { ++linenum; ACTION_ECHO; if ( indented_code ) BEGIN(INITIAL); } YY_BREAK case 43: YY_RULE_SETUP #line 257 "scan.l" { if( --brace_depth == 0){ /* TODO: Matched. */ yy_pop_state(); }else buf_strnappend(&top_buf, yytext, yyleng); } YY_BREAK case 44: YY_RULE_SETUP #line 265 "scan.l" { brace_depth++; buf_strnappend(&top_buf, yytext, yyleng); } YY_BREAK case 45: /* rule 45 can match eol */ YY_RULE_SETUP #line 270 "scan.l" { ++linenum; buf_strnappend(&top_buf, yytext, yyleng); } YY_BREAK case 46: YY_RULE_SETUP #line 275 "scan.l" buf_strnappend(&top_buf, escaped_qstart, strlen(escaped_qstart)); YY_BREAK case 47: YY_RULE_SETUP #line 276 "scan.l" buf_strnappend(&top_buf, escaped_qend, strlen(escaped_qend)); YY_BREAK case 48: YY_RULE_SETUP #line 278 "scan.l" { buf_strnappend(&top_buf, yytext, yyleng); } YY_BREAK case YY_STATE_EOF(CODEBLOCK_MATCH_BRACE): #line 282 "scan.l" { linenum = brace_start_line; synerr(_("Unmatched '{'")); yyterminate(); } YY_BREAK case 49: YY_RULE_SETUP #line 291 "scan.l" /* separates name and definition */ YY_BREAK case 50: YY_RULE_SETUP #line 293 "scan.l" { if(yyleng < MAXLINE) { strcpy( (char *) nmdef, yytext ); } else { format_synerr( _("Definition value for {%s} too long\n"), nmstr); FLEX_EXIT(EXIT_FAILURE); } /* Skip trailing whitespace. */ for ( i = strlen( (char *) nmdef ) - 1; i >= 0 && (nmdef[i] == ' ' || nmdef[i] == '\t'); --i ) ; nmdef[i + 1] = '\0'; ndinstal( nmstr, nmdef ); didadef = true; } YY_BREAK case 51: /* rule 51 can match eol */ YY_RULE_SETUP #line 315 "scan.l" { if ( ! didadef ) synerr( _( "incomplete name definition" ) ); BEGIN(INITIAL); ++linenum; } YY_BREAK case 52: /* rule 52 can match eol */ YY_RULE_SETUP #line 325 "scan.l" ++linenum; BEGIN(INITIAL); YY_BREAK case 53: YY_RULE_SETUP #line 326 "scan.l" option_sense = true; YY_BREAK case 54: YY_RULE_SETUP #line 328 "scan.l" return '='; YY_BREAK case 55: YY_RULE_SETUP #line 330 "scan.l" option_sense = ! option_sense; YY_BREAK case 56: YY_RULE_SETUP #line 332 "scan.l" csize = option_sense ? 128 : 256; YY_BREAK case 57: YY_RULE_SETUP #line 333 "scan.l" csize = option_sense ? 256 : 128; YY_BREAK case 58: YY_RULE_SETUP #line 335 "scan.l" long_align = option_sense; YY_BREAK case 59: YY_RULE_SETUP #line 336 "scan.l" { ACTION_M4_IFDEF( "M4""_YY_ALWAYS_INTERACTIVE", option_sense ); interactive = option_sense; } YY_BREAK case 60: YY_RULE_SETUP #line 340 "scan.l" yytext_is_array = option_sense; YY_BREAK case 61: YY_RULE_SETUP #line 341 "scan.l" ansi_func_defs = option_sense; YY_BREAK case 62: YY_RULE_SETUP #line 342 "scan.l" ansi_func_protos = option_sense; YY_BREAK case 63: YY_RULE_SETUP #line 343 "scan.l" backing_up_report = option_sense; YY_BREAK case 64: YY_RULE_SETUP #line 344 "scan.l" interactive = ! option_sense; YY_BREAK case 65: YY_RULE_SETUP #line 345 "scan.l" bison_bridge_lval = option_sense; YY_BREAK case 66: YY_RULE_SETUP #line 346 "scan.l" { if((bison_bridge_lloc = option_sense)) bison_bridge_lval = true; } YY_BREAK case 67: YY_RULE_SETUP #line 349 "scan.l" C_plus_plus = option_sense; YY_BREAK case 68: YY_RULE_SETUP #line 350 "scan.l" sf_set_case_ins(!option_sense); YY_BREAK case 69: YY_RULE_SETUP #line 351 "scan.l" sf_set_case_ins(option_sense); YY_BREAK case 70: YY_RULE_SETUP #line 352 "scan.l" ddebug = option_sense; YY_BREAK case 71: YY_RULE_SETUP #line 353 "scan.l" spprdflt = ! option_sense; YY_BREAK case 72: YY_RULE_SETUP #line 354 "scan.l" useecs = option_sense; YY_BREAK case 73: YY_RULE_SETUP #line 355 "scan.l" { useecs = usemecs = false; use_read = fullspd = true; } YY_BREAK case 74: YY_RULE_SETUP #line 359 "scan.l" { useecs = usemecs = false; use_read = fulltbl = true; } YY_BREAK case 75: YY_RULE_SETUP #line 363 "scan.l" ACTION_IFDEF("YY_NO_INPUT", ! option_sense); YY_BREAK case 76: YY_RULE_SETUP #line 364 "scan.l" interactive = option_sense; YY_BREAK case 77: YY_RULE_SETUP #line 365 "scan.l" lex_compat = option_sense; YY_BREAK case 78: YY_RULE_SETUP #line 366 "scan.l" posix_compat = option_sense; YY_BREAK case 79: YY_RULE_SETUP #line 367 "scan.l" { ACTION_M4_IFDEF( "M4""_YY_MAIN", option_sense); /* Override yywrap */ if( option_sense == true ) do_yywrap = false; } YY_BREAK case 80: YY_RULE_SETUP #line 373 "scan.l" usemecs = option_sense; YY_BREAK case 81: YY_RULE_SETUP #line 374 "scan.l" { ACTION_M4_IFDEF( "M4""_YY_NEVER_INTERACTIVE", option_sense ); interactive = !option_sense; } YY_BREAK case 82: YY_RULE_SETUP #line 378 "scan.l" performance_report += option_sense ? 1 : -1; YY_BREAK case 83: YY_RULE_SETUP #line 379 "scan.l" yytext_is_array = ! option_sense; YY_BREAK case 84: YY_RULE_SETUP #line 380 "scan.l" use_read = option_sense; YY_BREAK case 85: YY_RULE_SETUP #line 381 "scan.l" reentrant = option_sense; YY_BREAK case 86: YY_RULE_SETUP #line 382 "scan.l" reject_really_used = option_sense; YY_BREAK case 87: YY_RULE_SETUP #line 383 "scan.l" ACTION_M4_IFDEF( "M4""_YY_STACK_USED", option_sense ); YY_BREAK case 88: YY_RULE_SETUP #line 384 "scan.l" do_stdinit = option_sense; YY_BREAK case 89: YY_RULE_SETUP #line 385 "scan.l" use_stdout = option_sense; YY_BREAK case 90: YY_RULE_SETUP #line 386 "scan.l" ACTION_IFDEF("YY_NO_UNISTD_H", ! option_sense); YY_BREAK case 91: YY_RULE_SETUP #line 387 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_UNPUT", ! option_sense); YY_BREAK case 92: YY_RULE_SETUP #line 388 "scan.l" printstats = option_sense; YY_BREAK case 93: YY_RULE_SETUP #line 389 "scan.l" nowarn = ! option_sense; YY_BREAK case 94: YY_RULE_SETUP #line 390 "scan.l" do_yylineno = option_sense; ACTION_M4_IFDEF("M4""_YY_USE_LINENO", option_sense); YY_BREAK case 95: YY_RULE_SETUP #line 391 "scan.l" yymore_really_used = option_sense; YY_BREAK case 96: YY_RULE_SETUP #line 392 "scan.l" do_yywrap = option_sense; YY_BREAK case 97: YY_RULE_SETUP #line 394 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_PUSH_STATE", ! option_sense); YY_BREAK case 98: YY_RULE_SETUP #line 395 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_POP_STATE", ! option_sense); YY_BREAK case 99: YY_RULE_SETUP #line 396 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_TOP_STATE", ! option_sense); YY_BREAK case 100: YY_RULE_SETUP #line 398 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_SCAN_BUFFER", ! option_sense); YY_BREAK case 101: YY_RULE_SETUP #line 399 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_SCAN_BYTES", ! option_sense); YY_BREAK case 102: YY_RULE_SETUP #line 400 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_SCAN_STRING", ! option_sense); YY_BREAK case 103: YY_RULE_SETUP #line 402 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_FLEX_ALLOC", ! option_sense); YY_BREAK case 104: YY_RULE_SETUP #line 403 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_FLEX_REALLOC", ! option_sense); YY_BREAK case 105: YY_RULE_SETUP #line 404 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_FLEX_FREE", ! option_sense); YY_BREAK case 106: YY_RULE_SETUP #line 406 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_GET_DEBUG", ! option_sense); YY_BREAK case 107: YY_RULE_SETUP #line 407 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_SET_DEBUG", ! option_sense); YY_BREAK case 108: YY_RULE_SETUP #line 408 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_GET_EXTRA", ! option_sense); YY_BREAK case 109: YY_RULE_SETUP #line 409 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_SET_EXTRA", ! option_sense); YY_BREAK case 110: YY_RULE_SETUP #line 410 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_GET_LENG", ! option_sense); YY_BREAK case 111: YY_RULE_SETUP #line 411 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_GET_TEXT", ! option_sense); YY_BREAK case 112: YY_RULE_SETUP #line 412 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_GET_LINENO", ! option_sense); YY_BREAK case 113: YY_RULE_SETUP #line 413 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_SET_LINENO", ! option_sense); YY_BREAK case 114: YY_RULE_SETUP #line 414 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_GET_IN", ! option_sense); YY_BREAK case 115: YY_RULE_SETUP #line 415 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_SET_IN", ! option_sense); YY_BREAK case 116: YY_RULE_SETUP #line 416 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_GET_OUT", ! option_sense); YY_BREAK case 117: YY_RULE_SETUP #line 417 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_SET_OUT", ! option_sense); YY_BREAK case 118: YY_RULE_SETUP #line 418 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_GET_LVAL", ! option_sense); YY_BREAK case 119: YY_RULE_SETUP #line 419 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_SET_LVAL", ! option_sense); YY_BREAK case 120: YY_RULE_SETUP #line 420 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_GET_LLOC", ! option_sense); YY_BREAK case 121: YY_RULE_SETUP #line 421 "scan.l" ACTION_M4_IFDEF("M4""_YY_NO_SET_LLOC", ! option_sense); YY_BREAK case 122: YY_RULE_SETUP #line 423 "scan.l" return OPT_EXTRA_TYPE; YY_BREAK case 123: YY_RULE_SETUP #line 424 "scan.l" return OPT_OUTFILE; YY_BREAK case 124: YY_RULE_SETUP #line 425 "scan.l" return OPT_PREFIX; YY_BREAK case 125: YY_RULE_SETUP #line 426 "scan.l" return OPT_YYCLASS; YY_BREAK case 126: YY_RULE_SETUP #line 427 "scan.l" return OPT_HEADER; YY_BREAK case 127: YY_RULE_SETUP #line 428 "scan.l" return OPT_TABLES; YY_BREAK case 128: YY_RULE_SETUP #line 429 "scan.l" { tablesverify = option_sense; if(!tablesext && option_sense) tablesext = true; } YY_BREAK case 129: YY_RULE_SETUP #line 436 "scan.l" { if(yyleng-1 < MAXLINE) { strcpy( nmstr, yytext + 1 ); } else { synerr( _("Option line too long\n")); FLEX_EXIT(EXIT_FAILURE); } nmstr[strlen( nmstr ) - 1] = '\0'; return NAME; } YY_BREAK case 130: YY_RULE_SETUP #line 450 "scan.l" { format_synerr( _( "unrecognized %%option: %s" ), yytext ); BEGIN(RECOVER); } YY_BREAK case 131: /* rule 131 can match eol */ YY_RULE_SETUP #line 457 "scan.l" ++linenum; BEGIN(INITIAL); YY_BREAK case 132: YY_RULE_SETUP #line 461 "scan.l" ++bracelevel; yyless( 2 ); /* eat only %{ */ YY_BREAK case 133: YY_RULE_SETUP #line 462 "scan.l" --bracelevel; yyless( 2 ); /* eat only %} */ YY_BREAK case 134: YY_RULE_SETUP #line 464 "scan.l" ACTION_ECHO; /* indented code in prolog */ YY_BREAK case 135: YY_RULE_SETUP #line 466 "scan.l" { /* non-indented code */ if ( bracelevel <= 0 ) { /* not in %{ ... %} */ yyless( 0 ); /* put it all back */ yy_set_bol( 1 ); mark_prolog(); BEGIN(SECT2); } else ACTION_ECHO; } YY_BREAK case 136: YY_RULE_SETUP #line 478 "scan.l" ACTION_ECHO; YY_BREAK case 137: /* rule 137 can match eol */ YY_RULE_SETUP #line 479 "scan.l" ++linenum; ACTION_ECHO; YY_BREAK case YY_STATE_EOF(SECT2PROLOG): #line 481 "scan.l" { mark_prolog(); sectnum = 0; yyterminate(); /* to stop the parser */ } YY_BREAK case 138: /* rule 138 can match eol */ YY_RULE_SETUP #line 489 "scan.l" ++linenum; /* allow blank lines in section 2 */ YY_BREAK case 139: YY_RULE_SETUP #line 491 "scan.l" { indented_code = false; doing_codeblock = true; bracelevel = 1; BEGIN(PERCENT_BRACE_ACTION); } YY_BREAK case 140: YY_RULE_SETUP #line 498 "scan.l" { /* Allow "<" to appear in (?x) patterns. */ if (!sf_skip_ws()) BEGIN(SC); return '<'; } YY_BREAK case 141: YY_RULE_SETUP #line 504 "scan.l" return '^'; YY_BREAK case 142: YY_RULE_SETUP #line 505 "scan.l" BEGIN(QUOTE); return '"'; YY_BREAK case 143: *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ (yy_c_buf_p) = yy_cp = yy_bp + 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 506 "scan.l" { BEGIN(NUM); if ( lex_compat || posix_compat ) return BEGIN_REPEAT_POSIX; else return BEGIN_REPEAT_FLEX; } YY_BREAK case 144: /* rule 144 can match eol */ *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ (yy_c_buf_p) = yy_cp = yy_bp + 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 513 "scan.l" return '$'; YY_BREAK case 145: YY_RULE_SETUP #line 515 "scan.l" { bracelevel = 1; BEGIN(PERCENT_BRACE_ACTION); if ( in_rule ) { doing_rule_action = true; in_rule = false; return '\n'; } } YY_BREAK case 146: /* rule 146 can match eol */ YY_RULE_SETUP #line 526 "scan.l" { if (sf_skip_ws()){ /* We're in the middle of a (?x: ) pattern. */ /* Push back everything starting at the "|" */ size_t amt; amt = strchr (yytext, '|') - yytext; yyless(amt); } else { continued_action = true; ++linenum; return '\n'; } } YY_BREAK case 147: YY_RULE_SETUP #line 541 "scan.l" { if (sf_skip_ws()){ /* We're in the middle of a (?x: ) pattern. */ yy_push_state(COMMENT_DISCARD); } else{ yyless( yyleng - 2 ); /* put back '/', '*' */ bracelevel = 0; continued_action = false; BEGIN(ACTION); } } YY_BREAK case 148: YY_RULE_SETUP #line 555 "scan.l" /* allow indented rules */ ; YY_BREAK case 149: YY_RULE_SETUP #line 557 "scan.l" { if (sf_skip_ws()){ /* We're in the middle of a (?x: ) pattern. */ } else{ /* This rule is separate from the one below because * otherwise we get variable trailing context, so * we can't build the scanner using -{f,F}. */ bracelevel = 0; continued_action = false; BEGIN(ACTION); if ( in_rule ) { doing_rule_action = true; in_rule = false; return '\n'; } } } YY_BREAK case 150: /* rule 150 can match eol */ YY_RULE_SETUP #line 579 "scan.l" { if (sf_skip_ws()){ /* We're in the middle of a (?x: ) pattern. */ ++linenum; } else{ bracelevel = 0; continued_action = false; BEGIN(ACTION); unput( '\n' ); /* so sees it */ if ( in_rule ) { doing_rule_action = true; in_rule = false; return '\n'; } } } YY_BREAK case 151: #line 600 "scan.l" case 152: YY_RULE_SETUP #line 600 "scan.l" return EOF_OP; YY_BREAK case 153: YY_RULE_SETUP #line 602 "scan.l" { sectnum = 3; BEGIN(SECT3); outn("/* Begin user sect3 */"); yyterminate(); /* to stop the parser */ } YY_BREAK case 154: YY_RULE_SETUP #line 609 "scan.l" { int cclval; if(yyleng < MAXLINE) { strcpy( nmstr, yytext ); } else { synerr( _("Input line too long\n")); FLEX_EXIT(EXIT_FAILURE); } /* Check to see if we've already encountered this * ccl. */ if (0 /* <--- This "0" effectively disables the reuse of a * character class (purely based on its source text). * The reason it was disabled is so yacc/bison can parse * ccl operations, such as ccl difference and union. */ && (cclval = ccllookup( (Char *) nmstr )) != 0 ) { if ( input() != ']' ) synerr( _( "bad character class" ) ); yylval = cclval; ++cclreuse; return PREVCCL; } else { /* We fudge a bit. We know that this ccl will * soon be numbered as lastccl + 1 by cclinit. */ cclinstal( (Char *) nmstr, lastccl + 1 ); /* Push back everything but the leading bracket * so the ccl can be rescanned. */ yyless( 1 ); BEGIN(FIRSTCCL); return '['; } } YY_BREAK case 155: YY_RULE_SETUP #line 655 "scan.l" return CCL_OP_DIFF; YY_BREAK case 156: YY_RULE_SETUP #line 656 "scan.l" return CCL_OP_UNION; YY_BREAK /* Check for :space: at the end of the rule so we don't * wrap the expanded regex in '(' ')' -- breaking trailing * context. */ case 157: /* rule 157 can match eol */ YY_RULE_SETUP #line 663 "scan.l" { Char *nmdefptr; int end_is_ws, end_ch; end_ch = yytext[yyleng-1]; end_is_ws = end_ch != '}' ? 1 : 0; if(yyleng-1 < MAXLINE) { strcpy( nmstr, yytext + 1 ); } else { synerr( _("Input line too long\n")); FLEX_EXIT(EXIT_FAILURE); } nmstr[yyleng - 2 - end_is_ws] = '\0'; /* chop trailing brace */ if ( (nmdefptr = ndlookup( nmstr )) == 0 ) format_synerr( _( "undefined definition {%s}" ), nmstr ); else { /* push back name surrounded by ()'s */ int len = strlen( (char *) nmdefptr ); if (end_is_ws) unput(end_ch); if ( lex_compat || nmdefptr[0] == '^' || (len > 0 && nmdefptr[len - 1] == '$') || (end_is_ws && trlcontxt && !sf_skip_ws())) { /* don't use ()'s after all */ PUT_BACK_STRING((char *) nmdefptr, 0); if ( nmdefptr[0] == '^' ) BEGIN(CARETISBOL); } else { unput(')'); PUT_BACK_STRING((char *) nmdefptr, 0); unput('('); } } } YY_BREAK case 158: YY_RULE_SETUP #line 711 "scan.l" { if (sf_skip_ws()) yy_push_state(COMMENT_DISCARD); else{ /* Push back the "*" and return "/" as usual. */ yyless(1); return '/'; } } YY_BREAK case 159: YY_RULE_SETUP #line 721 "scan.l" { if (lex_compat || posix_compat){ /* Push back the "?#" and treat it like a normal parens. */ yyless(1); sf_push(); return '('; } else yy_push_state(EXTENDED_COMMENT); } YY_BREAK case 160: YY_RULE_SETUP #line 731 "scan.l" { sf_push(); if (lex_compat || posix_compat) /* Push back the "?" and treat it like a normal parens. */ yyless(1); else BEGIN(GROUP_WITH_PARAMS); return '('; } YY_BREAK case 161: YY_RULE_SETUP #line 740 "scan.l" sf_push(); return '('; YY_BREAK case 162: YY_RULE_SETUP #line 741 "scan.l" sf_pop(); return ')'; YY_BREAK case 163: YY_RULE_SETUP #line 743 "scan.l" return (unsigned char) yytext[0]; YY_BREAK case 164: YY_RULE_SETUP #line 744 "scan.l" RETURNCHAR; YY_BREAK case 165: /* rule 165 can match eol */ YY_RULE_SETUP #line 749 "scan.l" ++linenum; /* Allow blank lines & continuations */ YY_BREAK case 166: YY_RULE_SETUP #line 750 "scan.l" return (unsigned char) yytext[0]; YY_BREAK case 167: YY_RULE_SETUP #line 751 "scan.l" BEGIN(SECT2); return '>'; YY_BREAK case 168: *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ (yy_c_buf_p) = yy_cp = yy_bp + 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 752 "scan.l" BEGIN(CARETISBOL); return '>'; YY_BREAK case 169: YY_RULE_SETUP #line 753 "scan.l" RETURNNAME; YY_BREAK case 170: YY_RULE_SETUP #line 754 "scan.l" { format_synerr( _( "bad : %s" ), yytext ); } YY_BREAK case 171: YY_RULE_SETUP #line 760 "scan.l" BEGIN(SECT2); return '^'; YY_BREAK case 172: YY_RULE_SETUP #line 764 "scan.l" RETURNCHAR; YY_BREAK case 173: YY_RULE_SETUP #line 765 "scan.l" BEGIN(SECT2); return '"'; YY_BREAK case 174: /* rule 174 can match eol */ YY_RULE_SETUP #line 767 "scan.l" { synerr( _( "missing quote" ) ); BEGIN(SECT2); ++linenum; return '"'; } YY_BREAK case 175: YY_RULE_SETUP #line 776 "scan.l" BEGIN(SECT2); YY_BREAK case 176: YY_RULE_SETUP #line 777 "scan.l" BEGIN(GROUP_MINUS_PARAMS); YY_BREAK case 177: YY_RULE_SETUP #line 778 "scan.l" sf_set_case_ins(1); YY_BREAK case 178: YY_RULE_SETUP #line 779 "scan.l" sf_set_dot_all(1); YY_BREAK case 179: YY_RULE_SETUP #line 780 "scan.l" sf_set_skip_ws(1); YY_BREAK case 180: YY_RULE_SETUP #line 783 "scan.l" BEGIN(SECT2); YY_BREAK case 181: YY_RULE_SETUP #line 784 "scan.l" sf_set_case_ins(0); YY_BREAK case 182: YY_RULE_SETUP #line 785 "scan.l" sf_set_dot_all(0); YY_BREAK case 183: YY_RULE_SETUP #line 786 "scan.l" sf_set_skip_ws(0); YY_BREAK case 184: *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ (yy_c_buf_p) = yy_cp = yy_bp + 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 790 "scan.l" BEGIN(CCL); return '^'; YY_BREAK case 185: *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ (yy_c_buf_p) = yy_cp = yy_bp + 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 791 "scan.l" return '^'; YY_BREAK case 186: YY_RULE_SETUP #line 792 "scan.l" BEGIN(CCL); RETURNCHAR; YY_BREAK case 187: *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ (yy_c_buf_p) = yy_cp = yy_bp + 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 796 "scan.l" return '-'; YY_BREAK case 188: YY_RULE_SETUP #line 797 "scan.l" RETURNCHAR; YY_BREAK case 189: YY_RULE_SETUP #line 798 "scan.l" BEGIN(SECT2); return ']'; YY_BREAK case 190: /* rule 190 can match eol */ YY_RULE_SETUP #line 799 "scan.l" { synerr( _( "bad character class" ) ); BEGIN(SECT2); return ']'; } YY_BREAK case 191: YY_RULE_SETUP #line 807 "scan.l" BEGIN(CCL); return CCE_ALNUM; YY_BREAK case 192: YY_RULE_SETUP #line 808 "scan.l" BEGIN(CCL); return CCE_ALPHA; YY_BREAK case 193: YY_RULE_SETUP #line 809 "scan.l" BEGIN(CCL); return CCE_BLANK; YY_BREAK case 194: YY_RULE_SETUP #line 810 "scan.l" BEGIN(CCL); return CCE_CNTRL; YY_BREAK case 195: YY_RULE_SETUP #line 811 "scan.l" BEGIN(CCL); return CCE_DIGIT; YY_BREAK case 196: YY_RULE_SETUP #line 812 "scan.l" BEGIN(CCL); return CCE_GRAPH; YY_BREAK case 197: YY_RULE_SETUP #line 813 "scan.l" BEGIN(CCL); return CCE_LOWER; YY_BREAK case 198: YY_RULE_SETUP #line 814 "scan.l" BEGIN(CCL); return CCE_PRINT; YY_BREAK case 199: YY_RULE_SETUP #line 815 "scan.l" BEGIN(CCL); return CCE_PUNCT; YY_BREAK case 200: YY_RULE_SETUP #line 816 "scan.l" BEGIN(CCL); return CCE_SPACE; YY_BREAK case 201: YY_RULE_SETUP #line 817 "scan.l" BEGIN(CCL); return CCE_UPPER; YY_BREAK case 202: YY_RULE_SETUP #line 818 "scan.l" BEGIN(CCL); return CCE_XDIGIT; YY_BREAK case 203: YY_RULE_SETUP #line 820 "scan.l" BEGIN(CCL); return CCE_NEG_ALNUM; YY_BREAK case 204: YY_RULE_SETUP #line 821 "scan.l" BEGIN(CCL); return CCE_NEG_ALPHA; YY_BREAK case 205: YY_RULE_SETUP #line 822 "scan.l" BEGIN(CCL); return CCE_NEG_BLANK; YY_BREAK case 206: YY_RULE_SETUP #line 823 "scan.l" BEGIN(CCL); return CCE_NEG_CNTRL; YY_BREAK case 207: YY_RULE_SETUP #line 824 "scan.l" BEGIN(CCL); return CCE_NEG_DIGIT; YY_BREAK case 208: YY_RULE_SETUP #line 825 "scan.l" BEGIN(CCL); return CCE_NEG_GRAPH; YY_BREAK case 209: YY_RULE_SETUP #line 826 "scan.l" BEGIN(CCL); return CCE_NEG_LOWER; YY_BREAK case 210: YY_RULE_SETUP #line 827 "scan.l" BEGIN(CCL); return CCE_NEG_PRINT; YY_BREAK case 211: YY_RULE_SETUP #line 828 "scan.l" BEGIN(CCL); return CCE_NEG_PUNCT; YY_BREAK case 212: YY_RULE_SETUP #line 829 "scan.l" BEGIN(CCL); return CCE_NEG_SPACE; YY_BREAK case 213: YY_RULE_SETUP #line 830 "scan.l" BEGIN(CCL); return CCE_NEG_UPPER; YY_BREAK case 214: YY_RULE_SETUP #line 831 "scan.l" BEGIN(CCL); return CCE_NEG_XDIGIT; YY_BREAK case 215: YY_RULE_SETUP #line 832 "scan.l" { format_synerr( _( "bad character class expression: %s" ), yytext ); BEGIN(CCL); return CCE_ALNUM; } YY_BREAK case 216: YY_RULE_SETUP #line 841 "scan.l" { yylval = myctoi( yytext ); return NUMBER; } YY_BREAK case 217: YY_RULE_SETUP #line 846 "scan.l" return ','; YY_BREAK case 218: YY_RULE_SETUP #line 847 "scan.l" { BEGIN(SECT2); if ( lex_compat || posix_compat ) return END_REPEAT_POSIX; else return END_REPEAT_FLEX; } YY_BREAK case 219: YY_RULE_SETUP #line 855 "scan.l" { synerr( _( "bad character inside {}'s" ) ); BEGIN(SECT2); return '}'; } YY_BREAK case 220: /* rule 220 can match eol */ YY_RULE_SETUP #line 861 "scan.l" { synerr( _( "missing }" ) ); BEGIN(SECT2); ++linenum; return '}'; } YY_BREAK case 221: YY_RULE_SETUP #line 871 "scan.l" bracelevel = 0; YY_BREAK case 222: YY_RULE_SETUP #line 873 "scan.l" ACTION_ECHO; yy_push_state( COMMENT ); YY_BREAK case 223: YY_RULE_SETUP #line 876 "scan.l" { ACTION_ECHO; CHECK_REJECT(yytext); } YY_BREAK case 224: YY_RULE_SETUP #line 880 "scan.l" { ACTION_ECHO; CHECK_YYMORE(yytext); } YY_BREAK case 225: YY_RULE_SETUP #line 886 "scan.l" ACTION_ECHO_QSTART; YY_BREAK case 226: YY_RULE_SETUP #line 887 "scan.l" ACTION_ECHO_QEND; YY_BREAK case 227: YY_RULE_SETUP #line 888 "scan.l" ACTION_ECHO; YY_BREAK case 228: /* rule 228 can match eol */ YY_RULE_SETUP #line 889 "scan.l" { ++linenum; ACTION_ECHO; if ( bracelevel == 0 || (doing_codeblock && indented_code) ) { if ( doing_rule_action ) add_action( "\tYY_BREAK\n" ); doing_rule_action = doing_codeblock = false; BEGIN(SECT2); } } YY_BREAK /* Reject and YYmore() are checked for above, in PERCENT_BRACE_ACTION */ case 229: YY_RULE_SETUP #line 907 "scan.l" ACTION_ECHO; ++bracelevel; YY_BREAK case 230: YY_RULE_SETUP #line 908 "scan.l" ACTION_ECHO; --bracelevel; YY_BREAK case 231: YY_RULE_SETUP #line 909 "scan.l" ACTION_ECHO_QSTART; YY_BREAK case 232: YY_RULE_SETUP #line 910 "scan.l" ACTION_ECHO_QEND; YY_BREAK case 233: YY_RULE_SETUP #line 911 "scan.l" ACTION_ECHO; YY_BREAK case 234: YY_RULE_SETUP #line 912 "scan.l" ACTION_ECHO; YY_BREAK case 235: YY_RULE_SETUP #line 913 "scan.l" ACTION_ECHO; YY_BREAK case 236: YY_RULE_SETUP #line 914 "scan.l" ACTION_ECHO; /* character constant */ YY_BREAK case 237: YY_RULE_SETUP #line 915 "scan.l" ACTION_ECHO; BEGIN(ACTION_STRING); YY_BREAK case 238: /* rule 238 can match eol */ YY_RULE_SETUP #line 916 "scan.l" { ++linenum; ACTION_ECHO; if ( bracelevel == 0 ) { if ( doing_rule_action ) add_action( "\tYY_BREAK\n" ); doing_rule_action = false; BEGIN(SECT2); } } YY_BREAK case 239: YY_RULE_SETUP #line 928 "scan.l" ACTION_ECHO; YY_BREAK case 240: YY_RULE_SETUP #line 932 "scan.l" ACTION_ECHO; YY_BREAK case 241: YY_RULE_SETUP #line 933 "scan.l" ACTION_ECHO; YY_BREAK case 242: /* rule 242 can match eol */ YY_RULE_SETUP #line 934 "scan.l" ++linenum; ACTION_ECHO; BEGIN(ACTION); YY_BREAK case 243: YY_RULE_SETUP #line 935 "scan.l" ACTION_ECHO; BEGIN(ACTION); YY_BREAK case 244: YY_RULE_SETUP #line 936 "scan.l" ACTION_ECHO; YY_BREAK case YY_STATE_EOF(COMMENT): case YY_STATE_EOF(COMMENT_DISCARD): case YY_STATE_EOF(ACTION): case YY_STATE_EOF(ACTION_STRING): #line 939 "scan.l" { synerr( _( "EOF encountered inside an action" ) ); yyterminate(); } YY_BREAK case YY_STATE_EOF(EXTENDED_COMMENT): case YY_STATE_EOF(GROUP_WITH_PARAMS): case YY_STATE_EOF(GROUP_MINUS_PARAMS): #line 944 "scan.l" { synerr( _( "EOF encountered inside pattern" ) ); yyterminate(); } YY_BREAK case 245: YY_RULE_SETUP #line 949 "scan.l" { yylval = myesc( (Char *) yytext ); if ( YY_START == FIRSTCCL ) BEGIN(CCL); return CHAR; } YY_BREAK case 246: YY_RULE_SETUP #line 960 "scan.l" fwrite (escaped_qstart, 1, strlen(escaped_qstart), yyout); YY_BREAK case 247: YY_RULE_SETUP #line 961 "scan.l" fwrite (escaped_qend, 1, strlen(escaped_qend), yyout); YY_BREAK case 248: /* rule 248 can match eol */ YY_RULE_SETUP #line 962 "scan.l" ECHO; YY_BREAK case 249: /* rule 249 can match eol */ YY_RULE_SETUP #line 963 "scan.l" ECHO; YY_BREAK case YY_STATE_EOF(SECT3): #line 964 "scan.l" sectnum = 0; yyterminate(); YY_BREAK case 250: /* rule 250 can match eol */ YY_RULE_SETUP #line 967 "scan.l" format_synerr( _( "bad character: %s" ), yytext ); YY_BREAK case 251: YY_RULE_SETUP #line 969 "scan.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK #line 4127 "" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(SECT2): case YY_STATE_EOF(CODEBLOCK): case YY_STATE_EOF(PICKUPDEF): case YY_STATE_EOF(SC): case YY_STATE_EOF(CARETISBOL): case YY_STATE_EOF(NUM): case YY_STATE_EOF(QUOTE): case YY_STATE_EOF(FIRSTCCL): case YY_STATE_EOF(CCL): case YY_STATE_EOF(RECOVER): case YY_STATE_EOF(PERCENT_BRACE_ACTION): case YY_STATE_EOF(OPTION): case YY_STATE_EOF(LINEDIR): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_c_buf_p); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = (yytext_ptr); int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { yy_size_t num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart(yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { yy_state_type yy_current_state; char *yy_cp; yy_current_state = (yy_start); yy_current_state += YY_AT_BOL(); (yy_state_ptr) = (yy_state_buf); *(yy_state_ptr)++ = yy_current_state; for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1107 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; *(yy_state_ptr)++ = yy_current_state; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { int yy_is_jam; YY_CHAR yy_c = 1; while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1107 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 1106); if ( ! yy_is_jam ) *(yy_state_ptr)++ = yy_current_state; return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT static void yyunput (int c, char * yy_bp ) { char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up yytext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ yy_size_t number_to_move = (yy_n_chars) + 2; char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } #endif /* ifndef YY_NO_UNPUT */ #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart(yyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n'); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_init_buffer(YY_CURRENT_BUFFER,input_file ); yy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void yy_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * */ void yy_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree((void *) b->yy_ch_buf ); yyfree((void *) b ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; yy_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void yy_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; yyensure_buffer_stack(); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void yypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void yyensure_buffer_stack (void) { yy_size_t num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) { return yy_scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; yy_size_t i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) yyalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } static void yy_push_state (int new_state ) { if ( (yy_start_stack_ptr) >= (yy_start_stack_depth) ) { yy_size_t new_size; (yy_start_stack_depth) += YY_START_STACK_INCR; new_size = (yy_start_stack_depth) * sizeof( int ); if ( ! (yy_start_stack) ) (yy_start_stack) = (int *) yyalloc(new_size ); else (yy_start_stack) = (int *) yyrealloc((void *) (yy_start_stack),new_size ); if ( ! (yy_start_stack) ) YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); } (yy_start_stack)[(yy_start_stack_ptr)++] = YY_START; BEGIN(new_state); } static void yy_pop_state (void) { if ( --(yy_start_stack_ptr) < 0 ) YY_FATAL_ERROR( "start-condition stack underflow" ); BEGIN((yy_start_stack)[(yy_start_stack_ptr)]); } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int yyget_lineno (void) { return yylineno; } /** Get the input stream. * */ FILE *yyget_in (void) { return yyin; } /** Get the output stream. * */ FILE *yyget_out (void) { return yyout; } /** Get the length of the current token. * */ yy_size_t yyget_leng (void) { return yyleng; } /** Get the current token. * */ char *yyget_text (void) { return yytext; } /** Set the current line number. * @param line_number * */ void yyset_lineno (int line_number ) { yylineno = line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * * @see yy_switch_to_buffer */ void yyset_in (FILE * in_str ) { yyin = in_str ; } void yyset_out (FILE * out_str ) { yyout = out_str ; } int yyget_debug (void) { return yy_flex_debug; } void yyset_debug (int bdebug ) { yy_flex_debug = bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; (yy_start_stack_ptr) = 0; (yy_start_stack_depth) = 0; (yy_start_stack) = NULL; (yy_state_buf) = 0; (yy_state_ptr) = 0; (yy_full_match) = 0; (yy_lp) = 0; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = (FILE *) 0; yyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(); } /* Destroy the stack itself. */ yyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Destroy the start condition stack. */ yyfree((yy_start_stack) ); (yy_start_stack) = NULL; yyfree ( (yy_state_buf) ); (yy_state_buf) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *yyalloc (yy_size_t size ) { return (void *) malloc( size ); } void *yyrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void yyfree (void * ptr ) { free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 969 "scan.l" int yywrap() { if ( --num_input_files > 0 ) { set_input_file( *++input_files ); return 0; } else return 1; } /* set_input_file - open the given file (if NULL, stdin) for scanning */ void set_input_file( file ) char *file; { if ( file && strcmp( file, "-" ) ) { infilename = copy_string( file ); yyin = fopen( infilename, "r" ); if ( yyin == NULL ) lerrsf( _( "can't open %s" ), file ); } else { yyin = stdin; infilename = copy_string( "" ); } linenum = 1; } /* Wrapper routines for accessing the scanner's malloc routines. */ void *flex_alloc( size ) size_t size; { return (void *) malloc( size ); } void *flex_realloc( ptr, size ) void *ptr; size_t size; { return (void *) realloc( ptr, size ); } void flex_free( ptr ) void *ptr; { if ( ptr ) free( ptr ); } freebsd-buildutils-10.0/src/usr.bin/lex/lib/0000755000000000000000000000000012265500106015612 5ustar freebsd-buildutils-10.0/src/usr.bin/lex/lib/Makefile0000644000000000000000000000062312146745723017271 0ustar # $FreeBSD$ .include .PATH: ${.CURDIR}/../../../contrib/flex LIB= ln SRCS= libmain.c libyywrap.c NO_PIC= .if ${MK_INSTALLLIB} != "no" LINKS= ${LIBDIR}/libln.a ${LIBDIR}/libl.a LINKS+= ${LIBDIR}/libln.a ${LIBDIR}/libfl.a .endif .if ${MK_PROFILE} != "no" LINKS+= ${LIBDIR}/libln_p.a ${LIBDIR}/libl_p.a LINKS+= ${LIBDIR}/libln_p.a ${LIBDIR}/libfl_p.a .endif .include freebsd-buildutils-10.0/src/usr.bin/lex/config.h0000644000000000000000000001352112146745723016502 0ustar /* config.h. Generated from conf.in by configure. */ /* conf.in. Generated from configure.in by autoheader. */ /* $FreeBSD$ */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if translation of program messages to the user's native language is requested. */ /* #undef ENABLE_NLS */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ /* #undef HAVE_ALLOCA_H */ /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* #undef HAVE_DCGETTEXT */ /* Define to 1 if you have the `dup2' function. */ #define HAVE_DUP2 1 /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 /* Define if the GNU gettext() function is already present or preinstalled. */ /* #undef HAVE_GETTEXT */ /* Define if you have the iconv() function. */ /* #undef HAVE_ICONV */ /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the `isascii' function. */ #define HAVE_ISASCII 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_LIBINTL_H */ /* Define to 1 if you have the `m' library (-lm). */ #define HAVE_LIBM 1 /* pthread library */ #define HAVE_LIBPTHREAD 1 /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #define HAVE_MALLOC 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MALLOC_H */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `memset' function. */ #define HAVE_MEMSET 1 /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IN_H 1 /* Define to 1 if you have the `pow' function. */ #define HAVE_POW 1 /* Define to 1 if you have the header file. */ #define HAVE_PTHREAD_H 1 /* Define to 1 if your system has a GNU libc compatible `realloc' function, and to 0 otherwise. */ #define HAVE_REALLOC 1 /* Define to 1 if you have the `regcomp' function. */ #define HAVE_REGCOMP 1 /* Define to 1 if you have the header file. */ #define HAVE_REGEX_H 1 /* Define to 1 if you have the `setlocale' function. */ #define HAVE_SETLOCALE 1 /* Define to 1 if stdbool.h conforms to C99. */ #define HAVE_STDBOOL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strtol' function. */ #define HAVE_STRTOL 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have that is POSIX.1 compatible. */ #define HAVE_SYS_WAIT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `vfork' function. */ #define HAVE_VFORK 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VFORK_H */ /* Define to 1 if `fork' works. */ #define HAVE_WORKING_FORK 1 /* Define to 1 if `vfork' works. */ #define HAVE_WORKING_VFORK 1 /* Define to 1 if the system has the type `_Bool'. */ #define HAVE__BOOL 1 /* Define to the m4 executable name. */ #define M4 "m4" /* Define to 1 if your C compiler doesn't accept -c and -o together. */ /* #undef NO_MINUS_C_MINUS_O */ /* Name of package */ #define PACKAGE "flex" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "flex-help@lists.sourceforge.net" /* Define to the full name of this package. */ #define PACKAGE_NAME "the fast lexical analyser generator" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "the fast lexical analyser generator 2.5.37" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "flex" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "2.5.37" /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ #define VERSION "2.5.37" /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #define YYTEXT_POINTER 1 /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to rpl_malloc if the replacement function should be used. */ /* #undef malloc */ /* Define to `int' if does not define. */ /* #undef pid_t */ /* Define to rpl_realloc if the replacement function should be used. */ /* #undef realloc */ /* Define to `unsigned int' if does not define. */ /* #undef size_t */ /* Define as `fork' if `vfork' does not work. */ /* #undef vfork */ freebsd-buildutils-10.0/src/usr.bin/lex/lex.10000644000000000000000000031710012146745723015736 0ustar .\" $FreeBSD$ .\" .TH FLEX 1 "May 21, 2013" "Version 2.5.37" .SH NAME flex, lex \- fast lexical analyzer generator .SH SYNOPSIS .B flex .B [\-bcdfhilnpstvwBFILTV78+? \-C[aefFmr] \-ooutput \-Pprefix \-Sskeleton] .B [\-\-help \-\-version] .I [filename ...] .SH OVERVIEW This manual describes .I flex, a tool for generating programs that perform pattern-matching on text. The manual includes both tutorial and reference sections: .nf Description a brief overview of the tool Some Simple Examples Format Of The Input File Patterns the extended regular expressions used by flex How The Input Is Matched the rules for determining what has been matched Actions how to specify what to do when a pattern is matched The Generated Scanner details regarding the scanner that flex produces; how to control the input source Start Conditions introducing context into your scanners, and managing "mini-scanners" Multiple Input Buffers how to manipulate multiple input sources; how to scan from strings instead of files End-of-file Rules special rules for matching the end of the input Miscellaneous Macros a summary of macros available to the actions Values Available To The User a summary of values available to the actions Interfacing With Yacc connecting flex scanners together with yacc parsers Options flex command-line options, and the "%option" directive Performance Considerations how to make your scanner go as fast as possible Generating C++ Scanners the (experimental) facility for generating C++ scanner classes Incompatibilities With Lex And POSIX how flex differs from AT&T lex and the POSIX lex standard Diagnostics those error messages produced by flex (or scanners it generates) whose meanings might not be apparent Files files used by flex Deficiencies / Bugs known problems with flex See Also other documentation, related tools Author includes contact information .fi .SH DESCRIPTION .I flex is a tool for generating .I scanners: programs which recognize lexical patterns in text. .I flex reads the given input files, or its standard input if no file names are given, for a description of a scanner to generate. The description is in the form of pairs of regular expressions and C code, called .I rules. .I flex generates as output a C source file, .B lex.yy.c, which defines a routine .B yylex(). This file is compiled and linked with the .B \-ll library to produce an executable. When the executable is run, it analyzes its input for occurrences of the regular expressions. Whenever it finds one, it executes the corresponding C code. .SH SOME SIMPLE EXAMPLES First some simple examples to get the flavor of how one uses .I flex. The following .I flex input specifies a scanner which whenever it encounters the string "username" will replace it with the user's login name: .nf %% username printf( "%s", getlogin() ); .fi By default, any text not matched by a .I flex scanner is copied to the output, so the net effect of this scanner is to copy its input file to its output with each occurrence of "username" expanded. In this input, there is just one rule. "username" is the .I pattern and the "printf" is the .I action. The "%%" marks the beginning of the rules. .PP Here's another simple example: .nf %{ int num_lines = 0, num_chars = 0; %} %% \\n ++num_lines; ++num_chars; . ++num_chars; %% main() { yylex(); printf( "# of lines = %d, # of chars = %d\\n", num_lines, num_chars ); } .fi This scanner counts the number of characters and the number of lines in its input (it produces no output other than the final report on the counts). The first line declares two globals, "num_lines" and "num_chars", which are accessible both inside .B yylex() and in the .B main() routine declared after the second "%%". There are two rules, one which matches a newline ("\\n") and increments both the line count and the character count, and one which matches any character other than a newline (indicated by the "." regular expression). .PP A somewhat more complicated example: .nf /* scanner for a toy Pascal-like language */ %{ /* need this for the call to atof() below */ #include %} DIGIT [0-9] ID [a-z][a-z0-9]* %% {DIGIT}+ { printf( "An integer: %s (%d)\\n", yytext, atoi( yytext ) ); } {DIGIT}+"."{DIGIT}* { printf( "A float: %s (%g)\\n", yytext, atof( yytext ) ); } if|then|begin|end|procedure|function { printf( "A keyword: %s\\n", yytext ); } {ID} printf( "An identifier: %s\\n", yytext ); "+"|"-"|"*"|"/" printf( "An operator: %s\\n", yytext ); "{"[^}\\n]*"}" /* eat up one-line comments */ [ \\t\\n]+ /* eat up whitespace */ . printf( "Unrecognized character: %s\\n", yytext ); %% main( argc, argv ) int argc; char **argv; { ++argv, --argc; /* skip over program name */ if ( argc > 0 ) yyin = fopen( argv[0], "r" ); else yyin = stdin; yylex(); } .fi This is the beginnings of a simple scanner for a language like Pascal. It identifies different types of .I tokens and reports on what it has seen. .PP The details of this example will be explained in the following sections. .SH FORMAT OF THE INPUT FILE The .I flex input file consists of three sections, separated by a line with just .B %% in it: .nf definitions %% rules %% user code .fi The .I definitions section contains declarations of simple .I name definitions to simplify the scanner specification, and declarations of .I start conditions, which are explained in a later section. .PP Name definitions have the form: .nf name definition .fi The "name" is a word beginning with a letter or an underscore ('_') followed by zero or more letters, digits, '_', or '-' (dash). The definition is taken to begin at the first non-white-space character following the name and continuing to the end of the line. The definition can subsequently be referred to using "{name}", which will expand to "(definition)". For example, .nf DIGIT [0-9] ID [a-z][a-z0-9]* .fi defines "DIGIT" to be a regular expression which matches a single digit, and "ID" to be a regular expression which matches a letter followed by zero-or-more letters-or-digits. A subsequent reference to .nf {DIGIT}+"."{DIGIT}* .fi is identical to .nf ([0-9])+"."([0-9])* .fi and matches one-or-more digits followed by a '.' followed by zero-or-more digits. .PP The .I rules section of the .I flex input contains a series of rules of the form: .nf pattern action .fi where the pattern must be unindented and the action must begin on the same line. .PP See below for a further description of patterns and actions. .PP Finally, the user code section is simply copied to .B lex.yy.c verbatim. It is used for companion routines which call or are called by the scanner. The presence of this section is optional; if it is missing, the second .B %% in the input file may be skipped, too. .PP In the definitions and rules sections, any .I indented text or text enclosed in .B %{ and .B %} is copied verbatim to the output (with the %{}'s removed). The %{}'s must appear unindented on lines by themselves. .PP In the rules section, any indented or %{} text appearing before the first rule may be used to declare variables which are local to the scanning routine and (after the declarations) code which is to be executed whenever the scanning routine is entered. Other indented or %{} text in the rule section is still copied to the output, but its meaning is not well-defined and it may well cause compile-time errors (this feature is present for .I POSIX compliance; see below for other such features). .PP In the definitions section (but not in the rules section), an unindented comment (i.e., a line beginning with "/*") is also copied verbatim to the output up to the next "*/". .SH PATTERNS The patterns in the input are written using an extended set of regular expressions. These are: .nf x match the character 'x' . any character (byte) except newline [xyz] a "character class"; in this case, the pattern matches either an 'x', a 'y', or a 'z' [abj-oZ] a "character class" with a range in it; matches an 'a', a 'b', any letter from 'j' through 'o', or a 'Z' [^A-Z] a "negated character class", i.e., any character but those in the class. In this case, any character EXCEPT an uppercase letter. [^A-Z\\n] any character EXCEPT an uppercase letter or a newline r* zero or more r's, where r is any regular expression r+ one or more r's r? zero or one r's (that is, "an optional r") r{2,5} anywhere from two to five r's r{2,} two or more r's r{4} exactly 4 r's {name} the expansion of the "name" definition (see above) "[xyz]\\"foo" the literal string: [xyz]"foo \\X if X is an 'a', 'b', 'f', 'n', 'r', 't', or 'v', then the ANSI-C interpretation of \\x. Otherwise, a literal 'X' (used to escape operators such as '*') \\0 a NUL character (ASCII code 0) \\123 the character with octal value 123 \\x2a the character with hexadecimal value 2a (r) match an r; parentheses are used to override precedence (see below) rs the regular expression r followed by the regular expression s; called "concatenation" r|s either an r or an s r/s an r but only if it is followed by an s. The text matched by s is included when determining whether this rule is the "longest match", but is then returned to the input before the action is executed. So the action only sees the text matched by r. This type of pattern is called trailing context". (There are some combinations of r/s that flex cannot match correctly; see notes in the Deficiencies / Bugs section below regarding "dangerous trailing context".) ^r an r, but only at the beginning of a line (i.e., when just starting to scan, or right after a newline has been scanned). r$ an r, but only at the end of a line (i.e., just before a newline). Equivalent to "r/\\n". Note that flex's notion of "newline" is exactly whatever the C compiler used to compile flex interprets '\\n' as; in particular, on some DOS systems you must either filter out \\r's in the input yourself, or explicitly use r/\\r\\n for "r$". r an r, but only in start condition s (see below for discussion of start conditions) r same, but in any of start conditions s1, s2, or s3 <*>r an r in any start condition, even an exclusive one. <> an end-of-file <> an end-of-file when in start condition s1 or s2 .fi Note that inside of a character class, all regular expression operators lose their special meaning except escape ('\\') and the character class operators, '-', ']', and, at the beginning of the class, '^'. .PP The regular expressions listed above are grouped according to precedence, from highest precedence at the top to lowest at the bottom. Those grouped together have equal precedence. For example, .nf foo|bar* .fi is the same as .nf (foo)|(ba(r*)) .fi since the '*' operator has higher precedence than concatenation, and concatenation higher than alternation ('|'). This pattern therefore matches .I either the string "foo" .I or the string "ba" followed by zero-or-more r's. To match "foo" or zero-or-more "bar"'s, use: .nf foo|(bar)* .fi and to match zero-or-more "foo"'s-or-"bar"'s: .nf (foo|bar)* .fi .PP In addition to characters and ranges of characters, character classes can also contain character class .I expressions. These are expressions enclosed inside .B [: and .B :] delimiters (which themselves must appear between the '[' and ']' of the character class; other elements may occur inside the character class, too). The valid expressions are: .nf [:alnum:] [:alpha:] [:blank:] [:cntrl:] [:digit:] [:graph:] [:lower:] [:print:] [:punct:] [:space:] [:upper:] [:xdigit:] .fi These expressions all designate a set of characters equivalent to the corresponding standard C .B isXXX function. For example, .B [:alnum:] designates those characters for which .B isalnum() returns true - i.e., any alphabetic or numeric. Some systems don't provide .B isblank(), so flex defines .B [:blank:] as a blank or a tab. .PP For example, the following character classes are all equivalent: .nf [[:alnum:]] [[:alpha:][:digit:]] [[:alpha:]0-9] [a-zA-Z0-9] .fi If your scanner is case-insensitive (the .B \-i flag), then .B [:upper:] and .B [:lower:] are equivalent to .B [:alpha:]. .PP Some notes on patterns: .IP - A negated character class such as the example "[^A-Z]" above .I will match a newline unless "\\n" (or an equivalent escape sequence) is one of the characters explicitly present in the negated character class (e.g., "[^A-Z\\n]"). This is unlike how many other regular expression tools treat negated character classes, but unfortunately the inconsistency is historically entrenched. Matching newlines means that a pattern like [^"]* can match the entire input unless there's another quote in the input. .IP - A rule can have at most one instance of trailing context (the '/' operator or the '$' operator). The start condition, '^', and "<>" patterns can only occur at the beginning of a pattern, and, as well as with '/' and '$', cannot be grouped inside parentheses. A '^' which does not occur at the beginning of a rule or a '$' which does not occur at the end of a rule loses its special properties and is treated as a normal character. .IP The following are illegal: .nf foo/bar$ foobar .fi Note that the first of these, can be written "foo/bar\\n". .IP The following will result in '$' or '^' being treated as a normal character: .nf foo|(bar$) foo|^bar .fi If what's wanted is a "foo" or a bar-followed-by-a-newline, the following could be used (the special '|' action is explained below): .nf foo | bar$ /* action goes here */ .fi A similar trick will work for matching a foo or a bar-at-the-beginning-of-a-line. .SH HOW THE INPUT IS MATCHED When the generated scanner is run, it analyzes its input looking for strings which match any of its patterns. If it finds more than one match, it takes the one matching the most text (for trailing context rules, this includes the length of the trailing part, even though it will then be returned to the input). If it finds two or more matches of the same length, the rule listed first in the .I flex input file is chosen. .PP Once the match is determined, the text corresponding to the match (called the .I token) is made available in the global character pointer .B yytext, and its length in the global integer .B yyleng. The .I action corresponding to the matched pattern is then executed (a more detailed description of actions follows), and then the remaining input is scanned for another match. .PP If no match is found, then the .I default rule is executed: the next character in the input is considered matched and copied to the standard output. Thus, the simplest legal .I flex input is: .nf %% .fi which generates a scanner that simply copies its input (one character at a time) to its output. .PP Note that .B yytext can be defined in two different ways: either as a character .I pointer or as a character .I array. You can control which definition .I flex uses by including one of the special directives .B %pointer or .B %array in the first (definitions) section of your flex input. The default is .B %pointer, unless you use the .B -l lex compatibility option, in which case .B yytext will be an array. The advantage of using .B %pointer is substantially faster scanning and no buffer overflow when matching very large tokens (unless you run out of dynamic memory). The disadvantage is that you are restricted in how your actions can modify .B yytext (see the next section), and calls to the .B unput() function destroys the present contents of .B yytext, which can be a considerable porting headache when moving between different .I lex versions. .PP The advantage of .B %array is that you can then modify .B yytext to your heart's content, and calls to .B unput() do not destroy .B yytext (see below). Furthermore, existing .I lex programs sometimes access .B yytext externally using declarations of the form: .nf extern char yytext[]; .fi This definition is erroneous when used with .B %pointer, but correct for .B %array. .PP .B %array defines .B yytext to be an array of .B YYLMAX characters, which defaults to a fairly large value. You can change the size by simply #define'ing .B YYLMAX to a different value in the first section of your .I flex input. As mentioned above, with .B %pointer yytext grows dynamically to accommodate large tokens. While this means your .B %pointer scanner can accommodate very large tokens (such as matching entire blocks of comments), bear in mind that each time the scanner must resize .B yytext it also must rescan the entire token from the beginning, so matching such tokens can prove slow. .B yytext presently does .I not dynamically grow if a call to .B unput() results in too much text being pushed back; instead, a run-time error results. .PP Also note that you cannot use .B %array with C++ scanner classes (the .B c++ option; see below). .SH ACTIONS Each pattern in a rule has a corresponding action, which can be any arbitrary C statement. The pattern ends at the first non-escaped whitespace character; the remainder of the line is its action. If the action is empty, then when the pattern is matched the input token is simply discarded. For example, here is the specification for a program which deletes all occurrences of "zap me" from its input: .nf %% "zap me" .fi (It will copy all other characters in the input to the output since they will be matched by the default rule.) .PP Here is a program which compresses multiple blanks and tabs down to a single blank, and throws away whitespace found at the end of a line: .nf %% [ \\t]+ putchar( ' ' ); [ \\t]+$ /* ignore this token */ .fi .PP If the action contains a '{', then the action spans till the balancing '}' is found, and the action may cross multiple lines. .I flex knows about C strings and comments and won't be fooled by braces found within them, but also allows actions to begin with .B %{ and will consider the action to be all the text up to the next .B %} (regardless of ordinary braces inside the action). .PP An action consisting solely of a vertical bar ('|') means "same as the action for the next rule." See below for an illustration. .PP Actions can include arbitrary C code, including .B return statements to return a value to whatever routine called .B yylex(). Each time .B yylex() is called it continues processing tokens from where it last left off until it either reaches the end of the file or executes a return. .PP Actions are free to modify .B yytext except for lengthening it (adding characters to its end--these will overwrite later characters in the input stream). This however does not apply when using .B %array (see above); in that case, .B yytext may be freely modified in any way. .PP Actions are free to modify .B yyleng except they should not do so if the action also includes use of .B yymore() (see below). .PP There are a number of special directives which can be included within an action: .IP - .B ECHO copies yytext to the scanner's output. .IP - .B BEGIN followed by the name of a start condition places the scanner in the corresponding start condition (see below). .IP - .B REJECT directs the scanner to proceed on to the "second best" rule which matched the input (or a prefix of the input). The rule is chosen as described above in "How the Input is Matched", and .B yytext and .B yyleng set up appropriately. It may either be one which matched as much text as the originally chosen rule but came later in the .I flex input file, or one which matched less text. For example, the following will both count the words in the input and call the routine special() whenever "frob" is seen: .nf int word_count = 0; %% frob special(); REJECT; [^ \\t\\n]+ ++word_count; .fi Without the .B REJECT, any "frob"'s in the input would not be counted as words, since the scanner normally executes only one action per token. Multiple .B REJECT's are allowed, each one finding the next best choice to the currently active rule. For example, when the following scanner scans the token "abcd", it will write "abcdabcaba" to the output: .nf %% a | ab | abc | abcd ECHO; REJECT; .|\\n /* eat up any unmatched character */ .fi (The first three rules share the fourth's action since they use the special '|' action.) .B REJECT is a particularly expensive feature in terms of scanner performance; if it is used in .I any of the scanner's actions it will slow down .I all of the scanner's matching. Furthermore, .B REJECT cannot be used with the .I -Cf or .I -CF options (see below). .IP Note also that unlike the other special actions, .B REJECT is a .I branch; code immediately following it in the action will .I not be executed. .IP - .B yymore() tells the scanner that the next time it matches a rule, the corresponding token should be .I appended onto the current value of .B yytext rather than replacing it. For example, given the input "mega-kludge" the following will write "mega-mega-kludge" to the output: .nf %% mega- ECHO; yymore(); kludge ECHO; .fi First "mega-" is matched and echoed to the output. Then "kludge" is matched, but the previous "mega-" is still hanging around at the beginning of .B yytext so the .B ECHO for the "kludge" rule will actually write "mega-kludge". .PP Two notes regarding use of .B yymore(). First, .B yymore() depends on the value of .I yyleng correctly reflecting the size of the current token, so you must not modify .I yyleng if you are using .B yymore(). Second, the presence of .B yymore() in the scanner's action entails a minor performance penalty in the scanner's matching speed. .IP - .B yyless(n) returns all but the first .I n characters of the current token back to the input stream, where they will be rescanned when the scanner looks for the next match. .B yytext and .B yyleng are adjusted appropriately (e.g., .B yyleng will now be equal to .I n ). For example, on the input "foobar" the following will write out "foobarbar": .nf %% foobar ECHO; yyless(3); [a-z]+ ECHO; .fi An argument of 0 to .B yyless will cause the entire current input string to be scanned again. Unless you've changed how the scanner will subsequently process its input (using .B BEGIN, for example), this will result in an endless loop. .PP Note that .B yyless is a macro and can only be used in the flex input file, not from other source files. .IP - .B unput(c) puts the character .I c back onto the input stream. It will be the next character scanned. The following action will take the current token and cause it to be rescanned enclosed in parentheses. .nf { int i; /* Copy yytext because unput() trashes yytext */ char *yycopy = strdup( yytext ); unput( ')' ); for ( i = yyleng - 1; i >= 0; --i ) unput( yycopy[i] ); unput( '(' ); free( yycopy ); } .fi Note that since each .B unput() puts the given character back at the .I beginning of the input stream, pushing back strings must be done back-to-front. .PP An important potential problem when using .B unput() is that if you are using .B %pointer (the default), a call to .B unput() .I destroys the contents of .I yytext, starting with its rightmost character and devouring one character to the left with each call. If you need the value of yytext preserved after a call to .B unput() (as in the above example), you must either first copy it elsewhere, or build your scanner using .B %array instead (see How The Input Is Matched). .PP Finally, note that you cannot put back .B EOF to attempt to mark the input stream with an end-of-file. .IP - .B input() reads the next character from the input stream. For example, the following is one way to eat up C comments: .nf %% "/*" { int c; for ( ; ; ) { while ( (c = input()) != '*' && c != EOF ) ; /* eat up text of comment */ if ( c == '*' ) { while ( (c = input()) == '*' ) ; if ( c == '/' ) break; /* found the end */ } if ( c == EOF ) { error( "EOF in comment" ); break; } } } .fi (Note that if the scanner is compiled using .B C++, then .B input() is instead referred to as .B yyinput(), in order to avoid a name clash with the .B C++ stream by the name of .I input.) .IP - .B YY_FLUSH_BUFFER flushes the scanner's internal buffer so that the next time the scanner attempts to match a token, it will first refill the buffer using .B YY_INPUT (see The Generated Scanner, below). This action is a special case of the more general .B yy_flush_buffer() function, described below in the section Multiple Input Buffers. .IP - .B yyterminate() can be used in lieu of a return statement in an action. It terminates the scanner and returns a 0 to the scanner's caller, indicating "all done". By default, .B yyterminate() is also called when an end-of-file is encountered. It is a macro and may be redefined. .SH THE GENERATED SCANNER The output of .I flex is the file .B lex.yy.c, which contains the scanning routine .B yylex(), a number of tables used by it for matching tokens, and a number of auxiliary routines and macros. By default, .B yylex() is declared as follows: .nf int yylex() { ... various definitions and the actions in here ... } .fi (If your environment supports function prototypes, then it will be "int yylex( void )".) This definition may be changed by defining the "YY_DECL" macro. For example, you could use: .nf #define YY_DECL float lexscan( a, b ) float a, b; .fi to give the scanning routine the name .I lexscan, returning a float, and taking two floats as arguments. Note that if you give arguments to the scanning routine using a K&R-style/non-prototyped function declaration, you must terminate the definition with a semi-colon (;). .PP Whenever .B yylex() is called, it scans tokens from the global input file .I yyin (which defaults to stdin). It continues until it either reaches an end-of-file (at which point it returns the value 0) or one of its actions executes a .I return statement. .PP If the scanner reaches an end-of-file, subsequent calls are undefined unless either .I yyin is pointed at a new input file (in which case scanning continues from that file), or .B yyrestart() is called. .B yyrestart() takes one argument, a .B FILE * pointer (which can be nil, if you've set up .B YY_INPUT to scan from a source other than .I yyin), and initializes .I yyin for scanning from that file. Essentially there is no difference between just assigning .I yyin to a new input file or using .B yyrestart() to do so; the latter is available for compatibility with previous versions of .I flex, and because it can be used to switch input files in the middle of scanning. It can also be used to throw away the current input buffer, by calling it with an argument of .I yyin; but better is to use .B YY_FLUSH_BUFFER (see above). Note that .B yyrestart() does .I not reset the start condition to .B INITIAL (see Start Conditions, below). .PP If .B yylex() stops scanning due to executing a .I return statement in one of the actions, the scanner may then be called again and it will resume scanning where it left off. .PP By default (and for purposes of efficiency), the scanner uses block-reads rather than simple .I getc() calls to read characters from .I yyin. The nature of how it gets its input can be controlled by defining the .B YY_INPUT macro. YY_INPUT's calling sequence is "YY_INPUT(buf,result,max_size)". Its action is to place up to .I max_size characters in the character array .I buf and return in the integer variable .I result either the number of characters read or the constant YY_NULL (0 on Unix systems) to indicate EOF. The default YY_INPUT reads from the global file-pointer "yyin". .PP A sample definition of YY_INPUT (in the definitions section of the input file): .nf %{ #define YY_INPUT(buf,result,max_size) \\ { \\ int c = getchar(); \\ result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \\ } %} .fi This definition will change the input processing to occur one character at a time. .PP When the scanner receives an end-of-file indication from YY_INPUT, it then checks the .B yywrap() function. If .B yywrap() returns false (zero), then it is assumed that the function has gone ahead and set up .I yyin to point to another input file, and scanning continues. If it returns true (non-zero), then the scanner terminates, returning 0 to its caller. Note that in either case, the start condition remains unchanged; it does .I not revert to .B INITIAL. .PP If you do not supply your own version of .B yywrap(), then you must either use .B %option noyywrap (in which case the scanner behaves as though .B yywrap() returned 1), or you must link with .B \-ll to obtain the default version of the routine, which always returns 1. .PP Three routines are available for scanning from in-memory buffers rather than files: .B yy_scan_string(), yy_scan_bytes(), and .B yy_scan_buffer(). See the discussion of them below in the section Multiple Input Buffers. .PP The scanner writes its .B ECHO output to the .I yyout global (default, stdout), which may be redefined by the user simply by assigning it to some other .B FILE pointer. .SH START CONDITIONS .I flex provides a mechanism for conditionally activating rules. Any rule whose pattern is prefixed with "" will only be active when the scanner is in the start condition named "sc". For example, .nf [^"]* { /* eat up the string body ... */ ... } .fi will be active only when the scanner is in the "STRING" start condition, and .nf \\. { /* handle an escape ... */ ... } .fi will be active only when the current start condition is either "INITIAL", "STRING", or "QUOTE". .PP Start conditions are declared in the definitions (first) section of the input using unindented lines beginning with either .B %s or .B %x followed by a list of names. The former declares .I inclusive start conditions, the latter .I exclusive start conditions. A start condition is activated using the .B BEGIN action. Until the next .B BEGIN action is executed, rules with the given start condition will be active and rules with other start conditions will be inactive. If the start condition is .I inclusive, then rules with no start conditions at all will also be active. If it is .I exclusive, then .I only rules qualified with the start condition will be active. A set of rules contingent on the same exclusive start condition describe a scanner which is independent of any of the other rules in the .I flex input. Because of this, exclusive start conditions make it easy to specify "mini-scanners" which scan portions of the input that are syntactically different from the rest (e.g., comments). .PP If the distinction between inclusive and exclusive start conditions is still a little vague, here's a simple example illustrating the connection between the two. The set of rules: .nf %s example %% foo do_something(); bar something_else(); .fi is equivalent to .nf %x example %% foo do_something(); bar something_else(); .fi Without the .B qualifier, the .I bar pattern in the second example wouldn't be active (i.e., couldn't match) when in start condition .B example. If we just used .B to qualify .I bar, though, then it would only be active in .B example and not in .B INITIAL, while in the first example it's active in both, because in the first example the .B example start condition is an .I inclusive .B (%s) start condition. .PP Also note that the special start-condition specifier .B <*> matches every start condition. Thus, the above example could also have been written; .nf %x example %% foo do_something(); <*>bar something_else(); .fi .PP The default rule (to .B ECHO any unmatched character) remains active in start conditions. It is equivalent to: .nf <*>.|\\n ECHO; .fi .PP .B BEGIN(0) returns to the original state where only the rules with no start conditions are active. This state can also be referred to as the start-condition "INITIAL", so .B BEGIN(INITIAL) is equivalent to .B BEGIN(0). (The parentheses around the start condition name are not required but are considered good style.) .PP .B BEGIN actions can also be given as indented code at the beginning of the rules section. For example, the following will cause the scanner to enter the "SPECIAL" start condition whenever .B yylex() is called and the global variable .I enter_special is true: .nf int enter_special; %x SPECIAL %% if ( enter_special ) BEGIN(SPECIAL); blahblahblah ...more rules follow... .fi .PP To illustrate the uses of start conditions, here is a scanner which provides two different interpretations of a string like "123.456". By default it will treat it as three tokens, the integer "123", a dot ('.'), and the integer "456". But if the string is preceded earlier in the line by the string "expect-floats" it will treat it as a single token, the floating-point number 123.456: .nf %{ #include %} %s expect %% expect-floats BEGIN(expect); [0-9]+"."[0-9]+ { printf( "found a float, = %f\\n", atof( yytext ) ); } \\n { /* that's the end of the line, so * we need another "expect-number" * before we'll recognize any more * numbers */ BEGIN(INITIAL); } [0-9]+ { printf( "found an integer, = %d\\n", atoi( yytext ) ); } "." printf( "found a dot\\n" ); .fi Here is a scanner which recognizes (and discards) C comments while maintaining a count of the current input line. .nf %x comment %% int line_num = 1; "/*" BEGIN(comment); [^*\\n]* /* eat anything that's not a '*' */ "*"+[^*/\\n]* /* eat up '*'s not followed by '/'s */ \\n ++line_num; "*"+"/" BEGIN(INITIAL); .fi This scanner goes to a bit of trouble to match as much text as possible with each rule. In general, when attempting to write a high-speed scanner try to match as much possible in each rule, as it's a big win. .PP Note that start-conditions names are really integer values and can be stored as such. Thus, the above could be extended in the following fashion: .nf %x comment foo %% int line_num = 1; int comment_caller; "/*" { comment_caller = INITIAL; BEGIN(comment); } ... "/*" { comment_caller = foo; BEGIN(comment); } [^*\\n]* /* eat anything that's not a '*' */ "*"+[^*/\\n]* /* eat up '*'s not followed by '/'s */ \\n ++line_num; "*"+"/" BEGIN(comment_caller); .fi Furthermore, you can access the current start condition using the integer-valued .B YY_START macro. For example, the above assignments to .I comment_caller could instead be written .nf comment_caller = YY_START; .fi Flex provides .B YYSTATE as an alias for .B YY_START (since that is what's used by AT&T .I lex). .PP Note that start conditions do not have their own name-space; %s's and %x's declare names in the same fashion as #define's. .PP Finally, here's an example of how to match C-style quoted strings using exclusive start conditions, including expanded escape sequences (but not including checking for a string that's too long): .nf %x str %% char string_buf[MAX_STR_CONST]; char *string_buf_ptr; \\" string_buf_ptr = string_buf; BEGIN(str); \\" { /* saw closing quote - all done */ BEGIN(INITIAL); *string_buf_ptr = '\\0'; /* return string constant token type and * value to parser */ } \\n { /* error - unterminated string constant */ /* generate error message */ } \\\\[0-7]{1,3} { /* octal escape sequence */ int result; (void) sscanf( yytext + 1, "%o", &result ); if ( result > 0xff ) /* error, constant is out-of-bounds */ *string_buf_ptr++ = result; } \\\\[0-9]+ { /* generate error - bad escape sequence; something * like '\\48' or '\\0777777' */ } \\\\n *string_buf_ptr++ = '\\n'; \\\\t *string_buf_ptr++ = '\\t'; \\\\r *string_buf_ptr++ = '\\r'; \\\\b *string_buf_ptr++ = '\\b'; \\\\f *string_buf_ptr++ = '\\f'; \\\\(.|\\n) *string_buf_ptr++ = yytext[1]; [^\\\\\\n\\"]+ { char *yptr = yytext; while ( *yptr ) *string_buf_ptr++ = *yptr++; } .fi .PP Often, such as in some of the examples above, you wind up writing a whole bunch of rules all preceded by the same start condition(s). Flex makes this a little easier and cleaner by introducing a notion of start condition .I scope. A start condition scope is begun with: .nf { .fi where .I SCs is a list of one or more start conditions. Inside the start condition scope, every rule automatically has the prefix .I applied to it, until a .I '}' which matches the initial .I '{'. So, for example, .nf { "\\\\n" return '\\n'; "\\\\r" return '\\r'; "\\\\f" return '\\f'; "\\\\0" return '\\0'; } .fi is equivalent to: .nf "\\\\n" return '\\n'; "\\\\r" return '\\r'; "\\\\f" return '\\f'; "\\\\0" return '\\0'; .fi Start condition scopes may be nested. .PP Three routines are available for manipulating stacks of start conditions: .TP .B void yy_push_state(int new_state) pushes the current start condition onto the top of the start condition stack and switches to .I new_state as though you had used .B BEGIN new_state (recall that start condition names are also integers). .TP .B void yy_pop_state() pops the top of the stack and switches to it via .B BEGIN. .TP .B int yy_top_state() returns the top of the stack without altering the stack's contents. .PP The start condition stack grows dynamically and so has no built-in size limitation. If memory is exhausted, program execution aborts. .PP To use start condition stacks, your scanner must include a .B %option stack directive (see Options below). .SH MULTIPLE INPUT BUFFERS Some scanners (such as those which support "include" files) require reading from several input streams. As .I flex scanners do a large amount of buffering, one cannot control where the next input will be read from by simply writing a .B YY_INPUT which is sensitive to the scanning context. .B YY_INPUT is only called when the scanner reaches the end of its buffer, which may be a long time after scanning a statement such as an "include" which requires switching the input source. .PP To negotiate these sorts of problems, .I flex provides a mechanism for creating and switching between multiple input buffers. An input buffer is created by using: .nf YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) .fi which takes a .I FILE pointer and a size and creates a buffer associated with the given file and large enough to hold .I size characters (when in doubt, use .B YY_BUF_SIZE for the size). It returns a .B YY_BUFFER_STATE handle, which may then be passed to other routines (see below). The .B YY_BUFFER_STATE type is a pointer to an opaque .B struct yy_buffer_state structure, so you may safely initialize YY_BUFFER_STATE variables to .B ((YY_BUFFER_STATE) 0) if you wish, and also refer to the opaque structure in order to correctly declare input buffers in source files other than that of your scanner. Note that the .I FILE pointer in the call to .B yy_create_buffer is only used as the value of .I yyin seen by .B YY_INPUT; if you redefine .B YY_INPUT so it no longer uses .I yyin, then you can safely pass a nil .I FILE pointer to .B yy_create_buffer. You select a particular buffer to scan from using: .nf void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) .fi switches the scanner's input buffer so subsequent tokens will come from .I new_buffer. Note that .B yy_switch_to_buffer() may be used by yywrap() to set things up for continued scanning, instead of opening a new file and pointing .I yyin at it. Note also that switching input sources via either .B yy_switch_to_buffer() or .B yywrap() does .I not change the start condition. .nf void yy_delete_buffer( YY_BUFFER_STATE buffer ) .fi is used to reclaim the storage associated with a buffer. ( .B buffer can be nil, in which case the routine does nothing.) You can also clear the current contents of a buffer using: .nf void yy_flush_buffer( YY_BUFFER_STATE buffer ) .fi This function discards the buffer's contents, so the next time the scanner attempts to match a token from the buffer, it will first fill the buffer anew using .B YY_INPUT. .PP .B yy_new_buffer() is an alias for .B yy_create_buffer(), provided for compatibility with the C++ use of .I new and .I delete for creating and destroying dynamic objects. .PP Finally, the .B YY_CURRENT_BUFFER macro returns a .B YY_BUFFER_STATE handle to the current buffer. .PP Here is an example of using these features for writing a scanner which expands include files (the .B <> feature is discussed below): .nf /* the "incl" state is used for picking up the name * of an include file */ %x incl %{ #define MAX_INCLUDE_DEPTH 10 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; %} %% include BEGIN(incl); [a-z]+ ECHO; [^a-z\\n]*\\n? ECHO; [ \\t]* /* eat the whitespace */ [^ \\t\\n]+ { /* got the include file name */ if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) { fprintf( stderr, "Includes nested too deeply" ); exit( 1 ); } include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER; yyin = fopen( yytext, "r" ); if ( ! yyin ) error( ... ); yy_switch_to_buffer( yy_create_buffer( yyin, YY_BUF_SIZE ) ); BEGIN(INITIAL); } <> { if ( --include_stack_ptr < 0 ) { yyterminate(); } else { yy_delete_buffer( YY_CURRENT_BUFFER ); yy_switch_to_buffer( include_stack[include_stack_ptr] ); } } .fi Three routines are available for setting up input buffers for scanning in-memory strings instead of files. All of them create a new input buffer for scanning the string, and return a corresponding .B YY_BUFFER_STATE handle (which you should delete with .B yy_delete_buffer() when done with it). They also switch to the new buffer using .B yy_switch_to_buffer(), so the next call to .B yylex() will start scanning the string. .TP .B yy_scan_string(const char *str) scans a NUL-terminated string. .TP .B yy_scan_bytes(const char *bytes, int len) scans .I len bytes (including possibly NUL's) starting at location .I bytes. .PP Note that both of these functions create and scan a .I copy of the string or bytes. (This may be desirable, since .B yylex() modifies the contents of the buffer it is scanning.) You can avoid the copy by using: .TP .B yy_scan_buffer(char *base, yy_size_t size) which scans in place the buffer starting at .I base, consisting of .I size bytes, the last two bytes of which .I must be .B YY_END_OF_BUFFER_CHAR (ASCII NUL). These last two bytes are not scanned; thus, scanning consists of .B base[0] through .B base[size-2], inclusive. .IP If you fail to set up .I base in this manner (i.e., forget the final two .B YY_END_OF_BUFFER_CHAR bytes), then .B yy_scan_buffer() returns a nil pointer instead of creating a new input buffer. .IP The type .B yy_size_t is an integral type to which you can cast an integer expression reflecting the size of the buffer. .SH END-OF-FILE RULES The special rule "<>" indicates actions which are to be taken when an end-of-file is encountered and yywrap() returns non-zero (i.e., indicates no further files to process). The action must finish by doing one of four things: .IP - assigning .I yyin to a new input file (in previous versions of flex, after doing the assignment you had to call the special action .B YY_NEW_FILE; this is no longer necessary); .IP - executing a .I return statement; .IP - executing the special .B yyterminate() action; .IP - or, switching to a new buffer using .B yy_switch_to_buffer() as shown in the example above. .PP <> rules may not be used with other patterns; they may only be qualified with a list of start conditions. If an unqualified <> rule is given, it applies to .I all start conditions which do not already have <> actions. To specify an <> rule for only the initial start condition, use .nf <> .fi .PP These rules are useful for catching things like unclosed comments. An example: .nf %x quote %% ...other rules for dealing with quotes... <> { error( "unterminated quote" ); yyterminate(); } <> { if ( *++filelist ) yyin = fopen( *filelist, "r" ); else yyterminate(); } .fi .SH MISCELLANEOUS MACROS The macro .B YY_USER_ACTION can be defined to provide an action which is always executed prior to the matched rule's action. For example, it could be #define'd to call a routine to convert yytext to lower-case. When .B YY_USER_ACTION is invoked, the variable .I yy_act gives the number of the matched rule (rules are numbered starting with 1). Suppose you want to profile how often each of your rules is matched. The following would do the trick: .nf #define YY_USER_ACTION ++ctr[yy_act] .fi where .I ctr is an array to hold the counts for the different rules. Note that the macro .B YY_NUM_RULES gives the total number of rules (including the default rule, even if you use .B \-s), so a correct declaration for .I ctr is: .nf int ctr[YY_NUM_RULES]; .fi .PP The macro .B YY_USER_INIT may be defined to provide an action which is always executed before the first scan (and before the scanner's internal initializations are done). For example, it could be used to call a routine to read in a data table or open a logging file. .PP The macro .B yy_set_interactive(is_interactive) can be used to control whether the current buffer is considered .I interactive. An interactive buffer is processed more slowly, but must be used when the scanner's input source is indeed interactive to avoid problems due to waiting to fill buffers (see the discussion of the .B \-I flag below). A non-zero value in the macro invocation marks the buffer as interactive, a zero value as non-interactive. Note that use of this macro overrides .B %option interactive , .B %option always-interactive or .B %option never-interactive (see Options below). .B yy_set_interactive() must be invoked prior to beginning to scan the buffer that is (or is not) to be considered interactive. .PP The macro .B yy_set_bol(at_bol) can be used to control whether the current buffer's scanning context for the next token match is done as though at the beginning of a line. A non-zero macro argument makes rules anchored with '^' active, while a zero argument makes '^' rules inactive. .PP The macro .B YY_AT_BOL() returns true if the next token scanned from the current buffer will have '^' rules active, false otherwise. .PP In the generated scanner, the actions are all gathered in one large switch statement and separated using .B YY_BREAK, which may be redefined. By default, it is simply a "break", to separate each rule's action from the following rule's. Redefining .B YY_BREAK allows, for example, C++ users to #define YY_BREAK to do nothing (while being very careful that every rule ends with a "break" or a "return"!) to avoid suffering from unreachable statement warnings where because a rule's action ends with "return", the .B YY_BREAK is inaccessible. .SH VALUES AVAILABLE TO THE USER This section summarizes the various values available to the user in the rule actions. .IP - .B char *yytext holds the text of the current token. It may be modified but not lengthened (you cannot append characters to the end). .IP If the special directive .B %array appears in the first section of the scanner description, then .B yytext is instead declared .B char yytext[YYLMAX], where .B YYLMAX is a macro definition that you can redefine in the first section if you don't like the default value (generally 8KB). Using .B %array results in somewhat slower scanners, but the value of .B yytext becomes immune to calls to .I input() and .I unput(), which potentially destroy its value when .B yytext is a character pointer. The opposite of .B %array is .B %pointer, which is the default. .IP You cannot use .B %array when generating C++ scanner classes (the .B \-+ flag). .IP - .B int yyleng holds the length of the current token. .IP - .B FILE *yyin is the file which by default .I flex reads from. It may be redefined but doing so only makes sense before scanning begins or after an EOF has been encountered. Changing it in the midst of scanning will have unexpected results since .I flex buffers its input; use .B yyrestart() instead. Once scanning terminates because an end-of-file has been seen, you can assign .I yyin at the new input file and then call the scanner again to continue scanning. .IP - .B void yyrestart( FILE *new_file ) may be called to point .I yyin at the new input file. The switch-over to the new file is immediate (any previously buffered-up input is lost). Note that calling .B yyrestart() with .I yyin as an argument thus throws away the current input buffer and continues scanning the same input file. .IP - .B FILE *yyout is the file to which .B ECHO actions are done. It can be reassigned by the user. .IP - .B YY_CURRENT_BUFFER returns a .B YY_BUFFER_STATE handle to the current buffer. .IP - .B YY_START returns an integer value corresponding to the current start condition. You can subsequently use this value with .B BEGIN to return to that start condition. .SH INTERFACING WITH YACC One of the main uses of .I flex is as a companion to the .I yacc parser-generator. .I yacc parsers expect to call a routine named .B yylex() to find the next input token. The routine is supposed to return the type of the next token as well as putting any associated value in the global .B yylval. To use .I flex with .I yacc, one specifies the .B \-d option to .I yacc to instruct it to generate the file .B y.tab.h containing definitions of all the .B %tokens appearing in the .I yacc input. This file is then included in the .I flex scanner. For example, if one of the tokens is "TOK_NUMBER", part of the scanner might look like: .nf %{ #include "y.tab.h" %} %% [0-9]+ yylval = atoi( yytext ); return TOK_NUMBER; .fi .SH OPTIONS .I flex has the following options: .TP .B \-b, --backup Generate backing-up information to .I lex.backup. This is a list of scanner states which require backing up and the input characters on which they do so. By adding rules one can remove backing-up states. If .I all backing-up states are eliminated and .B \-Cf or .B \-CF is used, the generated scanner will run faster (see the .B \-p flag). Only users who wish to squeeze every last cycle out of their scanners need worry about this option. (See the section on Performance Considerations below.) .TP .B \-c is a do-nothing, deprecated option included for POSIX compliance. .TP .B \-d, \-\-debug makes the generated scanner run in .I debug mode. Whenever a pattern is recognized and the global .B yy_flex_debug is non-zero (which is the default), the scanner will write to .I stderr a line of the form: .nf --accepting rule at line 53 ("the matched text") .fi The line number refers to the location of the rule in the file defining the scanner (i.e., the file that was fed to flex). Messages are also generated when the scanner backs up, accepts the default rule, reaches the end of its input buffer (or encounters a NUL; at this point, the two look the same as far as the scanner's concerned), or reaches an end-of-file. .TP .B \-f, \-\-full specifies .I fast scanner. No table compression is done and stdio is bypassed. The result is large but fast. This option is equivalent to .B \-Cfr (see below). .TP .B \-h, \-\-help generates a "help" summary of .I flex's options to .I stdout and then exits. .B \-? and .B \-\-help are synonyms for .B \-h. .TP .B \-i, \-\-case-insensitive instructs .I flex to generate a .I case-insensitive scanner. The case of letters given in the .I flex input patterns will be ignored, and tokens in the input will be matched regardless of case. The matched text given in .I yytext will have the preserved case (i.e., it will not be folded). .TP .B \-l, \-\-lex\-compat turns on maximum compatibility with the original AT&T .I lex implementation. Note that this does not mean .I full compatibility. Use of this option costs a considerable amount of performance, and it cannot be used with the .B \-+, -f, -F, -Cf, or .B -CF options. For details on the compatibilities it provides, see the section "Incompatibilities With Lex And POSIX" below. This option also results in the name .B YY_FLEX_LEX_COMPAT being #define'd in the generated scanner. .TP .B \-n is another do-nothing, deprecated option included only for POSIX compliance. .TP .B \-p, \-\-perf\-report generates a performance report to stderr. The report consists of comments regarding features of the .I flex input file which will cause a serious loss of performance in the resulting scanner. If you give the flag twice, you will also get comments regarding features that lead to minor performance losses. .IP Note that the use of .B REJECT, .B %option yylineno, and variable trailing context (see the Deficiencies / Bugs section below) entails a substantial performance penalty; use of .I yymore(), the .B ^ operator, and the .B \-I flag entail minor performance penalties. .TP .B \-s, \-\-no\-default causes the .I default rule (that unmatched scanner input is echoed to .I stdout) to be suppressed. If the scanner encounters input that does not match any of its rules, it aborts with an error. This option is useful for finding holes in a scanner's rule set. .TP .B \-t, \-\-stdout instructs .I flex to write the scanner it generates to standard output instead of .B lex.yy.c. .TP .B \-v, \-\-verbose specifies that .I flex should write to .I stderr a summary of statistics regarding the scanner it generates. Most of the statistics are meaningless to the casual .I flex user, but the first line identifies the version of .I flex (same as reported by .B \-V), and the next line the flags used when generating the scanner, including those that are on by default. .TP .B \-w, \-\-nowarn suppresses warning messages. .TP .B \-B, \-\-batch instructs .I flex to generate a .I batch scanner, the opposite of .I interactive scanners generated by .B \-I (see below). In general, you use .B \-B when you are .I certain that your scanner will never be used interactively, and you want to squeeze a .I little more performance out of it. If your goal is instead to squeeze out a .I lot more performance, you should be using the .B \-Cf or .B \-CF options (discussed below), which turn on .B \-B automatically anyway. .TP .B \-F, \-\-fast specifies that the .ul fast scanner table representation should be used (and stdio bypassed). This representation is about as fast as the full table representation .B (-f), and for some sets of patterns will be considerably smaller (and for others, larger). In general, if the pattern set contains both "keywords" and a catch-all, "identifier" rule, such as in the set: .nf "case" return TOK_CASE; "switch" return TOK_SWITCH; ... "default" return TOK_DEFAULT; [a-z]+ return TOK_ID; .fi then you're better off using the full table representation. If only the "identifier" rule is present and you then use a hash table or some such to detect the keywords, you're better off using .B -F. .IP This option is equivalent to .B \-CFr (see below). It cannot be used with .B \-+. .TP .B \-I, \-\-interactive instructs .I flex to generate an .I interactive scanner. An interactive scanner is one that only looks ahead to decide what token has been matched if it absolutely must. It turns out that always looking one extra character ahead, even if the scanner has already seen enough text to disambiguate the current token, is a bit faster than only looking ahead when necessary. But scanners that always look ahead give dreadful interactive performance; for example, when a user types a newline, it is not recognized as a newline token until they enter .I another token, which often means typing in another whole line. .IP .I Flex scanners default to .I interactive unless you use the .B \-Cf or .B \-CF table-compression options (see below). That's because if you're looking for high-performance you should be using one of these options, so if you didn't, .I flex assumes you'd rather trade off a bit of run-time performance for intuitive interactive behavior. Note also that you .I cannot use .B \-I in conjunction with .B \-Cf or .B \-CF. Thus, this option is not really needed; it is on by default for all those cases in which it is allowed. .IP Note that if .B isatty() returns false for the scanner input, flex will revert to batch mode, even if .B \-I was specified. To force interactive mode no matter what, use .B %option always-interactive (see Options below). .IP You can force a scanner to .I not be interactive by using .B \-B (see above). .TP .B \-L, \-\-noline instructs .I flex not to generate .B #line directives. Without this option, .I flex peppers the generated scanner with #line directives so error messages in the actions will be correctly located with respect to either the original .I flex input file (if the errors are due to code in the input file), or .B lex.yy.c (if the errors are .I flex's fault -- you should report these sorts of errors to the email address given below). .TP .B \-T, \-\-trace makes .I flex run in .I trace mode. It will generate a lot of messages to .I stderr concerning the form of the input and the resultant non-deterministic and deterministic finite automata. This option is mostly for use in maintaining .I flex. .TP .B \-V, \-\-version prints the version number to .I stdout and exits. .B \-\-version is a synonym for .B \-V. .TP .B \-7, \-\-7bit instructs .I flex to generate a 7-bit scanner, i.e., one which can only recognize 7-bit characters in its input. The advantage of using .B \-7 is that the scanner's tables can be up to half the size of those generated using the .B \-8 option (see below). The disadvantage is that such scanners often hang or crash if their input contains an 8-bit character. .IP Note, however, that unless you generate your scanner using the .B \-Cf or .B \-CF table compression options, use of .B \-7 will save only a small amount of table space, and make your scanner considerably less portable. .I Flex's default behavior is to generate an 8-bit scanner unless you use the .B \-Cf or .B \-CF, in which case .I flex defaults to generating 7-bit scanners unless your site was always configured to generate 8-bit scanners (as will often be the case with non-USA sites). You can tell whether flex generated a 7-bit or an 8-bit scanner by inspecting the flag summary in the .B \-v output as described above. .IP Note that if you use .B \-Cfe or .B \-CFe (those table compression options, but also using equivalence classes as discussed see below), flex still defaults to generating an 8-bit scanner, since usually with these compression options full 8-bit tables are not much more expensive than 7-bit tables. .TP .B \-8, \-\-8bit instructs .I flex to generate an 8-bit scanner, i.e., one which can recognize 8-bit characters. This flag is only needed for scanners generated using .B \-Cf or .B \-CF, as otherwise flex defaults to generating an 8-bit scanner anyway. .IP See the discussion of .B \-7 above for flex's default behavior and the tradeoffs between 7-bit and 8-bit scanners. .TP .B \-+, \-\-c++ specifies that you want flex to generate a C++ scanner class. See the section on Generating C++ Scanners below for details. .TP .B \-C[aefFmr] controls the degree of table compression and, more generally, trade-offs between small scanners and fast scanners. .IP .B \-Ca, \-\-align ("align") instructs flex to trade off larger tables in the generated scanner for faster performance because the elements of the tables are better aligned for memory access and computation. On some RISC architectures, fetching and manipulating longwords is more efficient than with smaller-sized units such as shortwords. This option can double the size of the tables used by your scanner. .IP .B \-Ce, \-\-ecs directs .I flex to construct .I equivalence classes, i.e., sets of characters which have identical lexical properties (for example, if the only appearance of digits in the .I flex input is in the character class "[0-9]" then the digits '0', '1', ..., '9' will all be put in the same equivalence class). Equivalence classes usually give dramatic reductions in the final table/object file sizes (typically a factor of 2-5) and are pretty cheap performance-wise (one array look-up per character scanned). .IP .B \-Cf specifies that the .I full scanner tables should be generated - .I flex should not compress the tables by taking advantages of similar transition functions for different states. .IP .B \-CF specifies that the alternative fast scanner representation (described above under the .B \-F flag) should be used. This option cannot be used with .B \-+. .IP .B \-Cm, \-\-meta-ecs directs .I flex to construct .I meta-equivalence classes, which are sets of equivalence classes (or characters, if equivalence classes are not being used) that are commonly used together. Meta-equivalence classes are often a big win when using compressed tables, but they have a moderate performance impact (one or two "if" tests and one array look-up per character scanned). .IP .B \-Cr, \-\-read causes the generated scanner to .I bypass use of the standard I/O library (stdio) for input. Instead of calling .B fread() or .B getc(), the scanner will use the .B read() system call, resulting in a performance gain which varies from system to system, but in general is probably negligible unless you are also using .B \-Cf or .B \-CF. Using .B \-Cr can cause strange behavior if, for example, you read from .I yyin using stdio prior to calling the scanner (because the scanner will miss whatever text your previous reads left in the stdio input buffer). .IP .B \-Cr has no effect if you define .B YY_INPUT (see The Generated Scanner above). .IP A lone .B \-C specifies that the scanner tables should be compressed but neither equivalence classes nor meta-equivalence classes should be used. .IP The options .B \-Cf or .B \-CF and .B \-Cm do not make sense together - there is no opportunity for meta-equivalence classes if the table is not being compressed. Otherwise the options may be freely mixed, and are cumulative. .IP The default setting is .B \-Cem, which specifies that .I flex should generate equivalence classes and meta-equivalence classes. This setting provides the highest degree of table compression. You can trade off faster-executing scanners at the cost of larger tables with the following generally being true: .nf slowest & smallest -Cem -Cm -Ce -C -C{f,F}e -C{f,F} -C{f,F}a fastest & largest .fi Note that scanners with the smallest tables are usually generated and compiled the quickest, so during development you will usually want to use the default, maximal compression. .IP .B \-Cfe is often a good compromise between speed and size for production scanners. .TP .B \-ooutput, \-\-outputfile=FILE directs flex to write the scanner to the file .B output instead of .B lex.yy.c. If you combine .B \-o with the .B \-t option, then the scanner is written to .I stdout but its .B #line directives (see the .B \\-L option above) refer to the file .B output. .TP .B \-Pprefix, \-\-prefix=STRING changes the default .I "yy" prefix used by .I flex for all globally-visible variable and function names to instead be .I prefix. For example, .B \-Pfoo changes the name of .B yytext to .B footext. It also changes the name of the default output file from .B lex.yy.c to .B lex.foo.c. Here are all of the names affected: .nf yy_create_buffer yy_delete_buffer yy_flex_debug yy_init_buffer yy_flush_buffer yy_load_buffer_state yy_switch_to_buffer yyin yyleng yylex yylineno yyout yyrestart yytext yywrap .fi (If you are using a C++ scanner, then only .B yywrap and .B yyFlexLexer are affected.) Within your scanner itself, you can still refer to the global variables and functions using either version of their name; but externally, they have the modified name. .IP This option lets you easily link together multiple .I flex programs into the same executable. Note, though, that using this option also renames .B yywrap(), so you now .I must either provide your own (appropriately-named) version of the routine for your scanner, or use .B %option noyywrap, as linking with .B \-ll no longer provides one for you by default. .TP .B \-Sskeleton_file, \-\-skel=FILE overrides the default skeleton file from which .I flex constructs its scanners. You'll never need this option unless you are doing .I flex maintenance or development. .TP .B \-X, \-\-posix\-compat maximal compatibility with POSIX lex. .TP .B \-\-yylineno track line count in yylineno. .TP .B \-\-yyclass=NAME name of C++ class. .TP .B \-\-header\-file=FILE create a C header file in addition to the scanner. .TP .B \-\-tables\-file[=FILE] write tables to FILE. .TP .B \\-Dmacro[=defn] #define macro defn (default defn is '1'). .TP .B \-R, \-\-reentrant generate a reentrant C scanner .TP .B \-\-bison\-bridge scanner for bison pure parser. .TP .B \-\-bison\-locations include yylloc support. .TP .B \-\-stdinit initialize yyin/yyout to stdin/stdout. .TP .B \-\-noansi\-definitions old\-style function definitions. .TP .B \-\-noansi\-prototypes empty parameter list in prototypes. .TP .B \-\-nounistd do not include . .TP .B \-\-noFUNCTION do not generate a particular FUNCTION. .PP .I flex also provides a mechanism for controlling options within the scanner specification itself, rather than from the flex command-line. This is done by including .B %option directives in the first section of the scanner specification. You can specify multiple options with a single .B %option directive, and multiple directives in the first section of your flex input file. .PP Most options are given simply as names, optionally preceded by the word "no" (with no intervening whitespace) to negate their meaning. A number are equivalent to flex flags or their negation: .nf 7bit -7 option 8bit -8 option align -Ca option backup -b option batch -B option c++ -+ option caseful or case-sensitive opposite of -i (default) case-insensitive or caseless -i option debug -d option default opposite of -s option ecs -Ce option fast -F option full -f option interactive -I option lex-compat -l option meta-ecs -Cm option perf-report -p option read -Cr option stdout -t option verbose -v option warn opposite of -w option (use "%option nowarn" for -w) array equivalent to "%array" pointer equivalent to "%pointer" (default) .fi Some .B %option's provide features otherwise not available: .TP .B always-interactive instructs flex to generate a scanner which always considers its input "interactive". Normally, on each new input file the scanner calls .B isatty() in an attempt to determine whether the scanner's input source is interactive and thus should be read a character at a time. When this option is used, however, then no such call is made. .TP .B main directs flex to provide a default .B main() program for the scanner, which simply calls .B yylex(). This option implies .B noyywrap (see below). .TP .B never-interactive instructs flex to generate a scanner which never considers its input "interactive" (again, no call made to .B isatty()). This is the opposite of .B always-interactive. .TP .B stack enables the use of start condition stacks (see Start Conditions above). .TP .B stdinit if set (i.e., .B %option stdinit) initializes .I yyin and .I yyout to .I stdin and .I stdout, instead of the default of .I nil. Some existing .I lex programs depend on this behavior, even though it is not compliant with ANSI C, which does not require .I stdin and .I stdout to be compile-time constant. .TP .B yylineno directs .I flex to generate a scanner that maintains the number of the current line read from its input in the global variable .B yylineno. This option is implied by .B %option lex-compat. .TP .B yywrap if unset (i.e., .B %option noyywrap), makes the scanner not call .B yywrap() upon an end-of-file, but simply assume that there are no more files to scan (until the user points .I yyin at a new file and calls .B yylex() again). .PP .I flex scans your rule actions to determine whether you use the .B REJECT or .B yymore() features. The .B reject and .B yymore options are available to override its decision as to whether you use the options, either by setting them (e.g., .B %option reject) to indicate the feature is indeed used, or unsetting them to indicate it actually is not used (e.g., .B %option noyymore). .PP Three options take string-delimited values, offset with '=': .nf %option outfile="ABC" .fi is equivalent to .B -oABC, and .nf %option prefix="XYZ" .fi is equivalent to .B -PXYZ. Finally, .nf %option yyclass="foo" .fi only applies when generating a C++ scanner ( .B \-+ option). It informs .I flex that you have derived .B foo as a subclass of .B yyFlexLexer, so .I flex will place your actions in the member function .B foo::yylex() instead of .B yyFlexLexer::yylex(). It also generates a .B yyFlexLexer::yylex() member function that emits a run-time error (by invoking .B yyFlexLexer::LexerError()) if called. See Generating C++ Scanners, below, for additional information. .PP A number of options are available for lint purists who want to suppress the appearance of unneeded routines in the generated scanner. Each of the following, if unset (e.g., .B %option nounput ), results in the corresponding routine not appearing in the generated scanner: .nf input, unput yy_push_state, yy_pop_state, yy_top_state yy_scan_buffer, yy_scan_bytes, yy_scan_string .fi (though .B yy_push_state() and friends won't appear anyway unless you use .B %option stack). .SH PERFORMANCE CONSIDERATIONS The main design goal of .I flex is that it generate high-performance scanners. It has been optimized for dealing well with large sets of rules. Aside from the effects on scanner speed of the table compression .B \-C options outlined above, there are a number of options/actions which degrade performance. These are, from most expensive to least: .nf REJECT %option yylineno arbitrary trailing context pattern sets that require backing up %array %option interactive %option always-interactive '^' beginning-of-line operator yymore() .fi with the first three all being quite expensive and the last two being quite cheap. Note also that .B unput() is implemented as a routine call that potentially does quite a bit of work, while .B yyless() is a quite-cheap macro; so if just putting back some excess text you scanned, use .B yyless(). .PP .B REJECT should be avoided at all costs when performance is important. It is a particularly expensive option. .PP Getting rid of backing up is messy and often may be an enormous amount of work for a complicated scanner. In principal, one begins by using the .B \-b flag to generate a .I lex.backup file. For example, on the input .nf %% foo return TOK_KEYWORD; foobar return TOK_KEYWORD; .fi the file looks like: .nf State #6 is non-accepting - associated rule line numbers: 2 3 out-transitions: [ o ] jam-transitions: EOF [ \\001-n p-\\177 ] State #8 is non-accepting - associated rule line numbers: 3 out-transitions: [ a ] jam-transitions: EOF [ \\001-` b-\\177 ] State #9 is non-accepting - associated rule line numbers: 3 out-transitions: [ r ] jam-transitions: EOF [ \\001-q s-\\177 ] Compressed tables always back up. .fi The first few lines tell us that there's a scanner state in which it can make a transition on an 'o' but not on any other character, and that in that state the currently scanned text does not match any rule. The state occurs when trying to match the rules found at lines 2 and 3 in the input file. If the scanner is in that state and then reads something other than an 'o', it will have to back up to find a rule which is matched. With a bit of headscratching one can see that this must be the state it's in when it has seen "fo". When this has happened, if anything other than another 'o' is seen, the scanner will have to back up to simply match the 'f' (by the default rule). .PP The comment regarding State #8 indicates there's a problem when "foob" has been scanned. Indeed, on any character other than an 'a', the scanner will have to back up to accept "foo". Similarly, the comment for State #9 concerns when "fooba" has been scanned and an 'r' does not follow. .PP The final comment reminds us that there's no point going to all the trouble of removing backing up from the rules unless we're using .B \-Cf or .B \-CF, since there's no performance gain doing so with compressed scanners. .PP The way to remove the backing up is to add "error" rules: .nf %% foo return TOK_KEYWORD; foobar return TOK_KEYWORD; fooba | foob | fo { /* false alarm, not really a keyword */ return TOK_ID; } .fi .PP Eliminating backing up among a list of keywords can also be done using a "catch-all" rule: .nf %% foo return TOK_KEYWORD; foobar return TOK_KEYWORD; [a-z]+ return TOK_ID; .fi This is usually the best solution when appropriate. .PP Backing up messages tend to cascade. With a complicated set of rules it's not uncommon to get hundreds of messages. If one can decipher them, though, it often only takes a dozen or so rules to eliminate the backing up (though it's easy to make a mistake and have an error rule accidentally match a valid token. A possible future .I flex feature will be to automatically add rules to eliminate backing up). .PP It's important to keep in mind that you gain the benefits of eliminating backing up only if you eliminate .I every instance of backing up. Leaving just one means you gain nothing. .PP .I Variable trailing context (where both the leading and trailing parts do not have a fixed length) entails almost the same performance loss as .B REJECT (i.e., substantial). So when possible a rule like: .nf %% mouse|rat/(cat|dog) run(); .fi is better written: .nf %% mouse/cat|dog run(); rat/cat|dog run(); .fi or as .nf %% mouse|rat/cat run(); mouse|rat/dog run(); .fi Note that here the special '|' action does .I not provide any savings, and can even make things worse (see Deficiencies / Bugs below). .LP Another area where the user can increase a scanner's performance (and one that's easier to implement) arises from the fact that the longer the tokens matched, the faster the scanner will run. This is because with long tokens the processing of most input characters takes place in the (short) inner scanning loop, and does not often have to go through the additional work of setting up the scanning environment (e.g., .B yytext) for the action. Recall the scanner for C comments: .nf %x comment %% int line_num = 1; "/*" BEGIN(comment); [^*\\n]* "*"+[^*/\\n]* \\n ++line_num; "*"+"/" BEGIN(INITIAL); .fi This could be sped up by writing it as: .nf %x comment %% int line_num = 1; "/*" BEGIN(comment); [^*\\n]* [^*\\n]*\\n ++line_num; "*"+[^*/\\n]* "*"+[^*/\\n]*\\n ++line_num; "*"+"/" BEGIN(INITIAL); .fi Now instead of each newline requiring the processing of another action, recognizing the newlines is "distributed" over the other rules to keep the matched text as long as possible. Note that .I adding rules does .I not slow down the scanner! The speed of the scanner is independent of the number of rules or (modulo the considerations given at the beginning of this section) how complicated the rules are with regard to operators such as '*' and '|'. .PP A final example in speeding up a scanner: suppose you want to scan through a file containing identifiers and keywords, one per line and with no other extraneous characters, and recognize all the keywords. A natural first approach is: .nf %% asm | auto | break | ... etc ... volatile | while /* it's a keyword */ .|\\n /* it's not a keyword */ .fi To eliminate the back-tracking, introduce a catch-all rule: .nf %% asm | auto | break | ... etc ... volatile | while /* it's a keyword */ [a-z]+ | .|\\n /* it's not a keyword */ .fi Now, if it's guaranteed that there's exactly one word per line, then we can reduce the total number of matches by a half by merging in the recognition of newlines with that of the other tokens: .nf %% asm\\n | auto\\n | break\\n | ... etc ... volatile\\n | while\\n /* it's a keyword */ [a-z]+\\n | .|\\n /* it's not a keyword */ .fi One has to be careful here, as we have now reintroduced backing up into the scanner. In particular, while .I we know that there will never be any characters in the input stream other than letters or newlines, .I flex can't figure this out, and it will plan for possibly needing to back up when it has scanned a token like "auto" and then the next character is something other than a newline or a letter. Previously it would then just match the "auto" rule and be done, but now it has no "auto" rule, only an "auto\\n" rule. To eliminate the possibility of backing up, we could either duplicate all rules but without final newlines, or, since we never expect to encounter such an input and therefore don't how it's classified, we can introduce one more catch-all rule, this one which doesn't include a newline: .nf %% asm\\n | auto\\n | break\\n | ... etc ... volatile\\n | while\\n /* it's a keyword */ [a-z]+\\n | [a-z]+ | .|\\n /* it's not a keyword */ .fi Compiled with .B \-Cf, this is about as fast as one can get a .I flex scanner to go for this particular problem. .PP A final note: .I flex is slow when matching NUL's, particularly when a token contains multiple NUL's. It's best to write rules which match .I short amounts of text if it's anticipated that the text will often include NUL's. .PP Another final note regarding performance: as mentioned above in the section How the Input is Matched, dynamically resizing .B yytext to accommodate huge tokens is a slow process because it presently requires that the (huge) token be rescanned from the beginning. Thus if performance is vital, you should attempt to match "large" quantities of text but not "huge" quantities, where the cutoff between the two is at about 8K characters/token. .SH GENERATING C++ SCANNERS .I flex provides two different ways to generate scanners for use with C++. The first way is to simply compile a scanner generated by .I flex using a C++ compiler instead of a C compiler. You should not encounter any compilations errors (please report any you find to the email address given in the Author section below). You can then use C++ code in your rule actions instead of C code. Note that the default input source for your scanner remains .I yyin, and default echoing is still done to .I yyout. Both of these remain .I FILE * variables and not C++ .I streams. .PP You can also use .I flex to generate a C++ scanner class, using the .B \-+ option (or, equivalently, .B %option c++), which is automatically specified if the name of the flex executable ends in a '+', such as .I flex++. When using this option, flex defaults to generating the scanner to the file .B lex.yy.cc instead of .B lex.yy.c. The generated scanner includes the header file .I FlexLexer.h, which defines the interface to two C++ classes. .PP The first class, .B FlexLexer, provides an abstract base class defining the general scanner class interface. It provides the following member functions: .TP .B const char* YYText() returns the text of the most recently matched token, the equivalent of .B yytext. .TP .B int YYLeng() returns the length of the most recently matched token, the equivalent of .B yyleng. .TP .B int lineno() const returns the current input line number (see .B %option yylineno), or .B 1 if .B %option yylineno was not used. .TP .B void set_debug( int flag ) sets the debugging flag for the scanner, equivalent to assigning to .B yy_flex_debug (see the Options section above). Note that you must build the scanner using .B %option debug to include debugging information in it. .TP .B int debug() const returns the current setting of the debugging flag. .PP Also provided are member functions equivalent to .B yy_switch_to_buffer(), .B yy_create_buffer() (though the first argument is an .B std::istream* object pointer and not a .B FILE*), .B yy_flush_buffer(), .B yy_delete_buffer(), and .B yyrestart() (again, the first argument is a .B std::istream* object pointer). .PP The second class defined in .I FlexLexer.h is .B yyFlexLexer, which is derived from .B FlexLexer. It defines the following additional member functions: .TP .B yyFlexLexer( std::istream* arg_yyin = 0, std::ostream* arg_yyout = 0 ) constructs a .B yyFlexLexer object using the given streams for input and output. If not specified, the streams default to .B cin and .B cout, respectively. .TP .B virtual int yylex() performs the same role is .B yylex() does for ordinary flex scanners: it scans the input stream, consuming tokens, until a rule's action returns a value. If you derive a subclass .B S from .B yyFlexLexer and want to access the member functions and variables of .B S inside .B yylex(), then you need to use .B %option yyclass="S" to inform .I flex that you will be using that subclass instead of .B yyFlexLexer. In this case, rather than generating .B yyFlexLexer::yylex(), .I flex generates .B S::yylex() (and also generates a dummy .B yyFlexLexer::yylex() that calls .B yyFlexLexer::LexerError() if called). .TP .B virtual void switch_streams(std::istream* new_in = 0, .B std::ostream* new_out = 0) reassigns .B yyin to .B new_in (if non-nil) and .B yyout to .B new_out (ditto), deleting the previous input buffer if .B yyin is reassigned. .TP .B int yylex( std::istream* new_in, std::ostream* new_out = 0 ) first switches the input streams via .B switch_streams( new_in, new_out ) and then returns the value of .B yylex(). .PP In addition, .B yyFlexLexer defines the following protected virtual functions which you can redefine in derived classes to tailor the scanner: .TP .B virtual int LexerInput( char* buf, int max_size ) reads up to .B max_size characters into .B buf and returns the number of characters read. To indicate end-of-input, return 0 characters. Note that "interactive" scanners (see the .B \-B and .B \-I flags) define the macro .B YY_INTERACTIVE. If you redefine .B LexerInput() and need to take different actions depending on whether or not the scanner might be scanning an interactive input source, you can test for the presence of this name via .B #ifdef. .TP .B virtual void LexerOutput( const char* buf, int size ) writes out .B size characters from the buffer .B buf, which, while NUL-terminated, may also contain "internal" NUL's if the scanner's rules can match text with NUL's in them. .TP .B virtual void LexerError( const char* msg ) reports a fatal error message. The default version of this function writes the message to the stream .B cerr and exits. .PP Note that a .B yyFlexLexer object contains its .I entire scanning state. Thus you can use such objects to create reentrant scanners. You can instantiate multiple instances of the same .B yyFlexLexer class, and you can also combine multiple C++ scanner classes together in the same program using the .B \-P option discussed above. .PP Finally, note that the .B %array feature is not available to C++ scanner classes; you must use .B %pointer (the default). .PP Here is an example of a simple C++ scanner: .nf // An example of using the flex C++ scanner class. %{ int mylineno = 0; %} string \\"[^\\n"]+\\" ws [ \\t]+ alpha [A-Za-z] dig [0-9] name ({alpha}|{dig}|\\$)({alpha}|{dig}|[_.\\-/$])* num1 [-+]?{dig}+\\.?([eE][-+]?{dig}+)? num2 [-+]?{dig}*\\.{dig}+([eE][-+]?{dig}+)? number {num1}|{num2} %% {ws} /* skip blanks and tabs */ "/*" { int c; while((c = yyinput()) != 0) { if(c == '\\n') ++mylineno; else if(c == '*') { if((c = yyinput()) == '/') break; else unput(c); } } } {number} cout << "number " << YYText() << '\\n'; \\n mylineno++; {name} cout << "name " << YYText() << '\\n'; {string} cout << "string " << YYText() << '\\n'; %% int main( int /* argc */, char** /* argv */ ) { FlexLexer* lexer = new yyFlexLexer; while(lexer->yylex() != 0) ; return 0; } .fi If you want to create multiple (different) lexer classes, you use the .B \-P flag (or the .B prefix= option) to rename each .B yyFlexLexer to some other .B xxFlexLexer. You then can include .B in your other sources once per lexer class, first renaming .B yyFlexLexer as follows: .nf #undef yyFlexLexer #define yyFlexLexer xxFlexLexer #include #undef yyFlexLexer #define yyFlexLexer zzFlexLexer #include .fi if, for example, you used .B %option prefix="xx" for one of your scanners and .B %option prefix="zz" for the other. .PP IMPORTANT: the present form of the scanning class is .I experimental and may change considerably between major releases. .SH INCOMPATIBILITIES WITH LEX AND POSIX .I flex is a rewrite of the AT&T Unix .I lex tool (the two implementations do not share any code, though), with some extensions and incompatibilities, both of which are of concern to those who wish to write scanners acceptable to either implementation. Flex is fully compliant with the POSIX .I lex specification, except that when using .B %pointer (the default), a call to .B unput() destroys the contents of .B yytext, which is counter to the POSIX specification. .PP In this section we discuss all of the known areas of incompatibility between flex, AT&T lex, and the POSIX specification. .PP .I flex's .B \-l option turns on maximum compatibility with the original AT&T .I lex implementation, at the cost of a major loss in the generated scanner's performance. We note below which incompatibilities can be overcome using the .B \-l option. .PP .I flex is fully compatible with .I lex with the following exceptions: .IP - The undocumented .I lex scanner internal variable .B yylineno is not supported unless .B \-l or .B %option yylineno is used. .IP .B yylineno should be maintained on a per-buffer basis, rather than a per-scanner (single global variable) basis. .IP .B yylineno is not part of the POSIX specification. .IP - The .B input() routine is not redefinable, though it may be called to read characters following whatever has been matched by a rule. If .B input() encounters an end-of-file the normal .B yywrap() processing is done. A ``real'' end-of-file is returned by .B input() as .I EOF. .IP Input is instead controlled by defining the .B YY_INPUT macro. .IP The .I flex restriction that .B input() cannot be redefined is in accordance with the POSIX specification, which simply does not specify any way of controlling the scanner's input other than by making an initial assignment to .I yyin. .IP - The .B unput() routine is not redefinable. This restriction is in accordance with POSIX. .IP - .I flex scanners are not as reentrant as .I lex scanners. In particular, if you have an interactive scanner and an interrupt handler which long-jumps out of the scanner, and the scanner is subsequently called again, you may get the following message: .nf fatal flex scanner internal error--end of buffer missed .fi To reenter the scanner, first use .nf yyrestart( yyin ); .fi Note that this call will throw away any buffered input; usually this isn't a problem with an interactive scanner. .IP Also note that flex C++ scanner classes .I are reentrant, so if using C++ is an option for you, you should use them instead. See "Generating C++ Scanners" above for details. .IP - .B output() is not supported. Output from the .B ECHO macro is done to the file-pointer .I yyout (default .I stdout). .IP .B output() is not part of the POSIX specification. .IP - .I lex does not support exclusive start conditions (%x), though they are in the POSIX specification. .IP - When definitions are expanded, .I flex encloses them in parentheses. With lex, the following: .nf NAME [A-Z][A-Z0-9]* %% foo{NAME}? printf( "Found it\\n" ); %% .fi will not match the string "foo" because when the macro is expanded the rule is equivalent to "foo[A-Z][A-Z0-9]*?" and the precedence is such that the '?' is associated with "[A-Z0-9]*". With .I flex, the rule will be expanded to "foo([A-Z][A-Z0-9]*)?" and so the string "foo" will match. .IP Note that if the definition begins with .B ^ or ends with .B $ then it is .I not expanded with parentheses, to allow these operators to appear in definitions without losing their special meanings. But the .B , /, and .B <> operators cannot be used in a .I flex definition. .IP Using .B \-l results in the .I lex behavior of no parentheses around the definition. .IP The POSIX specification is that the definition be enclosed in parentheses. .IP - Some implementations of .I lex allow a rule's action to begin on a separate line, if the rule's pattern has trailing whitespace: .nf %% foo|bar { foobar_action(); } .fi .I flex does not support this feature. .IP - The .I lex .B %r (generate a Ratfor scanner) option is not supported. It is not part of the POSIX specification. .IP - After a call to .B unput(), .I yytext is undefined until the next token is matched, unless the scanner was built using .B %array. This is not the case with .I lex or the POSIX specification. The .B \-l option does away with this incompatibility. .IP - The precedence of the .B {} (numeric range) operator is different. .I lex interprets "abc{1,3}" as "match one, two, or three occurrences of 'abc'", whereas .I flex interprets it as "match 'ab' followed by one, two, or three occurrences of 'c'". The latter is in agreement with the POSIX specification. .IP - The precedence of the .B ^ operator is different. .I lex interprets "^foo|bar" as "match either 'foo' at the beginning of a line, or 'bar' anywhere", whereas .I flex interprets it as "match either 'foo' or 'bar' if they come at the beginning of a line". The latter is in agreement with the POSIX specification. .IP - The special table-size declarations such as .B %a supported by .I lex are not required by .I flex scanners; .I flex ignores them. .IP - The name .B FLEX_SCANNER is #define'd so scanners may be written for use with either .I flex or .I lex. Scanners also include .B YY_FLEX_MAJOR_VERSION and .B YY_FLEX_MINOR_VERSION indicating which version of .I flex generated the scanner (for example, for the 2.5 release, these defines would be 2 and 5 respectively). .PP The following .I flex features are not included in .I lex or the POSIX specification: .nf C++ scanners %option start condition scopes start condition stacks interactive/non-interactive scanners yy_scan_string() and friends yyterminate() yy_set_interactive() yy_set_bol() YY_AT_BOL() <> <*> YY_DECL YY_START YY_USER_ACTION YY_USER_INIT #line directives %{}'s around actions multiple actions on a line .fi plus almost all of the flex flags. The last feature in the list refers to the fact that with .I flex you can put multiple actions on the same line, separated with semi-colons, while with .I lex, the following .nf foo handle_foo(); ++num_foos_seen; .fi is (rather surprisingly) truncated to .nf foo handle_foo(); .fi .I flex does not truncate the action. Actions that are not enclosed in braces are simply terminated at the end of the line. .SH DIAGNOSTICS .I warning, rule cannot be matched indicates that the given rule cannot be matched because it follows other rules that will always match the same text as it. For example, in the following "foo" cannot be matched because it comes after an identifier "catch-all" rule: .nf [a-z]+ got_identifier(); foo got_foo(); .fi Using .B REJECT in a scanner suppresses this warning. .PP .I warning, .B \-s .I option given but default rule can be matched means that it is possible (perhaps only in a particular start condition) that the default rule (match any single character) is the only one that will match a particular input. Since .B \-s was given, presumably this is not intended. .PP .I reject_used_but_not_detected undefined or .I yymore_used_but_not_detected undefined - These errors can occur at compile time. They indicate that the scanner uses .B REJECT or .B yymore() but that .I flex failed to notice the fact, meaning that .I flex scanned the first two sections looking for occurrences of these actions and failed to find any, but somehow you snuck some in (via a #include file, for example). Use .B %option reject or .B %option yymore to indicate to flex that you really do use these features. .PP .I flex scanner jammed - a scanner compiled with .B \-s has encountered an input string which wasn't matched by any of its rules. This error can also occur due to internal problems. .PP .I token too large, exceeds YYLMAX - your scanner uses .B %array and one of its rules matched a string longer than the .B YYLMAX constant (8K bytes by default). You can increase the value by #define'ing .B YYLMAX in the definitions section of your .I flex input. .PP .I scanner requires \-8 flag to .I use the character 'x' - Your scanner specification includes recognizing the 8-bit character .I 'x' and you did not specify the \-8 flag, and your scanner defaulted to 7-bit because you used the .B \-Cf or .B \-CF table compression options. See the discussion of the .B \-7 flag for details. .PP .I flex scanner push-back overflow - you used .B unput() to push back so much text that the scanner's buffer could not hold both the pushed-back text and the current token in .B yytext. Ideally the scanner should dynamically resize the buffer in this case, but at present it does not. .PP .I input buffer overflow, can't enlarge buffer because scanner uses REJECT - the scanner was working on matching an extremely large token and needed to expand the input buffer. This doesn't work with scanners that use .B REJECT. .PP .I fatal flex scanner internal error--end of buffer missed - This can occur in a scanner which is reentered after a long-jump has jumped out (or over) the scanner's activation frame. Before reentering the scanner, use: .nf yyrestart( yyin ); .fi or, as noted above, switch to using the C++ scanner class. .PP .I too many start conditions in <> construct! - you listed more start conditions in a <> construct than exist (so you must have listed at least one of them twice). .SH FILES .TP .B \-ll library with which scanners must be linked. .TP .I lex.yy.c generated scanner (called .I lexyy.c on some systems). .TP .I lex.yy.cc generated C++ scanner class, when using .B -+. .TP .I header file defining the C++ scanner base class, .B FlexLexer, and its derived class, .B yyFlexLexer. .TP .I flex.skl skeleton scanner. This file is only used when building flex, not when flex executes. .TP .I lex.backup backing-up information for .B \-b flag (called .I lex.bck on some systems). .SH DEFICIENCIES / BUGS Some trailing context patterns cannot be properly matched and generate warning messages ("dangerous trailing context"). These are patterns where the ending of the first part of the rule matches the beginning of the second part, such as "zx*/xy*", where the 'x*' matches the 'x' at the beginning of the trailing context. (Note that the POSIX draft states that the text matched by such patterns is undefined.) .PP For some trailing context rules, parts which are actually fixed-length are not recognized as such, leading to the above mentioned performance loss. In particular, parts using '|' or {n} (such as "foo{3}") are always considered variable-length. .PP Combining trailing context with the special '|' action can result in .I fixed trailing context being turned into the more expensive .I variable trailing context. For example, in the following: .nf %% abc | xyz/def .fi .PP Use of .B unput() invalidates yytext and yyleng, unless the .B %array directive or the .B \-l option has been used. .PP Pattern-matching of NUL's is substantially slower than matching other characters. .PP Dynamic resizing of the input buffer is slow, as it entails rescanning all the text matched so far by the current (generally huge) token. .PP Due to both buffering of input and read-ahead, you cannot intermix calls to routines, such as, for example, .B getchar(), with .I flex rules and expect it to work. Call .B input() instead. .PP The total table entries listed by the .B \-v flag excludes the number of table entries needed to determine what rule has been matched. The number of entries is equal to the number of DFA states if the scanner does not use .B REJECT, and somewhat greater than the number of states if it does. .PP .B REJECT cannot be used with the .B \-f or .B \-F options. .PP The .I flex internal algorithms need documentation. .SH SEE ALSO lex(1), yacc(1), sed(1), awk(1). .PP John Levine, Tony Mason, and Doug Brown, .I Lex & Yacc, O'Reilly and Associates. Be sure to get the 2nd edition. .PP M. E. Lesk and E. Schmidt, .I LEX \- Lexical Analyzer Generator .PP Alfred Aho, Ravi Sethi and Jeffrey Ullman, .I Compilers: Principles, Techniques and Tools, Addison-Wesley (1986). Describes the pattern-matching techniques used by .I flex (deterministic finite automata). .SH AUTHOR Vern Paxson, with the help of many ideas and much inspiration from Van Jacobson. Original version by Jef Poskanzer. The fast table representation is a partial implementation of a design done by Van Jacobson. The implementation was done by Kevin Gong and Vern Paxson. .PP Thanks to the many .I flex beta-testers, feedbackers, and contributors, especially Francois Pinard, Casey Leedom, Robert Abramovitz, Stan Adermann, Terry Allen, David Barker-Plummer, John Basrai, Neal Becker, Nelson H.F. Beebe, benson@odi.com, Karl Berry, Peter A. Bigot, Simon Blanchard, Keith Bostic, Frederic Brehm, Ian Brockbank, Kin Cho, Nick Christopher, Brian Clapper, J.T. Conklin, Jason Coughlin, Bill Cox, Nick Cropper, Dave Curtis, Scott David Daniels, Chris G. Demetriou, Theo de Raadt, Mike Donahue, Chuck Doucette, Tom Epperly, Leo Eskin, Chris Faylor, Chris Flatters, Jon Forrest, Jeffrey Friedl, Joe Gayda, Kaveh R. Ghazi, Wolfgang Glunz, Eric Goldman, Christopher M. Gould, Ulrich Grepel, Peer Griebel, Jan Hajic, Charles Hemphill, NORO Hideo, Jarkko Hietaniemi, Scott Hofmann, Jeff Honig, Dana Hudes, Eric Hughes, John Interrante, Ceriel Jacobs, Michal Jaegermann, Sakari Jalovaara, Jeffrey R. Jones, Henry Juengst, Klaus Kaempf, Jonathan I. Kamens, Terrence O Kane, Amir Katz, ken@ken.hilco.com, Kevin B. Kenny, Steve Kirsch, Winfried Koenig, Marq Kole, Ronald Lamprecht, Greg Lee, Rohan Lenard, Craig Leres, John Levine, Steve Liddle, David Loffredo, Mike Long, Mohamed el Lozy, Brian Madsen, Malte, Joe Marshall, Bengt Martensson, Chris Metcalf, Luke Mewburn, Jim Meyering, R. Alexander Milowski, Erik Naggum, G.T. Nicol, Landon Noll, James Nordby, Marc Nozell, Richard Ohnemus, Karsten Pahnke, Sven Panne, Roland Pesch, Walter Pelissero, Gaumond Pierre, Esmond Pitt, Jef Poskanzer, Joe Rahmeh, Jarmo Raiha, Frederic Raimbault, Pat Rankin, Rick Richardson, Kevin Rodgers, Kai Uwe Rommel, Jim Roskind, Alberto Santini, Andreas Scherer, Darrell Schiebel, Raf Schietekat, Doug Schmidt, Philippe Schnoebelen, Andreas Schwab, Larry Schwimmer, Alex Siegel, Eckehard Stolz, Jan-Erik Strvmquist, Mike Stump, Paul Stuart, Dave Tallman, Ian Lance Taylor, Chris Thewalt, Richard M. Timoney, Jodi Tsai, Paul Tuinenga, Gary Weik, Frank Whaley, Gerhard Wilhelms, Kent Williams, Ken Yap, Ron Zellar, Nathan Zelle, David Zuhn, and those whose names have slipped my marginal mail-archiving skills but whose contributions are appreciated all the same. .PP Thanks to Keith Bostic, Jon Forrest, Noah Friedman, John Gilmore, Craig Leres, John Levine, Bob Mulcahy, G.T. Nicol, Francois Pinard, Rich Salz, and Richard Stallman for help with various distribution headaches. .PP Thanks to Esmond Pitt and Earle Horton for 8-bit character support; to Benson Margulies and Fred Burke for C++ support; to Kent Williams and Tom Epperly for C++ class support; to Ove Ewerlid for support of NUL's; and to Eric Hughes for support of multiple buffers. .PP This work was primarily done when I was with the Real Time Systems Group at the Lawrence Berkeley Laboratory in Berkeley, CA. Many thanks to all there for the support I received. .PP Send comments to vern@ee.lbl.gov. freebsd-buildutils-10.0/src/usr.bin/lex/initparse.c0000644000000000000000000013747512146745723017245 0ustar /* $FreeBSD$ */ #ifndef lint static const char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93"; #endif #define YYBYACC 1 #define YYMAJOR 1 #define YYMINOR 9 #define YYEMPTY (-1) #define yyclearin (yychar = YYEMPTY) #define yyerrok (yyerrflag = 0) #define YYRECOVERING() (yyerrflag != 0) #define YYPREFIX "yy" #define YYPURE 0 #line 35 "parse.y" /* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */ /* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */ /* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #include "flexdef.h" #include "tables.h" int pat, scnum, eps, headcnt, trailcnt, lastchar, i, rulelen; int trlcontxt, xcluflg, currccl, cclsorted, varlength, variable_trail_rule; int *scon_stk; int scon_stk_ptr; static int madeany = false; /* whether we've made the '.' character class */ static int ccldot, cclany; int previous_continued_action; /* whether the previous rule's action was '|' */ #define format_warn3(fmt, a1, a2) \ do{ \ char fw3_msg[MAXLINE];\ snprintf( fw3_msg, MAXLINE,(fmt), (a1), (a2) );\ warn( fw3_msg );\ }while(0) /* Expand a POSIX character class expression. */ #define CCL_EXPR(func) \ do{ \ int c; \ for ( c = 0; c < csize; ++c ) \ if ( isascii(c) && func(c) ) \ ccladd( currccl, c ); \ }while(0) /* negated class */ #define CCL_NEG_EXPR(func) \ do{ \ int c; \ for ( c = 0; c < csize; ++c ) \ if ( !func(c) ) \ ccladd( currccl, c ); \ }while(0) /* While POSIX defines isblank(), it's not ANSI C. */ #define IS_BLANK(c) ((c) == ' ' || (c) == '\t') /* On some over-ambitious machines, such as DEC Alpha's, the default * token type is "long" instead of "int"; this leads to problems with * declaring yylval in flexdef.h. But so far, all the yacc's I've seen * wrap their definitions of YYSTYPE with "#ifndef YYSTYPE"'s, so the * following should ensure that the default token type is "int". */ #define YYSTYPE int #line 99 "parse.c" #ifndef YYSTYPE typedef int YYSTYPE; #endif /* compatibility with bison */ #ifdef YYPARSE_PARAM /* compatibility with FreeBSD */ # ifdef YYPARSE_PARAM_TYPE # define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM) # else # define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM) # endif #else # define YYPARSE_DECL() yyparse(void) #endif /* Parameters sent to lex. */ #ifdef YYLEX_PARAM # define YYLEX_DECL() yylex(void *YYLEX_PARAM) # define YYLEX yylex(YYLEX_PARAM) #else # define YYLEX_DECL() yylex(void) # define YYLEX yylex() #endif /* Parameters sent to yyerror. */ #ifndef YYERROR_DECL #define YYERROR_DECL() yyerror(const char *s) #endif #ifndef YYERROR_CALL #define YYERROR_CALL(msg) yyerror(msg) #endif extern int YYPARSE_DECL(); #define CHAR 257 #define NUMBER 258 #define SECTEND 259 #define SCDECL 260 #define XSCDECL 261 #define NAME 262 #define PREVCCL 263 #define EOF_OP 264 #define OPTION_OP 265 #define OPT_OUTFILE 266 #define OPT_PREFIX 267 #define OPT_YYCLASS 268 #define OPT_HEADER 269 #define OPT_EXTRA_TYPE 270 #define OPT_TABLES 271 #define CCE_ALNUM 272 #define CCE_ALPHA 273 #define CCE_BLANK 274 #define CCE_CNTRL 275 #define CCE_DIGIT 276 #define CCE_GRAPH 277 #define CCE_LOWER 278 #define CCE_PRINT 279 #define CCE_PUNCT 280 #define CCE_SPACE 281 #define CCE_UPPER 282 #define CCE_XDIGIT 283 #define CCE_NEG_ALNUM 284 #define CCE_NEG_ALPHA 285 #define CCE_NEG_BLANK 286 #define CCE_NEG_CNTRL 287 #define CCE_NEG_DIGIT 288 #define CCE_NEG_GRAPH 289 #define CCE_NEG_LOWER 290 #define CCE_NEG_PRINT 291 #define CCE_NEG_PUNCT 292 #define CCE_NEG_SPACE 293 #define CCE_NEG_UPPER 294 #define CCE_NEG_XDIGIT 295 #define CCL_OP_DIFF 296 #define CCL_OP_UNION 297 #define BEGIN_REPEAT_POSIX 298 #define END_REPEAT_POSIX 299 #define BEGIN_REPEAT_FLEX 300 #define END_REPEAT_FLEX 301 #define YYERRCODE 256 static const short yylhs[] = { -1, 0, 1, 2, 2, 2, 2, 3, 6, 6, 7, 7, 7, 8, 9, 9, 10, 10, 10, 10, 10, 10, 4, 4, 4, 5, 12, 12, 12, 12, 14, 11, 11, 11, 15, 15, 15, 16, 13, 13, 13, 13, 18, 18, 17, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 22, 22, }; static const short yylen[] = { 2, 5, 0, 3, 2, 0, 1, 1, 1, 1, 2, 1, 1, 2, 2, 0, 3, 3, 3, 3, 3, 3, 5, 5, 0, 0, 2, 1, 1, 1, 0, 4, 3, 0, 3, 1, 1, 1, 2, 3, 2, 1, 3, 1, 2, 2, 1, 6, 5, 4, 2, 2, 2, 6, 5, 4, 1, 1, 1, 3, 3, 1, 3, 3, 1, 3, 4, 4, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, }; static const short yydefred[] = { 2, 0, 0, 6, 0, 7, 8, 9, 15, 24, 0, 4, 0, 0, 12, 11, 0, 0, 0, 0, 0, 0, 0, 14, 0, 1, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 16, 18, 19, 20, 17, 21, 32, 36, 37, 0, 35, 0, 29, 61, 58, 28, 0, 56, 96, 0, 0, 0, 27, 0, 0, 0, 0, 0, 64, 31, 0, 23, 26, 0, 0, 70, 0, 22, 0, 40, 0, 44, 0, 0, 0, 50, 51, 52, 0, 0, 34, 95, 59, 60, 0, 0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 82, 81, 83, 84, 85, 86, 87, 88, 93, 89, 90, 91, 94, 92, 65, 69, 39, 0, 0, 0, 62, 63, 66, 0, 49, 0, 55, 0, 67, 0, 48, 0, 54, 47, 53, }; static const short yydgoto[] = { 1, 2, 4, 9, 13, 25, 10, 16, 11, 12, 23, 26, 59, 60, 35, 47, 48, 61, 62, 63, 64, 65, 71, 66, 74, 119, }; static const short yysindex[] = { 0, 0, -222, 0, -155, 0, 0, 0, 0, 0, -215, 0, -123, 6, 0, 0, -193, 10, 21, 26, 31, 35, 37, 0, 59, 0, -44, 0, -147, -145, -140, -133, -132, -129, 75, -214, 0, -19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, -48, 0, 0, 0, 0, -17, 0, 0, -17, 27, 128, 0, -17, -1, -30, -41, -189, 0, 0, -121, 0, 0, -31, -34, 0, -87, 0, -25, 0, -17, 0, -109, -41, -108, 0, 0, 0, 60, 60, 0, 0, 0, 0, 46, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -30, -36, -39, 0, 0, 0, -104, 0, -219, 0, -238, 0, -144, 0, -143, 0, 0, 0, }; static const short yyrindex[] = { 0, 0, -141, 0, 0, 0, 0, 0, 0, 0, 0, 0, -134, 9, 0, 0, -125, 0, 0, 0, 0, 0, 0, 0, -178, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -21, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 144, 47, 4, -10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static const short yygindex[] = { 0, 0, 0, 0, 121, 133, 0, 0, 0, 0, 0, 0, 0, 106, 0, 0, 93, 0, 32, 84, -45, 0, 0, 25, 90, 0, }; #define YYTABLESIZE 419 static const short yytable[] = { 57, 83, 84, 90, 56, 131, 118, 91, 129, 25, 57, 120, 24, 33, 46, 56, 55, 56, 81, 33, 135, 57, 85, 57, 57, 33, 57, 55, 45, 55, 57, 57, 57, 57, 3, 77, 57, 57, 46, 133, 46, 14, 45, 33, 46, 46, 79, 15, 46, 33, 46, 46, 45, 57, 45, 33, 25, 43, 45, 45, 42, 58, 25, 136, 45, 45, 24, 68, 25, 27, 33, 28, 58, 33, 58, 54, 81, 69, 30, 36, 134, 57, 29, 43, 30, 67, 42, 30, 43, 72, 78, 42, 31, 76, 43, 46, 32, 42, 33, 78, 33, 34, 33, 33, 5, 6, 7, 86, 87, 45, 8, 124, 125, 25, 57, 38, 25, 39, 5, 5, 5, 73, 40, 78, 5, 13, 13, 13, 46, 41, 42, 13, 33, 43, 3, 3, 3, 44, 75, 126, 3, 46, 45, 17, 18, 19, 20, 21, 22, 122, 123, 58, 127, 132, 41, 137, 38, 49, 138, 37, 70, 88, 121, 92, 0, 0, 0, 0, 0, 0, 93, 43, 0, 0, 42, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 89, 51, 0, 0, 0, 0, 0, 52, 0, 33, 33, 50, 51, 0, 51, 0, 33, 33, 52, 53, 52, 57, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 82, 0, 46, 130, 128, 0, 33, 33, 46, 80, 0, 0, 0, 33, 33, 0, 45, 0, 0, 25, 25, 0, 45, 0, 0, 0, 25, 25, 0, 57, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, }; static const short yycheck[] = { 10, 42, 43, 34, 34, 44, 93, 41, 44, 0, 40, 36, 60, 34, 10, 34, 46, 34, 63, 40, 258, 40, 63, 40, 34, 46, 36, 46, 10, 46, 40, 41, 42, 43, 256, 36, 46, 47, 34, 258, 36, 256, 256, 34, 40, 41, 47, 262, 262, 40, 46, 47, 34, 63, 36, 46, 34, 10, 40, 41, 10, 91, 40, 301, 46, 47, 60, 44, 46, 262, 91, 61, 91, 94, 91, 94, 121, 125, 256, 123, 299, 91, 61, 36, 262, 62, 36, 61, 41, 57, 124, 41, 61, 61, 47, 91, 61, 47, 61, 124, 91, 42, 123, 94, 259, 260, 261, 296, 297, 91, 265, 86, 87, 91, 124, 262, 94, 262, 259, 260, 261, 94, 262, 124, 265, 259, 260, 261, 124, 262, 262, 265, 123, 262, 259, 260, 261, 62, 10, 93, 265, 262, 124, 266, 267, 268, 269, 270, 271, 258, 258, 91, 45, 257, 10, 299, 10, 36, 301, 26, 54, 68, 78, 73, -1, -1, -1, -1, -1, -1, 257, 124, -1, -1, 124, -1, -1, -1, 93, -1, -1, -1, -1, -1, -1, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, -1, -1, -1, -1, -1, -1, -1, -1, 93, -1, -1, -1, -1, -1, -1, -1, -1, 257, 257, -1, -1, -1, -1, -1, 263, -1, 256, 257, 256, 257, -1, 257, -1, 263, 264, 263, 264, 263, 257, -1, -1, -1, -1, -1, 263, -1, -1, -1, -1, -1, 300, -1, 257, 301, 299, -1, 256, 257, 263, 298, -1, -1, -1, 263, 264, -1, 257, -1, -1, 256, 257, -1, 263, -1, -1, -1, 263, 264, -1, 298, -1, 300, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 298, 257, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 298, -1, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 257, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 257, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, }; #define YYFINAL 1 #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYMAXTOKEN 301 #if YYDEBUG static const char *yyname[] = { "end-of-file",0,0,0,0,0,0,0,0,0,"'\\n'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,"'\"'",0,"'$'",0,0,0,"'('","')'","'*'","'+'","','","'-'","'.'","'/'",0,0, 0,0,0,0,0,0,0,0,0,0,"'<'","'='","'>'","'?'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,"'['",0,"']'","'^'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,"'{'","'|'","'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"CHAR","NUMBER","SECTEND", "SCDECL","XSCDECL","NAME","PREVCCL","EOF_OP","OPTION_OP","OPT_OUTFILE", "OPT_PREFIX","OPT_YYCLASS","OPT_HEADER","OPT_EXTRA_TYPE","OPT_TABLES", "CCE_ALNUM","CCE_ALPHA","CCE_BLANK","CCE_CNTRL","CCE_DIGIT","CCE_GRAPH", "CCE_LOWER","CCE_PRINT","CCE_PUNCT","CCE_SPACE","CCE_UPPER","CCE_XDIGIT", "CCE_NEG_ALNUM","CCE_NEG_ALPHA","CCE_NEG_BLANK","CCE_NEG_CNTRL","CCE_NEG_DIGIT", "CCE_NEG_GRAPH","CCE_NEG_LOWER","CCE_NEG_PRINT","CCE_NEG_PUNCT","CCE_NEG_SPACE", "CCE_NEG_UPPER","CCE_NEG_XDIGIT","CCL_OP_DIFF","CCL_OP_UNION", "BEGIN_REPEAT_POSIX","END_REPEAT_POSIX","BEGIN_REPEAT_FLEX","END_REPEAT_FLEX", }; static const char *yyrule[] = { "$accept : goal", "goal : initlex sect1 sect1end sect2 initforrule", "initlex :", "sect1 : sect1 startconddecl namelist1", "sect1 : sect1 options", "sect1 :", "sect1 : error", "sect1end : SECTEND", "startconddecl : SCDECL", "startconddecl : XSCDECL", "namelist1 : namelist1 NAME", "namelist1 : NAME", "namelist1 : error", "options : OPTION_OP optionlist", "optionlist : optionlist option", "optionlist :", "option : OPT_OUTFILE '=' NAME", "option : OPT_EXTRA_TYPE '=' NAME", "option : OPT_PREFIX '=' NAME", "option : OPT_YYCLASS '=' NAME", "option : OPT_HEADER '=' NAME", "option : OPT_TABLES '=' NAME", "sect2 : sect2 scon initforrule flexrule '\\n'", "sect2 : sect2 scon '{' sect2 '}'", "sect2 :", "initforrule :", "flexrule : '^' rule", "flexrule : rule", "flexrule : EOF_OP", "flexrule : error", "scon_stk_ptr :", "scon : '<' scon_stk_ptr namelist2 '>'", "scon : '<' '*' '>'", "scon :", "namelist2 : namelist2 ',' sconname", "namelist2 : sconname", "namelist2 : error", "sconname : NAME", "rule : re2 re", "rule : re2 re '$'", "rule : re '$'", "rule : re", "re : re '|' series", "re : series", "re2 : re '/'", "series : series singleton", "series : singleton", "series : series BEGIN_REPEAT_POSIX NUMBER ',' NUMBER END_REPEAT_POSIX", "series : series BEGIN_REPEAT_POSIX NUMBER ',' END_REPEAT_POSIX", "series : series BEGIN_REPEAT_POSIX NUMBER END_REPEAT_POSIX", "singleton : singleton '*'", "singleton : singleton '+'", "singleton : singleton '?'", "singleton : singleton BEGIN_REPEAT_FLEX NUMBER ',' NUMBER END_REPEAT_FLEX", "singleton : singleton BEGIN_REPEAT_FLEX NUMBER ',' END_REPEAT_FLEX", "singleton : singleton BEGIN_REPEAT_FLEX NUMBER END_REPEAT_FLEX", "singleton : '.'", "singleton : fullccl", "singleton : PREVCCL", "singleton : '\"' string '\"'", "singleton : '(' re ')'", "singleton : CHAR", "fullccl : fullccl CCL_OP_DIFF braceccl", "fullccl : fullccl CCL_OP_UNION braceccl", "fullccl : braceccl", "braceccl : '[' ccl ']'", "braceccl : '[' '^' ccl ']'", "ccl : ccl CHAR '-' CHAR", "ccl : ccl CHAR", "ccl : ccl ccl_expr", "ccl :", "ccl_expr : CCE_ALNUM", "ccl_expr : CCE_ALPHA", "ccl_expr : CCE_BLANK", "ccl_expr : CCE_CNTRL", "ccl_expr : CCE_DIGIT", "ccl_expr : CCE_GRAPH", "ccl_expr : CCE_LOWER", "ccl_expr : CCE_PRINT", "ccl_expr : CCE_PUNCT", "ccl_expr : CCE_SPACE", "ccl_expr : CCE_XDIGIT", "ccl_expr : CCE_UPPER", "ccl_expr : CCE_NEG_ALNUM", "ccl_expr : CCE_NEG_ALPHA", "ccl_expr : CCE_NEG_BLANK", "ccl_expr : CCE_NEG_CNTRL", "ccl_expr : CCE_NEG_DIGIT", "ccl_expr : CCE_NEG_GRAPH", "ccl_expr : CCE_NEG_PRINT", "ccl_expr : CCE_NEG_PUNCT", "ccl_expr : CCE_NEG_SPACE", "ccl_expr : CCE_NEG_XDIGIT", "ccl_expr : CCE_NEG_LOWER", "ccl_expr : CCE_NEG_UPPER", "string : string CHAR", "string :", }; #endif int yydebug; int yynerrs; int yyerrflag; int yychar; YYSTYPE yyval; YYSTYPE yylval; /* define the initial stack-sizes */ #ifdef YYSTACKSIZE #undef YYMAXDEPTH #define YYMAXDEPTH YYSTACKSIZE #else #ifdef YYMAXDEPTH #define YYSTACKSIZE YYMAXDEPTH #else #define YYSTACKSIZE 500 #define YYMAXDEPTH 500 #endif #endif #define YYINITSTACKSIZE 500 typedef struct { unsigned stacksize; short *s_base; short *s_mark; short *s_last; YYSTYPE *l_base; YYSTYPE *l_mark; } YYSTACKDATA; /* variables for the parser stack */ static YYSTACKDATA yystack; #line 948 "parse.y" /* build_eof_action - build the "<>" action for the active start * conditions */ void build_eof_action() { int i; char action_text[MAXLINE]; for ( i = 1; i <= scon_stk_ptr; ++i ) { if ( sceof[scon_stk[i]] ) format_pinpoint_message( "multiple <> rules for start condition %s", scname[scon_stk[i]] ); else { sceof[scon_stk[i]] = true; if (previous_continued_action /* && previous action was regular */) add_action("YY_RULE_SETUP\n"); snprintf( action_text, sizeof(action_text), "case YY_STATE_EOF(%s):\n", scname[scon_stk[i]] ); add_action( action_text ); } } line_directive_out( (FILE *) 0, 1 ); /* This isn't a normal rule after all - don't count it as * such, so we don't have any holes in the rule numbering * (which make generating "rule can never match" warnings * more difficult. */ --num_rules; ++num_eof_rules; } /* format_synerr - write out formatted syntax error */ void format_synerr( msg, arg ) const char *msg, arg[]; { char errmsg[MAXLINE]; (void) snprintf( errmsg, sizeof(errmsg), msg, arg ); synerr( errmsg ); } /* synerr - report a syntax error */ void synerr( str ) const char *str; { syntaxerror = true; pinpoint_message( str ); } /* format_warn - write out formatted warning */ void format_warn( msg, arg ) const char *msg, arg[]; { char warn_msg[MAXLINE]; snprintf( warn_msg, sizeof(warn_msg), msg, arg ); warn( warn_msg ); } /* warn - report a warning, unless -w was given */ void warn( str ) const char *str; { line_warning( str, linenum ); } /* format_pinpoint_message - write out a message formatted with one string, * pinpointing its location */ void format_pinpoint_message( msg, arg ) const char *msg, arg[]; { char errmsg[MAXLINE]; snprintf( errmsg, sizeof(errmsg), msg, arg ); pinpoint_message( errmsg ); } /* pinpoint_message - write out a message, pinpointing its location */ void pinpoint_message( str ) const char *str; { line_pinpoint( str, linenum ); } /* line_warning - report a warning at a given line, unless -w was given */ void line_warning( str, line ) const char *str; int line; { char warning[MAXLINE]; if ( ! nowarn ) { snprintf( warning, sizeof(warning), "warning, %s", str ); line_pinpoint( warning, line ); } } /* line_pinpoint - write out a message, pinpointing it at the given line */ void line_pinpoint( str, line ) const char *str; int line; { fprintf( stderr, "%s:%d: %s\n", infilename, line, str ); } /* yyerror - eat up an error message from the parser; * currently, messages are ignore */ void yyerror( msg ) const char *msg; { } #line 656 "parse.c" #if YYDEBUG #include /* needed for printf */ #endif #include /* needed for malloc, etc */ #include /* needed for memset */ /* allocate initial stack or double stack size, up to YYMAXDEPTH */ static int yygrowstack(YYSTACKDATA *data) { int i; unsigned newsize; short *newss; YYSTYPE *newvs; if ((newsize = data->stacksize) == 0) newsize = YYINITSTACKSIZE; else if (newsize >= YYMAXDEPTH) return -1; else if ((newsize *= 2) > YYMAXDEPTH) newsize = YYMAXDEPTH; i = data->s_mark - data->s_base; newss = (short *)realloc(data->s_base, newsize * sizeof(*newss)); if (newss == 0) return -1; data->s_base = newss; data->s_mark = newss + i; newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs)); if (newvs == 0) return -1; data->l_base = newvs; data->l_mark = newvs + i; data->stacksize = newsize; data->s_last = data->s_base + newsize - 1; return 0; } #if YYPURE || defined(YY_NO_LEAKS) static void yyfreestack(YYSTACKDATA *data) { free(data->s_base); free(data->l_base); memset(data, 0, sizeof(*data)); } #else #define yyfreestack(data) /* nothing */ #endif #define YYABORT goto yyabort #define YYREJECT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int YYPARSE_DECL() { int yym, yyn, yystate; #if YYDEBUG const char *yys; if ((yys = getenv("YYDEBUG")) != 0) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn - '0'; } #endif yynerrs = 0; yyerrflag = 0; yychar = YYEMPTY; yystate = 0; #if YYPURE memset(&yystack, 0, sizeof(yystack)); #endif if (yystack.s_base == NULL && yygrowstack(&yystack)) goto yyoverflow; yystack.s_mark = yystack.s_base; yystack.l_mark = yystack.l_base; yystate = 0; *yystack.s_mark = 0; yyloop: if ((yyn = yydefred[yystate]) != 0) goto yyreduce; if (yychar < 0) { if ((yychar = YYLEX) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("%sdebug: state %d, reading %d (%s)\n", YYPREFIX, yystate, yychar, yys); } #endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { #if YYDEBUG if (yydebug) printf("%sdebug: state %d, shifting to state %d\n", YYPREFIX, yystate, yytable[yyn]); #endif if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack)) { goto yyoverflow; } yystate = yytable[yyn]; *++yystack.s_mark = yytable[yyn]; *++yystack.l_mark = yylval; yychar = YYEMPTY; if (yyerrflag > 0) --yyerrflag; goto yyloop; } if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { yyn = yytable[yyn]; goto yyreduce; } if (yyerrflag) goto yyinrecovery; yyerror("syntax error"); goto yyerrlab; yyerrlab: ++yynerrs; yyinrecovery: if (yyerrflag < 3) { yyerrflag = 3; for (;;) { if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { #if YYDEBUG if (yydebug) printf("%sdebug: state %d, error recovery shifting\ to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]); #endif if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack)) { goto yyoverflow; } yystate = yytable[yyn]; *++yystack.s_mark = yytable[yyn]; *++yystack.l_mark = yylval; goto yyloop; } else { #if YYDEBUG if (yydebug) printf("%sdebug: error recovery discarding state %d\n", YYPREFIX, *yystack.s_mark); #endif if (yystack.s_mark <= yystack.s_base) goto yyabort; --yystack.s_mark; --yystack.l_mark; } } } else { if (yychar == 0) goto yyabort; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("%sdebug: state %d, error recovery discards token %d (%s)\n", YYPREFIX, yystate, yychar, yys); } #endif yychar = YYEMPTY; goto yyloop; } yyreduce: #if YYDEBUG if (yydebug) printf("%sdebug: state %d, reducing by rule %d (%s)\n", YYPREFIX, yystate, yyn, yyrule[yyn]); #endif yym = yylen[yyn]; if (yym) yyval = yystack.l_mark[1-yym]; else memset(&yyval, 0, sizeof yyval); switch (yyn) { case 1: #line 119 "parse.y" { /* add default rule */ int def_rule; pat = cclinit(); cclnegate( pat ); def_rule = mkstate( -pat ); /* Remember the number of the default rule so we * don't generate "can't match" warnings for it. */ default_rule = num_rules; finish_rule( def_rule, false, 0, 0, 0); for ( i = 1; i <= lastsc; ++i ) scset[i] = mkbranch( scset[i], def_rule ); if ( spprdflt ) add_action( "YY_FATAL_ERROR( \"flex scanner jammed\" )" ); else add_action( "ECHO" ); add_action( ";\n\tYY_BREAK\n" ); } break; case 2: #line 148 "parse.y" { /* initialize for processing rules */ /* Create default DFA start condition. */ scinstal( "INITIAL", false ); } break; case 6: #line 159 "parse.y" { synerr( _("unknown error processing section 1") ); } break; case 7: #line 163 "parse.y" { check_options(); scon_stk = allocate_integer_array( lastsc + 1 ); scon_stk_ptr = 0; } break; case 8: #line 171 "parse.y" { xcluflg = false; } break; case 9: #line 174 "parse.y" { xcluflg = true; } break; case 10: #line 178 "parse.y" { scinstal( nmstr, xcluflg ); } break; case 11: #line 181 "parse.y" { scinstal( nmstr, xcluflg ); } break; case 12: #line 184 "parse.y" { synerr( _("bad start condition list") ); } break; case 16: #line 195 "parse.y" { outfilename = copy_string( nmstr ); did_outfilename = 1; } break; case 17: #line 200 "parse.y" { extra_type = copy_string( nmstr ); } break; case 18: #line 202 "parse.y" { prefix = copy_string( nmstr ); } break; case 19: #line 204 "parse.y" { yyclass = copy_string( nmstr ); } break; case 20: #line 206 "parse.y" { headerfilename = copy_string( nmstr ); } break; case 21: #line 208 "parse.y" { tablesext = true; tablesfilename = copy_string( nmstr ); } break; case 22: #line 212 "parse.y" { scon_stk_ptr = yystack.l_mark[-3]; } break; case 23: #line 214 "parse.y" { scon_stk_ptr = yystack.l_mark[-3]; } break; case 25: #line 219 "parse.y" { /* Initialize for a parse of one rule. */ trlcontxt = variable_trail_rule = varlength = false; trailcnt = headcnt = rulelen = 0; current_state_type = STATE_NORMAL; previous_continued_action = continued_action; in_rule = true; new_rule(); } break; case 26: #line 232 "parse.y" { pat = yystack.l_mark[0]; finish_rule( pat, variable_trail_rule, headcnt, trailcnt , previous_continued_action); if ( scon_stk_ptr > 0 ) { for ( i = 1; i <= scon_stk_ptr; ++i ) scbol[scon_stk[i]] = mkbranch( scbol[scon_stk[i]], pat ); } else { /* Add to all non-exclusive start conditions, * including the default (0) start condition. */ for ( i = 1; i <= lastsc; ++i ) if ( ! scxclu[i] ) scbol[i] = mkbranch( scbol[i], pat ); } if ( ! bol_needed ) { bol_needed = true; if ( performance_report > 1 ) pinpoint_message( "'^' operator results in sub-optimal performance" ); } } break; case 27: #line 268 "parse.y" { pat = yystack.l_mark[0]; finish_rule( pat, variable_trail_rule, headcnt, trailcnt , previous_continued_action); if ( scon_stk_ptr > 0 ) { for ( i = 1; i <= scon_stk_ptr; ++i ) scset[scon_stk[i]] = mkbranch( scset[scon_stk[i]], pat ); } else { for ( i = 1; i <= lastsc; ++i ) if ( ! scxclu[i] ) scset[i] = mkbranch( scset[i], pat ); } } break; case 28: #line 292 "parse.y" { if ( scon_stk_ptr > 0 ) build_eof_action(); else { /* This EOF applies to all start conditions * which don't already have EOF actions. */ for ( i = 1; i <= lastsc; ++i ) if ( ! sceof[i] ) scon_stk[++scon_stk_ptr] = i; if ( scon_stk_ptr == 0 ) warn( "all start conditions already have <> rules" ); else build_eof_action(); } } break; case 29: #line 315 "parse.y" { synerr( _("unrecognized rule") ); } break; case 30: #line 319 "parse.y" { yyval = scon_stk_ptr; } break; case 31: #line 323 "parse.y" { yyval = yystack.l_mark[-2]; } break; case 32: #line 326 "parse.y" { yyval = scon_stk_ptr; for ( i = 1; i <= lastsc; ++i ) { int j; for ( j = 1; j <= scon_stk_ptr; ++j ) if ( scon_stk[j] == i ) break; if ( j > scon_stk_ptr ) scon_stk[++scon_stk_ptr] = i; } } break; case 33: #line 343 "parse.y" { yyval = scon_stk_ptr; } break; case 36: #line 351 "parse.y" { synerr( _("bad start condition list") ); } break; case 37: #line 355 "parse.y" { if ( (scnum = sclookup( nmstr )) == 0 ) format_pinpoint_message( "undeclared start condition %s", nmstr ); else { for ( i = 1; i <= scon_stk_ptr; ++i ) if ( scon_stk[i] == scnum ) { format_warn( "<%s> specified twice", scname[scnum] ); break; } if ( i > scon_stk_ptr ) scon_stk[++scon_stk_ptr] = scnum; } } break; case 38: #line 378 "parse.y" { if ( transchar[lastst[yystack.l_mark[0]]] != SYM_EPSILON ) /* Provide final transition \now/ so it * will be marked as a trailing context * state. */ yystack.l_mark[0] = link_machines( yystack.l_mark[0], mkstate( SYM_EPSILON ) ); mark_beginning_as_normal( yystack.l_mark[0] ); current_state_type = STATE_NORMAL; if ( previous_continued_action ) { /* We need to treat this as variable trailing * context so that the backup does not happen * in the action but before the action switch * statement. If the backup happens in the * action, then the rules "falling into" this * one's action will *also* do the backup, * erroneously. */ if ( ! varlength || headcnt != 0 ) warn( "trailing context made variable due to preceding '|' action" ); /* Mark as variable. */ varlength = true; headcnt = 0; } if ( lex_compat || (varlength && headcnt == 0) ) { /* variable trailing context rule */ /* Mark the first part of the rule as the * accepting "head" part of a trailing * context rule. * * By the way, we didn't do this at the * beginning of this production because back * then current_state_type was set up for a * trail rule, and add_accept() can create * a new state ... */ add_accept( yystack.l_mark[-1], num_rules | YY_TRAILING_HEAD_MASK ); variable_trail_rule = true; } else trailcnt = rulelen; yyval = link_machines( yystack.l_mark[-1], yystack.l_mark[0] ); } break; case 39: #line 434 "parse.y" { synerr( _("trailing context used twice") ); } break; case 40: #line 437 "parse.y" { headcnt = 0; trailcnt = 1; rulelen = 1; varlength = false; current_state_type = STATE_TRAILING_CONTEXT; if ( trlcontxt ) { synerr( _("trailing context used twice") ); yyval = mkstate( SYM_EPSILON ); } else if ( previous_continued_action ) { /* See the comment in the rule for "re2 re" * above. */ warn( "trailing context made variable due to preceding '|' action" ); varlength = true; } if ( lex_compat || varlength ) { /* Again, see the comment in the rule for * "re2 re" above. */ add_accept( yystack.l_mark[-1], num_rules | YY_TRAILING_HEAD_MASK ); variable_trail_rule = true; } trlcontxt = true; eps = mkstate( SYM_EPSILON ); yyval = link_machines( yystack.l_mark[-1], link_machines( eps, mkstate( '\n' ) ) ); } break; case 41: #line 480 "parse.y" { yyval = yystack.l_mark[0]; if ( trlcontxt ) { if ( lex_compat || (varlength && headcnt == 0) ) /* Both head and trail are * variable-length. */ variable_trail_rule = true; else trailcnt = rulelen; } } break; case 42: #line 498 "parse.y" { varlength = true; yyval = mkor( yystack.l_mark[-2], yystack.l_mark[0] ); } break; case 43: #line 504 "parse.y" { yyval = yystack.l_mark[0]; } break; case 44: #line 509 "parse.y" { /* This rule is written separately so the * reduction will occur before the trailing * series is parsed. */ if ( trlcontxt ) synerr( _("trailing context used twice") ); else trlcontxt = true; if ( varlength ) /* We hope the trailing context is * fixed-length. */ varlength = false; else headcnt = rulelen; rulelen = 0; current_state_type = STATE_TRAILING_CONTEXT; yyval = yystack.l_mark[-1]; } break; case 45: #line 536 "parse.y" { /* This is where concatenation of adjacent patterns * gets done. */ yyval = link_machines( yystack.l_mark[-1], yystack.l_mark[0] ); } break; case 46: #line 544 "parse.y" { yyval = yystack.l_mark[0]; } break; case 47: #line 547 "parse.y" { varlength = true; if ( yystack.l_mark[-3] > yystack.l_mark[-1] || yystack.l_mark[-3] < 0 ) { synerr( _("bad iteration values") ); yyval = yystack.l_mark[-5]; } else { if ( yystack.l_mark[-3] == 0 ) { if ( yystack.l_mark[-1] <= 0 ) { synerr( _("bad iteration values") ); yyval = yystack.l_mark[-5]; } else yyval = mkopt( mkrep( yystack.l_mark[-5], 1, yystack.l_mark[-1] ) ); } else yyval = mkrep( yystack.l_mark[-5], yystack.l_mark[-3], yystack.l_mark[-1] ); } } break; case 48: #line 575 "parse.y" { varlength = true; if ( yystack.l_mark[-2] <= 0 ) { synerr( _("iteration value must be positive") ); yyval = yystack.l_mark[-4]; } else yyval = mkrep( yystack.l_mark[-4], yystack.l_mark[-2], INFINITE_REPEAT ); } break; case 49: #line 589 "parse.y" { /* The series could be something like "(foo)", * in which case we have no idea what its length * is, so we punt here. */ varlength = true; if ( yystack.l_mark[-1] <= 0 ) { synerr( _("iteration value must be positive") ); yyval = yystack.l_mark[-3]; } else yyval = link_machines( yystack.l_mark[-3], copysingl( yystack.l_mark[-3], yystack.l_mark[-1] - 1 ) ); } break; case 50: #line 611 "parse.y" { varlength = true; yyval = mkclos( yystack.l_mark[-1] ); } break; case 51: #line 618 "parse.y" { varlength = true; yyval = mkposcl( yystack.l_mark[-1] ); } break; case 52: #line 624 "parse.y" { varlength = true; yyval = mkopt( yystack.l_mark[-1] ); } break; case 53: #line 630 "parse.y" { varlength = true; if ( yystack.l_mark[-3] > yystack.l_mark[-1] || yystack.l_mark[-3] < 0 ) { synerr( _("bad iteration values") ); yyval = yystack.l_mark[-5]; } else { if ( yystack.l_mark[-3] == 0 ) { if ( yystack.l_mark[-1] <= 0 ) { synerr( _("bad iteration values") ); yyval = yystack.l_mark[-5]; } else yyval = mkopt( mkrep( yystack.l_mark[-5], 1, yystack.l_mark[-1] ) ); } else yyval = mkrep( yystack.l_mark[-5], yystack.l_mark[-3], yystack.l_mark[-1] ); } } break; case 54: #line 658 "parse.y" { varlength = true; if ( yystack.l_mark[-2] <= 0 ) { synerr( _("iteration value must be positive") ); yyval = yystack.l_mark[-4]; } else yyval = mkrep( yystack.l_mark[-4], yystack.l_mark[-2], INFINITE_REPEAT ); } break; case 55: #line 672 "parse.y" { /* The singleton could be something like "(foo)", * in which case we have no idea what its length * is, so we punt here. */ varlength = true; if ( yystack.l_mark[-1] <= 0 ) { synerr( _("iteration value must be positive") ); yyval = yystack.l_mark[-3]; } else yyval = link_machines( yystack.l_mark[-3], copysingl( yystack.l_mark[-3], yystack.l_mark[-1] - 1 ) ); } break; case 56: #line 691 "parse.y" { if ( ! madeany ) { /* Create the '.' character class. */ ccldot = cclinit(); ccladd( ccldot, '\n' ); cclnegate( ccldot ); if ( useecs ) mkeccl( ccltbl + cclmap[ccldot], ccllen[ccldot], nextecm, ecgroup, csize, csize ); /* Create the (?s:'.') character class. */ cclany = cclinit(); cclnegate( cclany ); if ( useecs ) mkeccl( ccltbl + cclmap[cclany], ccllen[cclany], nextecm, ecgroup, csize, csize ); madeany = true; } ++rulelen; if (sf_dot_all()) yyval = mkstate( -cclany ); else yyval = mkstate( -ccldot ); } break; case 57: #line 725 "parse.y" { /* Sort characters for fast searching. */ qsort( ccltbl + cclmap[yystack.l_mark[0]], ccllen[yystack.l_mark[0]], sizeof (*ccltbl), cclcmp ); if ( useecs ) mkeccl( ccltbl + cclmap[yystack.l_mark[0]], ccllen[yystack.l_mark[0]], nextecm, ecgroup, csize, csize ); ++rulelen; if (ccl_has_nl[yystack.l_mark[0]]) rule_has_nl[num_rules] = true; yyval = mkstate( -yystack.l_mark[0] ); } break; case 58: #line 743 "parse.y" { ++rulelen; if (ccl_has_nl[yystack.l_mark[0]]) rule_has_nl[num_rules] = true; yyval = mkstate( -yystack.l_mark[0] ); } break; case 59: #line 753 "parse.y" { yyval = yystack.l_mark[-1]; } break; case 60: #line 756 "parse.y" { yyval = yystack.l_mark[-1]; } break; case 61: #line 759 "parse.y" { ++rulelen; if (yystack.l_mark[0] == nlch) rule_has_nl[num_rules] = true; if (sf_case_ins() && has_case(yystack.l_mark[0])) /* create an alternation, as in (a|A) */ yyval = mkor (mkstate(yystack.l_mark[0]), mkstate(reverse_case(yystack.l_mark[0]))); else yyval = mkstate( yystack.l_mark[0] ); } break; case 62: #line 773 "parse.y" { yyval = ccl_set_diff (yystack.l_mark[-2], yystack.l_mark[0]); } break; case 63: #line 774 "parse.y" { yyval = ccl_set_union (yystack.l_mark[-2], yystack.l_mark[0]); } break; case 65: #line 780 "parse.y" { yyval = yystack.l_mark[-1]; } break; case 66: #line 783 "parse.y" { cclnegate( yystack.l_mark[-1] ); yyval = yystack.l_mark[-1]; } break; case 67: #line 790 "parse.y" { if (sf_case_ins()) { /* If one end of the range has case and the other * does not, or the cases are different, then we're not * sure what range the user is trying to express. * Examples: [@-z] or [S-t] */ if (has_case (yystack.l_mark[-2]) != has_case (yystack.l_mark[0]) || (has_case (yystack.l_mark[-2]) && (b_islower (yystack.l_mark[-2]) != b_islower (yystack.l_mark[0]))) || (has_case (yystack.l_mark[-2]) && (b_isupper (yystack.l_mark[-2]) != b_isupper (yystack.l_mark[0])))) format_warn3 ( _("the character range [%c-%c] is ambiguous in a case-insensitive scanner"), yystack.l_mark[-2], yystack.l_mark[0]); /* If the range spans uppercase characters but not * lowercase (or vice-versa), then should we automatically * include lowercase characters in the range? * Example: [@-_] spans [a-z] but not [A-Z] */ else if (!has_case (yystack.l_mark[-2]) && !has_case (yystack.l_mark[0]) && !range_covers_case (yystack.l_mark[-2], yystack.l_mark[0])) format_warn3 ( _("the character range [%c-%c] is ambiguous in a case-insensitive scanner"), yystack.l_mark[-2], yystack.l_mark[0]); } if ( yystack.l_mark[-2] > yystack.l_mark[0] ) synerr( _("negative range in character class") ); else { for ( i = yystack.l_mark[-2]; i <= yystack.l_mark[0]; ++i ) ccladd( yystack.l_mark[-3], i ); /* Keep track if this ccl is staying in * alphabetical order. */ cclsorted = cclsorted && (yystack.l_mark[-2] > lastchar); lastchar = yystack.l_mark[0]; /* Do it again for upper/lowercase */ if (sf_case_ins() && has_case(yystack.l_mark[-2]) && has_case(yystack.l_mark[0])){ yystack.l_mark[-2] = reverse_case (yystack.l_mark[-2]); yystack.l_mark[0] = reverse_case (yystack.l_mark[0]); for ( i = yystack.l_mark[-2]; i <= yystack.l_mark[0]; ++i ) ccladd( yystack.l_mark[-3], i ); cclsorted = cclsorted && (yystack.l_mark[-2] > lastchar); lastchar = yystack.l_mark[0]; } } yyval = yystack.l_mark[-3]; } break; case 68: #line 850 "parse.y" { ccladd( yystack.l_mark[-1], yystack.l_mark[0] ); cclsorted = cclsorted && (yystack.l_mark[0] > lastchar); lastchar = yystack.l_mark[0]; /* Do it again for upper/lowercase */ if (sf_case_ins() && has_case(yystack.l_mark[0])){ yystack.l_mark[0] = reverse_case (yystack.l_mark[0]); ccladd (yystack.l_mark[-1], yystack.l_mark[0]); cclsorted = cclsorted && (yystack.l_mark[0] > lastchar); lastchar = yystack.l_mark[0]; } yyval = yystack.l_mark[-1]; } break; case 69: #line 868 "parse.y" { /* Too hard to properly maintain cclsorted. */ cclsorted = false; yyval = yystack.l_mark[-1]; } break; case 70: #line 875 "parse.y" { cclsorted = true; lastchar = 0; currccl = yyval = cclinit(); } break; case 71: #line 883 "parse.y" { CCL_EXPR(isalnum); } break; case 72: #line 884 "parse.y" { CCL_EXPR(isalpha); } break; case 73: #line 885 "parse.y" { CCL_EXPR(IS_BLANK); } break; case 74: #line 886 "parse.y" { CCL_EXPR(iscntrl); } break; case 75: #line 887 "parse.y" { CCL_EXPR(isdigit); } break; case 76: #line 888 "parse.y" { CCL_EXPR(isgraph); } break; case 77: #line 889 "parse.y" { CCL_EXPR(islower); if (sf_case_ins()) CCL_EXPR(isupper); } break; case 78: #line 894 "parse.y" { CCL_EXPR(isprint); } break; case 79: #line 895 "parse.y" { CCL_EXPR(ispunct); } break; case 80: #line 896 "parse.y" { CCL_EXPR(isspace); } break; case 81: #line 897 "parse.y" { CCL_EXPR(isxdigit); } break; case 82: #line 898 "parse.y" { CCL_EXPR(isupper); if (sf_case_ins()) CCL_EXPR(islower); } break; case 83: #line 904 "parse.y" { CCL_NEG_EXPR(isalnum); } break; case 84: #line 905 "parse.y" { CCL_NEG_EXPR(isalpha); } break; case 85: #line 906 "parse.y" { CCL_NEG_EXPR(IS_BLANK); } break; case 86: #line 907 "parse.y" { CCL_NEG_EXPR(iscntrl); } break; case 87: #line 908 "parse.y" { CCL_NEG_EXPR(isdigit); } break; case 88: #line 909 "parse.y" { CCL_NEG_EXPR(isgraph); } break; case 89: #line 910 "parse.y" { CCL_NEG_EXPR(isprint); } break; case 90: #line 911 "parse.y" { CCL_NEG_EXPR(ispunct); } break; case 91: #line 912 "parse.y" { CCL_NEG_EXPR(isspace); } break; case 92: #line 913 "parse.y" { CCL_NEG_EXPR(isxdigit); } break; case 93: #line 914 "parse.y" { if ( sf_case_ins() ) warn(_("[:^lower:] is ambiguous in case insensitive scanner")); else CCL_NEG_EXPR(islower); } break; case 94: #line 920 "parse.y" { if ( sf_case_ins() ) warn(_("[:^upper:] ambiguous in case insensitive scanner")); else CCL_NEG_EXPR(isupper); } break; case 95: #line 929 "parse.y" { if ( yystack.l_mark[0] == nlch ) rule_has_nl[num_rules] = true; ++rulelen; if (sf_case_ins() && has_case(yystack.l_mark[0])) yyval = mkor (mkstate(yystack.l_mark[0]), mkstate(reverse_case(yystack.l_mark[0]))); else yyval = mkstate (yystack.l_mark[0]); yyval = link_machines( yystack.l_mark[-1], yyval); } break; case 96: #line 944 "parse.y" { yyval = mkstate( SYM_EPSILON ); } break; #line 1787 "parse.c" } yystack.s_mark -= yym; yystate = *yystack.s_mark; yystack.l_mark -= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) { #if YYDEBUG if (yydebug) printf("%sdebug: after reduction, shifting from state 0 to\ state %d\n", YYPREFIX, YYFINAL); #endif yystate = YYFINAL; *++yystack.s_mark = YYFINAL; *++yystack.l_mark = yyval; if (yychar < 0) { if ((yychar = YYLEX) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("%sdebug: state %d, reading %d (%s)\n", YYPREFIX, YYFINAL, yychar, yys); } #endif } if (yychar == 0) goto yyaccept; goto yyloop; } if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yystate) yystate = yytable[yyn]; else yystate = yydgoto[yym]; #if YYDEBUG if (yydebug) printf("%sdebug: after reduction, shifting from state %d \ to state %d\n", YYPREFIX, *yystack.s_mark, yystate); #endif if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack)) { goto yyoverflow; } *++yystack.s_mark = (short) yystate; *++yystack.l_mark = yyval; goto yyloop; yyoverflow: yyerror("yacc stack overflow"); yyabort: yyfreestack(&yystack); return (1); yyaccept: yyfreestack(&yystack); return (0); } freebsd-buildutils-10.0/src/usr.bin/lex/initparse.h0000644000000000000000000000206612146745723017235 0ustar /* $FreeBSD$ */ #define CHAR 257 #define NUMBER 258 #define SECTEND 259 #define SCDECL 260 #define XSCDECL 261 #define NAME 262 #define PREVCCL 263 #define EOF_OP 264 #define OPTION_OP 265 #define OPT_OUTFILE 266 #define OPT_PREFIX 267 #define OPT_YYCLASS 268 #define OPT_HEADER 269 #define OPT_EXTRA_TYPE 270 #define OPT_TABLES 271 #define CCE_ALNUM 272 #define CCE_ALPHA 273 #define CCE_BLANK 274 #define CCE_CNTRL 275 #define CCE_DIGIT 276 #define CCE_GRAPH 277 #define CCE_LOWER 278 #define CCE_PRINT 279 #define CCE_PUNCT 280 #define CCE_SPACE 281 #define CCE_UPPER 282 #define CCE_XDIGIT 283 #define CCE_NEG_ALNUM 284 #define CCE_NEG_ALPHA 285 #define CCE_NEG_BLANK 286 #define CCE_NEG_CNTRL 287 #define CCE_NEG_DIGIT 288 #define CCE_NEG_GRAPH 289 #define CCE_NEG_LOWER 290 #define CCE_NEG_PRINT 291 #define CCE_NEG_PUNCT 292 #define CCE_NEG_SPACE 293 #define CCE_NEG_UPPER 294 #define CCE_NEG_XDIGIT 295 #define CCL_OP_DIFF 296 #define CCL_OP_UNION 297 #define BEGIN_REPEAT_POSIX 298 #define END_REPEAT_POSIX 299 #define BEGIN_REPEAT_FLEX 300 #define END_REPEAT_FLEX 301 freebsd-buildutils-10.0/src/usr.bin/lex/Makefile0000644000000000000000000000336412146745723016530 0ustar # $FreeBSD$ # # By default, flex will be configured to generate 8-bit scanners only if the # -8 flag is given. If you want it to always generate 8-bit scanners, add # "-DDEFAULT_CSIZE=256" to CFLAGS. Note that doing so will double the size # of all uncompressed scanners. # # Bootstrapping of lex is handled automatically. # Also note that flex.skel no longer gets installed. # PROG= lex LINKS+= ${BINDIR}/lex ${BINDIR}/lex++ LINKS+= ${BINDIR}/lex ${BINDIR}/flex LINKS+= ${BINDIR}/lex ${BINDIR}/flex++ FLEXDIR= ${.CURDIR}/../../contrib/flex .PATH: ${FLEXDIR} SRCS= buf.c ccl.c dfa.c ecs.c filter.c gen.c main.c misc.c \ nfa.c options.c parse.y regex.c scan.c scanflags.c \ scanopt.c skel.c sym.c tables.c tables_shared.c \ tblcmp.c yylex.c LFLAGS+= -is CFLAGS+= -I. -I${.CURDIR} -I${FLEXDIR} -DHAVE_CONFIG_H INCS= FlexLexer.h INCSDIR= ${INCLUDEDIR} MLINKS+= lex.1 flex.1 MLINKS+= lex.1 flex++.1 MLINKS+= lex.1 lex++.1 WARNS?= 3 CLEANFILES= scan.c skel.c GENFILES= parse.c parse.h scan.c skel.c SUBDIR= lib FLEX_VERSION= `awk -f ${.CURDIR}/version.awk ${.CURDIR}/config.h` skel.c: config.h mkskel.sh flex.skl version.awk sed 's/m4_/m4postproc_/g; s/m4preproc_/m4_/g' \ ${FLEXDIR}/flex.skl | \ m4 -I${FLEXDIR} -P ${FLEX_VERSION} | \ sed 's/m4postproc_/m4_/g' | \ sh ${FLEXDIR}/mkskel.sh > ${.TARGET} bootstrap: ${GENFILES:S/^/init/g} .for _f in ${GENFILES} @diff -I '^#line ' -I '\$$FreeBS[D]: .*\$$' -q \ ${.CURDIR}/init${_f} ${_f} 2> /dev/null || { \ echo "Bootstrapping ${_f}" ; \ cp -f ${.CURDIR}/init${_f} ${_f} ; \ } .endfor test: check check: ${PROG} ./${PROG} ${LFLAGS} -t ${COMPRESSION} ${FLEXDIR}/scan.l | \ diff -I '^#line ' -I '\$$FreeBS[D]: .*\$$' ${.CURDIR}/initscan.c - @echo "Check successful" .include freebsd-buildutils-10.0/src/usr.bin/file2c/0000755000000000000000000000000012265500070015420 5ustar freebsd-buildutils-10.0/src/usr.bin/file2c/file2c.10000644000000000000000000000461310711667214016662 0ustar .\"---------------------------------------------------------------------------- .\" "THE BEER-WARE LICENSE" (Revision 42): .\" wrote this file. As long as you retain this notice, you .\" can do whatever you want with this file. If we meet some day, and you think .\" this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp .\" --------------------------------------------------------------------------- .\" .\" $FreeBSD$ .\" .Dd March 22, 2007 .Dt FILE2C 1 .Os .Sh NAME .Nm file2c .Nd convert file to c-source .Sh SYNOPSIS .Nm .Op Fl sx .Op Fl n Ar count .Op Ar prefix Op Ar suffix .Sh DESCRIPTION The .Nm utility reads a file from stdin and writes it to stdout, converting each byte to its decimal or hexadecimal representation on the fly. The byte values are separated by a comma. This also means that the last byte value is not followed by a comma. By default the byte values are printed in decimal, but when the .Fl x option is given, the values will be printed in hexadecimal. When .Fl s option is given, each line is printed with a leading tab and each comma is followed by a space except for the last one on the line. .Pp If more than 70 characters are printed on the same line, that line is ended and the output continues on the next line. With the .Fl n option this can be made to happen after the specified number of byte values have been printed. The length of the line will not be considered anymore. To have all the byte values printed on the same line, give the .Fl n option a negative number. .Pp A prefix and suffix strings can be printed before and after the byte values (resp.) If a suffix is to be printed, a prefix must also be specified. The first non-option word is the prefix, which may optionally be followed by a word that is to be used as the suffix. .Pp This program is typically used to embed binary files into C source files. The prefix is used to define an array type and the suffix is used to end the C statement. The .Fl n , s and .Fl x options are useful when the binary data represents a bitmap and the output needs to remain readable and/or editable. Fonts, for example, are a good example of this. .Sh EXAMPLES The command: .Bd -literal -offset indent date | file2c 'const char date[] = {' ',0};' .Ed .Pp will produce: .Bd -literal -offset indent const char date[] = { 83,97,116,32,74,97,110,32,50,56,32,49,54,58,50,56,58,48,53, 32,80,83,84,32,49,57,57,53,10 ,0}; .Ed freebsd-buildutils-10.0/src/usr.bin/file2c/Makefile0000644000000000000000000000006111317617571017071 0ustar # $FreeBSD$ PROG= file2c .include freebsd-buildutils-10.0/src/usr.bin/file2c/file2c.c0000644000000000000000000000347411311055776016751 0ustar /* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- */ #include __FBSDID("$FreeBSD$"); #include #include #include #include static void usage(void) { fprintf(stderr, "usage: %s [-sx] [-n count] [prefix [suffix]]\n", getprogname()); exit(1); } int main(int argc, char *argv[]) { int c, count, linepos, maxcount, pretty, radix; maxcount = 0; pretty = 0; radix = 10; while ((c = getopt(argc, argv, "n:sx")) != -1) { switch (c) { case 'n': /* Max. number of bytes per line. */ maxcount = strtol(optarg, NULL, 10); break; case 's': /* Be more style(9) comliant. */ pretty = 1; break; case 'x': /* Print hexadecimal numbers. */ radix = 16; break; case '?': default: usage(); } } argc -= optind; argv += optind; if (argc > 0) printf("%s\n", argv[0]); count = linepos = 0; while((c = getchar()) != EOF) { if (count) { putchar(','); linepos++; } if ((maxcount == 0 && linepos > 70) || (maxcount > 0 && count >= maxcount)) { putchar('\n'); count = linepos = 0; } if (pretty) { if (count) { putchar(' '); linepos++; } else { putchar('\t'); linepos += 8; } } switch (radix) { case 10: linepos += printf("%d", c); break; case 16: linepos += printf("0x%02x", c); break; default: abort(); } count++; } putchar('\n'); if (argc > 1) printf("%s\n", argv[1]); return (0); } freebsd-buildutils-10.0/src/usr.bin/cksum/0000755000000000000000000000000012265500043015376 5ustar freebsd-buildutils-10.0/src/usr.bin/cksum/sum2.c0000644000000000000000000000450211500633420016426 0ustar /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 static char sccsid[] = "@(#)sum2.c 8.1 (Berkeley) 6/6/93"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include #include #include #include "extern.h" int csum2(int fd, uint32_t *cval, off_t *clen) { uint32_t lcrc; int nr; off_t total; u_char *p; u_char buf[8192]; /* * Draft 8 POSIX 1003.2: * * s = sum of all bytes * r = s % 2^16 + (s % 2^32) / 2^16 * lcrc = (r % 2^16) + r / 2^16 */ lcrc = total = 0; while ((nr = read(fd, buf, sizeof(buf))) > 0) for (total += nr, p = buf; nr--; ++p) lcrc += *p; if (nr < 0) return (1); lcrc = (lcrc & 0xffff) + (lcrc >> 16); lcrc = (lcrc & 0xffff) + (lcrc >> 16); *cval = lcrc; *clen = total; return (0); } freebsd-buildutils-10.0/src/usr.bin/cksum/cksum.10000644000000000000000000001227711500633420016610 0ustar .\" Copyright (c) 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" the Institute of Electrical and Electronics Engineers, Inc. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)cksum.1 8.2 (Berkeley) 4/28/95 .\" $FreeBSD$ .\" .Dd April 28, 1995 .Dt CKSUM 1 .Os .Sh NAME .Nm cksum , .Nm sum .Nd display file checksums and block counts .Sh SYNOPSIS .Nm .Op Fl o Ar 1 | 2 | 3 .Op Ar .Nm sum .Op Ar .Sh DESCRIPTION The .Nm utility writes to the standard output three whitespace separated fields for each input file. These fields are a checksum .Tn CRC , the total number of octets in the file and the file name. If no file name is specified, the standard input is used and no file name is written. .Pp The .Nm sum utility is identical to the .Nm utility, except that it defaults to using historic algorithm 1, as described below. It is provided for compatibility only. .Pp The options are as follows: .Bl -tag -width indent .It Fl o Use historic algorithms instead of the (superior) default one. .Pp Algorithm 1 is the algorithm used by historic .Bx systems as the .Xr sum 1 algorithm and by historic .At V systems as the .Xr sum 1 algorithm when using the .Fl r option. This is a 16-bit checksum, with a right rotation before each addition; overflow is discarded. .Pp Algorithm 2 is the algorithm used by historic .At V systems as the default .Xr sum 1 algorithm. This is a 32-bit checksum, and is defined as follows: .Bd -unfilled -offset indent s = sum of all bytes; r = s % 2^16 + (s % 2^32) / 2^16; cksum = (r % 2^16) + r / 2^16; .Ed .Pp Algorithm 3 is what is commonly called the .Ql 32bit CRC algorithm. This is a 32-bit checksum. .Pp Both algorithm 1 and 2 write to the standard output the same fields as the default algorithm except that the size of the file in bytes is replaced with the size of the file in blocks. For historic reasons, the block size is 1024 for algorithm 1 and 512 for algorithm 2. Partial blocks are rounded up. .El .Pp The default .Tn CRC used is based on the polynomial used for .Tn CRC error checking in the networking standard .St -iso8802-3 . The .Tn CRC checksum encoding is defined by the generating polynomial: .Bd -unfilled -offset indent G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 .Ed .Pp Mathematically, the .Tn CRC value corresponding to a given file is defined by the following procedure: .Bd -ragged -offset indent The .Ar n bits to be evaluated are considered to be the coefficients of a mod 2 polynomial M(x) of degree .Ar n Ns \-1 . These .Ar n bits are the bits from the file, with the most significant bit being the most significant bit of the first octet of the file and the last bit being the least significant bit of the last octet, padded with zero bits (if necessary) to achieve an integral number of octets, followed by one or more octets representing the length of the file as a binary value, least significant octet first. The smallest number of octets capable of representing this integer are used. .Pp M(x) is multiplied by x^32 (i.e., shifted left 32 bits) and divided by G(x) using mod 2 division, producing a remainder R(x) of degree <= 31. .Pp The coefficients of R(x) are considered to be a 32-bit sequence. .Pp The bit sequence is complemented and the result is the CRC. .Ed .Sh EXIT STATUS .Ex -std cksum sum .Sh SEE ALSO .Xr md5 1 .Pp The default calculation is identical to that given in pseudo-code in the following .Tn ACM article. .Rs .%T "Computation of Cyclic Redundancy Checks Via Table Lookup" .%A Dilip V. Sarwate .%J "Communications of the" Tn ACM .%D "August 1988" .Re .Sh STANDARDS The .Nm utility is expected to conform to .St -p1003.2-92 . .Sh HISTORY The .Nm utility appeared in .Bx 4.4 . freebsd-buildutils-10.0/src/usr.bin/cksum/sum1.c0000644000000000000000000000440711500633420016431 0ustar /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 static char sccsid[] = "@(#)sum1.c 8.1 (Berkeley) 6/6/93"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include #include #include #include "extern.h" int csum1(int fd, uint32_t *cval, off_t *clen) { int nr; u_int lcrc; off_t total; u_char *p; u_char buf[8192]; /* * 16-bit checksum, rotating right before each addition; * overflow is discarded. */ lcrc = total = 0; while ((nr = read(fd, buf, sizeof(buf))) > 0) for (total += nr, p = buf; nr--; ++p) { if (lcrc & 1) lcrc |= 0x10000; lcrc = ((lcrc >> 1) + *p) & 0xffff; } if (nr < 0) return (1); *cval = lcrc; *clen = total; return (0); } freebsd-buildutils-10.0/src/usr.bin/cksum/print.c0000644000000000000000000000450711500633420016701 0ustar /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 static char sccsid[] = "@(#)print.c 8.1 (Berkeley) 6/6/93"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include #include #include #include "extern.h" void pcrc(char *fn, uint32_t val, off_t len) { (void)printf("%lu %jd", (u_long)val, (intmax_t)len); if (fn != NULL) (void)printf(" %s", fn); (void)printf("\n"); } void psum1(char *fn, uint32_t val, off_t len) { (void)printf("%lu %jd", (u_long)val, (intmax_t)(len + 1023) / 1024); if (fn != NULL) (void)printf(" %s", fn); (void)printf("\n"); } void psum2(char *fn, uint32_t val, off_t len) { (void)printf("%lu %jd", (u_long)val, (intmax_t)(len + 511) / 512); if (fn != NULL) (void)printf(" %s", fn); (void)printf("\n"); } freebsd-buildutils-10.0/src/usr.bin/cksum/extern.h0000644000000000000000000000373512040476753017077 0ustar /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)extern.h 8.1 (Berkeley) 6/6/93 * $FreeBSD$ */ #include extern uint32_t crc_total; extern uint32_t crc32_total; __BEGIN_DECLS int crc(int, uint32_t *, off_t *); void pcrc(char *, uint32_t, off_t); void psum1(char *, uint32_t, off_t); void psum2(char *, uint32_t, off_t); int csum1(int, uint32_t *, off_t *); int csum2(int, uint32_t *, off_t *); int crc32(int, uint32_t *, off_t *); __END_DECLS freebsd-buildutils-10.0/src/usr.bin/cksum/cksum.c0000644000000000000000000000677511700647116016711 0ustar /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * James W. Williams of NASA Goddard Space Flight Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1991, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)cksum.c 8.2 (Berkeley) 4/28/95"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "extern.h" static void usage(void); int main(int argc, char **argv) { uint32_t val; int ch, fd, rval; off_t len; char *fn, *p; int (*cfncn)(int, uint32_t *, off_t *); void (*pfncn)(char *, uint32_t, off_t); if ((p = strrchr(argv[0], '/')) == NULL) p = argv[0]; else ++p; if (!strcmp(p, "sum")) { cfncn = csum1; pfncn = psum1; ++argv; } else { cfncn = crc; pfncn = pcrc; while ((ch = getopt(argc, argv, "o:")) != -1) switch (ch) { case 'o': if (!strcmp(optarg, "1")) { cfncn = csum1; pfncn = psum1; } else if (!strcmp(optarg, "2")) { cfncn = csum2; pfncn = psum2; } else if (!strcmp(optarg, "3")) { cfncn = crc32; pfncn = pcrc; } else { warnx("illegal argument to -o option"); usage(); } break; case '?': default: usage(); } argc -= optind; argv += optind; } fd = STDIN_FILENO; fn = NULL; rval = 0; do { if (*argv) { fn = *argv++; if ((fd = open(fn, O_RDONLY, 0)) < 0) { warn("%s", fn); rval = 1; continue; } } if (cfncn(fd, &val, &len)) { warn("%s", fn ? fn : "stdin"); rval = 1; } else pfncn(fn, val, len); (void)close(fd); } while (*argv); exit(rval); } static void usage(void) { (void)fprintf(stderr, "usage: cksum [-o 1 | 2 | 3] [file ...]\n"); (void)fprintf(stderr, " sum [file ...]\n"); exit(1); } freebsd-buildutils-10.0/src/usr.bin/cksum/crc.c0000644000000000000000000001370711500633420016316 0ustar /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * James W. Williams of NASA Goddard Space Flight Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 static char sccsid[] = "@(#)crc.c 8.1 (Berkeley) 6/17/93"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include #include #include #include "extern.h" static const uint32_t crctab[] = { 0x0, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 }; /* * Compute a POSIX 1003.2 checksum. This routine has been broken out so that * other programs can use it. It takes a file descriptor to read from and * locations to store the crc and the number of bytes read. It returns 0 on * success and 1 on failure. Errno is set on failure. */ uint32_t crc_total = ~0; /* The crc over a number of files. */ int crc(int fd, uint32_t *cval, off_t *clen) { uint32_t lcrc; int nr; off_t len; u_char *p; u_char buf[16 * 1024]; #define COMPUTE(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)] lcrc = len = 0; crc_total = ~crc_total; while ((nr = read(fd, buf, sizeof(buf))) > 0) for (len += nr, p = buf; nr--; ++p) { COMPUTE(lcrc, *p); COMPUTE(crc_total, *p); } if (nr < 0) return (1); *clen = len; /* Include the length of the file. */ for (; len != 0; len >>= 8) { COMPUTE(lcrc, len & 0xff); COMPUTE(crc_total, len & 0xff); } *cval = ~lcrc; crc_total = ~crc_total; return (0); } freebsd-buildutils-10.0/src/usr.bin/cksum/Makefile0000644000000000000000000000030411311055776017044 0ustar # @(#)Makefile 8.2 (Berkeley) 4/28/95 # $FreeBSD$ PROG= cksum SRCS= cksum.c crc.c print.c sum1.c sum2.c crc32.c LINKS= ${BINDIR}/cksum ${BINDIR}/sum MLINKS= cksum.1 sum.1 .include freebsd-buildutils-10.0/src/usr.bin/cksum/crc32.c0000644000000000000000000001101311311055776016463 0ustar /* * This code implements the AUTODIN II polynomial used by Ethernet, * and can be used to calculate multicast address hash indices. * It assumes that the low order bits will be transmitted first, * and consequently the low byte should be sent first when * the crc computation is finished. The crc should be complemented * before transmission. * The variable corresponding to the macro argument "crc" should * be an unsigned long and should be preset to all ones for Ethernet * use. An error-free packet will leave 0xDEBB20E3 in the crc. * Spencer Garrett */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include "extern.h" #define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff]) /* generated using the AUTODIN II polynomial * x^32 + x^26 + x^23 + x^22 + x^16 + * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1 */ static const uint32_t crctab[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, }; uint32_t crc32_total = 0; int crc32(int fd, uint32_t *cval, off_t *clen) { uint32_t lcrc = ~0; int nr ; off_t len ; char buf[BUFSIZ], *p ; len = 0 ; crc32_total = ~crc32_total ; while ((nr = read(fd, buf, sizeof(buf))) > 0) for (len += nr, p = buf; nr--; ++p) { CRC(lcrc, *p) ; CRC(crc32_total, *p) ; } if (nr < 0) return 1 ; *clen = len ; *cval = ~lcrc ; crc32_total = ~crc32_total ; return 0 ; } freebsd-buildutils-10.0/src/usr.bin/mkdep/0000755000000000000000000000000012265500172015357 5ustar freebsd-buildutils-10.0/src/usr.bin/mkdep/mkdep.gcc.sh0000644000000000000000000000560311500633420017544 0ustar #!/bin/sh - # # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 4. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # @(#)mkdep.gcc.sh 8.1 (Berkeley) 6/6/93 # $FreeBSD$ D=.depend # default dependency file is .depend append=0 pflag= while : do case "$1" in # -a appends to the depend file -a) append=1 shift ;; # -f allows you to select a makefile name -f) D=$2 shift; shift ;; # the -p flag produces "program: program.c" style dependencies # so .o's don't get produced -p) pflag=p shift ;; *) break ;; esac done case $# in 0) echo 'usage: mkdep [-ap] [-f file] [flags] file ...' >&2 exit 1;; esac TMP=_mkdep$$ trap 'rm -f $TMP ; trap 2 ; kill -2 $$' 1 2 3 13 15 trap 'rm -f $TMP' 0 # For C sources, mkdep must use exactly the same cpp and predefined flags # as the compiler would. This is easily arranged by letting the compiler # pick the cpp. mkdep must be told the cpp to use for exceptional cases. CC=${CC-"cc"} MKDEP_CPP=${MKDEP_CPP-"${CC} -E"} MKDEP_CPP_OPTS=${MKDEP_CPP_OPTS-"-M"}; echo "# $@" > $TMP # store arguments for debugging if $MKDEP_CPP $MKDEP_CPP_OPTS "$@" >> $TMP; then : else echo 'mkdep: compile failed' >&2 exit 1 fi case x$pflag in x) case $append in 0) sed -e 's; \./; ;g' < $TMP > $D;; *) sed -e 's; \./; ;g' < $TMP >> $D;; esac ;; *) case $append in 0) sed -e 's;\.o:;:;' -e 's; \./; ;g' < $TMP > $D;; *) sed -e 's;\.o:;:;' -e 's; \./; ;g' < $TMP >> $D;; esac ;; esac exit $? freebsd-buildutils-10.0/src/usr.bin/mkdep/Makefile0000644000000000000000000000020107263574077017031 0ustar # @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ SCRIPTS= mkdep.gcc.sh MAN= mkdep.1 SCRIPTSNAME= mkdep .include freebsd-buildutils-10.0/src/usr.bin/mkdep/mkdep.sh0000644000000000000000000000514211500633420017007 0ustar #!/bin/sh - # # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 4. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # # @(#)mkdep.sh 8.1 (Berkeley) 6/6/93 # PATH=/bin:/usr/bin:/usr/ucb:/usr/old/bin export PATH D=.depend # default dependency file is .depend append=0 while : do case "$1" in # -a appends to the depend file -a) append=1 shift ;; # -f allows you to select a makefile name -f) D=$2 shift; shift ;; # the -p flag produces "program: program.c" style dependencies # so .o's don't get produced -p) SED='s;\.o ; ;' shift ;; *) break ;; esac done if [ $# = 0 ] ; then echo 'usage: mkdep [-p] [-f depend_file] [cc_flags] file ...' exit 1 fi TMP=/tmp/mkdep$$ trap 'rm -f $TMP ; trap 2 ; kill -2 $$' 1 2 3 13 15 cc -M $* | sed " s; \./; ;g /\.c:$/d $SED" | awk '{ if ($1 != prev) { if (rec != "") print rec; rec = $0; prev = $1; } else { if (length(rec $2) > 78) { print rec; rec = $0; } else rec = rec " " $2 } } END { print rec }' > $TMP if [ $? != 0 ]; then echo 'mkdep: compile failed.' rm -f $TMP exit 1 fi if [ $append = 1 ]; then cat $TMP >> $D rm -f $TMP else mv $TMP $D fi exit 0 freebsd-buildutils-10.0/src/usr.bin/mkdep/mkdep.10000644000000000000000000000722111500633420016535 0ustar .\" Copyright (c) 1987, 1990, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)mkdep.1 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" .Dd June 6, 1993 .Dt MKDEP 1 .Os .Sh NAME .Nm mkdep .Nd construct Makefile dependency list .Sh SYNOPSIS .Nm .Op Fl ap .Op Fl f Ar file .Op Ar flags .Ar .Sh DESCRIPTION The .Nm utility takes a set of flags for the C compiler and a list of C source files as arguments and constructs a set of include file dependencies which are written into the file ``.depend''. An example of its use in a Makefile might be: .Bd -literal -offset indent CFLAGS= -O -I../include SRCS= file1.c file2.c depend: mkdep ${CFLAGS} ${SRCS} .Ed .Pp where the macro SRCS is the list of C source files and the macro CFLAGS is the list of flags for the C compiler. .Pp The user has the ability to change the preprocessor and preprocessor options used. For instance, to use gcc as the preprocessor and to ignore system headers, one would use .Bd -literal -offset indent depend: env MKDEP_CPP="gcc -E" MKDEP_CPP_OPTS=-MM mkdep \\ ${CFLAGS} ${SRCS} .Ed .Pp The options are as follows: .Bl -tag -width Ds .It Fl a Append to the output file, so that multiple .Nm Ns 's may be run from a single Makefile. .It Fl f Write the include file dependencies to .Ar file , instead of the default ``.depend''. .It Fl p Cause .Nm to produce dependencies of the form: .Bd -literal -offset indent program: program.c .Ed .Pp so that subsequent makes will produce .Ar program directly from its C module rather than using an intermediate .Pa \&.o module. This is useful for programs whose source is contained in a single module. .El .Sh ENVIRONMENT .Bl -tag -width MKDEP_CPP_OPTS .It Ev CC Specifies the C compiler to use. The specified compiler is expected to have options consistent with the GNU C compiler. .It Ev MKDEP_CPP Specifies the preprocessor to use. The default is "${CC} -E". .It Ev MKDEP_CPP_OPTS Specifies the non-CFLAGS options for the preprocessor. The default is "-M". .El .Sh FILES .Bl -tag -width .depend -compact .It Pa .depend File containing list of dependencies. .El .Sh SEE ALSO .Xr cc 1 , .Xr cpp 1 , .Xr make 1 .Sh HISTORY The .Nm command appeared in .Bx 4.3 Tahoe . freebsd-buildutils-10.0/src/usr.bin/make/0000755000000000000000000000000012265500155015175 5ustar freebsd-buildutils-10.0/src/usr.bin/make/shell.h0000644000000000000000000000757010244644173016472 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef shell_h_6002e3b8 #define shell_h_6002e3b8 #include #include "str.h" #include "util.h" /** * Shell Specifications: * * Some special stuff goes on if a shell doesn't have error control. In such * a case, errCheck becomes a printf template for echoing the command, * should echoing be on and ignErr becomes another printf template for * executing the command while ignoring the return status. If either of these * strings is empty when hasErrCtl is FALSE, the command will be executed * anyway as is and if it causes an error, so be it. */ struct Shell { TAILQ_ENTRY(Shell) link; /* link all shell descriptions */ /* * the name of the shell. For Bourne and C shells, this is used * only to find the shell description when used as the single * source of a .SHELL target. */ char *name; char *path; /* full path to the shell */ /* True if both echoOff and echoOn defined */ Boolean hasEchoCtl; char *echoOff; /* command to turn off echo */ char *echoOn; /* command to turn it back on */ /* * What the shell prints, and its length, when given the * echo-off command. This line will not be printed when * received from the shell. This is usually the command which * was executed to turn off echoing */ char *noPrint; /* set if can control error checking for individual commands */ Boolean hasErrCtl; /* string to turn error checking on */ char *errCheck; /* string to turn off error checking */ char *ignErr; char *echo; /* command line flag: echo commands */ char *exit; /* command line flag: exit on error */ ArgArray builtins; /* ordered list of shell builtins */ char *meta; /* shell meta characters */ Boolean unsetenv; /* unsetenv("ENV") before exec */ }; TAILQ_HEAD(Shells, Shell); extern struct Shell *commandShell; void Shell_Init(void); Boolean Shell_Parse(const char []); #endif /* shell_h_6002e3b8 */ freebsd-buildutils-10.0/src/usr.bin/make/proc.c0000644000000000000000000000723311306456044016313 0ustar /*- * Copyright (C) 2005 Max Okumoto. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include "proc.h" #include "shell.h" #include "util.h" /** * Replace the current process. */ void Proc_Exec(const ProcStuff *ps) { if (ps->in != STDIN_FILENO) { /* * Redirect the child's stdin to the input fd * and reset it to the beginning (again). */ if (dup2(ps->in, STDIN_FILENO) == -1) Punt("Cannot dup2: %s", strerror(errno)); lseek(STDIN_FILENO, (off_t)0, SEEK_SET); } if (ps->out != STDOUT_FILENO) { /* * Redirect the child's stdout to the output fd. */ if (dup2(ps->out, STDOUT_FILENO) == -1) Punt("Cannot dup2: %s", strerror(errno)); close(ps->out); } if (ps->err != STDERR_FILENO) { /* * Redirect the child's stderr to the err fd. */ if (dup2(ps->err, STDERR_FILENO) == -1) Punt("Cannot dup2: %s", strerror(errno)); close(ps->err); } if (ps->merge_errors) { /* * Send stderr to parent process too. */ if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) Punt("Cannot dup2: %s", strerror(errno)); } if (commandShell->unsetenv) { /* for the benfit of ksh */ unsetenv("ENV"); } /* * The file descriptors for stdin, stdout, or stderr might * have been marked close-on-exec. Clear the flag on all * of them. */ fcntl(STDIN_FILENO, F_SETFD, fcntl(STDIN_FILENO, F_GETFD) & (~FD_CLOEXEC)); fcntl(STDOUT_FILENO, F_SETFD, fcntl(STDOUT_FILENO, F_GETFD) & (~FD_CLOEXEC)); fcntl(STDERR_FILENO, F_SETFD, fcntl(STDERR_FILENO, F_GETFD) & (~FD_CLOEXEC)); if (ps->pgroup) { #ifdef USE_PGRP /* * Become a process group leader, so we can kill it and all * its descendants in one fell swoop, by killing its process * family, but not commit suicide. */ #if defined(SYSV) setsid(); #else setpgid(0, getpid()); #endif #endif /* USE_PGRP */ } if (ps->searchpath) { execvp(ps->argv[0], ps->argv); write(STDERR_FILENO, ps->argv[0], strlen(ps->argv[0])); write(STDERR_FILENO, ": ", 2); write(STDERR_FILENO, strerror(errno), strlen(strerror(errno))); write(STDERR_FILENO, "\n", 1); } else { execv(commandShell->path, ps->argv); write(STDERR_FILENO, "Could not execute shell\n", sizeof("Could not execute shell")); } /* * Since we are the child process, exit without flushing buffers. */ _exit(1); } freebsd-buildutils-10.0/src/usr.bin/make/make.h0000644000000000000000000000527211126122672016270 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)make.h 8.3 (Berkeley) 6/13/95 * $FreeBSD$ */ #ifndef make_h_a91074b9 #define make_h_a91074b9 /** * make.h * The global definitions for make */ #include "util.h" #define MAKE_JOB_PREFIX ".MAKE.JOB.PREFIX" struct GNode; struct Lst; struct Buffer; /* * Warning flags */ enum { WARN_DIRSYNTAX = 0x0001, /* syntax errors in directives */ }; int Make_TimeStamp(struct GNode *, struct GNode *); Boolean Make_OODate(struct GNode *); int Make_HandleUse(struct GNode *, struct GNode *); void Make_Update(struct GNode *); void Make_DoAllVar(struct GNode *); Boolean Make_Run(struct Lst *); void Main_ParseArgLine(char *, int); int Main_ParseWarn(const char *, int); void Main_AddSourceMakefile(const char *); #endif /* make_h_a91074b9 */ freebsd-buildutils-10.0/src/usr.bin/make/util.h0000644000000000000000000000725010242562677016341 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef util_h_b7020fdb #define util_h_b7020fdb #include #include /* * A boolean type is defined as an integer, not an enum. This allows a * boolean argument to be an expression that isn't strictly 0 or 1 valued. */ typedef int Boolean; #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif /* TRUE */ #define CONCAT(a,b) a##b struct flag2str { u_int flag; const char *str; }; /* * debug control: * There is one bit per module. It is up to the module what debug * information to print. */ #define DEBUG_ARCH 0x0001 #define DEBUG_COND 0x0002 #define DEBUG_DIR 0x0004 #define DEBUG_GRAPH1 0x0008 #define DEBUG_GRAPH2 0x0010 #define DEBUG_JOB 0x0020 #define DEBUG_MAKE 0x0040 #define DEBUG_SUFF 0x0080 #define DEBUG_TARG 0x0100 #define DEBUG_VAR 0x0200 #define DEBUG_FOR 0x0400 #define DEBUG_LOUD 0x0800 #define DEBUG(module) (debug & CONCAT(DEBUG_,module)) #define DEBUGF(module,args) \ do { \ if (DEBUG(module)) { \ Debug args ; \ } \ } while (0) #define DEBUGM(module, args) do { \ if (DEBUG(module)) { \ DebugM args; \ } \ } while (0) #define ISDOT(c) ((c)[0] == '.' && (((c)[1] == '\0') || ((c)[1] == '/'))) #define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1]))) #ifndef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif void Debug(const char *, ...); void DebugM(const char *, ...); void Error(const char *, ...); void Fatal(const char *, ...) __dead2; void Punt(const char *, ...) __dead2; void DieHorribly(void) __dead2; void Finish(int) __dead2; char *estrdup(const char *); void *emalloc(size_t); void *erealloc(void *, size_t); int eunlink(const char *); void print_flags(FILE *, const struct flag2str *, u_int, int); #endif /* util_h_b7020fdb */ freebsd-buildutils-10.0/src/usr.bin/make/str.c0000644000000000000000000002771711677315120016171 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)str.c 5.8 (Berkeley) 6/1/90 */ #include __FBSDID("$FreeBSD$"); #include #include #include "buf.h" #include "str.h" #include "util.h" /** * Initialize the argument array object. The array is initially * eight positions, and will be expanded as necessary. The first * position is set to NULL since everything ignores it. We allocate * (size + 1) since we need space for the terminating NULL. The * buffer is set to NULL, since no common buffer is allocated yet. */ void ArgArray_Init(ArgArray *aa) { aa->size = 8; aa->argv = emalloc((aa->size + 1) * sizeof(char *)); aa->argc = 0; aa->argv[aa->argc++] = NULL; aa->len = 0; aa->buffer = NULL; } /** * Cleanup the memory allocated for in the argument array object. */ void ArgArray_Done(ArgArray *aa) { if (aa->buffer == NULL) { int i; /* args are individually allocated */ for (i = 0; i < aa->argc; ++i) { if (aa->argv[i]) { free(aa->argv[i]); aa->argv[i] = NULL; } } } else { /* args are part of a single allocation */ free(aa->buffer); aa->buffer = NULL; } free(aa->argv); aa->argv = NULL; aa->argc = 0; aa->size = 0; } /*- * str_concat -- * concatenate the two strings, inserting a space or slash between them. * * returns -- * the resulting string in allocated space. */ char * str_concat(const char *s1, const char *s2, int flags) { int len1, len2; char *result; /* get the length of both strings */ len1 = strlen(s1); len2 = strlen(s2); /* allocate length plus separator plus EOS */ result = emalloc(len1 + len2 + 2); /* copy first string into place */ memcpy(result, s1, len1); /* add separator character */ if (flags & STR_ADDSPACE) { result[len1] = ' '; ++len1; } else if (flags & STR_ADDSLASH) { result[len1] = '/'; ++len1; } /* copy second string plus EOS into place */ memcpy(result + len1, s2, len2 + 1); return (result); } /** * Fracture a string into an array of words (as delineated by tabs or * spaces) taking quotation marks into account. Leading tabs/spaces * are ignored. */ void brk_string(ArgArray *aa, const char str[], Boolean expand) { char inquote; char *start; char *arg; /* skip leading space chars. */ for (; *str == ' ' || *str == '\t'; ++str) continue; ArgArray_Init(aa); aa->buffer = estrdup(str); arg = aa->buffer; start = arg; inquote = '\0'; /* * copy the string; at the same time, parse backslashes, * quotes and build the argument list. */ for (;;) { switch (str[0]) { case '"': case '\'': if (inquote == '\0') { inquote = str[0]; if (expand) break; if (start == NULL) start = arg; } else if (inquote == str[0]) { inquote = '\0'; /* Don't miss "" or '' */ if (start == NULL) start = arg; if (expand) break; } else { /* other type of quote found */ if (start == NULL) start = arg; } *arg++ = str[0]; break; case ' ': case '\t': case '\n': if (inquote) { if (start == NULL) start = arg; *arg++ = str[0]; break; } if (start == NULL) break; /* FALLTHROUGH */ case '\0': /* * end of a token -- make sure there's enough argv * space and save off a pointer. */ if (aa->argc == aa->size) { aa->size *= 2; /* ramp up fast */ aa->argv = erealloc(aa->argv, (aa->size + 1) * sizeof(char *)); } *arg++ = '\0'; if (start == NULL) { aa->argv[aa->argc] = start; return; } if (str[0] == '\n' || str[0] == '\0') { aa->argv[aa->argc++] = start; aa->argv[aa->argc] = NULL; return; } else { aa->argv[aa->argc++] = start; start = NULL; break; } case '\\': if (start == NULL) start = arg; if (expand) { switch (str[1]) { case '\0': case '\n': /* hmmm; fix it up as best we can */ *arg++ = '\\'; break; case 'b': *arg++ = '\b'; ++str; break; case 'f': *arg++ = '\f'; ++str; break; case 'n': *arg++ = '\n'; ++str; break; case 'r': *arg++ = '\r'; ++str; break; case 't': *arg++ = '\t'; ++str; break; default: *arg++ = str[1]; ++str; break; } } else { *arg++ = str[0]; if (str[1] != '\0') { ++str; *arg++ = str[0]; } } break; default: if (start == NULL) start = arg; *arg++ = str[0]; break; } ++str; } } /* * Quote a string for appending it to MAKEFLAGS. According to Posix the * kind of quoting here is implementation-defined. This quoting must ensure * that the parsing of MAKEFLAGS's contents in a sub-shell yields the same * options, option arguments and macro definitions as in the calling make. * We simply quote all blanks, which according to Posix are space and tab * in the POSIX locale. Don't use isblank because in that case makes with * different locale settings could not communicate. We must also quote * backslashes obviously. */ char * MAKEFLAGS_quote(const char *str) { char *ret, *q; const char *p; /* assume worst case - everything has to be quoted */ ret = emalloc(strlen(str) * 2 + 1); p = str; q = ret; while (*p != '\0') { switch (*p) { case ' ': case '\t': *q++ = '\\'; break; default: break; } *q++ = *p++; } *q++ = '\0'; return (ret); } void MAKEFLAGS_break(ArgArray *aa, const char str[]) { char *arg; char *start; ArgArray_Init(aa); aa->buffer = strdup(str); arg = aa->buffer; start = NULL; for (;;) { switch (str[0]) { case ' ': case '\t': /* word separator */ if (start == NULL) { /* not in a word */ str++; continue; } /* FALLTHRU */ case '\0': if (aa->argc == aa->size) { aa->size *= 2; aa->argv = erealloc(aa->argv, (aa->size + 1) * sizeof(char *)); } *arg++ = '\0'; if (start == NULL) { aa->argv[aa->argc] = start; return; } if (str[0] == '\0') { aa->argv[aa->argc++] = start; aa->argv[aa->argc] = NULL; return; } else { aa->argv[aa->argc++] = start; start = NULL; str++; continue; } case '\\': if (str[1] == ' ' || str[1] == '\t') str++; break; default: break; } if (start == NULL) start = arg; *arg++ = *str++; } } /* * Str_Match -- * * See if a particular string matches a particular pattern. * * Results: Non-zero is returned if string matches pattern, 0 otherwise. The * matching operation permits the following special characters in the * pattern: *?\[] (see the man page for details on what these mean). * * Side effects: None. */ int Str_Match(const char *string, const char *pattern) { char c2; for (;;) { /* * See if we're at the end of both the pattern and the * string. If, we succeeded. If we're at the end of the * pattern but not at the end of the string, we failed. */ if (*pattern == 0) return (!*string); if (*string == 0 && *pattern != '*') return (0); /* * Check for a "*" as the next pattern character. It matches * any substring. We handle this by calling ourselves * recursively for each postfix of string, until either we * match or we reach the end of the string. */ if (*pattern == '*') { pattern += 1; if (*pattern == 0) return (1); while (*string != 0) { if (Str_Match(string, pattern)) return (1); ++string; } return (0); } /* * Check for a "?" as the next pattern character. It matches * any single character. */ if (*pattern == '?') goto thisCharOK; /* * Check for a "[" as the next pattern character. It is * followed by a list of characters that are acceptable, or * by a range (two characters separated by "-"). */ if (*pattern == '[') { ++pattern; for (;;) { if ((*pattern == ']') || (*pattern == 0)) return (0); if (*pattern == *string) break; if (pattern[1] == '-') { c2 = pattern[2]; if (c2 == 0) return (0); if ((*pattern <= *string) && (c2 >= *string)) break; if ((*pattern >= *string) && (c2 <= *string)) break; pattern += 2; } ++pattern; } while ((*pattern != ']') && (*pattern != 0)) ++pattern; goto thisCharOK; } /* * If the next pattern character is '/', just strip off the * '/' so we do exact matching on the character that follows. */ if (*pattern == '\\') { ++pattern; if (*pattern == 0) return (0); } /* * There's no special character. Just make sure that the * next characters of each string match. */ if (*pattern != *string) return (0); thisCharOK: ++pattern; ++string; } } /** * Str_SYSVMatch * Check word against pattern for a match (% is wild), * * Results: * Returns the beginning position of a match or null. The number * of characters matched is returned in len. */ const char * Str_SYSVMatch(const char *word, const char *pattern, int *len) { const char *m, *p, *w; p = pattern; w = word; if (*w == '\0') { /* Zero-length word cannot be matched against */ *len = 0; return (NULL); } if (*p == '\0') { /* Null pattern is the whole string */ *len = strlen(w); return (w); } if ((m = strchr(p, '%')) != NULL) { /* check that the prefix matches */ for (; p != m && *w && *w == *p; w++, p++) continue; if (p != m) return (NULL); /* No match */ if (*++p == '\0') { /* No more pattern, return the rest of the string */ *len = strlen(w); return (w); } } m = w; /* Find a matching tail */ do if (strcmp(p, w) == 0) { *len = w - m; return (m); } while (*w++ != '\0'); return (NULL); } /** * Str_SYSVSubst * Substitute '%' on the pattern with len characters from src. * If the pattern does not contain a '%' prepend len characters * from src. * * Side Effects: * Places result on buf */ void Str_SYSVSubst(Buffer *buf, const char *pat, const char *src, int len) { const char *m; if ((m = strchr(pat, '%')) != NULL) { /* Copy the prefix */ Buf_AppendRange(buf, pat, m); /* skip the % */ pat = m + 1; } /* Copy the pattern */ Buf_AddBytes(buf, len, (const Byte *)src); /* append the rest */ Buf_Append(buf, pat); } freebsd-buildutils-10.0/src/usr.bin/make/cond.c0000644000000000000000000006426210245121166016273 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)cond.c 8.2 (Berkeley) 1/2/94 */ #include __FBSDID("$FreeBSD$"); /* * Functions to handle conditionals in a makefile. * * Interface: * Cond_Eval Evaluate the conditional in the passed line. */ #include #include #include #include "buf.h" #include "cond.h" #include "dir.h" #include "globals.h" #include "GNode.h" #include "make.h" #include "parse.h" #include "str.h" #include "targ.h" #include "util.h" #include "var.h" /* * The parsing of conditional expressions is based on this grammar: * E -> F || E * E -> F * F -> T && F * F -> T * T -> defined(variable) * T -> make(target) * T -> exists(file) * T -> empty(varspec) * T -> target(name) * T -> symbol * T -> $(varspec) op value * T -> $(varspec) == "string" * T -> $(varspec) != "string" * T -> ( E ) * T -> ! T * op -> == | != | > | < | >= | <= * * 'symbol' is some other symbol to which the default function (condDefProc) * is applied. * * Tokens are scanned from the 'condExpr' string. The scanner (CondToken) * will return And for '&' and '&&', Or for '|' and '||', Not for '!', * LParen for '(', RParen for ')' and will evaluate the other terminal * symbols, using either the default function or the function given in the * terminal, and return the result as either True or False. * * All Non-Terminal functions (CondE, CondF and CondT) return Err on error. */ typedef enum { And, Or, Not, True, False, LParen, RParen, EndOfFile, None, Err } Token; typedef Boolean CondProc(int, char *); /*- * Structures to handle elegantly the different forms of #if's. The * last two fields are stored in condInvert and condDefProc, respectively. */ static void CondPushBack(Token); static int CondGetArg(char **, char **, const char *, Boolean); static CondProc CondDoDefined; static CondProc CondDoMake; static CondProc CondDoExists; static CondProc CondDoTarget; static char *CondCvtArg(char *, double *); static Token CondToken(Boolean); static Token CondT(Boolean); static Token CondF(Boolean); static Token CondE(Boolean); static const struct If { Boolean doNot; /* TRUE if default function should be negated */ CondProc *defProc; /* Default function to apply */ Boolean isElse; /* actually el */ } ifs[] = { [COND_IF] = { FALSE, CondDoDefined, FALSE }, [COND_IFDEF] = { FALSE, CondDoDefined, FALSE }, [COND_IFNDEF] = { TRUE, CondDoDefined, FALSE }, [COND_IFMAKE] = { FALSE, CondDoMake, FALSE }, [COND_IFNMAKE] = { TRUE, CondDoMake, FALSE }, [COND_ELIF] = { FALSE, CondDoDefined, TRUE }, [COND_ELIFDEF] = { FALSE, CondDoDefined, TRUE }, [COND_ELIFNDEF] = { TRUE, CondDoDefined, TRUE }, [COND_ELIFMAKE] = { FALSE, CondDoMake, TRUE }, [COND_ELIFNMAKE] = { TRUE, CondDoMake, TRUE }, }; static Boolean condInvert; /* Invert the default function */ static CondProc *condDefProc; /* default function to apply */ static char *condExpr; /* The expression to parse */ static Token condPushBack = None; /* Single push-back token in parsing */ #define MAXIF 30 /* greatest depth of #if'ing */ static Boolean condStack[MAXIF]; /* Stack of conditionals's values */ static int condLineno[MAXIF]; /* Line numbers of the opening .if */ static int condTop = MAXIF; /* Top-most conditional */ static int skipIfLevel = 0; /* Depth of skipped conditionals */ static int skipIfLineno[MAXIF]; /* Line numbers of skipped .ifs */ Boolean skipLine = FALSE; /* Whether the parse module is skipping * lines */ /** * CondPushBack * Push back the most recent token read. We only need one level of * this, so the thing is just stored in 'condPushback'. * * Side Effects: * condPushback is overwritten. */ static void CondPushBack(Token t) { condPushBack = t; } /** * CondGetArg * Find the argument of a built-in function. parens is set to TRUE * if the arguments are bounded by parens. * * Results: * The length of the argument and the address of the argument. * * Side Effects: * The pointer is set to point to the closing parenthesis of the * function call. */ static int CondGetArg(char **linePtr, char **argPtr, const char *func, Boolean parens) { char *cp; size_t argLen; Buffer *buf; cp = *linePtr; if (parens) { while (*cp != '(' && *cp != '\0') { cp++; } if (*cp == '(') { cp++; } } if (*cp == '\0') { /* * No arguments whatsoever. Because 'make' and 'defined' * aren't really "reserved words", we don't print a message. * I think this is better than hitting the user with a warning * message every time s/he uses the word 'make' or 'defined' * at the beginning of a symbol... */ *argPtr = cp; return (0); } while (*cp == ' ' || *cp == '\t') { cp++; } /* * Create a buffer for the argument and start it out at 16 characters * long. Why 16? Why not? */ buf = Buf_Init(16); while ((strchr(" \t)&|", *cp) == NULL) && (*cp != '\0')) { if (*cp == '$') { /* * Parse the variable spec and install it as part of * the argument if it's valid. We tell Var_Parse to * complain on an undefined variable, so we don't do * it too. Nor do we return an error, though perhaps * we should... */ char *cp2; size_t len = 0; Boolean doFree; cp2 = Var_Parse(cp, VAR_CMD, TRUE, &len, &doFree); Buf_Append(buf, cp2); if (doFree) { free(cp2); } cp += len; } else { Buf_AddByte(buf, (Byte)*cp); cp++; } } Buf_AddByte(buf, (Byte)'\0'); *argPtr = (char *)Buf_GetAll(buf, &argLen); Buf_Destroy(buf, FALSE); while (*cp == ' ' || *cp == '\t') { cp++; } if (parens && *cp != ')') { Parse_Error(PARSE_WARNING, "Missing closing parenthesis for %s()", func); return (0); } else if (parens) { /* * Advance pointer past close parenthesis. */ cp++; } *linePtr = cp; return (argLen); } /** * CondDoDefined * Handle the 'defined' function for conditionals. * * Results: * TRUE if the given variable is defined. */ static Boolean CondDoDefined(int argLen, char *arg) { char savec = arg[argLen]; Boolean result; arg[argLen] = '\0'; if (Var_Value(arg, VAR_CMD) != NULL) { result = TRUE; } else { result = FALSE; } arg[argLen] = savec; return (result); } /** * CondDoMake * Handle the 'make' function for conditionals. * * Results: * TRUE if the given target is being made. */ static Boolean CondDoMake(int argLen, char *arg) { char savec = arg[argLen]; Boolean result; const LstNode *ln; arg[argLen] = '\0'; result = FALSE; LST_FOREACH(ln, &create) { if (Str_Match(Lst_Datum(ln), arg)) { result = TRUE; break; } } arg[argLen] = savec; return (result); } /** * CondDoExists * See if the given file exists. * * Results: * TRUE if the file exists and FALSE if it does not. */ static Boolean CondDoExists(int argLen, char *arg) { char savec = arg[argLen]; Boolean result; char *path; arg[argLen] = '\0'; path = Path_FindFile(arg, &dirSearchPath); if (path != NULL) { result = TRUE; free(path); } else { result = FALSE; } arg[argLen] = savec; return (result); } /** * CondDoTarget * See if the given node exists and is an actual target. * * Results: * TRUE if the node exists as a target and FALSE if it does not. */ static Boolean CondDoTarget(int argLen, char *arg) { char savec = arg[argLen]; Boolean result; GNode *gn; arg[argLen] = '\0'; gn = Targ_FindNode(arg, TARG_NOCREATE); if ((gn != NULL) && !OP_NOP(gn->type)) { result = TRUE; } else { result = FALSE; } arg[argLen] = savec; return (result); } /** * CondCvtArg * Convert the given number into a double. If the number begins * with 0x, it is interpreted as a hexadecimal integer * and converted to a double from there. All other strings just have * strtod called on them. * * Results: * Sets 'value' to double value of string. * Returns address of the first character after the last valid * character of the converted number. * * Side Effects: * Can change 'value' even if string is not a valid number. */ static char * CondCvtArg(char *str, double *value) { if ((*str == '0') && (str[1] == 'x')) { long i; for (str += 2, i = 0; ; str++) { int x; if (isdigit((unsigned char)*str)) x = *str - '0'; else if (isxdigit((unsigned char)*str)) x = 10 + *str - isupper((unsigned char)*str) ? 'A' : 'a'; else { *value = (double)i; return (str); } i = (i << 4) + x; } } else { char *eptr; *value = strtod(str, &eptr); return (eptr); } } /** * CondToken * Return the next token from the input. * * Results: * A Token for the next lexical token in the stream. * * Side Effects: * condPushback will be set back to None if it is used. */ static Token CondToken(Boolean doEval) { Token t; if (condPushBack != None) { t = condPushBack; condPushBack = None; return (t); } while (*condExpr == ' ' || *condExpr == '\t') { condExpr++; } switch (*condExpr) { case '(': t = LParen; condExpr++; break; case ')': t = RParen; condExpr++; break; case '|': if (condExpr[1] == '|') { condExpr++; } condExpr++; t = Or; break; case '&': if (condExpr[1] == '&') { condExpr++; } condExpr++; t = And; break; case '!': t = Not; condExpr++; break; case '\n': case '\0': t = EndOfFile; break; case '$': { char *lhs; const char *op; char *rhs; char zero[] = "0"; size_t varSpecLen = 0; Boolean doFree; /* * Parse the variable spec and skip over it, saving its * value in lhs. */ t = Err; lhs = Var_Parse(condExpr, VAR_CMD, doEval, &varSpecLen, &doFree); if (lhs == var_Error) { /* * Even if !doEval, we still report syntax * errors, which is what getting var_Error * back with !doEval means. */ return (Err); } condExpr += varSpecLen; if (!isspace((unsigned char)*condExpr) && strchr("!=><", *condExpr) == NULL) { Buffer *buf; buf = Buf_Init(0); Buf_Append(buf, lhs); if (doFree) free(lhs); for (;*condExpr && !isspace((unsigned char)*condExpr); condExpr++) Buf_AddByte(buf, (Byte)*condExpr); Buf_AddByte(buf, (Byte)'\0'); lhs = (char *)Buf_GetAll(buf, &varSpecLen); Buf_Destroy(buf, FALSE); doFree = TRUE; } /* * Skip whitespace to get to the operator */ while (isspace((unsigned char)*condExpr)) condExpr++; /* * Make sure the operator is a valid one. If it isn't a * known relational operator, pretend we got a * != 0 comparison. */ op = condExpr; switch (*condExpr) { case '!': case '=': case '<': case '>': if (condExpr[1] == '=') { condExpr += 2; } else { condExpr += 1; } while (isspace((unsigned char)*condExpr)) { condExpr++; } if (*condExpr == '\0') { Parse_Error(PARSE_WARNING, "Missing right-hand-side of operator"); goto error; } rhs = condExpr; break; default: op = "!="; rhs = zero; break; } if (*rhs == '"') { /* * Doing a string comparison. Only allow == and * != for * operators. */ char *string; char *cp, *cp2; int qt; Buffer *buf; do_string_compare: if (((*op != '!') && (*op != '=')) || (op[1] != '=')) { Parse_Error(PARSE_WARNING, "String comparison operator should " "be either == or !="); goto error; } buf = Buf_Init(0); qt = *rhs == '"' ? 1 : 0; for (cp = &rhs[qt]; ((qt && (*cp != '"')) || (!qt && strchr(" \t)", *cp) == NULL)) && (*cp != '\0'); cp++) { if ((*cp == '\\') && (cp[1] != '\0')) { /* * Backslash escapes things -- * skip over next character, * if it exists. */ cp++; Buf_AddByte(buf, (Byte)*cp); } else if (*cp == '$') { size_t len = 0; Boolean freeIt; cp2 = Var_Parse(cp, VAR_CMD, doEval, &len, &freeIt); if (cp2 != var_Error) { Buf_Append(buf, cp2); if (freeIt) { free(cp2); } cp += len - 1; } else { Buf_AddByte(buf, (Byte)*cp); } } else { Buf_AddByte(buf, (Byte)*cp); } } string = Buf_Peel(buf); DEBUGF(COND, ("lhs = \"%s\", rhs = \"%s\", " "op = %.2s\n", lhs, string, op)); /* * Null-terminate rhs and perform the * comparison. t is set to the result. */ if (*op == '=') { t = strcmp(lhs, string) ? False : True; } else { t = strcmp(lhs, string) ? True : False; } free(string); if (rhs == condExpr) { if (*cp == '\0' || (!qt && *cp == ')')) condExpr = cp; else condExpr = cp + 1; } } else { /* * rhs is either a float or an integer. * Convert both the lhs and the rhs to a * double and compare the two. */ double left, right; char *string; if (*CondCvtArg(lhs, &left) != '\0') goto do_string_compare; if (*rhs == '$') { size_t len = 0; Boolean freeIt; string = Var_Parse(rhs, VAR_CMD, doEval, &len, &freeIt); if (string == var_Error) { right = 0.0; } else { if (*CondCvtArg(string, &right) != '\0') { if (freeIt) free(string); goto do_string_compare; } if (freeIt) free(string); if (rhs == condExpr) condExpr += len; } } else { char *c = CondCvtArg(rhs, &right); if (c == rhs) goto do_string_compare; if (rhs == condExpr) { /* * Skip over the right-hand side */ condExpr = c; } } DEBUGF(COND, ("left = %f, right = %f, " "op = %.2s\n", left, right, op)); switch (op[0]) { case '!': if (op[1] != '=') { Parse_Error(PARSE_WARNING, "Unknown operator"); goto error; } t = (left != right ? True : False); break; case '=': if (op[1] != '=') { Parse_Error(PARSE_WARNING, "Unknown operator"); goto error; } t = (left == right ? True : False); break; case '<': if (op[1] == '=') { t = (left <= right?True:False); } else { t = (left < right?True:False); } break; case '>': if (op[1] == '=') { t = (left >= right?True:False); } else { t = (left > right?True:False); } break; default: break; } } error: if (doFree) free(lhs); break; } default: { CondProc *evalProc; Boolean invert = FALSE; char *arg; int arglen; if (strncmp(condExpr, "defined", 7) == 0) { /* * Use CondDoDefined to evaluate the argument * and CondGetArg to extract the argument from * the 'function call'. */ evalProc = CondDoDefined; condExpr += 7; arglen = CondGetArg(&condExpr, &arg, "defined", TRUE); if (arglen == 0) { condExpr -= 7; goto use_default; } } else if (strncmp(condExpr, "make", 4) == 0) { /* * Use CondDoMake to evaluate the argument and * CondGetArg to extract the argument from the * 'function call'. */ evalProc = CondDoMake; condExpr += 4; arglen = CondGetArg(&condExpr, &arg, "make", TRUE); if (arglen == 0) { condExpr -= 4; goto use_default; } } else if (strncmp(condExpr, "exists", 6) == 0) { /* * Use CondDoExists to evaluate the argument and * CondGetArg to extract the argument from the * 'function call'. */ evalProc = CondDoExists; condExpr += 6; arglen = CondGetArg(&condExpr, &arg, "exists", TRUE); if (arglen == 0) { condExpr -= 6; goto use_default; } } else if (strncmp(condExpr, "empty", 5) == 0) { /* * Use Var_Parse to parse the spec in parens and * return True if the resulting string is empty. */ size_t length; Boolean doFree; char *val; condExpr += 5; for (arglen = 0; condExpr[arglen] != '(' && condExpr[arglen] != '\0'; arglen += 1) continue; if (condExpr[arglen] != '\0') { length = 0; val = Var_Parse(&condExpr[arglen - 1], VAR_CMD, FALSE, &length, &doFree); if (val == var_Error) { t = Err; } else { /* * A variable is empty when it * just contains spaces... * 4/15/92, christos */ char *p; for (p = val; *p && isspace((unsigned char)*p); p++) continue; t = (*p == '\0') ? True : False; } if (doFree) { free(val); } /* * Advance condExpr to beyond the * closing ). Note that we subtract * one from arglen + length b/c length * is calculated from * condExpr[arglen - 1]. */ condExpr += arglen + length - 1; } else { condExpr -= 5; goto use_default; } break; } else if (strncmp(condExpr, "target", 6) == 0) { /* * Use CondDoTarget to evaluate the argument and * CondGetArg to extract the argument from the * 'function call'. */ evalProc = CondDoTarget; condExpr += 6; arglen = CondGetArg(&condExpr, &arg, "target", TRUE); if (arglen == 0) { condExpr -= 6; goto use_default; } } else { /* * The symbol is itself the argument to the * default function. We advance condExpr to * the end of the symbol by hand (the next * whitespace, closing paren or binary operator) * and set to invert the evaluation * function if condInvert is TRUE. */ use_default: invert = condInvert; evalProc = condDefProc; arglen = CondGetArg(&condExpr, &arg, "", FALSE); } /* * Evaluate the argument using the set function. If * invert is TRUE, we invert the sense of the function. */ t = (!doEval || (* evalProc) (arglen, arg) ? (invert ? False : True) : (invert ? True : False)); free(arg); break; } } return (t); } /** * CondT * Parse a single term in the expression. This consists of a terminal * symbol or Not and a terminal symbol (not including the binary * operators): * T -> defined(variable) | make(target) | exists(file) | symbol * T -> ! T | ( E ) * * Results: * True, False or Err. * * Side Effects: * Tokens are consumed. */ static Token CondT(Boolean doEval) { Token t; t = CondToken(doEval); if (t == EndOfFile) { /* * If we reached the end of the expression, the expression * is malformed... */ t = Err; } else if (t == LParen) { /* * T -> ( E ) */ t = CondE(doEval); if (t != Err) { if (CondToken(doEval) != RParen) { t = Err; } } } else if (t == Not) { t = CondT(doEval); if (t == True) { t = False; } else if (t == False) { t = True; } } return (t); } /** * CondF -- * Parse a conjunctive factor (nice name, wot?) * F -> T && F | T * * Results: * True, False or Err * * Side Effects: * Tokens are consumed. */ static Token CondF(Boolean doEval) { Token l, o; l = CondT(doEval); if (l != Err) { o = CondToken(doEval); if (o == And) { /* * F -> T && F * * If T is False, the whole thing will be False, but * we have to parse the r.h.s. anyway (to throw it * away). If T is True, the result is the r.h.s., * be it an Err or no. */ if (l == True) { l = CondF(doEval); } else { CondF(FALSE); } } else { /* * F -> T */ CondPushBack(o); } } return (l); } /** * CondE -- * Main expression production. * E -> F || E | F * * Results: * True, False or Err. * * Side Effects: * Tokens are, of course, consumed. */ static Token CondE(Boolean doEval) { Token l, o; l = CondF(doEval); if (l != Err) { o = CondToken(doEval); if (o == Or) { /* * E -> F || E * * A similar thing occurs for ||, except that here we * make sure the l.h.s. is False before we bother to * evaluate the r.h.s. Once again, if l is False, the * result is the r.h.s. and once again if l is True, * we parse the r.h.s. to throw it away. */ if (l == False) { l = CondE(doEval); } else { CondE(FALSE); } } else { /* * E -> F */ CondPushBack(o); } } return (l); } /** * Cond_If * Handle .if and .elif directives. * This function is called even when we're skipping. */ void Cond_If(char *line, int code, int lineno) { const struct If *ifp; Boolean value; ifp = &ifs[code]; if (ifp->isElse) { if (condTop == MAXIF) { Parse_Error(PARSE_FATAL, "if-less elif"); return; } if (skipIfLevel != 0) { /* * If skipping this conditional, just ignore * the whole thing. If we don't, the user * might be employing a variable that's * undefined, for which there's an enclosing * ifdef that we're skipping... */ skipIfLineno[skipIfLevel - 1] = lineno; return; } } else if (skipLine) { /* * Don't even try to evaluate a conditional that's * not an else if we're skipping things... */ skipIfLineno[skipIfLevel] = lineno; skipIfLevel += 1; return; } /* * Initialize file-global variables for parsing */ condDefProc = ifp->defProc; condInvert = ifp->doNot; while (*line == ' ' || *line == '\t') { line++; } condExpr = line; condPushBack = None; switch (CondE(TRUE)) { case True: if (CondToken(TRUE) != EndOfFile) goto err; value = TRUE; break; case False: if (CondToken(TRUE) != EndOfFile) goto err; value = FALSE; break; case Err: err: Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", line); return; default: abort(); } if (!ifp->isElse) { /* push this value */ condTop -= 1; } else if (skipIfLevel != 0 || condStack[condTop]) { /* * If this is an else-type conditional, it should only take * effect if its corresponding if was evaluated and FALSE. * If its if was TRUE or skipped, we return COND_SKIP (and * start skipping in case we weren't already), leaving the * stack unmolested so later elif's don't screw up... */ skipLine = TRUE; return; } if (condTop < 0) { /* * This is the one case where we can definitely proclaim a fatal * error. If we don't, we're hosed. */ Parse_Error(PARSE_FATAL, "Too many nested if's. %d max.",MAXIF); return; } /* push */ condStack[condTop] = value; condLineno[condTop] = lineno; skipLine = !value; } /** * Cond_Else * Handle .else statement. */ void Cond_Else(char *line __unused, int code __unused, int lineno __unused) { while (isspace((u_char)*line)) line++; if (*line != '\0' && (warn_flags & WARN_DIRSYNTAX)) { Parse_Error(PARSE_WARNING, "junk after .else ignored '%s'", line); } if (condTop == MAXIF) { Parse_Error(PARSE_FATAL, "if-less else"); return; } if (skipIfLevel != 0) return; if (skipIfLevel != 0 || condStack[condTop]) { /* * An else should only take effect if its corresponding if was * evaluated and FALSE. * If its if was TRUE or skipped, we return COND_SKIP (and * start skipping in case we weren't already), leaving the * stack unmolested so later elif's don't screw up... * XXX How does this work with two .else's? */ skipLine = TRUE; return; } /* inverse value */ condStack[condTop] = !condStack[condTop]; skipLine = !condStack[condTop]; } /** * Cond_Endif * Handle .endif statement. */ void Cond_Endif(char *line __unused, int code __unused, int lineno __unused) { while (isspace((u_char)*line)) line++; if (*line != '\0' && (warn_flags & WARN_DIRSYNTAX)) { Parse_Error(PARSE_WARNING, "junk after .endif ignored '%s'", line); } /* * End of a conditional section. If skipIfLevel is non-zero, * that conditional was skipped, so lines following it should * also be skipped. Hence, we return COND_SKIP. Otherwise, * the conditional was read so succeeding lines should be * parsed (think about it...) so we return COND_PARSE, unless * this endif isn't paired with a decent if. */ if (skipIfLevel != 0) { skipIfLevel -= 1; return; } if (condTop == MAXIF) { Parse_Error(PARSE_FATAL, "if-less endif"); return; } /* pop */ skipLine = FALSE; condTop += 1; } /** * Cond_End * Make sure everything's clean at the end of a makefile. * * Side Effects: * Parse_Error will be called if open conditionals are around. */ void Cond_End(void) { int level; if (condTop != MAXIF) { Parse_Error(PARSE_FATAL, "%d open conditional%s:", MAXIF - condTop + skipIfLevel, MAXIF - condTop + skipIfLevel== 1 ? "" : "s"); for (level = skipIfLevel; level > 0; level--) Parse_Error(PARSE_FATAL, "\t%*sat line %d (skipped)", MAXIF - condTop + level + 1, "", skipIfLineno[level - 1]); for (level = condTop; level < MAXIF; level++) Parse_Error(PARSE_FATAL, "\t%*sat line %d " "(evaluated to %s)", MAXIF - level + skipIfLevel, "", condLineno[level], condStack[level] ? "true" : "false"); } condTop = MAXIF; } freebsd-buildutils-10.0/src/usr.bin/make/parse.h0000644000000000000000000000654410241065354016470 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef parse_h_470eeb9a #define parse_h_470eeb9a #include #include "util.h" struct GNode; struct Lst; /* * Error levels for parsing. PARSE_FATAL means the process cannot continue * once the makefile has been parsed. PARSE_WARNING means it can. Passed * as the first argument to Parse_Error. */ #define PARSE_WARNING 2 #define PARSE_FATAL 1 /* * Definitions for the "local" variables. Used only for clarity. */ #define TARGET "@" /* Target of dependency */ #define OODATE "?" /* All out-of-date sources */ #define ALLSRC ">" /* All sources */ #define IMPSRC "<" /* Source implied by transformation */ #define PREFIX "*" /* Common prefix */ #define ARCHIVE "!" /* Archive in "archive(member)" syntax */ #define MEMBER "%" /* Member in "archive(member)" syntax */ #define FTARGET "@F" /* file part of TARGET */ #define DTARGET "@D" /* directory part of TARGET */ #define FIMPSRC " #include #include "lst.h" #include "util.h" /** * Lst_Append * Create a new node and add it to the given list after the given node. * * Arguments: * l affected list * ln node after which to append the datum * d said datum * * Side Effects: * A new LstNode is created and linked in to the List. The lastPtr * field of the List will be altered if ln is the last node in the * list. lastPtr and firstPtr will alter if the list was empty and * ln was NULL. */ void Lst_Append(Lst *list, LstNode *ln, void *d) { LstNode *nLNode; nLNode = emalloc(sizeof(*nLNode)); nLNode->datum = d; if (ln == NULL) { nLNode->nextPtr = nLNode->prevPtr = NULL; list->firstPtr = list->lastPtr = nLNode; } else { nLNode->prevPtr = ln; nLNode->nextPtr = ln->nextPtr; ln->nextPtr = nLNode; if (nLNode->nextPtr != NULL) { nLNode->nextPtr->prevPtr = nLNode; } if (ln == list->lastPtr) { list->lastPtr = nLNode; } } } /** * Lst_Concat * Concatenate two lists. New elements are created to hold the data * elements, if specified, but the elements themselves are not copied. * If the elements should be duplicated to avoid confusion with another * list, the Lst_Duplicate function should be called first. * * Arguments: * list1 The list to which list2 is to be appended * list2 The list to append to list1 * flags LST_CONCNEW if LstNode's should be duplicated * LST_CONCLINK if should just be relinked * * Side Effects: * New elements are created and appended the first list. */ void Lst_Concat(Lst *list1, Lst *list2, int flags) { LstNode *ln; /* original LstNode */ LstNode *nln; /* new LstNode */ LstNode *last; /* the last element in the list. Keeps * bookkeeping until the end */ if (list2->firstPtr == NULL) return; if (flags == LST_CONCLINK) { /* * Link the first element of the second list to the last * element of the first list. If the first list isn't empty, * we then link the last element of the list to the first * element of the second list. The last element of the second * list, if it exists, then becomes the last element of the * first list. */ list2->firstPtr->prevPtr = list1->lastPtr; if (list1->lastPtr != NULL) list1->lastPtr->nextPtr = list2->firstPtr; else list1->firstPtr = list2->firstPtr; list1->lastPtr = list2->lastPtr; Lst_Init(list2); } else { /* * The loop simply goes through the entire second list creating * new LstNodes and filling in the nextPtr, and prevPtr to fit * into list1 and its datum field from the datum field of the * corresponding element in list2. The 'last' node follows the * last of the new nodes along until the entire list2 has been * appended. Only then does the bookkeeping catch up with the * changes. During the first iteration of the loop, if 'last' * is NULL, the first list must have been empty so the * newly-created node is made the first node of the list. */ for (last = list1->lastPtr, ln = list2->firstPtr; ln != NULL; ln = ln->nextPtr) { nln = emalloc(sizeof(*nln)); nln->datum = ln->datum; if (last != NULL) { last->nextPtr = nln; } else { list1->firstPtr = nln; } nln->prevPtr = last; last = nln; } /* * Finish bookkeeping. The last new element becomes the last * element of list one. */ list1->lastPtr = last; last->nextPtr = NULL; } } /** * Lst_DeQueue * Remove and return the datum at the head of the given list. * * Results: * The datum in the node at the head or (ick) NULL if the list * is empty. * * Side Effects: * The head node is removed from the list. */ void * Lst_DeQueue(Lst *l) { void *rd; LstNode *tln; tln = Lst_First(l); if (tln == NULL) { return (NULL); } rd = tln->datum; Lst_Remove(l, tln); return (rd); } /** * Lst_Destroy * Destroy a list and free all its resources. If the freeProc is * given, it is called with the datum from each node in turn before * the node is freed. * * Side Effects: * The given list is freed in its entirety. */ void Lst_Destroy(Lst *list, FreeProc *freeProc) { LstNode *ln; if (list->firstPtr == NULL) return; if (freeProc != NOFREE) { while ((ln = list->firstPtr) != NULL) { list->firstPtr = ln->nextPtr; (*freeProc)(ln->datum); free(ln); } } else { while ((ln = list->firstPtr) != NULL) { list->firstPtr = ln->nextPtr; free(ln); } } list->lastPtr = NULL; } /** * Lst_Duplicate * Duplicate an entire list. If a function to copy a void * is * given, the individual client elements will be duplicated as well. * * Arguments: * dst the destination list (initialized) * src the list to duplicate * copyProc A function to duplicate each void */ void Lst_Duplicate(Lst *dst, Lst *src, DuplicateProc *copyProc) { LstNode *ln; ln = src->firstPtr; while (ln != NULL) { if (copyProc != NOCOPY) Lst_AtEnd(dst, (*copyProc)(ln->datum)); else Lst_AtEnd(dst, ln->datum); ln = ln->nextPtr; } } /** * Lst_Insert * Insert a new node with the given piece of data before the given * node in the given list. * * Parameters: * l list to manipulate * ln node before which to insert d * d datum to be inserted * * Side Effects: * the firstPtr field will be changed if ln is the first node in the * list. */ void Lst_Insert(Lst *list, LstNode *ln, void *d) { LstNode *nLNode; /* new lnode for d */ nLNode = emalloc(sizeof(*nLNode)); nLNode->datum = d; if (ln == NULL) { nLNode->prevPtr = nLNode->nextPtr = NULL; list->firstPtr = list->lastPtr = nLNode; } else { nLNode->prevPtr = ln->prevPtr; nLNode->nextPtr = ln; if (nLNode->prevPtr != NULL) { nLNode->prevPtr->nextPtr = nLNode; } ln->prevPtr = nLNode; if (ln == list->firstPtr) { list->firstPtr = nLNode; } } } LstNode * Lst_Member(Lst *list, void *d) { LstNode *lNode; lNode = list->firstPtr; if (lNode == NULL) { return (NULL); } do { if (lNode->datum == d) { return (lNode); } lNode = lNode->nextPtr; } while (lNode != NULL && lNode != list->firstPtr); return (NULL); } /** * Lst_Remove * Remove the given node from the given list. * * Side Effects: * The list's firstPtr will be set to NULL if ln is the last * node on the list. firsPtr and lastPtr will be altered if ln is * either the first or last node, respectively, on the list. */ void Lst_Remove(Lst *list, LstNode *ln) { /* * unlink it from the list */ if (ln->nextPtr != NULL) /* unlink from the backward chain */ ln->nextPtr->prevPtr = ln->prevPtr; else /* this was the last element */ list->lastPtr = ln->prevPtr; if (ln->prevPtr != NULL) /* unlink from the forward chain */ ln->prevPtr->nextPtr = ln->nextPtr; else /* this was the first element */ list->firstPtr = ln->nextPtr; /* * note that the datum is unmolested. The caller must free it as * necessary and as expected. */ free(ln); } freebsd-buildutils-10.0/src/usr.bin/make/arch.h0000644000000000000000000000470710242562677016305 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef arch_h_488adf7a #define arch_h_488adf7a #include "util.h" struct GNode; struct Lst; struct Path; /* archive errors are fatal */ extern Boolean arch_fatal; Boolean Arch_ParseArchive(char **, struct Lst *, struct GNode *); void Arch_Touch(struct GNode *); void Arch_TouchLib(struct GNode *); int Arch_MTime(struct GNode *); int Arch_MemMTime(struct GNode *); void Arch_FindLib(struct GNode *, struct Path *); Boolean Arch_LibOODate(struct GNode *); #endif /* arch_h_488adf7a */ freebsd-buildutils-10.0/src/usr.bin/make/var.h0000644000000000000000000000654710244650337016155 0ustar /*- * Copyright (c) 2002 Juli Mallett. * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef var_h_9cccafce #define var_h_9cccafce struct Buffer; struct GNode; struct List; /* Variables defined in a global context, e.g in the Makefile itself */ extern struct GNode *VAR_GLOBAL; /* Variables defined on the command line */ extern struct GNode *VAR_CMD; /* * Value returned by Var_Parse when an error is encountered. It actually * points to an empty string, so naive callers needn't worry about it. */ extern char var_Error[]; /* * TRUE if environment should be searched for all variables before * the global context */ extern Boolean checkEnvFirst; /* Do old-style variable substitution */ extern Boolean oldVars; void Var_Append(const char *, const char *, struct GNode *); void Var_Delete(const char *, struct GNode *); void Var_Dump(void); Boolean Var_Exists(const char *, struct GNode *); void Var_Init(char **); size_t Var_Match(const char [], struct GNode *); char *Var_Parse(const char *, struct GNode *, Boolean, size_t *, Boolean *); void Var_Print(struct Lst *, Boolean); void Var_Set(const char *, const char *, struct GNode *); void Var_SetGlobal(const char *, const char *); void Var_SetEnv(const char *, struct GNode *); struct Buffer *Var_Subst(const char *, struct GNode *, Boolean); struct Buffer *Var_SubstOnly(const char *, const char *, Boolean); const char *Var_Value(const char [], struct GNode *); #endif /* var_h_9cccafce */ freebsd-buildutils-10.0/src/usr.bin/make/hash_tables.h0000644000000000000000000000276610234447620017637 0ustar /* * Copyright (C) 2005 Max Okumoto. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef hash_tables_h_ #define hash_tables_h_ #include int directive_hash(const u_char *, size_t); int keyword_hash(const u_char *, size_t); #endif freebsd-buildutils-10.0/src/usr.bin/make/job.h0000644000000000000000000000555511126122672016131 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)job.h 8.1 (Berkeley) 6/6/93 * $FreeBSD$ */ #ifndef job_h_4678dfd1 #define job_h_4678dfd1 /*- * job.h -- * Definitions pertaining to the running of jobs in parallel mode. */ #include #include "util.h" struct Buffer; struct GNode; struct Lst; void Job_Touch(struct GNode *, Boolean); Boolean Job_CheckCommands(struct GNode *, void (*abortProc)(const char *, ...)); void Job_CatchChildren(Boolean); void Job_CatchOutput(int flag); void Job_Make(struct GNode *); void Job_Init(int); Boolean Job_Full(void); Boolean Job_Empty(void); void Job_Finish(void); void Job_Wait(void); void Job_AbortAll(void); void Job_SetPrefix(void); void Proc_Init(void); struct Buffer *Cmd_Exec(const char *, const char **); int Compat_Make(struct GNode *gn, struct GNode *pgn); void Compat_InstallSignalHandlers(void); void Compat_Run(struct Lst *); #endif /* job_h_4678dfd1 */ freebsd-buildutils-10.0/src/usr.bin/make/make.10000644000000000000000000013216711761750370016214 0ustar .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)make.1 8.8 (Berkeley) 6/13/95 .\" $FreeBSD$ .\" .Dd May 30, 2012 .Dt MAKE 1 .Os .Sh NAME .Nm make .Nd maintain program dependencies .Sh SYNOPSIS .Nm .Op Fl ABPSXeiknpqrstv .Op Fl C Ar directory .Op Fl D Ar variable .Op Fl d Ar flags .Op Fl E Ar variable .Op Fl f Ar makefile .Op Fl I Ar directory .Bk -words .Op Fl j Ar max_jobs .Op Fl m Ar directory .Ek .Op Fl V Ar variable .Op Fl x Ar warning_options .Op Ar variable Ns No = Ns Ar value .Op Ar target ... .Sh DESCRIPTION The .Nm utility is a program designed to simplify the maintenance of other programs. Its input is a list of specifications describing dependency relationships between the generation of files and programs. .Pp First of all, the initial list of specifications will be read from the system makefile, .Pa sys.mk , unless inhibited with the .Fl r option. The standard .Pa sys.mk as shipped with .Fx also handles .Xr make.conf 5 , the default path to which can be altered via the .Nm variable .Va __MAKE_CONF . .Pp Then the first of .Pa BSDmakefile , .Pa makefile , and .Pa Makefile that can be found in the current directory, object directory (see .Va .OBJDIR ) , or search path (see the .Fl I option) will be read for the main list of dependency specifications. A different makefile or list of them can be supplied via the .Fl f option(s). Finally, if the file .Pa .depend can be found in any of the aforesaid locations, it will also be read (see .Xr mkdep 1 ) . .Pp When .Nm searches for a makefile, its name takes precedence over its location. For instance, .Pa BSDmakefile in the object directory will be favored over .Pa Makefile in the current directory. .Pp The options are as follows: .Bl -tag -width Ds .It Fl A Make archive errors non-fatal, causing .Nm to just skip the remainder or all of the archive and continue after printing a message. .It Fl B Try to be backwards compatible by executing a single shell per command and by executing the commands to make the sources of a dependency line in sequence. This is turned on by default unless .Fl j is used. .It Fl C Ar directory Change to .Ar directory before reading the makefiles or doing anything else. If multiple .Fl C options are specified, each is interpreted relative to the previous one: .Fl C Pa / Fl C Pa etc is equivalent to .Fl C Pa /etc . .It Fl D Ar variable Define .Ar variable to be 1, in the global context. .It Fl d Ar flags Turn on debugging, and specify which portions of .Nm are to print debugging information. Argument .Ar flags is one or more of the following: .Bl -tag -width Ds .It Ar A Print all possible debugging information; equivalent to specifying all of the debugging flags. .It Ar a Print debugging information about archive searching and caching. .It Ar c Print debugging information about conditional evaluation. .It Ar d Print debugging information about directory searching and caching. .It Ar f Print debugging information about the execution of for loops. .It Ar "g1" Print the input graph before making anything. .It Ar "g2" Print the input graph after making everything, or before exiting on error. .It Ar j Print debugging information about running multiple shells. .It Ar l Print commands in Makefiles regardless of whether or not they are prefixed by @ or other "quiet" flags. Also known as "loud" behavior. .It Ar m Print debugging information about making targets, including modification dates. .It Ar s Print debugging information about suffix-transformation rules. .It Ar t Print debugging information about target list maintenance. .It Ar v Print debugging information about variable assignment. .El .It Fl E Ar variable Specify a variable whose environment value (if any) will override macro assignments within makefiles. .It Fl e Specify that environment values override macro assignments within makefiles for all variables. .It Fl f Ar makefile Specify a makefile to read instead of the default one. If .Ar makefile is not an absolute pathname, .Nm will search for it as described above. In case .Ar makefile is .Sq Fl , standard input is read. Multiple .Fl f options can be supplied, and the makefiles will be read in that order. Unlike the other command-line options, .Fl f is neither stored in .Va .MAKEFLAGS nor pushed down to sub-makes via .Ev MAKEFLAGS . See below for more details on these variables. .It Fl I Ar directory Specify a directory in which to search for makefiles and included makefiles. Multiple .Fl I options can be specified to form a search path. The system makefile directory (or directories, see the .Fl m option) is automatically appended at the tail of this path. .It Fl i Ignore non-zero exit of shell commands in the makefile. Equivalent to specifying .Sq Ic \- before each command line in the makefile. .It Fl j Ar max_jobs Specify the maximum number of jobs that .Nm may have running at any one time. Turns compatibility mode off, unless the .Fl B flag is also specified. .It Fl k Continue processing after errors are encountered, but only on those targets that do not depend on the target whose creation caused the error. .It Fl m Ar directory Specify a directory in which to search for the system makefile and makefiles included via the <...> style. Multiple .Fl m options can be specified to form a search path. This path will override the default system include path, .Pa /usr/share/mk . The system include path will always be appended to the search path used for "..."-style inclusions and makefile searches (see the .Fl I option). .Pp If a file or directory name in the .Fl m argument (or the .Ev MAKESYSPATH environment variable) starts with the string .Qq \&.../ then .Nm will search for the specified file or directory named in the remaining part of the argument string. The search starts with the current directory of the Makefile and then works upward towards the root of the filesystem. If the search is successful, then the resulting directory replaces the .Qq \&.../ specification in the .Fl m argument. If used, this feature allows .Nm to easily search in the current source tree for customized sys.mk files (e.g. by using .Qq \&.../mk/sys.mk as an argument). Note that a .Fl C that are earlier on the command line affect where .Fl m Qq \&.../ searches. .It Fl n Display the commands that would have been executed, but do not actually execute them. .It Fl P Collate the output of a given job and display it only when the job finishes, instead of mixing the output of parallel jobs together. This option has no effect unless .Fl j is used too. .It Fl p Only print the input graph, not executing any commands. The output is the same as .Fl d Ar g1 . When combined with .Fl f Pa /dev/null , only the builtin rules of .Nm are displayed. .It Fl Q Be extra quiet. For multi-job makes, this will cause file banners not to be generated. .It Fl q Do not execute any commands, but exit 0 if the specified targets are up-to-date and 1, otherwise. .It Fl r Do not process the system makefile. .It Fl S Stop processing when an error is encountered. Default behaviour. This is needed to negate the .Fl k option during recursive builds. .It Fl s Do not echo any commands as they are executed. Equivalent to specifying .Sq Ic @ before each command line in the makefile. .It Fl t Rather than re-building a target as specified in the makefile, create it or update its modification time to make it appear up-to-date. .It Fl V Ar variable Print .Nm Ns 's idea of the value of .Ar variable , in the global context. Do not build any targets. Multiple instances of this option may be specified; the variables will be printed one per line, with a blank line for each null or undefined variable. If .Ar variable contains a .Sq Ic $ then the value will be expanded before printing. .It Fl v Be extra verbose. Print any extra information. .It Fl X When using the .Fl V option to print the values of variables, do not recursively expand the values. .It Ar variable Ns No = Ns Ar value Set the value of the variable .Ar variable to .Ar value . .It Fl x Ar warning_options Specify extended warning options. This option may be specified several times. A .Ar warning_option can be prefixed with .Dq Li no in which case the warning is switched off. The currently available options are: .Bl -tag -width indent .It Li dirsyntax Warn if anything except blanks and comments follows an .Ic .endif or .Ic .else directive. .El .Pp See also the .Ic .WARN special target. .El .Pp There are seven different types of lines in a makefile: file dependency specifications, shell commands, variable assignments, include statements, conditional directives, for loops, and comments. .Pp In general, lines may be continued from one line to the next by ending them with a backslash .Pq Ql \e . The trailing newline character and initial whitespace on the following line are compressed into a single space. .Sh FILE DEPENDENCY SPECIFICATIONS Dependency lines consist of one or more targets, an operator, and zero or more sources. This creates a relationship where the targets .Dq depend on the sources and are usually created from them. The exact relationship between the target and the source is determined by the operator that separates them. The three operators are as follows: .Bl -tag -width flag .It Ic \&: A target is considered out-of-date if its modification time is less than those of any of its sources. Sources for a target accumulate over dependency lines when this operator is used. The target is removed if .Nm is interrupted. .It Ic \&! Targets are always re-created, but not until all sources have been examined and re-created as necessary. Sources for a target accumulate over dependency lines when this operator is used. The target is removed if .Nm is interrupted. .It Ic :: If no sources are specified, the target is always re-created. Otherwise, a target is considered out-of-date if any of its sources has been modified more recently than the target. Sources for a target do not accumulate over dependency lines when this operator is used. The target will not be removed if .Nm is interrupted. .El .Pp Targets and sources may contain the shell wildcard expressions .Ql \&? , .Ql * , .Ql [] and .Ql {} . The expressions .Ql \&? , .Ql * and .Ql [] may only be used as part of the final component of the target or source, and must be used to describe existing files. The expression .Ql {} need not necessarily be used to describe existing files. Expansion is in directory order, not alphabetically as done in the shell. .Sh SHELL COMMANDS Each target may have associated with it a series of shell commands, normally used to create the target. Each of the commands in this script .Em must be preceded by a tab. While any target may appear on a dependency line, only one of these dependencies may be followed by a creation script, unless the .Sq Ic :: operator is used. .Pp If the first characters of the command line are .Sq Ic @ , .Sq Ic \- , and/or .Sq Ic + , the command is treated specially. A .Sq Ic @ causes the command not to be echoed before it is executed. A .Sq Ic \- causes any non-zero exit status of the command line to be ignored. A .Sq Ic + causes the command to be executed even if .Fl n is specified on the command line. .Sh VARIABLE ASSIGNMENTS Variables in .Nm are much like variables in the shell, and, by tradition, consist of all upper-case letters. The five operators that can be used to assign values to variables are as follows: .Bl -tag -width Ds .It Ic = Assign the value to the variable. Any previous value is overridden. .It Ic += Append the value to the current value of the variable. .It Ic ?= Assign the value to the variable if it is not already defined. .It Ic := Assign with expansion, i.e., expand the value before assigning it to the variable. Normally, expansion is not done until the variable is referenced. .It Ic != Expand the value and pass it to the shell for execution and assign the result to the variable. Any newlines in the result are replaced with spaces. .El .Pp Any whitespace before the assigned .Ar value is removed; if the value is being appended, a single space is inserted between the previous contents of the variable and the appended value. .Pp Variables are expanded by surrounding the variable name with either curly braces .Pq Ql {} or parentheses .Pq Ql () and preceding it with a dollar sign .Pq Ql $ . If the variable name contains only a single letter, the surrounding braces or parentheses are not required. This shorter form is not recommended. .Pp Variable substitution occurs at two distinct times, depending on where the variable is being used. Variables in dependency lines are expanded as the line is read. Variables in shell commands are expanded when the shell command is executed. .Pp The four different classes of variables (in order of increasing precedence) are: .Bl -tag -width Ds .It Environment variables Variables defined as part of .Nm Ns 's environment. .It Global variables Variables defined in the makefile or in included makefiles. .It Command line variables Variables defined as part of the command line and variables obtained from the .Ev MAKEFLAGS environment variable or the .Ic .MAKEFLAGS target. .It Local variables Variables that are defined specific to a certain target. .El .Pp If the name of an environment variable appears in a makefile on the left-hand side of an assignment, a global variable with the same name is created, and the latter shadows the former as per their relative precedences. The environment is not changed in this case, and the change is not exported to programs executed by .Nm . However, a command-line variable actually replaces the environment variable of the same name if the latter exists, which is visible to child programs. .Pp There are seven local variables in .Nm : .Bl -tag -width ".ARCHIVE" .It Va .ALLSRC The list of all sources for this target; also known as .Sq Va > . .It Va .ARCHIVE The name of the archive file; also known as .Sq Va \&! . .It Va .IMPSRC The name/path of the source from which the target is to be transformed (the .Dq implied source); also known as .Sq Va < . .It Va .MEMBER The name of the archive member; also known as .Sq Va % . .It Va .OODATE The list of sources for this target that were deemed out-of-date; also known as .Sq Va \&? . .It Va .PREFIX The file prefix of the file, containing only the file portion, no suffix or preceding directory components; also known as .Sq Va * . .It Va .TARGET The name of the target; also known as .Sq Va @ . .El .Pp The shorter forms .Sq Va @ , .Sq Va \&! , .Sq Va < , .Sq Va % , .Sq Va \&? , .Sq Va > , and .Sq Va * are permitted for backward compatibility and are not recommended. The six variables .Sq Va @F , .Sq Va @D , .Sq Va .It Ic .include Ar \*qfile\*q Include the specified makefile. Variables between the angle brackets or double quotes are expanded to form the file name. If angle brackets are used, the included makefile is expected to be in the system makefile directory. If double quotes are used, the including makefile's directory and any directories specified using the .Fl I option are searched before the system makefile directory. .It Ic .sinclude Ar .It Ic .sinclude Ar \*qfile\*q Like .Ic .include , but silently ignored if the file cannot be found and opened. .It Ic .undef Ar variable Un-define the specified global variable. Only global variables may be un-defined. .It Ic .error Ar message Terminate processing of the makefile immediately. The filename of the makefile, the line on which the error was encountered and the specified message are printed to the standard error output and .Nm terminates with exit code 1. Variables in the message are expanded. .It Ic .warning Ar message Emit a warning message. The filename of the makefile, the line on which the warning was encountered, and the specified message are printed to the standard error output. Variables in the message are expanded. .El .Pp Conditionals are used to determine which parts of the Makefile to process. They are used similarly to the conditionals supported by the C pre-processor. The following conditionals are supported: .Bl -tag -width Ds .It Xo .Ic .if .Oo \&! Oc Ns Ar expression .Op Ar operator expression ... .Xc Test the value of an expression. .It Xo .Ic .ifdef .Oo \&! Oc Ns Ar variable .Op Ar operator variable ... .Xc Test the value of a variable. .It Xo .Ic .ifndef .Oo \&! Oc Ns Ar variable .Op Ar operator variable ... .Xc Test the value of a variable. .It Xo .Ic .ifmake .Oo \&! Oc Ns Ar target .Op Ar operator target ... .Xc Test the target being built. .It Xo .Ic .ifnmake .Oo \&! Oc Ns Ar target .Op Ar operator target ... .Xc Test the target being built. .It Ic .else Reverse the sense of the last conditional. .It Xo .Ic .elif .Oo \&! Oc Ns Ar expression .Op Ar operator expression ... .Xc A combination of .Ic .else followed by .Ic .if . .It Xo .Ic .elifdef .Oo \&! Oc Ns Ar variable .Op Ar operator variable ... .Xc A combination of .Ic .else followed by .Ic .ifdef . .It Xo .Ic .elifndef .Oo \&! Oc Ns Ar variable .Op Ar operator variable ... .Xc A combination of .Ic .else followed by .Ic .ifndef . .It Xo .Ic .elifmake .Oo \&! Oc Ns Ar target .Op Ar operator target ... .Xc A combination of .Ic .else followed by .Ic .ifmake . .It Xo .Ic .elifnmake .Oo \&! Oc Ns Ar target .Op Ar operator target ... .Xc A combination of .Ic .else followed by .Ic .ifnmake . .It Ic .endif End the body of the conditional. .El .Pp The .Ar operator may be any one of the following: .Bl -tag -width "Cm XX" .It Cm || Logical .Tn OR .It Cm && Logical .Tn AND ; of higher precedence than .Sq Ic || . .El .Pp As in C, .Nm will only evaluate a conditional as far as is necessary to determine its value. Parentheses may be used to change the order of evaluation. The boolean operator .Sq Ic !\& may be used to logically negate an entire conditional. It is of higher precedence than .Sq Ic && . .Pp The value of .Ar expression may be any of the following: .Bl -tag -width Ic .It Ic defined Takes a variable name as an argument and evaluates to true if the variable has been defined. .It Ic make Takes a target name as an argument and evaluates to true if the target was specified as part of .Nm Ns 's command line or was declared the default target (either implicitly or explicitly, see .Va .MAIN ) before the line containing the conditional. .It Ic empty Takes a variable, with possible modifiers, and evaluates to true if the expansion of the variable would result in an empty string. .It Ic exists Takes a file name as an argument and evaluates to true if the file exists. The file is searched for on the system search path (see .Va .PATH ) . .It Ic target Takes a target name as an argument and evaluates to true if the target has been defined. .El .Pp An .Ar expression may also be a numeric or string comparison: in this case, the left-hand side .Ar must be a variable expansion, whereas the right-hand side can be a constant or a variable expansion. Variable expansion is performed on both sides, after which the resulting values are compared. A value is interpreted as hexadecimal if it is preceded by 0x, otherwise it is decimal; octal numbers are not supported. .Pp String comparison can only use the .Sq Ic == or .Sq Ic != operators, whereas numeric values (both integer and floating point) can also be compared using the .Sq Ic > , .Sq Ic >= , .Sq Ic < and .Sq Ic <= operators. .Pp If no relational operator (and right-hand value) are given, an implicit .Sq Ic != 0 is used. However be very careful in using this feature especially when the left-hand side variable expansion returns a string. .Pp When .Nm is evaluating one of these conditional expressions, and it encounters a word it does not recognize, either the .Dq make or .Dq defined expression is applied to it, depending on the form of the conditional. If the form is .Ic .if , .Ic .ifdef or .Ic .ifndef , the .Dq defined expression is applied. Similarly, if the form is .Ic .ifmake or .Ic .ifnmake , the .Dq make expression is applied. .Pp If the conditional evaluates to true the parsing of the makefile continues as before. If it evaluates to false, the following lines are skipped. In both cases this continues until a .Ic .else or .Ic .endif is found. .Pp For loops are typically used to apply a set of rules to a list of files. The syntax of a for loop is: .Pp .Bl -tag -width indent -compact .It Ic .for Ar variable Ic in Ar expression .It .It Ic .endfor .El .Pp After the for .Ar expression is evaluated, it is split into words. The iteration .Ar variable is successively set to each word, and substituted in the .Ic make-rules inside the body of the for loop. .Sh COMMENTS Comments begin with a hash .Pq Ql # character, anywhere but in a shell command line, and continue to the end of the line. .Sh SPECIAL SOURCES .Bl -tag -width Ic .It Ic .IGNORE Ignore any errors from the commands associated with this target, exactly as if they all were preceded by a dash .Pq Ql \- . .It Ic .MAKE Execute the commands associated with this target even if the .Fl n or .Fl t options were specified. Normally used to mark recursive .Nm Ns 's . .It Ic .NOTMAIN Normally .Nm selects the first target it encounters as the default target to be built if no target was specified. This source prevents this target from being selected. .It Ic .OPTIONAL If a target is marked with this attribute and .Nm cannot figure out how to create it, it will ignore this fact and assume the file is not needed or already exists. .It Ic .PRECIOUS When .Nm is interrupted, it removes any partially made targets. This source prevents the target from being removed. .It Ic .SILENT Do not echo any of the commands associated with this target, exactly as if they all were preceded by an at sign .Pq Ql @ . .It Ic .USE Turn the target into .Nm Ns 's version of a macro. When the target is used as a source for another target, the other target acquires the commands, sources, and attributes (except for .Ic .USE ) of the source. If the target already has commands, the .Ic .USE target's commands are appended to them. .It Ic .WAIT If special .Ic .WAIT source appears in a dependency line, the sources that precede it are made before the sources that succeed it in the line. Loops are not being detected and targets that form loops will be silently ignored. .El .Sh SPECIAL TARGETS Special targets may not be included with other targets, i.e., they must be the only target specified. .Bl -tag -width Ic .It Ic .BEGIN Any command lines attached to this target are executed before anything else is done. .It Ic .DEFAULT This is sort of a .Ic .USE rule for any target (that was used only as a source) that .Nm cannot figure out any other way to create. Only the shell script is used. The .Ic .IMPSRC variable of a target that inherits .Ic .DEFAULT Ns 's commands is set to the target's own name. .It Ic .END Any command lines attached to this target are executed after everything else is done. .It Ic .IGNORE Mark each of the sources with the .Ic .IGNORE attribute. If no sources are specified, this is the equivalent of specifying the .Fl i option. .It Ic .INCLUDES A list of suffixes that indicate files that can be included in a source file. The suffix must have already been declared with .Ic .SUFFIXES ; any suffix so declared will have the directories on its search path (see .Ic .PATH ) placed in the .Va .INCLUDES special variable, each preceded by a .Fl I flag. .It Ic .INTERRUPT If .Nm is interrupted, the commands for this target will be executed. .It Ic .LIBS This does for libraries what .Ic .INCLUDES does for include files, except that the flag used is .Fl L . .It Ic .MAIN If no target is specified when .Nm is invoked, this target will be built. This is always set, either explicitly, or implicitly when .Nm selects the default target, to give the user a way to refer to the default target on the command line. .It Ic .MAKEFILEDEPS Enable the .Dq Remaking Makefiles functionality, as explained in the .Sx REMAKING MAKEFILES section below. .It Ic .MAKEFLAGS This target provides a way to specify flags for .Nm when the makefile is used. The flags are as if typed to the shell, though the .Fl f option will have no effect. Flags (except for .Fl f ) and variable assignments specified as the source for this target are also appended to the .Va .MAKEFLAGS internal variable. Please note the difference between this target and the .Va .MAKEFLAGS internal variable: specifying an option or variable assignment as the source for this target will affect .Em both the current makefile and all processes that .Nm executes. .It Ic .MFLAGS Same as above, for backward compatibility. .\" XXX: NOT YET!!!! .\" .It Ic .NOTPARALLEL .\" The named targets are executed in non parallel mode. If no targets are .\" specified, then all targets are executed in non parallel mode. .It Ic .NOTPARALLEL Disable parallel mode. .It Ic .NO_PARALLEL Same as above, for compatibility with other .Nm pmake variants. .It Ic .ORDER The named targets are made in sequence. .\" XXX: NOT YET!!!! .\" .It Ic .PARALLEL .\" The named targets are executed in parallel mode. If no targets are .\" specified, then all targets are executed in parallel mode. .It Ic .PATH The sources are directories which are to be searched for files not found in the current directory. If no sources are specified, any previously specified directories are deleted. Where possible, use of .Ic .PATH is preferred over use of the .Va VPATH variable. .It Ic .PATH\fIsuffix\fR The sources are directories which are to be searched for suffixed files not found in the current directory. The .Nm utility first searches the suffixed search path, before reverting to the default path if the file is not found there. This form is required for .Ic .LIBS and .Ic .INCLUDES to work. .It Ic .PHONY Apply the .Ic .PHONY attribute to any specified sources. Targets with this attribute are always considered to be out of date. .It Ic .POSIX Adjust .Nm Ap s behavior to match the applicable .Tn POSIX specifications. (Note this disables the .Dq Remaking Makefiles feature.) .It Ic .PRECIOUS Apply the .Ic .PRECIOUS attribute to any specified sources. If no sources are specified, the .Ic .PRECIOUS attribute is applied to every target in the file. .It Ic .SHELL Select another shell. The sources of this target have the format .Ar key Ns = Ns Ar value . The .Ar key is one of: .Bl -tag -width ".Va hasErrCtl" .It Va path Specify the path to the new shell. .It Va name Specify the name of the new shell. This may be either one of the three builtin shells (see below) or any other name. .It Va quiet Specify the shell command to turn echoing off. .It Va echo Specify the shell command to turn echoing on. .It Va filter Usually shells print the echo off command before turning echoing off. This is the exact string that will be printed by the shell and is used to filter the shell output to remove the echo off command. .It Va echoFlag The shell option that turns echoing on. .It Va errFlag The shell option to turn on error checking. If error checking is on, the shell should exit if a command returns a non-zero status. .It Va hasErrCtl True if the shell has error control. .It Va check If .Va hasErrCtl is true then this is the shell command to turn error checking on. If .Va hasErrCtl is false then this is a command template to echo commands for which error checking is disabled. The template must contain a .Ql %s . .It Va ignore If .Va hasErrCtl is true, this is the shell command to turn error checking off. If .Va hasErrCtl is false, this is a command template to execute a command so that errors are ignored. The template must contain a .Ql %s . .It Va meta This is a string of meta characters of the shell. .It Va builtins This is a string holding all the shell's builtin commands separated by blanks. The .Va meta and .Va builtins strings are used in compat mode. When a command line contains neither a meta character nor starts with a shell builtin, it is executed directly without invoking a shell. When one of these strings (or both) is empty all commands are executed through a shell. .It Va unsetenv If true, remove the .Ev ENV environment variable before executing any command. This is useful for the Korn-shell .Pq Nm ksh . .El .Pp Values that are strings must be surrounded by double quotes. Boolean values are specified as .Ql T or .Ql Y (in either case) to mean true. Any other value is taken to mean false. .Pp There are several uses of the .Ic .SHELL target: .Bl -bullet .It Selecting one of the builtin shells. This is done by just specifying the name of the shell with the .Va name keyword. It is also possible to modify the parameters of the builtin shell by just specifying other keywords (except for .Va path ) . .It Using another executable for one of the builtin shells. This is done by specifying the path to the executable with the .Va path keyword. If the last component is the same as the name of the builtin shell, no name needs to be specified; if it is different, the name must be given: .Bd -literal -offset indent \&.SHELL: path="/usr/local/bin/sh" .Ed .Pp selects the builtin shell .Dq Li sh but will execute it from .Pa /usr/local/bin/sh . Like in the previous case, it is possible to modify parameters of the builtin shell by just specifying them. .It Using an entirely different shell. This is done by specifying all keywords. .El .Pp The builtin shells are .Dq Li sh , .Dq Li csh and .Dq Li ksh . Because .Fx has no .Nm ksh in .Pa /bin , it is unwise to specify .Va name Ns = Ns Qq Li ksh without also specifying a path. .It Ic .SILENT Apply the .Ic .SILENT attribute to any specified sources. If no sources are specified, the .Ic .SILENT attribute is applied to every command in the file. .It Ic .SUFFIXES Each source specifies a suffix to .Nm . If no sources are specified, any previous specified suffixes are deleted. .It Ic .WARN Each source specifies a warning flag as previously described for the .Fl x command line option. Warning flags specified on the command line take precedence over flags specified in the makefile. Also, command line warning flags are pushed to sub-makes through the .Ev MAKEFLAGS environment variables so that a warning flag specified on the command line will influence all sub-makes. Several flags can be specified on a single .Ic .WARN target by separating them with blanks. .El .Sh REMAKING MAKEFILES If the special target .Ic .MAKEFILEDEPS exists in the Makefile, .Nm enables the .Dq Remaking Makefiles feature. After reading Makefile and all the files that are included using .Ic .include or .Ic .sinclude directives (source Makefiles) .Nm considers each source Makefile as a target and tries to rebuild it. Both explicit and implicit rules are checked and all source Makefiles are updated if necessary. If any of the source Makefiles were rebuilt, .Nm restarts from clean state. .Pp To prevent infinite loops the following source Makefile targets are ignored: .Bl -bullet .It .Ic :: targets that have no prerequisites .It .Ic \&! targets .It targets that have .Ic .PHONY or .Ic .EXEC attributes .It targets without prerequisites and without commands .El .Pp When remaking a source Makefile options .Ic -t (touch target), .Ic -q (query mode), and .Ic -n (no exec) do not take effect, unless source Makefile is specified explicitly as a target in .Nm command line. .Pp Additionally, system makefiles and .Ic .depend are not considered as Makefiles that can be rebuilt. .Sh ENVIRONMENT The .Nm utility uses the following environment variables, if they exist: .Ev MACHINE , .Ev MAKE , .Ev MAKEFLAGS , .Ev MAKEOBJDIR , .Ev MAKEOBJDIRPREFIX , and .Ev MAKESYSPATH . .Sh FILES .Bl -tag -width /usr/share/doc/psd/12.make -compact .It Pa .depend list of dependencies .It Pa Makefile list of dependencies .It Pa makefile list of dependencies .It Pa obj object directory .It Pa sys.mk system makefile .It Pa /usr/share/mk default system makefile directory .It Pa /usr/share/doc/psd/12.make PMake tutorial .It Pa /usr/obj default .Ev MAKEOBJDIRPREFIX directory. .It Pa /etc/make.conf default path to .Xr make.conf 5 .El .Sh EXAMPLES List all included makefiles in order visited: .Pp .Dl "make -V .MAKEFILE_LIST | tr \e\ \e\en" .Sh COMPATIBILITY Older versions of .Nm used .Ev MAKE instead of .Ev MAKEFLAGS . This was removed for .Tn POSIX compatibility. The internal variable .Va MAKE is set to the same value as .Va .MAKE ; support for this may be removed in the future. .Pp The use of the .Cm :L and .Cm :U modifiers are deprecated in .Fx 10.0 and the more portable (among Pmake decedents) .Cm :tl and .Cm :tu should be used instead. .Pp Most of the more esoteric features of .Nm should probably be avoided for greater compatibility. .Sh SEE ALSO .Xr mkdep 1 , .Xr make.conf 5 .Rs .%T "PMake - A Tutorial" .Re in .Pa /usr/share/doc/psd/12.make .Sh HISTORY A .Nm command appeared in PWB UNIX. .Sh BUGS The determination of .Va .OBJDIR is contorted to the point of absurdity. .Pp In the presence of several .Ic .MAIN special targets, .Nm silently ignores all but the first. .Pp .Va .TARGETS is not set to the default target when .Nm is invoked without a target name and no .Ic .MAIN special target exists. .Pp The evaluation of .Ar expression in a test is very simple-minded. Currently, the only form that works is .Ql .if ${VAR} op something . For instance, you should write tests as .Ql .if ${VAR} == "string" not the other way around, which would give you an error. .Pp For loops are expanded before tests, so a fragment such as: .Bd -literal -offset indent \&.for ARCH in ${SHARED_ARCHS} \&.if ${ARCH} == ${MACHINE} ... \&.endif \&.endfor .Ed .Pp will not work, and should be rewritten as: .Bd -literal -offset indent \&.for ARCH in ${SHARED_ARCHS} \&.if ${MACHINE} == ${ARCH} ... \&.endif \&.endfor .Ed .Pp The parsing code is broken with respect to handling a semicolon after a colon, so a fragment like this will fail: .Bd -literal -offset indent HDRS= foo.h bar.h all: \&.for h in ${HDRS:S;^;${.CURDIR}/;} ... \&.endfor .Ed .Pp A trailing backslash in a variable value defined on the command line causes the delimiting space in the .Ev MAKEFLAGS environment variable to be preceded by that backslash. That causes a submake to not treat that space as a word delimiter. Fixing this requires a larger rewrite of the code handling command line macros and assignments to .Va .MAKEFLAGS . freebsd-buildutils-10.0/src/usr.bin/make/targ.c0000644000000000000000000002640711310551642016304 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)targ.c 8.2 (Berkeley) 3/19/94 */ #include __FBSDID("$FreeBSD$"); /* * Functions for maintaining the Lst allTargets. Target nodes are * kept in two structures: a Lst, maintained by the list library, and a * hash table, maintained by the hash library. * * Interface: * Targ_Init Initialization procedure. * * Targ_NewGN Create a new GNode for the passed target (string). * The node is *not* placed in the hash table, though all * its fields are initialized. * * Targ_FindNode Find the node for a given target, creating and storing * it if it doesn't exist and the flags are right * (TARG_CREATE) * * Targ_FindList Given a list of names, find nodes for all of them. If a * name doesn't exist and the TARG_NOCREATE flag was given, * an error message is printed. Else, if a name doesn't * exist, its node is created. * * Targ_Ignore Return TRUE if errors should be ignored when creating * the given target. * * Targ_Silent Return TRUE if we should be silent when creating the * given target. * * Targ_Precious Return TRUE if the target is precious and should not * be removed if we are interrupted. * * Debugging: * Targ_PrintGraph Print out the entire graphm all variables and statistics * for the directory cache. Should print something for * suffixes, too, but... */ #include #include "dir.h" #include "globals.h" #include "GNode.h" #include "hash.h" #include "suff.h" #include "targ.h" #include "util.h" #include "var.h" /* the list of all targets found so far */ static Lst allTargets = Lst_Initializer(allTargets); static Hash_Table targets; /* a hash table of same */ #define HTSIZE 191 /* initial size of hash table */ /** * Targ_Init * Initialize this module * * Side Effects: * The allTargets list and the targets hash table are initialized */ void Targ_Init(void) { Hash_InitTable(&targets, HTSIZE); } /** * Targ_NewGN * Create and initialize a new graph node * * Results: * An initialized graph node with the name field filled with a copy * of the passed name * * Side Effects: * The gnode is added to the list of all gnodes. */ GNode * Targ_NewGN(const char *name) { GNode *gn; gn = emalloc(sizeof(GNode)); gn->name = estrdup(name); gn->path = NULL; if (name[0] == '-' && name[1] == 'l') { gn->type = OP_LIB; } else { gn->type = 0; } gn->unmade = 0; gn->make = FALSE; gn->made = UNMADE; gn->childMade = FALSE; gn->order = 0; gn->mtime = gn->cmtime = 0; gn->cmtime_gn = NULL; Lst_Init(&gn->iParents); Lst_Init(&gn->cohorts); Lst_Init(&gn->parents); Lst_Init(&gn->children); Lst_Init(&gn->successors); Lst_Init(&gn->preds); Lst_Init(&gn->context); Lst_Init(&gn->commands); gn->suffix = NULL; return (gn); } /** * Targ_FindNode * Find a node in the list using the given name for matching * * Results: * The node in the list if it was. If it wasn't, return NULL of * flags was TARG_NOCREATE or the newly created and initialized node * if it was TARG_CREATE * * Side Effects: * Sometimes a node is created and added to the list */ GNode * Targ_FindNode(const char *name, int flags) { GNode *gn; /* node in that element */ Hash_Entry *he; /* New or used hash entry for node */ Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */ /* an entry for the node */ if (flags & TARG_CREATE) { he = Hash_CreateEntry(&targets, name, &isNew); if (isNew) { gn = Targ_NewGN(name); Hash_SetValue(he, gn); Lst_AtEnd(&allTargets, gn); } } else { he = Hash_FindEntry(&targets, name); } if (he == NULL) { return (NULL); } else { return (Hash_GetValue(he)); } } /** * Targ_FindList * Make a complete list of GNodes from the given list of names * * Results: * A complete list of graph nodes corresponding to all instances of all * the names in names. * * Side Effects: * If flags is TARG_CREATE, nodes will be created for all names in * names which do not yet have graph nodes. If flags is TARG_NOCREATE, * an error message will be printed for each name which can't be found. */ void Targ_FindList(Lst *nodes, Lst *names, int flags) { LstNode *ln; /* name list element */ GNode *gn; /* node in tLn */ char *name; for (ln = Lst_First(names); ln != NULL; ln = Lst_Succ(ln)) { name = Lst_Datum(ln); gn = Targ_FindNode(name, flags); if (gn != NULL) { /* * Note: Lst_AtEnd must come before the Lst_Concat so * the nodes are added to the list in the order in which * they were encountered in the makefile. */ Lst_AtEnd(nodes, gn); if (gn->type & OP_DOUBLEDEP) { Lst_Concat(nodes, &gn->cohorts, LST_CONCNEW); } } else if (flags == TARG_NOCREATE) { Error("\"%s\" -- target unknown.", name); } } } /** * Targ_Ignore * Return true if should ignore errors when creating gn * * Results: * TRUE if should ignore errors */ Boolean Targ_Ignore(GNode *gn) { if (ignoreErrors || (gn->type & OP_IGNORE)) { return (TRUE); } else { return (FALSE); } } /** * Targ_Silent * Return true if be silent when creating gn * * Results: * TRUE if should be silent */ Boolean Targ_Silent(GNode *gn) { if (beSilent || (gn->type & OP_SILENT)) { return (TRUE); } else { return (FALSE); } } /** * Targ_Precious * See if the given target is precious * * Results: * TRUE if it is precious. FALSE otherwise */ Boolean Targ_Precious(GNode *gn) { if (allPrecious || (gn->type & (OP_PRECIOUS | OP_DOUBLEDEP))) { return (TRUE); } else { return (FALSE); } } static GNode *mainTarg; /* the main target, as set by Targ_SetMain */ /** * Targ_SetMain * Set our idea of the main target we'll be creating. Used for * debugging output. * * Side Effects: * "mainTarg" is set to the main target's node. */ void Targ_SetMain(GNode *gn) { mainTarg = gn; } /** * Targ_FmtTime * Format a modification time in some reasonable way and return it. * * Results: * The time reformatted. * * Side Effects: * The time is placed in a static area, so it is overwritten * with each call. */ char * Targ_FmtTime(time_t modtime) { struct tm *parts; static char buf[128]; parts = localtime(&modtime); strftime(buf, sizeof(buf), "%H:%M:%S %b %d, %Y", parts); buf[sizeof(buf) - 1] = '\0'; return (buf); } /** * Targ_PrintType * Print out a type field giving only those attributes the user can * set. */ void Targ_PrintType(int type) { static const struct flag2str type2str[] = { { OP_OPTIONAL, ".OPTIONAL" }, { OP_USE, ".USE" }, { OP_EXEC, ".EXEC" }, { OP_IGNORE, ".IGNORE" }, { OP_PRECIOUS, ".PRECIOUS" }, { OP_SILENT, ".SILENT" }, { OP_MAKE, ".MAKE" }, { OP_JOIN, ".JOIN" }, { OP_INVISIBLE, ".INVISIBLE" }, { OP_NOTMAIN, ".NOTMAIN" }, { OP_PHONY, ".PHONY" }, { OP_LIB, ".LIB" }, { OP_MEMBER, ".MEMBER" }, { OP_ARCHV, ".ARCHV" }, { 0, NULL } }; type &= ~OP_OPMASK; if (!DEBUG(TARG)) type &= ~(OP_ARCHV | OP_LIB | OP_MEMBER); print_flags(stdout, type2str, type, 0); } /** * TargPrintNode * print the contents of a node */ static int TargPrintNode(const GNode *gn, int pass) { const LstNode *tln; if (!OP_NOP(gn->type)) { printf("#\n"); if (gn == mainTarg) { printf("# *** MAIN TARGET ***\n"); } if (pass == 2) { if (gn->unmade) { printf("# %d unmade children\n", gn->unmade); } else { printf("# No unmade children\n"); } if (!(gn->type & (OP_JOIN | OP_USE | OP_EXEC))) { if (gn->mtime != 0) { printf("# last modified %s: %s\n", Targ_FmtTime(gn->mtime), gn->made == UNMADE ? "unmade" : gn->made == MADE ? "made" : gn->made == UPTODATE ? "up-to-date": "error when made"); } else if (gn->made != UNMADE) { printf("# non-existent (maybe): %s\n", gn->made == MADE ? "made" : gn->made == UPTODATE ? "up-to-date": gn->made == ERROR?"error when made": "aborted"); } else { printf("# unmade\n"); } } if (!Lst_IsEmpty(&gn->iParents)) { printf("# implicit parents: "); LST_FOREACH(tln, &gn->iParents) printf("%s ", ((const GNode *) Lst_Datum(tln))->name); printf("\n"); } } if (!Lst_IsEmpty(&gn->parents)) { printf("# parents: "); LST_FOREACH(tln, &gn->parents) printf("%s ", ((const GNode *) Lst_Datum(tln))->name); printf("\n"); } printf("%-16s", gn->name); switch (gn->type & OP_OPMASK) { case OP_DEPENDS: printf(": "); break; case OP_FORCE: printf("! "); break; case OP_DOUBLEDEP: printf(":: "); break; default: break; } Targ_PrintType(gn->type); LST_FOREACH(tln, &gn->children) printf("%s ", ((const GNode *)Lst_Datum(tln))->name); printf("\n"); LST_FOREACH(tln, &gn->commands) printf("\t%s\n", (const char *)Lst_Datum(tln)); printf("\n\n"); if (gn->type & OP_DOUBLEDEP) { LST_FOREACH(tln, &gn->cohorts) TargPrintNode((const GNode *)Lst_Datum(tln), pass); } } return (0); } /** * Targ_PrintGraph * Print the entire graph. */ void Targ_PrintGraph(int pass) { const GNode *gn; const LstNode *tln; printf("#*** Input graph:\n"); LST_FOREACH(tln, &allTargets) TargPrintNode((const GNode *)Lst_Datum(tln), pass); printf("\n\n"); printf("#\n# Files that are only sources:\n"); LST_FOREACH(tln, &allTargets) { gn = Lst_Datum(tln); if (OP_NOP(gn->type)) printf("#\t%s [%s]\n", gn->name, gn->path ? gn->path : gn->name); } Var_Dump(); printf("\n"); Dir_PrintDirectories(); printf("\n"); Suff_PrintAll(); } freebsd-buildutils-10.0/src/usr.bin/make/buf.h0000644000000000000000000000711410241065354016124 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)buf.h 8.2 (Berkeley) 4/28/95 * $FreeBSD$ */ #ifndef buf_h_a61a6812 #define buf_h_a61a6812 /*- * buf.h -- * Header for users of the buf library. */ #include #include "util.h" /* * There are several places where expandable buffers are used (parse.c and * var.c). This constant is merely the starting point for those buffers. If * lines tend to be much shorter than this, it would be best to reduce BSIZE. * If longer, it should be increased. Reducing it will cause more copying to * be done for longer lines, but will save space for shorter ones. In any * case, it ought to be a power of two simply because most storage allocation * schemes allocate in powers of two. */ #define MAKE_BSIZE 256 /* starting size for expandable buffers */ #define BUF_DEF_SIZE 256 /* Default buffer size */ #define BUF_ADD_INC 256 /* Expansion increment when Adding */ typedef char Byte; typedef struct Buffer { size_t size; /* Current size of the buffer */ Byte *buf; /* The buffer itself */ Byte *end; /* Place to write to */ } Buffer; void Buf_AddByte(Buffer *, Byte); void Buf_AddBytes(Buffer *, size_t, const Byte *); void Buf_Append(Buffer *, const char []); void Buf_AppendBuf(Buffer *, const Buffer *); void Buf_AppendRange(Buffer *, const char [], const char *); void Buf_Clear(Buffer *); char *Buf_Data(const Buffer *); void Buf_Destroy(Buffer *, Boolean); Byte *Buf_GetAll(Buffer *, size_t *); Buffer *Buf_Init(size_t); char *Buf_Peel(Buffer *); void Buf_ReplaceLastByte(Buffer *, Byte); size_t Buf_Size(const Buffer *); void Buf_StripNewlines(Buffer *); #endif /* buf_h_a61a6812 */ freebsd-buildutils-10.0/src/usr.bin/make/Makefile.dist0000644000000000000000000000043510763157637017617 0ustar # $FreeBSD$ # a simple makefile to help builds on !FreeBSD systems pmake: @echo 'make started.' cc -D__dead2="" -D__unused="" -Darc4random=random -D__FBSDID="static const char *id=" -DDEFSHELLNAME=\"sh\" -I. -c *.c cc *.o -o pmake @echo 'make completed.' clean: @rm -f *.o pmake freebsd-buildutils-10.0/src/usr.bin/make/dir.c0000644000000000000000000010576211320435022016121 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)dir.c 8.2 (Berkeley) 1/2/94 */ #include __FBSDID("$FreeBSD$"); /*- * dir.c -- * Directory searching using wildcards and/or normal names... * Used both for source wildcarding in the Makefile and for finding * implicit sources. * * The interface for this module is: * Dir_Init Initialize the module. * * Dir_HasWildcards Returns TRUE if the name given it needs to * be wildcard-expanded. * * Path_Expand Given a pattern and a path, return a Lst of names * which match the pattern on the search path. * * Path_FindFile Searches for a file on a given search path. * If it exists, the entire path is returned. * Otherwise NULL is returned. * * Dir_FindHereOrAbove Search for a path in the current directory and * then all the directories above it in turn until * the path is found or we reach the root ("/"). * * Dir_MTime Return the modification time of a node. The file * is searched for along the default search path. * The path and mtime fields of the node are filled in. * * Path_AddDir Add a directory to a search path. * * Dir_MakeFlags Given a search path and a command flag, create * a string with each of the directories in the path * preceded by the command flag and all of them * separated by a space. * * Dir_Destroy Destroy an element of a search path. Frees up all * things that can be freed for the element as long * as the element is no longer referenced by any other * search path. * * Dir_ClearPath Resets a search path to the empty list. * * For debugging: * Dir_PrintDirectories Print stats about the directory cache. */ #include #include #include #include #include #include #include #include "arch.h" #include "dir.h" #include "globals.h" #include "GNode.h" #include "hash.h" #include "lst.h" #include "str.h" #include "targ.h" #include "util.h" /* * A search path consists of a list of Dir structures. A Dir structure * has in it the name of the directory and a hash table of all the files * in the directory. This is used to cut down on the number of system * calls necessary to find implicit dependents and their like. Since * these searches are made before any actions are taken, we need not * worry about the directory changing due to creation commands. If this * hampers the style of some makefiles, they must be changed. * * A list of all previously-read directories is kept in the * openDirectories list. This list is checked first before a directory * is opened. * * The need for the caching of whole directories is brought about by * the multi-level transformation code in suff.c, which tends to search * for far more files than regular make does. In the initial * implementation, the amount of time spent performing "stat" calls was * truly astronomical. The problem with hashing at the start is, * of course, that pmake doesn't then detect changes to these directories * during the course of the make. Three possibilities suggest themselves: * * 1) just use stat to test for a file's existence. As mentioned * above, this is very inefficient due to the number of checks * engendered by the multi-level transformation code. * 2) use readdir() and company to search the directories, keeping * them open between checks. I have tried this and while it * didn't slow down the process too much, it could severely * affect the amount of parallelism available as each directory * open would take another file descriptor out of play for * handling I/O for another job. Given that it is only recently * that UNIX OS's have taken to allowing more than 20 or 32 * file descriptors for a process, this doesn't seem acceptable * to me. * 3) record the mtime of the directory in the Dir structure and * verify the directory hasn't changed since the contents were * hashed. This will catch the creation or deletion of files, * but not the updating of files. However, since it is the * creation and deletion that is the problem, this could be * a good thing to do. Unfortunately, if the directory (say ".") * were fairly large and changed fairly frequently, the constant * rehashing could seriously degrade performance. It might be * good in such cases to keep track of the number of rehashes * and if the number goes over a (small) limit, resort to using * stat in its place. * * An additional thing to consider is that pmake is used primarily * to create C programs and until recently pcc-based compilers refused * to allow you to specify where the resulting object file should be * placed. This forced all objects to be created in the current * directory. This isn't meant as a full excuse, just an explanation of * some of the reasons for the caching used here. * * One more note: the location of a target's file is only performed * on the downward traversal of the graph and then only for terminal * nodes in the graph. This could be construed as wrong in some cases, * but prevents inadvertent modification of files when the "installed" * directory for a file is provided in the search path. * * Another data structure maintained by this module is an mtime * cache used when the searching of cached directories fails to find * a file. In the past, Path_FindFile would simply perform an access() * call in such a case to determine if the file could be found using * just the name given. When this hit, however, all that was gained * was the knowledge that the file existed. Given that an access() is * essentially a stat() without the copyout() call, and that the same * filesystem overhead would have to be incurred in Dir_MTime, it made * sense to replace the access() with a stat() and record the mtime * in a cache for when Dir_MTime was actually called. */ typedef struct Dir { char *name; /* Name of directory */ int refCount; /* No. of paths with this directory */ int hits; /* No. of times a file has been found here */ Hash_Table files; /* Hash table of files in directory */ TAILQ_ENTRY(Dir) link; /* allDirs link */ } Dir; /* * A path is a list of pointers to directories. These directories are * reference counted so a directory can be on more than one path. */ struct PathElement { struct Dir *dir; /* pointer to the directory */ TAILQ_ENTRY(PathElement) link; /* path link */ }; /* main search path */ struct Path dirSearchPath = TAILQ_HEAD_INITIALIZER(dirSearchPath); /* the list of all open directories */ static TAILQ_HEAD(, Dir) openDirectories = TAILQ_HEAD_INITIALIZER(openDirectories); /* * Variables for gathering statistics on the efficiency of the hashing * mechanism. */ static int hits; /* Found in directory cache */ static int misses; /* Sad, but not evil misses */ static int nearmisses; /* Found under search path */ static int bigmisses; /* Sought by itself */ static Dir *dot; /* contents of current directory */ /* Results of doing a last-resort stat in Path_FindFile -- * if we have to go to the system to find the file, we might as well * have its mtime on record. * XXX: If this is done way early, there's a chance other rules will * have already updated the file, in which case we'll update it again. * Generally, there won't be two rules to update a single file, so this * should be ok, but... */ static Hash_Table mtimes; /*- *----------------------------------------------------------------------- * Dir_Init -- * initialize things for this module * * Results: * none * * Side Effects: * none *----------------------------------------------------------------------- */ void Dir_Init(void) { Hash_InitTable(&mtimes, 0); } /*- *----------------------------------------------------------------------- * Dir_InitDot -- * initialize the "." directory * * Results: * none * * Side Effects: * some directories may be opened. *----------------------------------------------------------------------- */ void Dir_InitDot(void) { dot = Path_AddDir(NULL, "."); if (dot == NULL) err(1, "cannot open current directory"); /* * We always need to have dot around, so we increment its * reference count to make sure it's not destroyed. */ dot->refCount += 1; } /*- *----------------------------------------------------------------------- * Dir_HasWildcards -- * See if the given name has any wildcard characters in it. * * Results: * returns TRUE if the word should be expanded, FALSE otherwise * * Side Effects: * none *----------------------------------------------------------------------- */ Boolean Dir_HasWildcards(const char *name) { const char *cp; int wild = 0, brace = 0, bracket = 0; for (cp = name; *cp; cp++) { switch (*cp) { case '{': brace++; wild = 1; break; case '}': brace--; break; case '[': bracket++; wild = 1; break; case ']': bracket--; break; case '?': case '*': wild = 1; break; default: break; } } return (wild && bracket == 0 && brace == 0); } /*- *----------------------------------------------------------------------- * DirMatchFiles -- * Given a pattern and a Dir structure, see if any files * match the pattern and add their names to the 'expansions' list if * any do. This is incomplete -- it doesn't take care of patterns like * src / *src / *.c properly (just *.c on any of the directories), but it * will do for now. * * Results: * Always returns 0 * * Side Effects: * File names are added to the expansions lst. The directory will be * fully hashed when this is done. *----------------------------------------------------------------------- */ static int DirMatchFiles(const char *pattern, const Dir *p, Lst *expansions) { Hash_Search search; /* Index into the directory's table */ Hash_Entry *entry; /* Current entry in the table */ Boolean isDot; /* TRUE if the directory being searched is . */ isDot = (*p->name == '.' && p->name[1] == '\0'); for (entry = Hash_EnumFirst(&p->files, &search); entry != NULL; entry = Hash_EnumNext(&search)) { /* * See if the file matches the given pattern. Note we follow * the UNIX convention that dot files will only be found if * the pattern begins with a dot (note also that as a side * effect of the hashing scheme, .* won't match . or .. * since they aren't hashed). */ if (Str_Match(entry->name, pattern) && ((entry->name[0] != '.') || (pattern[0] == '.'))) { Lst_AtEnd(expansions, (isDot ? estrdup(entry->name) : str_concat(p->name, entry->name, STR_ADDSLASH))); } } return (0); } /*- *----------------------------------------------------------------------- * DirExpandCurly -- * Expand curly braces like the C shell. Does this recursively. * Note the special case: if after the piece of the curly brace is * done there are no wildcard characters in the result, the result is * placed on the list WITHOUT CHECKING FOR ITS EXISTENCE. The * given arguments are the entire word to expand, the first curly * brace in the word, the search path, and the list to store the * expansions in. * * Results: * None. * * Side Effects: * The given list is filled with the expansions... * *----------------------------------------------------------------------- */ static void DirExpandCurly(const char *word, const char *brace, struct Path *path, Lst *expansions) { const char *end; /* Character after the closing brace */ const char *cp; /* Current position in brace clause */ const char *start; /* Start of current piece of brace clause */ int bracelevel; /* Number of braces we've seen. If we see a right brace * when this is 0, we've hit the end of the clause. */ char *file; /* Current expansion */ int otherLen; /* The length of the other pieces of the expansion * (chars before and after the clause in 'word') */ char *cp2; /* Pointer for checking for wildcards in * expansion before calling Dir_Expand */ start = brace + 1; /* * Find the end of the brace clause first, being wary of nested brace * clauses. */ for (end = start, bracelevel = 0; *end != '\0'; end++) { if (*end == '{') bracelevel++; else if ((*end == '}') && (bracelevel-- == 0)) break; } if (*end == '\0') { Error("Unterminated {} clause \"%s\"", start); return; } else end++; otherLen = brace - word + strlen(end); for (cp = start; cp < end; cp++) { /* * Find the end of this piece of the clause. */ bracelevel = 0; while (*cp != ',') { if (*cp == '{') bracelevel++; else if ((*cp == '}') && (bracelevel-- <= 0)) break; cp++; } /* * Allocate room for the combination and install the * three pieces. */ file = emalloc(otherLen + cp - start + 1); if (brace != word) strncpy(file, word, brace - word); if (cp != start) strncpy(&file[brace - word], start, cp - start); strcpy(&file[(brace - word) + (cp - start)], end); /* * See if the result has any wildcards in it. If we find one, * call Dir_Expand right away, telling it to place the result * on our list of expansions. */ for (cp2 = file; *cp2 != '\0'; cp2++) { switch (*cp2) { case '*': case '?': case '{': case '[': Path_Expand(file, path, expansions); goto next; default: break; } } if (*cp2 == '\0') { /* * Hit the end w/o finding any wildcards, so stick * the expansion on the end of the list. */ Lst_AtEnd(expansions, file); } else { next: free(file); } start = cp + 1; } } /*- *----------------------------------------------------------------------- * DirExpandInt -- * Internal expand routine. Passes through the directories in the * path one by one, calling DirMatchFiles for each. NOTE: This still * doesn't handle patterns in directories... Works given a word to * expand, a path to look in, and a list to store expansions in. * * Results: * None. * * Side Effects: * Things are added to the expansions list. * *----------------------------------------------------------------------- */ static void DirExpandInt(const char *word, const struct Path *path, Lst *expansions) { struct PathElement *pe; TAILQ_FOREACH(pe, path, link) DirMatchFiles(word, pe->dir, expansions); } /*- *----------------------------------------------------------------------- * Dir_Expand -- * Expand the given word into a list of words by globbing it looking * in the directories on the given search path. * * Results: * A list of words consisting of the files which exist along the search * path matching the given pattern is placed in expansions. * * Side Effects: * Directories may be opened. Who knows? *----------------------------------------------------------------------- */ void Path_Expand(char *word, struct Path *path, Lst *expansions) { LstNode *ln; char *cp; DEBUGF(DIR, ("expanding \"%s\"...", word)); cp = strchr(word, '{'); if (cp != NULL) DirExpandCurly(word, cp, path, expansions); else { cp = strchr(word, '/'); if (cp != NULL) { /* * The thing has a directory component -- find the * first wildcard in the string. */ for (cp = word; *cp != '\0'; cp++) { if (*cp == '?' || *cp == '[' || *cp == '*' || *cp == '{') { break; } } if (*cp == '{') { /* * This one will be fun. */ DirExpandCurly(word, cp, path, expansions); return; } else if (*cp != '\0') { /* * Back up to the start of the component */ char *dirpath; while (cp > word && *cp != '/') cp--; if (cp != word) { char sc; /* * If the glob isn't in the first * component, try and find all the * components up to the one with a * wildcard. */ sc = cp[1]; cp[1] = '\0'; dirpath = Path_FindFile(word, path); cp[1] = sc; /* * dirpath is null if can't find the * leading component * XXX: Path_FindFile won't find internal * components. i.e. if the path contains * ../Etc/Object and we're looking for * Etc, * it won't be found. Ah well. * Probably not important. */ if (dirpath != NULL) { char *dp = &dirpath[strlen(dirpath) - 1]; struct Path tp = TAILQ_HEAD_INITIALIZER(tp); if (*dp == '/') *dp = '\0'; Path_AddDir(&tp, dirpath); DirExpandInt(cp + 1, &tp, expansions); Path_Clear(&tp); } } else { /* * Start the search from the local * directory */ DirExpandInt(word, path, expansions); } } else { /* * Return the file -- this should never happen. */ DirExpandInt(word, path, expansions); } } else { /* * First the files in dot */ DirMatchFiles(word, dot, expansions); /* * Then the files in every other directory on the path. */ DirExpandInt(word, path, expansions); } } if (DEBUG(DIR)) { LST_FOREACH(ln, expansions) DEBUGF(DIR, ("%s ", (const char *)Lst_Datum(ln))); DEBUGF(DIR, ("\n")); } } /** * Path_FindFile * Find the file with the given name along the given search path. * * Results: * The path to the file or NULL. This path is guaranteed to be in a * different part of memory than name and so may be safely free'd. * * Side Effects: * If the file is found in a directory which is not on the path * already (either 'name' is absolute or it is a relative path * [ dir1/.../dirn/file ] which exists below one of the directories * already on the search path), its directory is added to the end * of the path on the assumption that there will be more files in * that directory later on. Sometimes this is true. Sometimes not. */ char * Path_FindFile(char *name, struct Path *path) { char *p1; /* pointer into p->name */ char *p2; /* pointer into name */ char *file; /* the current filename to check */ const struct PathElement *pe; /* current path member */ char *cp; /* final component of the name */ Boolean hasSlash; /* true if 'name' contains a / */ struct stat stb; /* Buffer for stat, if necessary */ Hash_Entry *entry; /* Entry for mtimes table */ /* * Find the final component of the name and note whether it has a * slash in it (the name, I mean) */ cp = strrchr(name, '/'); if (cp != NULL) { hasSlash = TRUE; cp += 1; } else { hasSlash = FALSE; cp = name; } DEBUGF(DIR, ("Searching for %s...", name)); /* * No matter what, we always look for the file in the current directory * before anywhere else and we *do not* add the ./ to it if it exists. * This is so there are no conflicts between what the user specifies * (fish.c) and what pmake finds (./fish.c). */ if ((!hasSlash || (cp - name == 2 && *name == '.')) && (Hash_FindEntry(&dot->files, cp) != NULL)) { DEBUGF(DIR, ("in '.'\n")); hits += 1; dot->hits += 1; return (estrdup(name)); } /* * We look through all the directories on the path seeking one which * contains the final component of the given name and whose final * component(s) match the name's initial component(s). If such a beast * is found, we concatenate the directory name and the final component * and return the resulting string. If we don't find any such thing, * we go on to phase two... */ TAILQ_FOREACH(pe, path, link) { DEBUGF(DIR, ("%s...", pe->dir->name)); if (Hash_FindEntry(&pe->dir->files, cp) != NULL) { DEBUGF(DIR, ("here...")); if (hasSlash) { /* * If the name had a slash, its initial * components and p's final components must * match. This is false if a mismatch is * encountered before all of the initial * components have been checked (p2 > name at * the end of the loop), or we matched only * part of one of the components of p * along with all the rest of them (*p1 != '/'). */ p1 = pe->dir->name + strlen(pe->dir->name) - 1; p2 = cp - 2; while (p2 >= name && p1 >= pe->dir->name && *p1 == *p2) { p1 -= 1; p2 -= 1; } if (p2 >= name || (p1 >= pe->dir->name && *p1 != '/')) { DEBUGF(DIR, ("component mismatch -- " "continuing...")); continue; } } file = str_concat(pe->dir->name, cp, STR_ADDSLASH); DEBUGF(DIR, ("returning %s\n", file)); pe->dir->hits += 1; hits += 1; return (file); } else if (hasSlash) { /* * If the file has a leading path component and that * component exactly matches the entire name of the * current search directory, we assume the file * doesn't exist and return NULL. */ for (p1 = pe->dir->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) continue; if (*p1 == '\0' && p2 == cp - 1) { if (*cp == '\0' || ISDOT(cp) || ISDOTDOT(cp)) { DEBUGF(DIR, ("returning %s\n", name)); return (estrdup(name)); } else { DEBUGF(DIR, ("must be here but isn't --" " returning NULL\n")); return (NULL); } } } } /* * We didn't find the file on any existing members of the directory. * If the name doesn't contain a slash, that means it doesn't exist. * If it *does* contain a slash, however, there is still hope: it * could be in a subdirectory of one of the members of the search * path. (eg. /usr/include and sys/types.h. The above search would * fail to turn up types.h in /usr/include, but it *is* in * /usr/include/sys/types.h) If we find such a beast, we assume there * will be more (what else can we assume?) and add all but the last * component of the resulting name onto the search path (at the * end). This phase is only performed if the file is *not* absolute. */ if (!hasSlash) { DEBUGF(DIR, ("failed.\n")); misses += 1; return (NULL); } if (*name != '/') { Boolean checkedDot = FALSE; DEBUGF(DIR, ("failed. Trying subdirectories...")); TAILQ_FOREACH(pe, path, link) { if (pe->dir != dot) { file = str_concat(pe->dir->name, name, STR_ADDSLASH); } else { /* * Checking in dot -- DON'T put a leading ./ * on the thing. */ file = estrdup(name); checkedDot = TRUE; } DEBUGF(DIR, ("checking %s...", file)); if (stat(file, &stb) == 0) { DEBUGF(DIR, ("got it.\n")); /* * We've found another directory to search. We * know there's a slash in 'file' because we put * one there. We nuke it after finding it and * call Path_AddDir to add this new directory * onto the existing search path. Once that's * done, we restore the slash and triumphantly * return the file name, knowing that should a * file in this directory every be referenced * again in such a manner, we will find it * without having to do numerous numbers of * access calls. Hurrah! */ cp = strrchr(file, '/'); *cp = '\0'; Path_AddDir(path, file); *cp = '/'; /* * Save the modification time so if * it's needed, we don't have to fetch it again. */ DEBUGF(DIR, ("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime), file)); entry = Hash_CreateEntry(&mtimes, file, (Boolean *)NULL); Hash_SetValue(entry, (void *)(long)stb.st_mtime); nearmisses += 1; return (file); } else { free(file); } } DEBUGF(DIR, ("failed. ")); if (checkedDot) { /* * Already checked by the given name, since . was in * the path, so no point in proceeding... */ DEBUGF(DIR, ("Checked . already, returning NULL\n")); return (NULL); } } /* * Didn't find it that way, either. Sigh. Phase 3. Add its directory * onto the search path in any case, just in case, then look for the * thing in the hash table. If we find it, grand. We return a new * copy of the name. Otherwise we sadly return a NULL pointer. Sigh. * Note that if the directory holding the file doesn't exist, this will * do an extra search of the final directory on the path. Unless * something weird happens, this search won't succeed and life will * be groovy. * * Sigh. We cannot add the directory onto the search path because * of this amusing case: * $(INSTALLDIR)/$(FILE): $(FILE) * * $(FILE) exists in $(INSTALLDIR) but not in the current one. * When searching for $(FILE), we will find it in $(INSTALLDIR) * b/c we added it here. This is not good... */ DEBUGF(DIR, ("Looking for \"%s\"...", name)); bigmisses += 1; entry = Hash_FindEntry(&mtimes, name); if (entry != NULL) { DEBUGF(DIR, ("got it (in mtime cache)\n")); return (estrdup(name)); } else if (stat (name, &stb) == 0) { entry = Hash_CreateEntry(&mtimes, name, (Boolean *)NULL); DEBUGF(DIR, ("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime), name)); Hash_SetValue(entry, (void *)(long)stb.st_mtime); return (estrdup(name)); } else { DEBUGF(DIR, ("failed. Returning NULL\n")); return (NULL); } } /*- *----------------------------------------------------------------------- * Dir_FindHereOrAbove -- * search for a path starting at a given directory and then working * our way up towards the root. * * Input: * here starting directory * search_path the path we are looking for * result the result of a successful search is placed here * rlen the length of the result buffer * (typically MAXPATHLEN + 1) * * Results: * 0 on failure, 1 on success [in which case the found path is put * in the result buffer]. * * Side Effects: *----------------------------------------------------------------------- */ int Dir_FindHereOrAbove(char *here, char *search_path, char *result, int rlen) { struct stat st; char dirbase[MAXPATHLEN + 1], *db_end; char try[MAXPATHLEN + 1], *try_end; /* copy out our starting point */ snprintf(dirbase, sizeof(dirbase), "%s", here); db_end = dirbase + strlen(dirbase); /* loop until we determine a result */ while (1) { /* try and stat(2) it ... */ snprintf(try, sizeof(try), "%s/%s", dirbase, search_path); if (stat(try, &st) != -1) { /* * Success! If we found a file, chop off * the filename so we return a directory. */ if ((st.st_mode & S_IFMT) != S_IFDIR) { try_end = try + strlen(try); while (try_end > try && *try_end != '/') try_end--; if (try_end > try) *try_end = 0; /* chop! */ } /* * Done! */ snprintf(result, rlen, "%s", try); return(1); } /* * Nope, we didn't find it. If we used up dirbase we've * reached the root and failed. */ if (db_end == dirbase) break; /* Failed! */ /* * truncate dirbase from the end to move up a dir */ while (db_end > dirbase && *db_end != '/') db_end--; *db_end = 0; /* chop! */ } /* while (1) */ /* * We failed... */ return(0); } /*- *----------------------------------------------------------------------- * Dir_MTime -- * Find the modification time of the file described by gn along the * search path dirSearchPath. * * Results: * The modification time or 0 if it doesn't exist * * Side Effects: * The modification time is placed in the node's mtime slot. * If the node didn't have a path entry before, and Path_FindFile * found one for it, the full name is placed in the path slot. *----------------------------------------------------------------------- */ int Dir_MTime(GNode *gn) { char *fullName; /* the full pathname of name */ struct stat stb; /* buffer for finding the mod time */ Hash_Entry *entry; if (gn->type & OP_ARCHV) return (Arch_MTime(gn)); else if (gn->path == NULL) fullName = Path_FindFile(gn->name, &dirSearchPath); else fullName = gn->path; if (fullName == NULL) fullName = estrdup(gn->name); entry = Hash_FindEntry(&mtimes, fullName); if (entry != NULL) { /* * Only do this once -- the second time folks are checking to * see if the file was actually updated, so we need to * actually go to the filesystem. */ DEBUGF(DIR, ("Using cached time %s for %s\n", Targ_FmtTime((time_t)(long)Hash_GetValue(entry)), fullName)); stb.st_mtime = (time_t)(long)Hash_GetValue(entry); Hash_DeleteEntry(&mtimes, entry); } else if (stat(fullName, &stb) < 0) { if (gn->type & OP_MEMBER) { if (fullName != gn->path) free(fullName); return (Arch_MemMTime(gn)); } else { stb.st_mtime = 0; } } if (fullName && gn->path == (char *)NULL) gn->path = fullName; gn->mtime = stb.st_mtime; return (gn->mtime); } /*- *----------------------------------------------------------------------- * Path_AddDir -- * Add the given name to the end of the given path. * * Results: * none * * Side Effects: * A structure is added to the list and the directory is * read and hashed. *----------------------------------------------------------------------- */ struct Dir * Path_AddDir(struct Path *path, const char *name) { Dir *d; /* pointer to new Path structure */ DIR *dir; /* for reading directory */ struct PathElement *pe; struct dirent *dp; /* entry in directory */ /* check whether we know this directory */ TAILQ_FOREACH(d, &openDirectories, link) { if (strcmp(d->name, name) == 0) { /* Found it. */ if (path == NULL) return (d); /* Check whether its already on the path. */ TAILQ_FOREACH(pe, path, link) { if (pe->dir == d) return (d); } /* Add it to the path */ d->refCount += 1; pe = emalloc(sizeof(*pe)); pe->dir = d; TAILQ_INSERT_TAIL(path, pe, link); return (d); } } DEBUGF(DIR, ("Caching %s...", name)); if ((dir = opendir(name)) == NULL) { DEBUGF(DIR, (" cannot open\n")); return (NULL); } d = emalloc(sizeof(*d)); d->name = estrdup(name); d->hits = 0; d->refCount = 1; Hash_InitTable(&d->files, -1); while ((dp = readdir(dir)) != NULL) { #if defined(sun) && defined(d_ino) /* d_ino is a sunos4 #define for d_fileno */ /* * The sun directory library doesn't check for * a 0 inode (0-inode slots just take up space), * so we have to do it ourselves. */ if (dp->d_fileno == 0) continue; #endif /* sun && d_ino */ /* Skip the '.' and '..' entries by checking * for them specifically instead of assuming * readdir() reuturns them in that order when * first going through a directory. This is * needed for XFS over NFS filesystems since * SGI does not guarantee that these are the * first two entries returned from readdir(). */ if (ISDOT(dp->d_name) || ISDOTDOT(dp->d_name)) continue; Hash_CreateEntry(&d->files, dp->d_name, (Boolean *)NULL); } closedir(dir); if (path != NULL) { /* Add it to the path */ d->refCount += 1; pe = emalloc(sizeof(*pe)); pe->dir = d; TAILQ_INSERT_TAIL(path, pe, link); } /* Add to list of all directories */ TAILQ_INSERT_TAIL(&openDirectories, d, link); DEBUGF(DIR, ("done\n")); return (d); } /** * Path_Duplicate * Duplicate a path. Ups the reference count for the directories. */ void Path_Duplicate(struct Path *dst, const struct Path *src) { struct PathElement *ped, *pes; TAILQ_FOREACH(pes, src, link) { ped = emalloc(sizeof(*ped)); ped->dir = pes->dir; ped->dir->refCount++; TAILQ_INSERT_TAIL(dst, ped, link); } } /** * Path_MakeFlags * Make a string by taking all the directories in the given search * path and preceding them by the given flag. Used by the suffix * module to create variables for compilers based on suffix search * paths. * * Results: * The string mentioned above. Note that there is no space between * the given flag and each directory. The empty string is returned if * Things don't go well. */ char * Path_MakeFlags(const char *flag, const struct Path *path) { char *str; /* the string which will be returned */ char *tstr; /* the current directory preceded by 'flag' */ char *nstr; const struct PathElement *pe; str = estrdup(""); TAILQ_FOREACH(pe, path, link) { tstr = str_concat(flag, pe->dir->name, 0); nstr = str_concat(str, tstr, STR_ADDSPACE); free(str); free(tstr); str = nstr; } return (str); } /** * Path_Clear * * Destroy a path. This decrements the reference counts of all * directories of this path and, if a reference count goes 0, * destroys the directory object. */ void Path_Clear(struct Path *path) { struct PathElement *pe; while ((pe = TAILQ_FIRST(path)) != NULL) { pe->dir->refCount--; TAILQ_REMOVE(path, pe, link); if (pe->dir->refCount == 0) { TAILQ_REMOVE(&openDirectories, pe->dir, link); Hash_DeleteTable(&pe->dir->files); free(pe->dir->name); free(pe->dir); } free(pe); } } /** * Path_Concat * * Concatenate two paths, adding the second to the end of the first. * Make sure to avoid duplicates. * * Side Effects: * Reference counts for added dirs are upped. */ void Path_Concat(struct Path *path1, const struct Path *path2) { struct PathElement *p1, *p2; TAILQ_FOREACH(p2, path2, link) { TAILQ_FOREACH(p1, path1, link) { if (p1->dir == p2->dir) break; } if (p1 == NULL) { p1 = emalloc(sizeof(*p1)); p1->dir = p2->dir; p1->dir->refCount++; TAILQ_INSERT_TAIL(path1, p1, link); } } } /********** DEBUG INFO **********/ void Dir_PrintDirectories(void) { const Dir *d; printf("#*** Directory Cache:\n"); printf("# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n", hits, misses, nearmisses, bigmisses, (hits + bigmisses + nearmisses ? hits * 100 / (hits + bigmisses + nearmisses) : 0)); printf("# %-20s referenced\thits\n", "directory"); TAILQ_FOREACH(d, &openDirectories, link) printf("# %-20s %10d\t%4d\n", d->name, d->refCount, d->hits); } void Path_Print(const struct Path *path) { const struct PathElement *p; TAILQ_FOREACH(p, path, link) printf("%s ", p->dir->name); } freebsd-buildutils-10.0/src/usr.bin/make/hash.h0000644000000000000000000000726210241065354016277 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)hash.h 8.1 (Berkeley) 6/6/93 * $FreeBSD$ */ #ifndef hash_h_f6312f46 #define hash_h_f6312f46 /* hash.h -- * * This file contains definitions used by the hash module, * which maintains hash tables. */ #include "util.h" /* * The following defines one entry in the hash table. */ typedef struct Hash_Entry { struct Hash_Entry *next; /* Link entries within same bucket. */ void *clientData; /* Data associated with key. */ unsigned namehash; /* hash value of key */ char name[1]; /* key string */ } Hash_Entry; typedef struct Hash_Table { struct Hash_Entry **bucketPtr; /* Buckets in the table */ int size; /* Actual size of array. */ int numEntries; /* Number of entries in the table. */ int mask; /* Used to select bits for hashing. */ } Hash_Table; /* * The following structure is used by the searching routines * to record where we are in the search. */ typedef struct Hash_Search { const Hash_Table *tablePtr; /* Table being searched. */ int nextIndex; /* Next bucket to check */ Hash_Entry *hashEntryPtr; /* Next entry in current bucket */ } Hash_Search; /* * Macros. */ /* * void *Hash_GetValue(const Hash_Entry *h) */ #define Hash_GetValue(h) ((h)->clientData) /* * Hash_SetValue(Hash_Entry *h, void *val); */ #define Hash_SetValue(h, val) ((h)->clientData = (val)) void Hash_InitTable(Hash_Table *, int); void Hash_DeleteTable(Hash_Table *); Hash_Entry *Hash_FindEntry(const Hash_Table *, const char *); Hash_Entry *Hash_CreateEntry(Hash_Table *, const char *, Boolean *); void Hash_DeleteEntry(Hash_Table *, Hash_Entry *); Hash_Entry *Hash_EnumFirst(const Hash_Table *, Hash_Search *); Hash_Entry *Hash_EnumNext(Hash_Search *); #endif /* hash_h_f6312f46 */ freebsd-buildutils-10.0/src/usr.bin/make/config.h0000644000000000000000000000770210177657375016642 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)config.h 8.2 (Berkeley) 4/28/95 * $FreeBSD$ */ #ifndef config_h_efe0765e #define config_h_efe0765e /* * DEFMAXJOBS * This control the default concurrency. On no occasion will more * than DEFMAXJOBS targets be created at once. */ #define DEFMAXJOBS 1 /* * INCLUDES * LIBRARIES * These control the handling of the .INCLUDES and .LIBS variables. * If INCLUDES is defined, the .INCLUDES variable will be filled * from the search paths of those suffixes which are marked by * .INCLUDES dependency lines. Similarly for LIBRARIES and .LIBS * See suff.c for more details. */ #define INCLUDES #define LIBRARIES /* * LIBSUFF * Is the suffix used to denote libraries and is used by the Suff module * to find the search path on which to seek any -l targets. * * RECHECK * If defined, Make_Update will check a target for its current * modification time after it has been re-made, setting it to the * starting time of the make only if the target still doesn't exist. * Unfortunately, under NFS the modification time often doesn't * get updated in time, so a target will appear to not have been * re-made, causing later targets to appear up-to-date. On systems * that don't have this problem, you should defined this. Under * NFS you probably should not, unless you aren't exporting jobs. */ #define LIBSUFF ".a" #define RECHECK /* * SYSVINCLUDE * Recognize system V like include directives [include "filename"] * SYSVVARSUB * Recognize system V like ${VAR:x=y} variable substitutions */ #define SYSVINCLUDE #define SYSVVARSUB /* * SUNSHCMD * Recognize SunOS and Solaris: * VAR :sh= CMD # Assign VAR to the command substitution of CMD * ${VAR:sh} # Return the command substitution of the value * # of ${VAR} */ #define SUNSHCMD #if !defined(__svr4__) && !defined(__SVR4) && !defined(__ELF__) # ifndef RANLIBMAG # define RANLIBMAG "__.SYMDEF" # endif #else # ifndef RANLIBMAG # define RANLIBMAG "/" # endif #endif #endif /* config_h_efe0765e */ freebsd-buildutils-10.0/src/usr.bin/make/for.c0000644000000000000000000001450211677315120016133 0ustar /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Christos Zoulas. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)for.c 8.1 (Berkeley) 6/6/93 */ #include __FBSDID("$FreeBSD$"); /*- * for.c -- * Functions to handle loops in a makefile. * * Interface: * For_Eval Evaluate the loop in the passed line. * For_Run Run accumulated loop * */ #include #include #include #include "buf.h" #include "for.h" #include "globals.h" #include "lst.h" #include "parse.h" #include "str.h" #include "util.h" #include "var.h" /* * For statements are of the form: * * .for in * ... * .endfor * * The trick is to look for the matching end inside for for loop * To do that, we count the current nesting level of the for loops. * and the .endfor statements, accumulating all the statements between * the initial .for loop and the matching .endfor; * then we evaluate the for loop for each variable in the varlist. */ static int forLevel = 0; /* Nesting level */ static char *forVar; /* Iteration variable */ static Buffer *forBuf; /* Commands in loop */ static Lst forLst; /* List of items */ /** * For_For * Evaluate the for loop in the passed line. The line * looks like this: * .for in * The line pointer points just behind the for. * * Results: * TRUE: Syntax ok. * FALSE: Syntax error. */ Boolean For_For(char *line) { char *ptr; char *wrd; char *sub; Buffer *buf; size_t varlen; int i; ArgArray words; ptr = line; /* * Skip space between for and the variable. */ for (ptr++; *ptr && isspace((u_char)*ptr); ptr++) ; /* * Grab the variable */ for (wrd = ptr; *ptr && !isspace((u_char)*ptr); ptr++) ; buf = Buf_Init(0); Buf_AppendRange(buf, wrd, ptr); forVar = Buf_GetAll(buf, &varlen); if (varlen == 0) { Buf_Destroy(buf, TRUE); Parse_Error(PARSE_FATAL, "missing variable in for"); return (FALSE); } Buf_Destroy(buf, FALSE); /* * Skip to 'in'. */ while (*ptr && isspace((u_char)*ptr)) ptr++; /* * Grab the `in' */ if (ptr[0] != 'i' || ptr[1] != 'n' || !isspace((u_char)ptr[2])) { free(forVar); Parse_Error(PARSE_FATAL, "missing `in' in for"); fprintf(stderr, "%s\n", ptr); return (FALSE); } ptr += 3; /* * Skip to values */ while (*ptr && isspace((u_char)*ptr)) ptr++; /* * Make a list with the remaining words */ sub = Buf_Peel(Var_Subst(ptr, VAR_CMD, FALSE)); brk_string(&words, sub, FALSE); Lst_Init(&forLst); for (i = 1; i < words.argc; i++) { if (words.argv[i][0] != '\0') Lst_AtFront(&forLst, estrdup(words.argv[i])); } ArgArray_Done(&words); DEBUGF(FOR, ("For: Iterator %s List %s\n", forVar, sub)); free(sub); forBuf = Buf_Init(0); forLevel++; return (TRUE); } /** * For_Eval * Eat a line of the .for body looking for embedded .for loops * and the .endfor */ Boolean For_Eval(char *line) { char *ptr; ptr = line; if (*ptr == '.') { /* * Need to check for 'endfor' and 'for' to find the end * of our loop or to find embedded for loops. */ for (ptr++; *ptr != '\0' && isspace((u_char)*ptr); ptr++) ; /* XXX the isspace is wrong */ if (strncmp(ptr, "endfor", 6) == 0 && (isspace((u_char)ptr[6]) || ptr[6] == '\0')) { DEBUGF(FOR, ("For: end for %d\n", forLevel)); if (forLevel == 0) { /* should not be here */ abort(); } forLevel--; } else if (strncmp(ptr, "for", 3) == 0 && isspace((u_char)ptr[3])) { forLevel++; DEBUGF(FOR, ("For: new loop %d\n", forLevel)); } } if (forLevel != 0) { /* * Still in loop - append the line */ Buf_Append(forBuf, line); Buf_AddByte(forBuf, (Byte)'\n'); return (TRUE); } return (FALSE); } /*- *----------------------------------------------------------------------- * For_Run -- * Run the for loop, imitating the actions of an include file * * Results: * None. * * Side Effects: * The values of the variables forLst, forVar and forBuf are freed. * *----------------------------------------------------------------------- */ void For_Run(int lineno) { Lst values; /* list of values for the variable */ char *var; /* the variable's name */ Buffer *buf; /* the contents of the for loop */ const char *val; /* current value of loop variable */ LstNode *ln; char *str; if (forVar == NULL || forBuf == NULL) return; /* copy the global variables to have them free for embedded fors */ var = forVar; buf = forBuf; Lst_Init(&values); Lst_Concat(&values, &forLst, LST_CONCLINK); forVar = NULL; forBuf = NULL; LST_FOREACH(ln, &values) { val = Lst_Datum(ln); Var_SetGlobal(var, val); DEBUGF(FOR, ("--- %s = %s\n", var, val)); str = Buf_Peel(Var_SubstOnly(var, Buf_Data(buf), FALSE)); Parse_FromString(str, lineno); Var_Delete(var, VAR_GLOBAL); } free(var); Lst_Destroy(&values, free); Buf_Destroy(buf, TRUE); } freebsd-buildutils-10.0/src/usr.bin/make/lst.h0000644000000000000000000001303111310551642016143 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)lst.h 8.2 (Berkeley) 4/28/95 * $FreeBSD$ */ #ifndef lst_h_38f3ead1 #define lst_h_38f3ead1 /*- * lst.h -- * Header for using the list library */ /* * Structure of a list node. */ struct LstNode { struct LstNode *prevPtr; /* previous element in list */ struct LstNode *nextPtr; /* next in list */ void *datum; /* datum associated with this element */ }; typedef struct LstNode LstNode; /* * The list itself */ struct Lst { LstNode *firstPtr; /* first node in list */ LstNode *lastPtr; /* last node in list */ }; typedef struct Lst Lst; typedef void *DuplicateProc(void *); typedef void FreeProc(void *); /* * NOFREE can be used as the freeProc to Lst_Destroy when the elements are * not to be freed. * NOCOPY performs similarly when given as the copyProc to Lst_Duplicate. */ #define NOFREE ((FreeProc *)NULL) #define NOCOPY ((DuplicateProc *)NULL) #define LST_CONCNEW 0 /* create new LstNode's when using Lst_Concat */ #define LST_CONCLINK 1 /* relink LstNode's when using Lst_Concat */ /* * Creation/destruction functions */ /* Create a new list */ #define Lst_Init(LST) do { \ (LST)->firstPtr = NULL; \ (LST)->lastPtr = NULL; \ } while (0) #define Lst_Initializer(NAME) { NULL, NULL } /* Duplicate an existing list */ void Lst_Duplicate(Lst *, Lst *, DuplicateProc *); /* Destroy an old one */ void Lst_Destroy(Lst *, FreeProc *); /* * Functions to modify a list */ /* Insert an element before another */ void Lst_Insert(Lst *, LstNode *, void *); /* Insert an element after another */ void Lst_Append(Lst *, LstNode *, void *); /* Place an element at the front of a lst. */ #define Lst_AtFront(LST, D) (Lst_Insert((LST), Lst_First(LST), (D))) /* Place an element at the end of a lst. */ #define Lst_AtEnd(LST, D) (Lst_Append((LST), Lst_Last(LST), (D))) /* Remove an element */ void Lst_Remove(Lst *, LstNode *); /* Replace a node with a new value */ #define Lst_Replace(NODE, D) ((void)((NODE)->datum = (D))) /* Concatenate two lists */ void Lst_Concat(Lst *, Lst *, int); /* * Node-specific functions */ /* Return first element in list */ #define Lst_First(LST) ((Lst_Valid(LST) && !Lst_IsEmpty(LST)) \ ? (LST)->firstPtr : NULL) /* Return last element in list */ #define Lst_Last(LST) ((Lst_Valid(LST) && !Lst_IsEmpty(LST)) \ ? (LST)->lastPtr : NULL) /* Return successor to given element */ #define Lst_Succ(NODE) (((NODE) == NULL) ? NULL : (NODE)->nextPtr) #define LST_NEXT(NODE) ((NODE)->nextPtr) /* Get datum from LstNode */ #define Lst_Datum(NODE) ((NODE)->datum) /* * Functions for entire lists */ /* * See if the given datum is on the list. Returns the LstNode containing * the datum */ LstNode *Lst_Member(Lst *, void *); /* Loop through a list. Note, that you may not delete the list element. */ #define LST_FOREACH(PTR, LST) \ for ((PTR) = (LST)->firstPtr; (PTR) != NULL; (PTR) = (PTR)->nextPtr) /* * for using the list as a queue */ /* Place an element at tail of queue */ #define Lst_EnQueue(LST, D) (Lst_Valid(LST) \ ? Lst_Append((LST), Lst_Last(LST), (D)) \ : (void)0) /* Remove an element from head of queue */ void *Lst_DeQueue(Lst *); /* * LstValid (L) -- * Return TRUE if the list L is valid */ #define Lst_Valid(L) (((L) == NULL) ? FALSE : TRUE) /* * LstNodeValid (LN, L) -- * Return TRUE if the LstNode LN is valid with respect to L */ #define Lst_NodeValid(LN, L) (((LN) == NULL) ? FALSE : TRUE) /* * Lst_IsEmpty(L) -- * TRUE if the list L is empty. */ #define Lst_IsEmpty(L) (!Lst_Valid(L) || (L)->firstPtr == NULL) #endif /* lst_h_38f3ead1 */ freebsd-buildutils-10.0/src/usr.bin/make/arch.c0000644000000000000000000010125111677315120016260 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)arch.c 8.2 (Berkeley) 1/2/94 */ #include __FBSDID("$FreeBSD$"); /*- * arch.c -- * Functions to manipulate libraries, archives and their members. * * Once again, cacheing/hashing comes into play in the manipulation * of archives. The first time an archive is referenced, all of its members' * headers are read and hashed and the archive closed again. All hashed * archives are kept on a list which is searched each time an archive member * is referenced. * * The interface to this module is: * Arch_ParseArchive Given an archive specification, return a list * of GNode's, one for each member in the spec. * FALSE is returned if the specification is * invalid for some reason. * * Arch_Touch Alter the modification time of the archive * member described by the given node to be * the current time. * * Arch_TouchLib Update the modification time of the library * described by the given node. This is special * because it also updates the modification time * of the library's table of contents. * * Arch_MTime Find the modification time of a member of * an archive *in the archive*. The time is also * placed in the member's GNode. Returns the * modification time. * * Arch_MemTime Find the modification time of a member of * an archive. Called when the member doesn't * already exist. Looks in the archive for the * modification time. Returns the modification * time. * * Arch_FindLib Search for a library along a path. The * library name in the GNode should be in * -l format. * * Arch_LibOODate Special function to decide if a library node * is out-of-date. * * Arch_Init Initialize this module. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "arch.h" #include "buf.h" #include "config.h" #include "dir.h" #include "globals.h" #include "GNode.h" #include "hash.h" #include "make.h" #include "parse.h" #include "targ.h" #include "util.h" #include "var.h" typedef struct Arch { char *name; /* Name of archive */ /* * All the members of the archive described * by key/value pairs */ Hash_Table members; TAILQ_ENTRY(Arch) link; /* link all cached archives */ } Arch; /* Lst of archives we've already examined */ static TAILQ_HEAD(, Arch) archives = TAILQ_HEAD_INITIALIZER(archives); /* size of the name field in the archive member header */ #define AR_NAMSIZ sizeof(((struct ar_hdr *)0)->ar_name) /* * This structure is used while reading/writing an archive */ struct arfile { FILE *fp; /* archive file */ char *fname; /* name of the file */ struct ar_hdr hdr; /* current header */ char sname[AR_NAMSIZ + 1]; /* short name */ char *member; /* (long) member name */ size_t mlen; /* size of the above */ char *nametab; /* name table */ size_t nametablen; /* size of the table */ int64_t time; /* from ar_date */ uint64_t size; /* from ar_size */ off_t pos; /* header pos of current entry */ }; /* * Name of the symbol table. The original BSD used "__.SYMDEF". Rumours go * that this name may have a slash appended sometimes. Actually FreeBSD * uses "/" which probably came from SVR4. */ #define SVR4_RANLIBMAG "/" #define BSD_RANLIBMAG "__.SYMDEF" /* * Name of the filename table. The 4.4BSD ar format did not use this, but * puts long filenames directly between the member header and the object * file. */ #define SVR4_NAMEMAG "//" #define BSD_NAMEMAG "ARFILENAMES/" /* * 44BSD long filename key. Use a local define here instead of relying * on ar.h because we want this to continue working even when the * definition is removed from ar.h. */ #define BSD_EXT1 "#1/" #define BSD_EXT1LEN 3 /* if this is TRUE make archive errors fatal */ Boolean arch_fatal = TRUE; /** * ArchError * An error happened while handling an archive. BSDmake traditionally * ignored these errors. Now this is dependent on the global arch_fatal * which, if true, makes these errors fatal and, if false, just emits an * error message. */ #define ArchError(ARGS) do { \ if (arch_fatal) \ Fatal ARGS; \ else \ Error ARGS; \ } while (0) /*- *----------------------------------------------------------------------- * Arch_ParseArchive -- * Parse the archive specification in the given line and find/create * the nodes for the specified archive members, placing their nodes * on the given list, given the pointer to the start of the * specification, a Lst on which to place the nodes, and a context * in which to expand variables. * * Results: * TRUE if it was a valid specification. The linePtr is updated * to point to the first non-space after the archive spec. The * nodes for the members are placed on the given list. * * Side Effects: * Some nodes may be created. The given list is extended. * *----------------------------------------------------------------------- */ Boolean Arch_ParseArchive(char **linePtr, Lst *nodeLst, GNode *ctxt) { char *cp; /* Pointer into line */ GNode *gn; /* New node */ char *libName; /* Library-part of specification */ char *memName; /* Member-part of specification */ char *nameBuf; /* temporary place for node name */ char saveChar; /* Ending delimiter of member-name */ Boolean subLibName; /* TRUE if libName should have/had * variable substitution performed on it */ libName = *linePtr; subLibName = FALSE; for (cp = libName; *cp != '(' && *cp != '\0'; cp++) { if (*cp == '$') { /* * Variable spec, so call the Var module to parse the * puppy so we can safely advance beyond it... */ size_t length = 0; Boolean freeIt; char *result; result = Var_Parse(cp, ctxt, TRUE, &length, &freeIt); if (result == var_Error) { return (FALSE); } subLibName = TRUE; if (freeIt) { free(result); } cp += length - 1; } } *cp++ = '\0'; if (subLibName) { libName = Buf_Peel(Var_Subst(libName, ctxt, TRUE)); } for (;;) { /* * First skip to the start of the member's name, mark that * place and skip to the end of it (either white-space or * a close paren). */ /* * TRUE if need to substitute in memName */ Boolean doSubst = FALSE; while (*cp != '\0' && *cp != ')' && isspace((unsigned char)*cp)) { cp++; } memName = cp; while (*cp != '\0' && *cp != ')' && !isspace((unsigned char)*cp)) { if (*cp == '$') { /* * Variable spec, so call the Var module to * parse the puppy so we can safely advance * beyond it... */ size_t length = 0; Boolean freeIt; char *result; result = Var_Parse(cp, ctxt, TRUE, &length, &freeIt); if (result == var_Error) { return (FALSE); } doSubst = TRUE; if (freeIt) { free(result); } cp += length; } else { cp++; } } /* * If the specification ends without a closing parenthesis, * chances are there's something wrong (like a missing * backslash), so it's better to return failure than allow * such things to happen */ if (*cp == '\0') { printf("No closing parenthesis in archive " "specification\n"); return (FALSE); } /* * If we didn't move anywhere, we must be done */ if (cp == memName) { break; } saveChar = *cp; *cp = '\0'; /* * XXX: This should be taken care of intelligently by * SuffExpandChildren, both for the archive and the member * portions. */ /* * If member contains variables, try and substitute for them. * This will slow down archive specs with dynamic sources, of * course, since we'll be (non-)substituting them three times, * but them's the breaks -- we need to do this since * SuffExpandChildren calls us, otherwise we could assume the * thing would be taken care of later. */ if (doSubst) { char *buf; char *sacrifice; char *oldMemName = memName; size_t sz; Buffer *buf1; /* * Now form an archive spec and recurse to deal with * nested variables and multi-word variable values.... * The results are just placed at the end of the * nodeLst we're returning. */ buf1 = Var_Subst(memName, ctxt, TRUE); memName = Buf_Data(buf1); sz = strlen(memName) + strlen(libName) + 3; buf = emalloc(sz); snprintf(buf, sz, "%s(%s)", libName, memName); sacrifice = buf; if (strchr(memName, '$') && strcmp(memName, oldMemName) == 0) { /* * Must contain dynamic sources, so we can't * deal with it now. * Just create an ARCHV node for the thing and * let SuffExpandChildren handle it... */ gn = Targ_FindNode(buf, TARG_CREATE); if (gn == NULL) { free(buf); Buf_Destroy(buf1, FALSE); return (FALSE); } gn->type |= OP_ARCHV; Lst_AtEnd(nodeLst, (void *)gn); } else if (!Arch_ParseArchive(&sacrifice, nodeLst, ctxt)) { /* * Error in nested call -- free buffer and * return FALSE ourselves. */ free(buf); Buf_Destroy(buf1, FALSE); return (FALSE); } /* Free buffer and continue with our work. */ free(buf); Buf_Destroy(buf1, FALSE); } else if (Dir_HasWildcards(memName)) { Lst members = Lst_Initializer(members); char *member; size_t sz = MAXPATHLEN; size_t nsz; nameBuf = emalloc(sz); Path_Expand(memName, &dirSearchPath, &members); while (!Lst_IsEmpty(&members)) { member = Lst_DeQueue(&members); nsz = strlen(libName) + strlen(member) + 3; if (nsz > sz) { sz = nsz * 2; nameBuf = erealloc(nameBuf, sz); } snprintf(nameBuf, sz, "%s(%s)", libName, member); free(member); gn = Targ_FindNode(nameBuf, TARG_CREATE); if (gn == NULL) { free(nameBuf); /* XXXHB Lst_Destroy(&members) */ return (FALSE); } /* * We've found the node, but have to make sure * the rest of the world knows it's an archive * member, without having to constantly check * for parentheses, so we type the thing with * the OP_ARCHV bit before we place it on the * end of the provided list. */ gn->type |= OP_ARCHV; Lst_AtEnd(nodeLst, gn); } free(nameBuf); } else { size_t sz = strlen(libName) + strlen(memName) + 3; nameBuf = emalloc(sz); snprintf(nameBuf, sz, "%s(%s)", libName, memName); gn = Targ_FindNode(nameBuf, TARG_CREATE); free(nameBuf); if (gn == NULL) { return (FALSE); } /* * We've found the node, but have to make sure the * rest of the world knows it's an archive member, * without having to constantly check for parentheses, * so we type the thing with the OP_ARCHV bit before * we place it on the end of the provided list. */ gn->type |= OP_ARCHV; Lst_AtEnd(nodeLst, gn); } if (doSubst) { free(memName); } *cp = saveChar; } /* * If substituted libName, free it now, since we need it no longer. */ if (subLibName) { free(libName); } /* * We promised the pointer would be set up at the next non-space, so * we must advance cp there before setting *linePtr... (note that on * entrance to the loop, cp is guaranteed to point at a ')') */ do { cp++; } while (*cp != '\0' && isspace((unsigned char)*cp)); *linePtr = cp; return (TRUE); } /* * Close an archive file an free all resources */ static void ArchArchiveClose(struct arfile *ar) { if (ar->nametab != NULL) free(ar->nametab); free(ar->member); if (ar->fp != NULL) { if (fclose(ar->fp) == EOF) ArchError(("%s: close error", ar->fname)); } free(ar->fname); free(ar); } /* * Open an archive file. */ static struct arfile * ArchArchiveOpen(const char *archive, const char *mode) { struct arfile *ar; char magic[SARMAG]; ar = emalloc(sizeof(*ar)); ar->fname = estrdup(archive); ar->mlen = 100; ar->member = emalloc(ar->mlen); ar->nametab = NULL; ar->nametablen = 0; if ((ar->fp = fopen(ar->fname, mode)) == NULL) { DEBUGM(ARCH, ("%s", ar->fname)); ArchArchiveClose(ar); return (NULL); } /* read MAGIC */ if (fread(magic, SARMAG, 1, ar->fp) != 1 || strncmp(magic, ARMAG, SARMAG) != 0) { ArchError(("%s: bad archive magic\n", ar->fname)); ArchArchiveClose(ar); return (NULL); } ar->pos = 0; return (ar); } /* * Read the next header from the archive. The return value will be +1 if * the header is read successfully, 0 on EOF and -1 if an error happened. * On a successful return sname contains the truncated member name and * member the full name. hdr contains the member header. For the symbol table * names of length 0 are returned. The entry for the file name table is never * returned. */ static int ArchArchiveNext(struct arfile *ar) { char *end; int have_long_name; u_long offs; char *ptr; size_t ret; char buf[MAX(sizeof(ar->hdr.ar_size), sizeof(ar->hdr.ar_date)) + 1]; next: /* * Seek to the next header. */ if (ar->pos == 0) { ar->pos = SARMAG; } else { ar->pos += sizeof(ar->hdr) + ar->size; if (ar->size % 2 == 1) ar->pos++; } if (fseeko(ar->fp, ar->pos, SEEK_SET) == -1) { ArchError(("%s: cannot seek to %jd: %s", ar->fname, (intmax_t)ar->pos, strerror(errno))); return (-1); } /* * Read next member header */ ret = fread(&ar->hdr, sizeof(ar->hdr), 1, ar->fp); if (ret != 1) { if (feof(ar->fp)) return (0); ArchError(("%s: error reading member header: %s", ar->fname, strerror(errno))); return (-1); } if (strncmp(ar->hdr.ar_fmag, ARFMAG, sizeof(ar->hdr.ar_fmag)) != 0) { ArchError(("%s: bad entry magic", ar->fname)); return (-1); } /* * looks like a member - get name by stripping trailing spaces * and NUL terminating. */ strlcpy(ar->sname, ar->hdr.ar_name, AR_NAMSIZ + 1); for (ptr = ar->sname + AR_NAMSIZ; ptr > ar->sname; ptr--) if (ptr[-1] != ' ') break; *ptr = '\0'; /* * Parse the size. All entries need to have a size. Be careful * to not allow buffer overruns. */ strlcpy(buf, ar->hdr.ar_size, sizeof(ar->hdr.ar_size) + 1); errno = 0; ar->size = strtoumax(buf, &end, 10); if (errno != 0 || strspn(end, " ") != strlen(end)) { ArchError(("%s: bad size format in archive '%s'", ar->fname, buf)); return (-1); } /* * Look for the extended name table. Do this before parsing * the date because this table doesn't need a date. */ if (strcmp(ar->sname, BSD_NAMEMAG) == 0 || strcmp(ar->sname, SVR4_NAMEMAG) == 0) { /* filename table - read it in */ ar->nametablen = ar->size; ar->nametab = emalloc(ar->nametablen); ret = fread(ar->nametab, 1, ar->nametablen, ar->fp); if (ret != ar->nametablen) { if (ferror(ar->fp)) { ArchError(("%s: cannot read nametab: %s", ar->fname, strerror(errno))); } else { ArchError(("%s: cannot read nametab: " "short read", ar->fname, strerror(errno))); } return (-1); } /* * NUL terminate the entries. Entries are \n terminated * and may have a trailing / or \. */ ptr = ar->nametab; while (ptr < ar->nametab + ar->nametablen) { if (*ptr == '\n') { if (ptr[-1] == '/' || ptr[-1] == '\\') ptr[-1] = '\0'; *ptr = '\0'; } ptr++; } /* get next archive entry */ goto next; } /* * Now parse the modification date. Be careful to not overrun * buffers. */ strlcpy(buf, ar->hdr.ar_date, sizeof(ar->hdr.ar_date) + 1); errno = 0; ar->time = (int64_t)strtoll(buf, &end, 10); if (errno != 0 || strspn(end, " ") != strlen(end)) { ArchError(("%s: bad date format in archive '%s'", ar->fname, buf)); return (-1); } /* * Now check for the symbol table. This should really be the first * entry, but we don't check this. */ if (strcmp(ar->sname, BSD_RANLIBMAG) == 0 || strcmp(ar->sname, SVR4_RANLIBMAG) == 0) { /* symbol table - return a zero length name */ ar->member[0] = '\0'; ar->sname[0] = '\0'; return (1); } have_long_name = 0; /* * Look whether this is a long name. There are several variants * of long names: * "#1/12 " - 12 length of following filename * "/17 " - index into name table * " 17 " - index into name table * Note that in the last case we must also check that there is no * slash in the name because of filenames with leading spaces: * " 777.o/ " - filename 777.o */ if (ar->sname[0] == '/' || (ar->sname[0] == ' ' && strchr(ar->sname, '/') == NULL)) { /* SVR4 extended name */ errno = 0; offs = strtoul(ar->sname + 1, &end, 10); if (errno != 0 || *end != '\0' || offs >= ar->nametablen || end == ar->sname + 1) { ArchError(("%s: bad extended name '%s'", ar->fname, ar->sname)); return (-1); } /* fetch the name */ if (ar->mlen <= strlen(ar->nametab + offs)) { ar->mlen = strlen(ar->nametab + offs) + 1; ar->member = erealloc(ar->member, ar->mlen); } strcpy(ar->member, ar->nametab + offs); have_long_name = 1; } else if (strncmp(ar->sname, BSD_EXT1, BSD_EXT1LEN) == 0 && isdigit(ar->sname[BSD_EXT1LEN])) { /* BSD4.4 extended name */ errno = 0; offs = strtoul(ar->sname + BSD_EXT1LEN, &end, 10); if (errno != 0 || *end != '\0' || end == ar->sname + BSD_EXT1LEN) { ArchError(("%s: bad extended name '%s'", ar->fname, ar->sname)); return (-1); } /* read it from the archive */ if (ar->mlen <= offs) { ar->mlen = offs + 1; ar->member = erealloc(ar->member, ar->mlen); } ret = fread(ar->member, 1, offs, ar->fp); if (ret != offs) { if (ferror(ar->fp)) { ArchError(("%s: reading extended name: %s", ar->fname, strerror(errno))); } else { ArchError(("%s: reading extended name: " "short read", ar->fname)); } return (-1); } ar->member[offs] = '\0'; have_long_name = 1; } /* * Now remove the trailing slash that Svr4 puts at * the end of the member name to support trailing spaces in names. */ if (ptr > ar->sname && ptr[-1] == '/') *--ptr = '\0'; if (!have_long_name) { if (strlen(ar->sname) >= ar->mlen) { ar->mlen = strlen(ar->sname) + 1; ar->member = erealloc(ar->member, ar->mlen); } strcpy(ar->member, ar->sname); } return (1); } /* * Touch the current archive member by writing a new header with an * updated timestamp. The return value is 0 for success and -1 for errors. */ static int ArchArchiveTouch(struct arfile *ar, int64_t ts) { /* seek to our header */ if (fseeko(ar->fp, ar->pos, SEEK_SET) == -1) { ArchError(("%s: cannot seek to %jd: %s", ar->fname, (intmax_t)ar->pos, strerror(errno))); return (-1); } /* * change timestamp, be sure to not NUL-terminated it, but * to fill with spaces. */ snprintf(ar->hdr.ar_date, sizeof(ar->hdr.ar_date), "%jd", (intmax_t)ts); memset(ar->hdr.ar_date + strlen(ar->hdr.ar_date), ' ', sizeof(ar->hdr.ar_date) - strlen(ar->hdr.ar_date)); if (fwrite(&ar->hdr, sizeof(ar->hdr), 1, ar->fp) != 1) { ArchError(("%s: cannot touch: %s", ar->fname, strerror(errno))); return (-1); } return (0); } /*- *----------------------------------------------------------------------- * ArchFindMember -- * Locate a member of an archive, given the path of the archive and * the path of the desired member. If the archive is to be modified, * the mode should be "r+", if not, it should be "r". The archive * file is returned positioned at the correct header. * * Results: * A struct arfile *, opened for reading and, possibly writing, * positioned at the member's header, or NULL if the member was * nonexistent. * *----------------------------------------------------------------------- */ static struct arfile * ArchFindMember(const char *archive, const char *member, const char *mode) { struct arfile *ar; const char *cp; /* Useful character pointer */ if ((ar = ArchArchiveOpen(archive, mode)) == NULL) return (NULL); /* * Because of space constraints and similar things, files are archived * using their final path components, not the entire thing, so we need * to point 'member' to the final component, if there is one, to make * the comparisons easier... */ if (member != NULL) { cp = strrchr(member, '/'); if (cp != NULL) { member = cp + 1; } } while (ArchArchiveNext(ar) > 0) { /* * When comparing there are actually three cases: * (1) the name fits into the limit og af_name, * (2) the name is longer and the archive supports long names, * (3) the name is longer and the archive doesn't support long * names. * Because we don't know whether the archive supports long * names or not we need to be careful. */ if (member == NULL) { /* special case - symbol table */ if (ar->member[0] == '\0') return (ar); } else if (strlen(member) <= AR_NAMSIZ) { /* case (1) */ if (strcmp(ar->member, member) == 0) return (ar); } else if (strcmp(ar->member, member) == 0) { /* case (3) */ return (ar); } else { /* case (2) */ if (strlen(ar->member) == AR_NAMSIZ && strncmp(member, ar->member, AR_NAMSIZ) == 0) return (ar); } } /* not found */ ArchArchiveClose(ar); return (NULL); } /*- *----------------------------------------------------------------------- * ArchStatMember -- * Locate a member of an archive, given the path of the archive and * the path of the desired member, and a boolean representing whether * or not the archive should be hashed (if not already hashed). * * Results: * A pointer to the current struct ar_hdr structure for the member. Note * That no position is returned, so this is not useful for touching * archive members. This is mostly because we have no assurances that * The archive will remain constant after we read all the headers, so * there's not much point in remembering the position... * * Side Effects: * *----------------------------------------------------------------------- */ static int64_t ArchStatMember(const char *archive, const char *member, Boolean hash) { struct arfile *arf; int64_t ret; int t; char *cp; /* Useful character pointer */ Arch *ar; /* Archive descriptor */ Hash_Entry *he; /* Entry containing member's description */ char copy[AR_NAMSIZ + 1]; /* * Because of space constraints and similar things, files are archived * using their final path components, not the entire thing, so we need * to point 'member' to the final component, if there is one, to make * the comparisons easier... */ if (member != NULL) { cp = strrchr(member, '/'); if (cp != NULL) member = cp + 1; } TAILQ_FOREACH(ar, &archives, link) { if (strcmp(archive, ar->name) == 0) break; } if (ar == NULL) { /* archive not found */ if (!hash) { /* * Caller doesn't want the thing hashed, just use * ArchFindMember to read the header for the member * out and close down the stream again. */ arf = ArchFindMember(archive, member, "r"); if (arf == NULL) { return (INT64_MIN); } ret = arf->time; ArchArchiveClose(arf); return (ret); } /* * We don't have this archive on the list yet, so we want to * find out everything that's in it and cache it so we can get * at it quickly. */ arf = ArchArchiveOpen(archive, "r"); if (arf == NULL) { return (INT64_MIN); } /* create archive data structure */ ar = emalloc(sizeof(*ar)); ar->name = estrdup(archive); Hash_InitTable(&ar->members, -1); while ((t = ArchArchiveNext(arf)) > 0) { he = Hash_CreateEntry(&ar->members, arf->member, NULL); Hash_SetValue(he, emalloc(sizeof(int64_t))); *(int64_t *)Hash_GetValue(he) = arf->time; } ArchArchiveClose(arf); if (t < 0) { /* error happened - throw away everything */ Hash_DeleteTable(&ar->members); free(ar->name); free(ar); return (INT64_MIN); } TAILQ_INSERT_TAIL(&archives, ar, link); } /* * Now that the archive has been read and cached, we can look into * the hash table to find the desired member's header. */ he = Hash_FindEntry(&ar->members, member); if (he != NULL) return (*(int64_t *)Hash_GetValue (he)); if (member != NULL && strlen(member) > AR_NAMSIZ) { /* Try truncated name */ strlcpy(copy, member, AR_NAMSIZ + 1); if ((he = Hash_FindEntry(&ar->members, copy)) != NULL) return (*(int64_t *)Hash_GetValue(he)); } return (INT64_MIN); } /*- *----------------------------------------------------------------------- * Arch_Touch -- * Touch a member of an archive. * * Results: * The 'time' field of the member's header is updated. * * Side Effects: * The modification time of the entire archive is also changed. * For a library, this could necessitate the re-ranlib'ing of the * whole thing. * *----------------------------------------------------------------------- */ void Arch_Touch(GNode *gn) { struct arfile *ar; ar = ArchFindMember(Var_Value(ARCHIVE, gn), Var_Value(TARGET, gn), "r+"); if (ar != NULL) { ArchArchiveTouch(ar, (int64_t)now); ArchArchiveClose(ar); } } /*- *----------------------------------------------------------------------- * Arch_TouchLib -- * Given a node which represents a library, touch the thing, making * sure that the table of contents also is touched. * * Results: * None. * * Side Effects: * Both the modification time of the library and of the RANLIBMAG * member are set to 'now'. * *----------------------------------------------------------------------- */ void Arch_TouchLib(GNode *gn) { struct arfile *ar; /* Open archive */ struct utimbuf times; /* Times for utime() call */ ar = ArchFindMember(gn->path, NULL, "r+"); if (ar != NULL) { ArchArchiveTouch(ar, (int64_t)now); ArchArchiveClose(ar); times.actime = times.modtime = now; utime(gn->path, ×); } } /*- *----------------------------------------------------------------------- * Arch_MTime -- * Return the modification time of a member of an archive, given its * name. * * Results: * The modification time(seconds). * XXXHB this should be a long. * * Side Effects: * The mtime field of the given node is filled in with the value * returned by the function. * *----------------------------------------------------------------------- */ int Arch_MTime(GNode *gn) { int64_t mtime; mtime = ArchStatMember(Var_Value(ARCHIVE, gn), Var_Value(TARGET, gn), TRUE); if (mtime == INT_MIN) { mtime = 0; } gn->mtime = (int)mtime; /* XXX */ return (gn->mtime); } /*- *----------------------------------------------------------------------- * Arch_MemMTime -- * Given a non-existent archive member's node, get its modification * time from its archived form, if it exists. * * Results: * The modification time. * * Side Effects: * The mtime field is filled in. * *----------------------------------------------------------------------- */ int Arch_MemMTime(GNode *gn) { LstNode *ln; GNode *pgn; char *nameStart; char *nameEnd; for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Succ(ln)) { pgn = Lst_Datum(ln); if (pgn->type & OP_ARCHV) { /* * If the parent is an archive specification and is * being made and its member's name matches the name of * the node we were given, record the modification time * of the parent in the child. We keep searching its * parents in case some other parent requires this * child to exist... */ nameStart = strchr(pgn->name, '(') + 1; nameEnd = strchr(nameStart, ')'); if (pgn->make && strncmp(nameStart, gn->name, nameEnd - nameStart) == 0) { gn->mtime = Arch_MTime(pgn); } } else if (pgn->make) { /* * Something which isn't a library depends on the * existence of this target, so it needs to exist. */ gn->mtime = 0; break; } } return (gn->mtime); } /*- *----------------------------------------------------------------------- * Arch_FindLib -- * Search for a named library along the given search path. * * Results: * None. * * Side Effects: * The node's 'path' field is set to the found path (including the * actual file name, not -l...). If the system can handle the -L * flag when linking (or we cannot find the library), we assume that * the user has placed the .LIBRARIES variable in the final linking * command (or the linker will know where to find it) and set the * TARGET variable for this node to be the node's name. Otherwise, * we set the TARGET variable to be the full path of the library, * as returned by Path_FindFile. * *----------------------------------------------------------------------- */ void Arch_FindLib(GNode *gn, struct Path *path) { char *libName; /* file name for archive */ size_t sz; sz = strlen(gn->name) + 4; libName = emalloc(sz); snprintf(libName, sz, "lib%s.a", &gn->name[2]); gn->path = Path_FindFile(libName, path); free(libName); #ifdef LIBRARIES Var_Set(TARGET, gn->name, gn); #else Var_Set(TARGET, gn->path == NULL ? gn->name : gn->path, gn); #endif /* LIBRARIES */ } /*- *----------------------------------------------------------------------- * Arch_LibOODate -- * Decide if a node with the OP_LIB attribute is out-of-date. Called * from Make_OODate to make its life easier, with the library's * graph node. * * There are several ways for a library to be out-of-date that are * not available to ordinary files. In addition, there are ways * that are open to regular files that are not available to * libraries. A library that is only used as a source is never * considered out-of-date by itself. This does not preclude the * library's modification time from making its parent be out-of-date. * A library will be considered out-of-date for any of these reasons, * given that it is a target on a dependency line somewhere: * Its modification time is less than that of one of its * sources (gn->mtime < gn->cmtime). * Its modification time is greater than the time at which the * make began (i.e. it's been modified in the course * of the make, probably by archiving). * The modification time of one of its sources is greater than * the one of its RANLIBMAG member (i.e. its table of contents * is out-of-date). We don't compare of the archive time * vs. TOC time because they can be too close. In my * opinion we should not bother with the TOC at all since * this is used by 'ar' rules that affect the data contents * of the archive, not by ranlib rules, which affect the * TOC. * * Results: * TRUE if the library is out-of-date. FALSE otherwise. * * Side Effects: * The library will be hashed if it hasn't been already. * *----------------------------------------------------------------------- */ Boolean Arch_LibOODate(GNode *gn) { int64_t mtime; /* The table-of-contents's mod time */ if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->children)) { return (FALSE); } if (gn->mtime > now || gn->mtime < gn->cmtime) { return (TRUE); } mtime = ArchStatMember(gn->path, NULL, FALSE); if (mtime == INT64_MIN) { /* * Not found. A library w/o a table of contents is out-of-date */ if (DEBUG(ARCH) || DEBUG(MAKE)) { Debug("No TOC..."); } return (TRUE); } /* XXX choose one. */ if (DEBUG(ARCH) || DEBUG(MAKE)) { Debug("TOC modified %s...", Targ_FmtTime(mtime)); } return (gn->cmtime > mtime); } freebsd-buildutils-10.0/src/usr.bin/make/var.c0000644000000000000000000016647712034102104016140 0ustar /*- * Copyright (c) 2002 Juli Mallett. * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)var.c 8.3 (Berkeley) 3/19/94 */ #include __FBSDID("$FreeBSD$"); /** * var.c -- * Variable-handling functions * * Interface: * Var_Set Set the value of a variable in the given * context. The variable is created if it doesn't * yet exist. The value and variable name need not * be preserved. * * Var_Append Append more characters to an existing variable * in the given context. The variable needn't * exist already -- it will be created if it doesn't. * A space is placed between the old value and the * new one. * * Var_Exists See if a variable exists. * * Var_Value Return the value of a variable in a context or * NULL if the variable is undefined. * * Var_Subst Substitute named variable, or all variables if * NULL in a string using * the given context as the top-most one. If the * third argument is non-zero, Parse_Error is * called if any variables are undefined. * * Var_Parse Parse a variable expansion from a string and * return the result and the number of characters * consumed. * * Var_Delete Delete a variable in a context. * * Var_Init Initialize this module. * * Debugging: * Var_Dump Print out all variables defined in the given * context. * * XXX: There's a lot of duplication in these functions. */ #include #include #include #include #include #include "buf.h" #include "config.h" #include "globals.h" #include "GNode.h" #include "job.h" #include "lst.h" #include "parse.h" #include "str.h" #include "targ.h" #include "util.h" #include "var.h" /** * */ typedef struct VarParser { const char *const input; /* pointer to input string */ const char *ptr; /* current parser pos in input str */ GNode *ctxt; Boolean err; Boolean execute; } VarParser; typedef struct Var { char *name; /* the variable's name */ struct Buffer *val; /* its value */ int flags; /* miscellaneous status flags */ #define VAR_IN_USE 1 /* Variable's value currently being used. * Used to avoid recursion */ #define VAR_JUNK 4 /* Variable is a junk variable that * should be destroyed when done with * it. Used by Var_Parse for undefined, * modified variables */ #define VAR_TO_ENV 8 /* Place variable in environment */ } Var; typedef struct { struct Buffer *lhs; /* String to match */ struct Buffer *rhs; /* Replacement string (w/ &'s removed) */ regex_t re; int nsub; regmatch_t *matches; int flags; #define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */ #define VAR_SUB_ONE 0x02 /* Apply substitution to one word */ #define VAR_SUB_MATCHED 0x04 /* There was a match */ #define VAR_MATCH_START 0x08 /* Match at start of word */ #define VAR_MATCH_END 0x10 /* Match at end of word */ } VarPattern; typedef Boolean VarModifyProc(const char *, Boolean, struct Buffer *, void *); static char *VarParse(VarParser *, Boolean *); /* * This is a harmless return value for Var_Parse that can be used by Var_Subst * to determine if there was an error in parsing -- easier than returning * a flag, as things outside this module don't give a hoot. */ char var_Error[] = ""; /* * Similar to var_Error, but returned when the 'err' flag for Var_Parse is * set false. Why not just use a constant? Well, gcc likes to condense * identical string instances... */ static char varNoError[] = ""; /* * Internally, variables are contained in four different contexts. * 1) the environment. They may not be changed. If an environment * variable is appended-to, the result is placed in the global * context. * 2) the global context. Variables set in the Makefile are located in * the global context. It is the penultimate context searched when * substituting. * 3) the command-line context. All variables set on the command line * are placed in this context. They are UNALTERABLE once placed here. * 4) the local context. Each target has associated with it a context * list. On this list are located the structures describing such * local variables as $(@) and $(*) * The four contexts are searched in the reverse order from which they are * listed. */ static GNode *VAR_ENV; /* variables from the environment */ GNode *VAR_GLOBAL; /* variables from the makefile */ GNode *VAR_CMD; /* variables defined on the command-line */ Boolean oldVars; /* variable substitution style */ Boolean checkEnvFirst; /* -e flag */ #define OPEN_PAREN '(' #define CLOSE_PAREN ')' #define OPEN_BRACE '{' #define CLOSE_BRACE '}' /** * Create a Var object. * * Params: * name Name of variable (copied). * value Value of variable (copied) or NULL. * flags Flags set on variable. * * Returns: * New variable. */ static Var * VarCreate(const char name[], const char value[], int flags) { Var *v; v = emalloc(sizeof(Var)); v->name = estrdup(name); v->val = Buf_Init(0); v->flags = flags; if (value != NULL) { Buf_Append(v->val, value); } return (v); } /** * Destroy a Var object. * * Params: * v Object to destroy. * f True if internal buffer in Buffer object is to be removed. */ static void VarDestroy(Var *v, Boolean f) { Buf_Destroy(v->val, f); free(v->name); free(v); } /** * Remove the tail of the given word and place the result in the given * buffer. * * Results: * TRUE if characters were added to the buffer (a space needs to be * added to the buffer before the next word). * * Side Effects: * The trimmed word is added to the buffer. */ static Boolean VarHead(const char *word, Boolean addSpace, Buffer *buf, void *dummy __unused) { char *slash; slash = strrchr(word, '/'); if (slash != NULL) { if (addSpace) { Buf_AddByte(buf, (Byte)' '); } Buf_AppendRange(buf, word, slash); } else { /* * If no directory part, give . (q.v. the POSIX standard) */ if (addSpace) { Buf_Append(buf, " ."); } else { Buf_AddByte(buf, (Byte)'.'); } } return (TRUE); } /** * Remove the head of the given word and place the result in the given * buffer. * * Results: * TRUE if characters were added to the buffer (a space needs to be * added to the buffer before the next word). * * Side Effects: * The trimmed word is added to the buffer. */ static Boolean VarTail(const char *word, Boolean addSpace, Buffer *buf, void *dummy __unused) { const char *slash; if (addSpace) { Buf_AddByte (buf, (Byte)' '); } slash = strrchr(word, '/'); if (slash != NULL) { slash++; Buf_Append(buf, slash); } else { Buf_Append(buf, word); } return (TRUE); } /** * Place the suffix of the given word in the given buffer. * * Results: * TRUE if characters were added to the buffer (a space needs to be * added to the buffer before the next word). * * Side Effects: * The suffix from the word is placed in the buffer. */ static Boolean VarSuffix(const char *word, Boolean addSpace, Buffer *buf, void *dummy __unused) { const char *dot; dot = strrchr(word, '.'); if (dot != NULL) { if (addSpace) { Buf_AddByte(buf, (Byte)' '); } dot++; Buf_Append(buf, dot); addSpace = TRUE; } return (addSpace); } /** * Remove the suffix of the given word and place the result in the * buffer. * * Results: * TRUE if characters were added to the buffer (a space needs to be * added to the buffer before the next word). * * Side Effects: * The trimmed word is added to the buffer. */ static Boolean VarRoot(const char *word, Boolean addSpace, Buffer *buf, void *dummy __unused) { char *dot; if (addSpace) { Buf_AddByte(buf, (Byte)' '); } dot = strrchr(word, '.'); if (dot != NULL) { Buf_AppendRange(buf, word, dot); } else { Buf_Append(buf, word); } return (TRUE); } /** * Place the word in the buffer if it matches the given pattern. * Callback function for VarModify to implement the :M modifier. * A space will be added if requested. A pattern is supplied * which the word must match. * * Results: * TRUE if a space should be placed in the buffer before the next * word. * * Side Effects: * The word may be copied to the buffer. */ static Boolean VarMatch(const char *word, Boolean addSpace, Buffer *buf, void *pattern) { if (Str_Match(word, pattern)) { if (addSpace) { Buf_AddByte(buf, (Byte)' '); } addSpace = TRUE; Buf_Append(buf, word); } return (addSpace); } #ifdef SYSVVARSUB /** * Place the word in the buffer if it matches the given pattern. * Callback function for VarModify to implement the System V % * modifiers. A space is added if requested. * * Results: * TRUE if a space should be placed in the buffer before the next * word. * * Side Effects: * The word may be copied to the buffer. */ static Boolean VarSYSVMatch(const char *word, Boolean addSpace, Buffer *buf, void *patp) { int len; const char *ptr; VarPattern *pat = (VarPattern *)patp; if (addSpace) Buf_AddByte(buf, (Byte)' '); addSpace = TRUE; if ((ptr = Str_SYSVMatch(word, Buf_Data(pat->lhs), &len)) != NULL) Str_SYSVSubst(buf, Buf_Data(pat->rhs), ptr, len); else Buf_Append(buf, word); return (addSpace); } #endif /** * Place the word in the buffer if it doesn't match the given pattern. * Callback function for VarModify to implement the :N modifier. A * space is added if requested. * * Results: * TRUE if a space should be placed in the buffer before the next * word. * * Side Effects: * The word may be copied to the buffer. */ static Boolean VarNoMatch(const char *word, Boolean addSpace, Buffer *buf, void *pattern) { if (!Str_Match(word, pattern)) { if (addSpace) { Buf_AddByte(buf, (Byte)' '); } addSpace = TRUE; Buf_Append(buf, word); } return (addSpace); } /** * Perform a string-substitution on the given word, placing the * result in the passed buffer. A space is added if requested. * * Results: * TRUE if a space is needed before more characters are added. */ static Boolean VarSubstitute(const char *word, Boolean addSpace, Buffer *buf, void *patternp) { size_t wordLen; /* Length of word */ const char *cp; /* General pointer */ VarPattern *pattern = patternp; wordLen = strlen(word); if (1) { /* substitute in each word of the variable */ /* * Break substitution down into simple anchored cases * and if none of them fits, perform the general substitution * case. */ if ((pattern->flags & VAR_MATCH_START) && (strncmp(word, Buf_Data(pattern->lhs), Buf_Size(pattern->lhs)) == 0)) { /* * Anchored at start and beginning of word matches * pattern. */ if ((pattern->flags & VAR_MATCH_END) && (wordLen == Buf_Size(pattern->lhs))) { /* * Also anchored at end and matches to the end * (word is same length as pattern) add space * and rhs only if rhs is non-null. */ if (Buf_Size(pattern->rhs) != 0) { if (addSpace) { Buf_AddByte(buf, (Byte)' '); } addSpace = TRUE; Buf_AppendBuf(buf, pattern->rhs); } } else if (pattern->flags & VAR_MATCH_END) { /* * Doesn't match to end -- copy word wholesale */ goto nosub; } else { /* * Matches at start but need to copy in * trailing characters. */ if ((Buf_Size(pattern->rhs) + wordLen - Buf_Size(pattern->lhs)) != 0) { if (addSpace) { Buf_AddByte(buf, (Byte)' '); } addSpace = TRUE; } Buf_AppendBuf(buf, pattern->rhs); Buf_AddBytes(buf, wordLen - Buf_Size(pattern->lhs), (word + Buf_Size(pattern->lhs))); } } else if (pattern->flags & VAR_MATCH_START) { /* * Had to match at start of word and didn't -- copy * whole word. */ goto nosub; } else if (pattern->flags & VAR_MATCH_END) { /* * Anchored at end, Find only place match could occur * (leftLen characters from the end of the word) and * see if it does. Note that because the $ will be * left at the end of the lhs, we have to use strncmp. */ cp = word + (wordLen - Buf_Size(pattern->lhs)); if ((cp >= word) && (strncmp(cp, Buf_Data(pattern->lhs), Buf_Size(pattern->lhs)) == 0)) { /* * Match found. If we will place characters in * the buffer, add a space before hand as * indicated by addSpace, then stuff in the * initial, unmatched part of the word followed * by the right-hand-side. */ if ((cp - word) + Buf_Size(pattern->rhs) != 0) { if (addSpace) { Buf_AddByte(buf, (Byte)' '); } addSpace = TRUE; } Buf_AppendRange(buf, word, cp); Buf_AppendBuf(buf, pattern->rhs); } else { /* * Had to match at end and didn't. Copy entire * word. */ goto nosub; } } else { /* * Pattern is unanchored: search for the pattern in the * word using strstr(3), copying unmatched portions and * the right-hand-side for each match found, handling * non-global substitutions correctly, etc. When the * loop is done, any remaining part of the word (word * and wordLen are adjusted accordingly through the * loop) is copied straight into the buffer. * addSpace is set FALSE as soon as a space is added * to the buffer. */ Boolean done; size_t origSize; done = FALSE; origSize = Buf_Size(buf); while (!done) { cp = strstr(word, Buf_Data(pattern->lhs)); if (cp != NULL) { if (addSpace && (((cp - word) + Buf_Size(pattern->rhs)) != 0)) { Buf_AddByte(buf, (Byte)' '); addSpace = FALSE; } Buf_AppendRange(buf, word, cp); Buf_AppendBuf(buf, pattern->rhs); wordLen -= (cp - word) + Buf_Size(pattern->lhs); word = cp + Buf_Size(pattern->lhs); if (wordLen == 0 || (pattern->flags & VAR_SUB_GLOBAL) == 0) { done = TRUE; } } else { done = TRUE; } } if (wordLen != 0) { if (addSpace) { Buf_AddByte(buf, (Byte)' '); } Buf_AddBytes(buf, wordLen, (const Byte *)word); } /* * If added characters to the buffer, need to add a * space before we add any more. If we didn't add any, * just return the previous value of addSpace. */ return ((Buf_Size(buf) != origSize) || addSpace); } /* * Common code for anchored substitutions: * addSpace was set TRUE if characters were added to the buffer. */ return (addSpace); } nosub: if (addSpace) { Buf_AddByte(buf, (Byte)' '); } Buf_AddBytes(buf, wordLen, (const Byte *)word); return (TRUE); } /** * Print the error caused by a regcomp or regexec call. * * Side Effects: * An error gets printed. */ static void VarREError(int err, regex_t *pat, const char *str) { char *errbuf; int errlen; errlen = regerror(err, pat, 0, 0); errbuf = emalloc(errlen); regerror(err, pat, errbuf, errlen); Error("%s: %s", str, errbuf); free(errbuf); } /** * Perform a regex substitution on the given word, placing the * result in the passed buffer. A space is added if requested. * * Results: * TRUE if a space is needed before more characters are added. */ static Boolean VarRESubstitute(const char *word, Boolean addSpace, Buffer *buf, void *patternp) { VarPattern *pat; int xrv; const char *wp; char *rp; int added; int flags = 0; #define MAYBE_ADD_SPACE() \ if (addSpace && !added) \ Buf_AddByte(buf, (Byte)' '); \ added = 1 added = 0; wp = word; pat = patternp; if ((pat->flags & (VAR_SUB_ONE | VAR_SUB_MATCHED)) == (VAR_SUB_ONE | VAR_SUB_MATCHED)) { xrv = REG_NOMATCH; } else { tryagain: xrv = regexec(&pat->re, wp, pat->nsub, pat->matches, flags); } switch (xrv) { case 0: pat->flags |= VAR_SUB_MATCHED; if (pat->matches[0].rm_so > 0) { MAYBE_ADD_SPACE(); Buf_AddBytes(buf, pat->matches[0].rm_so, (const Byte *)wp); } for (rp = Buf_Data(pat->rhs); *rp; rp++) { if ((*rp == '\\') && ((rp[1] == '&') || (rp[1] == '\\'))) { MAYBE_ADD_SPACE(); Buf_AddByte(buf, (Byte)rp[1]); rp++; } else if ((*rp == '&') || ((*rp == '\\') && isdigit((unsigned char)rp[1]))) { int n; const char *subbuf; int sublen; char errstr[3]; if (*rp == '&') { n = 0; errstr[0] = '&'; errstr[1] = '\0'; } else { n = rp[1] - '0'; errstr[0] = '\\'; errstr[1] = rp[1]; errstr[2] = '\0'; rp++; } if (n > pat->nsub) { Error("No subexpression %s", &errstr[0]); subbuf = ""; sublen = 0; } else if ((pat->matches[n].rm_so == -1) && (pat->matches[n].rm_eo == -1)) { Error("No match for subexpression %s", &errstr[0]); subbuf = ""; sublen = 0; } else { subbuf = wp + pat->matches[n].rm_so; sublen = pat->matches[n].rm_eo - pat->matches[n].rm_so; } if (sublen > 0) { MAYBE_ADD_SPACE(); Buf_AddBytes(buf, sublen, (const Byte *)subbuf); } } else { MAYBE_ADD_SPACE(); Buf_AddByte(buf, (Byte)*rp); } } wp += pat->matches[0].rm_eo; if (pat->flags & VAR_SUB_GLOBAL) { flags |= REG_NOTBOL; if (pat->matches[0].rm_so == 0 && pat->matches[0].rm_eo == 0) { MAYBE_ADD_SPACE(); Buf_AddByte(buf, (Byte)*wp); wp++; } if (*wp) goto tryagain; } if (*wp) { MAYBE_ADD_SPACE(); Buf_Append(buf, wp); } break; default: VarREError(xrv, &pat->re, "Unexpected regex error"); /* fall through */ case REG_NOMATCH: if (*wp) { MAYBE_ADD_SPACE(); Buf_Append(buf, wp); } break; } return (addSpace || added); } /** * Find a variable in a variable list. */ static Var * VarLookup(Lst *vlist, const char *name) { LstNode *ln; LST_FOREACH(ln, vlist) if (strcmp(((const Var *)Lst_Datum(ln))->name, name) == 0) return (Lst_Datum(ln)); return (NULL); } /** * Expand a variable name's embedded variables in the given context. * * Results: * The contents of name, possibly expanded. */ static char * VarPossiblyExpand(const char *name, GNode *ctxt) { Buffer *buf; if (strchr(name, '$') != NULL) { buf = Var_Subst(name, ctxt, 0); return (Buf_Peel(buf)); } else { return estrdup(name); } } /** * If the variable name begins with a '.', it could very well be * one of the local ones. We check the name against all the local * variables and substitute the short version in for 'name' if it * matches one of them. */ static const char * VarLocal(const char name[]) { if (name[0] == '.') { switch (name[1]) { case 'A': if (!strcmp(name, ".ALLSRC")) return (ALLSRC); if (!strcmp(name, ".ARCHIVE")) return (ARCHIVE); break; case 'I': if (!strcmp(name, ".IMPSRC")) return (IMPSRC); break; case 'M': if (!strcmp(name, ".MEMBER")) return (MEMBER); break; case 'O': if (!strcmp(name, ".OODATE")) return (OODATE); break; case 'P': if (!strcmp(name, ".PREFIX")) return (PREFIX); break; case 'T': if (!strcmp(name, ".TARGET")) return (TARGET); break; default: break; } } return (name); } /** * Find the given variable in the given context and the environment. * * Results: * A pointer to the structure describing the desired variable or * NULL if the variable does not exist. */ static Var * VarFindEnv(const char name[], GNode *ctxt) { Var *var; name = VarLocal(name); if ((var = VarLookup(&ctxt->context, name)) != NULL) return (var); if ((var = VarLookup(&VAR_ENV->context, name)) != NULL) return (var); return (NULL); } /** * Look for the variable in the given context. */ static Var * VarFindOnly(const char name[], GNode *ctxt) { Var *var; name = VarLocal(name); if ((var = VarLookup(&ctxt->context, name)) != NULL) return (var); return (NULL); } /** * Look for the variable in all contexts. */ static Var * VarFindAny(const char name[], GNode *ctxt) { Boolean localCheckEnvFirst; LstNode *ln; Var *var; name = VarLocal(name); /* * Note whether this is one of the specific variables we were told * through the -E flag to use environment-variable-override for. */ localCheckEnvFirst = FALSE; LST_FOREACH(ln, &envFirstVars) { if (strcmp(Lst_Datum(ln), name) == 0) { localCheckEnvFirst = TRUE; break; } } /* * First look for the variable in the given context. If it's not there, * look for it in VAR_CMD, VAR_GLOBAL and the environment, * in that order, depending on the FIND_* flags in 'flags' */ if ((var = VarLookup(&ctxt->context, name)) != NULL) return (var); /* not there - try command line context */ if (ctxt != VAR_CMD) { if ((var = VarLookup(&VAR_CMD->context, name)) != NULL) return (var); } /* not there - try global context, but only if not -e/-E */ if (ctxt != VAR_GLOBAL && (!checkEnvFirst && !localCheckEnvFirst)) { if ((var = VarLookup(&VAR_GLOBAL->context, name)) != NULL) return (var); } if ((var = VarLookup(&VAR_ENV->context, name)) != NULL) return (var); /* deferred check for the environment (in case of -e/-E) */ if ((ctxt != VAR_GLOBAL) && (checkEnvFirst || localCheckEnvFirst)) { if ((var = VarLookup(&VAR_GLOBAL->context, name)) != NULL) return (var); } return (NULL); } /** * Add a new variable of name name and value val to the given context. * * Side Effects: * The new variable is placed at the front of the given context * The name and val arguments are duplicated so they may * safely be freed. */ static Var * VarAdd(const char *name, const char *val, GNode *ctxt) { Var *v; Lst_AtFront(&ctxt->context, v = VarCreate(name, val, 0)); DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name, val)); return (v); } /** * Remove a variable from a context. * * Side Effects: * The Var structure is removed and freed. */ void Var_Delete(const char *name, GNode *ctxt) { LstNode *ln; DEBUGF(VAR, ("%s:delete %s\n", ctxt->name, name)); LST_FOREACH(ln, &ctxt->context) { if (strcmp(((const Var *)Lst_Datum(ln))->name, name) == 0) { VarDestroy(Lst_Datum(ln), TRUE); Lst_Remove(&ctxt->context, ln); break; } } } /** * Set the variable name to the value val in the given context. * * Side Effects: * If the variable doesn't yet exist, a new record is created for it. * Else the old value is freed and the new one stuck in its place * * Notes: * The variable is searched for only in its context before being * created in that context. I.e. if the context is VAR_GLOBAL, * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only * VAR_CMD->context is searched. This is done to avoid the literally * thousands of unnecessary strcmp's that used to be done to * set, say, $(@) or $(<). */ void Var_Set(const char *name, const char *val, GNode *ctxt) { Var *v; char *n; /* * We only look for a variable in the given context since anything * set here will override anything in a lower context, so there's not * much point in searching them all just to save a bit of memory... */ n = VarPossiblyExpand(name, ctxt); v = VarFindOnly(n, ctxt); if (v == NULL) { v = VarAdd(n, val, ctxt); } else { Buf_Clear(v->val); Buf_Append(v->val, val); DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, n, val)); } if (ctxt == VAR_CMD || (v->flags & VAR_TO_ENV)) { /* * Any variables given on the command line * are automatically exported to the * environment (as per POSIX standard) */ setenv(n, val, 1); } free(n); } /** * Set the a global name variable to the value. */ void Var_SetGlobal(const char name[], const char value[]) { Var_Set(name, value, VAR_GLOBAL); } /** * Set the VAR_TO_ENV flag on a variable */ void Var_SetEnv(const char *name, GNode *ctxt) { Var *v; v = VarFindOnly(name, VAR_CMD); if (v != NULL) { /* * Do not allow .EXPORT: to be set on variables * from the comand line or MAKEFLAGS. */ Error( "Warning: Did not set .EXPORTVAR: on %s because it " "is from the comand line or MAKEFLAGS", name); return; } v = VarFindAny(name, ctxt); if (v == NULL) { Lst_AtFront(&VAR_ENV->context, VarCreate(name, NULL, VAR_TO_ENV)); setenv(name, "", 1); Error("Warning: .EXPORTVAR: set on undefined variable %s", name); } else { if ((v->flags & VAR_TO_ENV) == 0) { v->flags |= VAR_TO_ENV; setenv(v->name, Buf_Data(v->val), 1); } } } /** * The variable of the given name has the given value appended to it in * the given context. * * Side Effects: * If the variable doesn't exist, it is created. Else the strings * are concatenated (with a space in between). * * Notes: * Only if the variable is being sought in the global context is the * environment searched. * XXX: Knows its calling circumstances in that if called with ctxt * an actual target, it will only search that context since only * a local variable could be being appended to. This is actually * a big win and must be tolerated. */ void Var_Append(const char *name, const char *val, GNode *ctxt) { Var *v; char *n; n = VarPossiblyExpand(name, ctxt); if (ctxt == VAR_GLOBAL) { v = VarFindEnv(n, ctxt); } else { v = VarFindOnly(n, ctxt); } if (v == NULL) { VarAdd(n, val, ctxt); } else { Buf_AddByte(v->val, (Byte)' '); Buf_Append(v->val, val); DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, n, Buf_Data(v->val))); } free(n); } /** * See if the given variable exists. * * Results: * TRUE if it does, FALSE if it doesn't */ Boolean Var_Exists(const char *name, GNode *ctxt) { Var *v; char *n; n = VarPossiblyExpand(name, ctxt); v = VarFindAny(n, ctxt); if (v == NULL) { free(n); return (FALSE); } else { free(n); return (TRUE); } } /** * Return the value of the named variable in the given context * * Results: * The value if the variable exists, NULL if it doesn't. */ const char * Var_Value(const char name[], GNode *ctxt) { Var *v; char *n; n = VarPossiblyExpand(name, ctxt); v = VarFindAny(n, ctxt); free(n); if (v == NULL) { return (NULL); } else { return (Buf_Data(v->val)); } } /** * Modify each of the words of the passed string using the given * function. Used to implement all modifiers. * * Results: * A string of all the words modified appropriately. * * Side Effects: * Uses brk_string() so it invalidates any previous call to * brk_string(). */ static char * VarModify(const char *str, VarModifyProc *modProc, void *datum) { ArgArray aa; Buffer *buf; /* Buffer for the new string */ int i; Boolean addSpace; /* * TRUE if need to add a space to * the buffer before adding the * trimmed word */ brk_string(&aa, str, FALSE); addSpace = FALSE; buf = Buf_Init(0); for (i = 1; i < aa.argc; i++) addSpace = (*modProc)(aa.argv[i], addSpace, buf, datum); ArgArray_Done(&aa); return (Buf_Peel(buf)); } /** * Sort the words in the string. * * Input: * str String whose words should be sorted * cmp A comparison function to control the ordering * * Results: * A string containing the words sorted */ static char * VarSortWords(const char *str, int (*cmp)(const void *, const void *)) { ArgArray aa; Buffer *buf; int i; brk_string(&aa, str, FALSE); qsort(aa.argv + 1, aa.argc - 1, sizeof(char *), cmp); buf = Buf_Init(0); for (i = 1; i < aa.argc; i++) { Buf_Append(buf, aa.argv[i]); Buf_AddByte(buf, (Byte)((i < aa.argc - 1) ? ' ' : '\0')); } ArgArray_Done(&aa); return (Buf_Peel(buf)); } static int SortIncreasing(const void *l, const void *r) { return (strcmp(*(const char* const*)l, *(const char* const*)r)); } /** * Remove adjacent duplicate words. * * Results: * A string containing the resulting words. */ static char * VarUniq(const char *str) { ArgArray aa; Buffer *buf; /* Buffer for new string */ int i, j; buf = Buf_Init(0); brk_string(&aa, str, FALSE); if (aa.argc > 2) { for (j = 1, i = 2; i < aa.argc; i++) { if (strcmp(aa.argv[i], aa.argv[j]) != 0 && (++j != i)) aa.argv[j] = aa.argv[i]; } aa.argc = j + 1; } for (i = 1; i < aa.argc; i++) { Buf_AddBytes(buf, strlen(aa.argv[i]), (Byte *)aa.argv[i]); if (i != aa.argc - 1) Buf_AddByte(buf, ' '); } Buf_AddByte(buf, '\0'); ArgArray_Done(&aa); return (Buf_Peel(buf)); } /** * Pass through the tstr looking for 1) escaped delimiters, * '$'s and backslashes (place the escaped character in * uninterpreted) and 2) unescaped $'s that aren't before * the delimiter (expand the variable substitution). * Return the expanded string or NULL if the delimiter was missing * If pattern is specified, handle escaped ampersands, and replace * unescaped ampersands with the lhs of the pattern. * * Results: * A string of all the words modified appropriately. * If length is specified, return the string length of the buffer * If flags is specified and the last character of the pattern is a * $ set the VAR_MATCH_END bit of flags. */ static Buffer * VarGetPattern(VarParser *vp, int delim, int *flags, VarPattern *patt) { Buffer *buf; buf = Buf_Init(0); /* * Skim through until the matching delimiter is found; pick up * variable substitutions on the way. Also allow backslashes to quote * the delimiter, $, and \, but don't touch other backslashes. */ while (*vp->ptr != '\0') { if (*vp->ptr == delim) { return (buf); } else if ((vp->ptr[0] == '\\') && ((vp->ptr[1] == delim) || (vp->ptr[1] == '\\') || (vp->ptr[1] == '$') || (vp->ptr[1] == '&' && patt != NULL))) { vp->ptr++; /* consume backslash */ Buf_AddByte(buf, (Byte)vp->ptr[0]); vp->ptr++; } else if (vp->ptr[0] == '$') { if (vp->ptr[1] == delim) { if (flags == NULL) { Buf_AddByte(buf, (Byte)vp->ptr[0]); vp->ptr++; } else { /* * Unescaped $ at end of patt => * anchor patt at end. */ *flags |= VAR_MATCH_END; vp->ptr++; } } else { VarParser subvp = { vp->ptr, vp->ptr, vp->ctxt, vp->err, vp->execute }; char *rval; Boolean rfree; /* * If unescaped dollar sign not * before the delimiter, assume it's * a variable substitution and * recurse. */ rval = VarParse(&subvp, &rfree); Buf_Append(buf, rval); if (rfree) free(rval); vp->ptr = subvp.ptr; } } else if (vp->ptr[0] == '&' && patt != NULL) { Buf_AppendBuf(buf, patt->lhs); vp->ptr++; } else { Buf_AddByte(buf, (Byte)vp->ptr[0]); vp->ptr++; } } Buf_Destroy(buf, TRUE); return (NULL); } /** * Make sure this variable is fully expanded. */ static char * VarExpand(Var *v, VarParser *vp) { char *value; char *result; if (v->flags & VAR_IN_USE) { Fatal("Variable %s is recursive.", v->name); /* NOTREACHED */ } v->flags |= VAR_IN_USE; /* * Before doing any modification, we have to make sure the * value has been fully expanded. If it looks like recursion * might be necessary (there's a dollar sign somewhere in the * variable's value) we just call Var_Subst to do any other * substitutions that are necessary. Note that the value * returned by Var_Subst will have been * dynamically-allocated, so it will need freeing when we * return. */ value = Buf_Data(v->val); if (strchr(value, '$') == NULL) { result = strdup(value); } else { Buffer *buf; buf = Var_Subst(value, vp->ctxt, vp->err); result = Buf_Peel(buf); } v->flags &= ~VAR_IN_USE; return (result); } /** * Select only those words in value that match the modifier. */ static char * modifier_M(VarParser *vp, const char value[], char endc) { char *patt; char *ptr; char *newValue; char modifier; modifier = vp->ptr[0]; vp->ptr++; /* consume 'M' or 'N' */ /* * Compress the \:'s out of the pattern, so allocate enough * room to hold the uncompressed pattern and compress the * pattern into that space. */ patt = estrdup(vp->ptr); ptr = patt; while (vp->ptr[0] != '\0') { if (vp->ptr[0] == endc || vp->ptr[0] == ':') { break; } if (vp->ptr[0] == '\\' && (vp->ptr[1] == endc || vp->ptr[1] == ':')) { vp->ptr++; /* consume backslash */ } *ptr = vp->ptr[0]; ptr++; vp->ptr++; } *ptr = '\0'; DEBUGF(VAR, ("Pattern :%s\n", patt)); if (modifier == 'M') { newValue = VarModify(value, VarMatch, patt); } else { newValue = VarModify(value, VarNoMatch, patt); } free(patt); return (newValue); } /** * Substitute the replacement string for the pattern. The substitution * is applied to each word in value. */ static char * modifier_S(VarParser *vp, const char value[], Var *v) { VarPattern patt; char delim; char *newValue; patt.flags = 0; vp->ptr++; /* consume 'S' */ delim = *vp->ptr; /* used to find end of pattern */ vp->ptr++; /* consume 1st delim */ /* * If pattern begins with '^', it is anchored to the start of the * word -- skip over it and flag pattern. */ if (*vp->ptr == '^') { patt.flags |= VAR_MATCH_START; vp->ptr++; } patt.lhs = VarGetPattern(vp, delim, &patt.flags, NULL); if (patt.lhs == NULL) { /* * LHS didn't end with the delim, complain and exit. */ Fatal("Unclosed substitution for %s (%c missing)", v->name, delim); } vp->ptr++; /* consume 2nd delim */ patt.rhs = VarGetPattern(vp, delim, NULL, &patt); if (patt.rhs == NULL) { /* * RHS didn't end with the delim, complain and exit. */ Fatal("Unclosed substitution for %s (%c missing)", v->name, delim); } vp->ptr++; /* consume last delim */ /* * Check for global substitution. If 'g' after the final delimiter, * substitution is global and is marked that way. */ if (vp->ptr[0] == 'g') { patt.flags |= VAR_SUB_GLOBAL; vp->ptr++; } /* * Global substitution of the empty string causes an infinite number * of matches, unless anchored by '^' (start of string) or '$' (end * of string). Catch the infinite substitution here. Note that flags * can only contain the 3 bits we're interested in so we don't have * to mask unrelated bits. We can test for equality. */ if (Buf_Size(patt.lhs) == 0 && patt.flags == VAR_SUB_GLOBAL) Fatal("Global substitution of the empty string"); newValue = VarModify(value, VarSubstitute, &patt); /* * Free the two strings. */ free(patt.lhs); free(patt.rhs); return (newValue); } static char * modifier_C(VarParser *vp, char value[], Var *v) { VarPattern patt; char delim; int error; char *newValue; patt.flags = 0; vp->ptr++; /* consume 'C' */ delim = *vp->ptr; /* delimiter between sections */ vp->ptr++; /* consume 1st delim */ patt.lhs = VarGetPattern(vp, delim, NULL, NULL); if (patt.lhs == NULL) { Fatal("Unclosed substitution for %s (%c missing)", v->name, delim); } vp->ptr++; /* consume 2st delim */ patt.rhs = VarGetPattern(vp, delim, NULL, NULL); if (patt.rhs == NULL) { Fatal("Unclosed substitution for %s (%c missing)", v->name, delim); } vp->ptr++; /* consume last delim */ switch (*vp->ptr) { case 'g': patt.flags |= VAR_SUB_GLOBAL; vp->ptr++; /* consume 'g' */ break; case '1': patt.flags |= VAR_SUB_ONE; vp->ptr++; /* consume '1' */ break; default: break; } error = regcomp(&patt.re, Buf_Data(patt.lhs), REG_EXTENDED); if (error) { VarREError(error, &patt.re, "RE substitution error"); free(patt.rhs); free(patt.lhs); return (var_Error); } patt.nsub = patt.re.re_nsub + 1; if (patt.nsub < 1) patt.nsub = 1; if (patt.nsub > 10) patt.nsub = 10; patt.matches = emalloc(patt.nsub * sizeof(regmatch_t)); newValue = VarModify(value, VarRESubstitute, &patt); regfree(&patt.re); free(patt.matches); free(patt.rhs); free(patt.lhs); return (newValue); } static char * sysVvarsub(VarParser *vp, char startc, Var *v, const char value[]) { #ifdef SYSVVARSUB /* * This can either be a bogus modifier or a System-V substitution * command. */ char endc; VarPattern patt; Boolean eqFound; int cnt; char *newStr; const char *cp; endc = (startc == OPEN_PAREN) ? CLOSE_PAREN : CLOSE_BRACE; patt.flags = 0; /* * First we make a pass through the string trying to verify it is a * SYSV-make-style translation: it must be: =) */ eqFound = FALSE; cp = vp->ptr; cnt = 1; while (*cp != '\0' && cnt) { if (*cp == '=') { eqFound = TRUE; /* continue looking for endc */ } else if (*cp == endc) cnt--; else if (*cp == startc) cnt++; if (cnt) cp++; } if (*cp == endc && eqFound) { /* * Now we break this sucker into the lhs and rhs. */ patt.lhs = VarGetPattern(vp, '=', &patt.flags, NULL); if (patt.lhs == NULL) { Fatal("Unclosed substitution for %s (%c missing)", v->name, '='); } vp->ptr++; /* consume '=' */ patt.rhs = VarGetPattern(vp, endc, NULL, &patt); if (patt.rhs == NULL) { Fatal("Unclosed substitution for %s (%c missing)", v->name, endc); } /* * SYSV modifications happen through the whole string. Note * the pattern is anchored at the end. */ newStr = VarModify(value, VarSYSVMatch, &patt); free(patt.lhs); free(patt.rhs); } else #endif { Error("Unknown modifier '%c'\n", *vp->ptr); vp->ptr++; while (*vp->ptr != '\0') { if (*vp->ptr == endc && *vp->ptr == ':') { break; } vp->ptr++; } newStr = var_Error; } return (newStr); } /** * Quote shell meta-characters in the string * * Results: * The quoted string */ static char * Var_Quote(const char *str) { Buffer *buf; /* This should cover most shells :-( */ static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~"; buf = Buf_Init(MAKE_BSIZE); for (; *str; str++) { if (strchr(meta, *str) != NULL) Buf_AddByte(buf, (Byte)'\\'); Buf_AddByte(buf, (Byte)*str); } return (Buf_Peel(buf)); } /* * Now we need to apply any modifiers the user wants applied. * These are: * :M * words which match the given . * is of the standard file * wildcarding form. * :N * words which do not match the given * is of the standard file * wildcarding form. * :S[g] * Substitute for in the value * :C[g] * Substitute for regex in the value * :H Substitute the head of each word * :T Substitute the tail of each word * :E Substitute the extension (minus '.') of * each word * :R Substitute the root of each word * (pathname minus the suffix). * :lhs=rhs * Like :S, but the rhs goes to the end of * the invocation. * :U Converts variable to upper-case. * :L Converts variable to lower-case. * :O ("Order") Alphabeticaly sort words in variable. * :u ("uniq") Remove adjacent duplicate words. */ static char * ParseModifier(VarParser *vp, char startc, Var *v, Boolean *freeResult) { char *value; char endc; value = VarExpand(v, vp); *freeResult = TRUE; endc = (startc == OPEN_PAREN) ? CLOSE_PAREN : CLOSE_BRACE; vp->ptr++; /* consume first colon */ while (*vp->ptr != '\0') { char *newStr; /* New value to return */ if (*vp->ptr == endc) { return (value); } DEBUGF(VAR, ("Applying :%c to \"%s\"\n", *vp->ptr, value)); switch (*vp->ptr) { case 'N': case 'M': newStr = modifier_M(vp, value, endc); break; case 'S': newStr = modifier_S(vp, value, v); break; case 'C': newStr = modifier_C(vp, value, v); break; case 't': /* :tl :tu for OSF ODE & NetBSD make compatibility */ switch (vp->ptr[1]) { case 'l': vp->ptr++; goto mod_lower; break; case 'u': vp->ptr++; goto mod_upper; break; } /* FALLTHROUGH */ default: if (vp->ptr[1] != endc && vp->ptr[1] != ':') { #ifdef SUNSHCMD if ((vp->ptr[0] == 's') && (vp->ptr[1] == 'h') && (vp->ptr[2] == endc || vp->ptr[2] == ':')) { const char *error = NULL; if (vp->execute) { newStr = Buf_Peel( Cmd_Exec(value, &error)); } else { newStr = estrdup(""); } if (error) Error(error, value); vp->ptr += 2; } else #endif { newStr = sysVvarsub(vp, startc, v, value); } break; } switch (vp->ptr[0]) { case 'L': mod_lower: { const char *cp; Buffer *buf; buf = Buf_Init(MAKE_BSIZE); for (cp = value; *cp; cp++) Buf_AddByte(buf, (Byte)tolower(*cp)); newStr = Buf_Peel(buf); vp->ptr++; break; } case 'O': newStr = VarSortWords(value, SortIncreasing); vp->ptr++; break; case 'Q': newStr = Var_Quote(value); vp->ptr++; break; case 'T': newStr = VarModify(value, VarTail, NULL); vp->ptr++; break; case 'U': mod_upper: { const char *cp; Buffer *buf; buf = Buf_Init(MAKE_BSIZE); for (cp = value; *cp; cp++) Buf_AddByte(buf, (Byte)toupper(*cp)); newStr = Buf_Peel(buf); vp->ptr++; break; } case 'H': newStr = VarModify(value, VarHead, NULL); vp->ptr++; break; case 'E': newStr = VarModify(value, VarSuffix, NULL); vp->ptr++; break; case 'R': newStr = VarModify(value, VarRoot, NULL); vp->ptr++; break; case 'u': newStr = VarUniq(value); vp->ptr++; break; default: newStr = sysVvarsub(vp, startc, v, value); break; } break; } DEBUGF(VAR, ("Result is \"%s\"\n", newStr)); if (*freeResult) { free(value); } value = newStr; *freeResult = (value == var_Error) ? FALSE : TRUE; if (vp->ptr[0] == ':') { vp->ptr++; /* consume colon */ } } return (value); } static char * ParseRestModifier(VarParser *vp, char startc, Buffer *buf, Boolean *freeResult) { const char *vname; size_t vlen; Var *v; char *value; vname = Buf_GetAll(buf, &vlen); v = VarFindAny(vname, vp->ctxt); if (v != NULL) { value = ParseModifier(vp, startc, v, freeResult); return (value); } if ((vp->ctxt == VAR_CMD) || (vp->ctxt == VAR_GLOBAL)) { size_t consumed; /* * Still need to get to the end of the variable * specification, so kludge up a Var structure for the * modifications */ v = VarCreate(vname, NULL, VAR_JUNK); value = ParseModifier(vp, startc, v, freeResult); if (*freeResult) { free(value); } VarDestroy(v, TRUE); consumed = vp->ptr - vp->input + 1; /* * If substituting a local variable in a non-local context, * assume it's for dynamic source stuff. We have to handle * this specially and return the longhand for the variable * with the dollar sign escaped so it makes it back to the * caller. Only four of the local variables are treated * specially as they are the only four that will be set when * dynamic sources are expanded. */ if (vlen == 1 || (vlen == 2 && (vname[1] == 'F' || vname[1] == 'D'))) { if (strchr("!%*@", vname[0]) != NULL) { value = emalloc(consumed + 1); strncpy(value, vp->input, consumed); value[consumed] = '\0'; *freeResult = TRUE; return (value); } } if (vlen > 2 && vname[0] == '.' && isupper((unsigned char)vname[1])) { if ((strncmp(vname, ".TARGET", vlen - 1) == 0) || (strncmp(vname, ".ARCHIVE", vlen - 1) == 0) || (strncmp(vname, ".PREFIX", vlen - 1) == 0) || (strncmp(vname, ".MEMBER", vlen - 1) == 0)) { value = emalloc(consumed + 1); strncpy(value, vp->input, consumed); value[consumed] = '\0'; *freeResult = TRUE; return (value); } } *freeResult = FALSE; return (vp->err ? var_Error : varNoError); } else { /* * Check for D and F forms of local variables since we're in * a local context and the name is the right length. */ if (vlen == 2 && (vname[1] == 'F' || vname[1] == 'D') && (strchr("!%*<>@", vname[0]) != NULL)) { char name[2]; name[0] = vname[0]; name[1] = '\0'; v = VarFindOnly(name, vp->ctxt); if (v != NULL) { value = ParseModifier(vp, startc, v, freeResult); return (value); } } /* * Still need to get to the end of the variable * specification, so kludge up a Var structure for the * modifications */ v = VarCreate(vname, NULL, VAR_JUNK); value = ParseModifier(vp, startc, v, freeResult); if (*freeResult) { free(value); } VarDestroy(v, TRUE); *freeResult = FALSE; return (vp->err ? var_Error : varNoError); } } static char * ParseRestEnd(VarParser *vp, Buffer *buf, Boolean *freeResult) { const char *vname; size_t vlen; Var *v; char *value; vname = Buf_GetAll(buf, &vlen); v = VarFindAny(vname, vp->ctxt); if (v != NULL) { value = VarExpand(v, vp); *freeResult = TRUE; return (value); } if ((vp->ctxt == VAR_CMD) || (vp->ctxt == VAR_GLOBAL)) { size_t consumed = vp->ptr - vp->input + 1; /* * If substituting a local variable in a non-local context, * assume it's for dynamic source stuff. We have to handle * this specially and return the longhand for the variable * with the dollar sign escaped so it makes it back to the * caller. Only four of the local variables are treated * specially as they are the only four that will be set when * dynamic sources are expanded. */ if (vlen == 1 || (vlen == 2 && (vname[1] == 'F' || vname[1] == 'D'))) { if (strchr("!%*@", vname[0]) != NULL) { value = emalloc(consumed + 1); strncpy(value, vp->input, consumed); value[consumed] = '\0'; *freeResult = TRUE; return (value); } } if (vlen > 2 && vname[0] == '.' && isupper((unsigned char)vname[1])) { if ((strncmp(vname, ".TARGET", vlen - 1) == 0) || (strncmp(vname, ".ARCHIVE", vlen - 1) == 0) || (strncmp(vname, ".PREFIX", vlen - 1) == 0) || (strncmp(vname, ".MEMBER", vlen - 1) == 0)) { value = emalloc(consumed + 1); strncpy(value, vp->input, consumed); value[consumed] = '\0'; *freeResult = TRUE; return (value); } } } else { /* * Check for D and F forms of local variables since we're in * a local context and the name is the right length. */ if (vlen == 2 && (vname[1] == 'F' || vname[1] == 'D') && (strchr("!%*<>@", vname[0]) != NULL)) { char name[2]; name[0] = vname[0]; name[1] = '\0'; v = VarFindOnly(name, vp->ctxt); if (v != NULL) { char *val; /* * No need for nested expansion or anything, * as we're the only one who sets these * things and we sure don't put nested * invocations in them... */ val = Buf_Data(v->val); if (vname[1] == 'D') { val = VarModify(val, VarHead, NULL); } else { val = VarModify(val, VarTail, NULL); } *freeResult = TRUE; return (val); } } } *freeResult = FALSE; return (vp->err ? var_Error : varNoError); } /** * Parse a multi letter variable name, and return it's value. */ static char * VarParseLong(VarParser *vp, Boolean *freeResult) { Buffer *buf; char startc; char endc; char *value; buf = Buf_Init(MAKE_BSIZE); startc = vp->ptr[0]; vp->ptr++; /* consume opening paren or brace */ endc = (startc == OPEN_PAREN) ? CLOSE_PAREN : CLOSE_BRACE; /* * Process characters until we reach an end character or a colon, * replacing embedded variables as we go. */ while (*vp->ptr != '\0') { if (*vp->ptr == endc) { value = ParseRestEnd(vp, buf, freeResult); vp->ptr++; /* consume closing paren or brace */ Buf_Destroy(buf, TRUE); return (value); } else if (*vp->ptr == ':') { value = ParseRestModifier(vp, startc, buf, freeResult); vp->ptr++; /* consume closing paren or brace */ Buf_Destroy(buf, TRUE); return (value); } else if (*vp->ptr == '$') { VarParser subvp = { vp->ptr, vp->ptr, vp->ctxt, vp->err, vp->execute }; char *rval; Boolean rfree; rval = VarParse(&subvp, &rfree); if (rval == var_Error) { Fatal("Error expanding embedded variable."); } Buf_Append(buf, rval); if (rfree) free(rval); vp->ptr = subvp.ptr; } else { Buf_AddByte(buf, (Byte)*vp->ptr); vp->ptr++; } } /* If we did not find the end character, return var_Error */ Buf_Destroy(buf, TRUE); *freeResult = FALSE; return (var_Error); } /** * Parse a single letter variable name, and return it's value. */ static char * VarParseShort(VarParser *vp, Boolean *freeResult) { char vname[2]; Var *v; char *value; vname[0] = vp->ptr[0]; vname[1] = '\0'; vp->ptr++; /* consume single letter */ v = VarFindAny(vname, vp->ctxt); if (v != NULL) { value = VarExpand(v, vp); *freeResult = TRUE; return (value); } /* * If substituting a local variable in a non-local context, assume * it's for dynamic source stuff. We have to handle this specially * and return the longhand for the variable with the dollar sign * escaped so it makes it back to the caller. Only four of the local * variables are treated specially as they are the only four that * will be set when dynamic sources are expanded. */ if ((vp->ctxt == VAR_CMD) || (vp->ctxt == VAR_GLOBAL)) { /* XXX: It looks like $% and $! are reversed here */ switch (vname[0]) { case '@': *freeResult = TRUE; return (estrdup("$(.TARGET)")); case '%': *freeResult = TRUE; return (estrdup("$(.ARCHIVE)")); case '*': *freeResult = TRUE; return (estrdup("$(.PREFIX)")); case '!': *freeResult = TRUE; return (estrdup("$(.MEMBER)")); default: *freeResult = FALSE; return (vp->err ? var_Error : varNoError); } } /* Variable name was not found. */ *freeResult = FALSE; return (vp->err ? var_Error : varNoError); } static char * VarParse(VarParser *vp, Boolean *freeResult) { vp->ptr++; /* consume '$' or last letter of conditional */ if (vp->ptr[0] == '\0') { /* Error, there is only a dollar sign in the input string. */ *freeResult = FALSE; return (vp->err ? var_Error : varNoError); } else if (vp->ptr[0] == OPEN_PAREN || vp->ptr[0] == OPEN_BRACE) { /* multi letter variable name */ return (VarParseLong(vp, freeResult)); } else { /* single letter variable name */ return (VarParseShort(vp, freeResult)); } } /** * Given the start of a variable invocation, extract the variable * name and find its value, then modify it according to the * specification. * * Results: * The value of the variable or var_Error if the specification * is invalid. The number of characters in the specification * is placed in the variable pointed to by consumed. (for * invalid specifications, this is just 2 to skip the '$' and * the following letter, or 1 if '$' was the last character * in the string). A Boolean in *freeResult telling whether the * returned string should be freed by the caller. */ char * Var_Parse(const char input[], GNode *ctxt, Boolean err, size_t *consumed, Boolean *freeResult) { VarParser vp = { input, input, ctxt, err, TRUE }; char *value; value = VarParse(&vp, freeResult); *consumed += vp.ptr - vp.input; return (value); } /* * Given the start of a variable invocation, determine the length * of the specification. * * Results: * The number of characters in the specification. For invalid * specifications, this is just 2 to skip the '$' and the * following letter, or 1 if '$' was the last character in the * string. */ size_t Var_Match(const char input[], GNode *ctxt) { VarParser vp = { input, input, ctxt, FALSE, FALSE }; char *value; Boolean freeResult; value = VarParse(&vp, &freeResult); if (freeResult) { free(value); } return (vp.ptr - vp.input); } static int match_var(const char str[], const char var[]) { const char *start = str; size_t len; str++; /* consume '$' */ if (str[0] == OPEN_PAREN || str[0] == OPEN_BRACE) { str++; /* consume opening paren or brace */ while (str[0] != '\0') { if (str[0] == '$') { /* * A variable inside the variable. We cannot * expand the external variable yet. */ return (str - start); } else if (str[0] == ':' || str[0] == CLOSE_PAREN || str[0] == CLOSE_BRACE) { len = str - (start + 2); if (strncmp(var, start + 2, len) == 0 && var[len] == '\0') { return (0); /* match */ } else { /* * Not the variable we want to * expand. */ return (str - start); } } else { ++str; } } return (str - start); } else { /* Single letter variable name */ if (var[1] == '\0' && var[0] == str[0]) { return (0); /* match */ } else { str++; /* consume variable name */ return (str - start); } } } /** * Substitute for all variables in the given string in the given * context If err is TRUE, Parse_Error will be called when an * undefined variable is encountered. * * Results: * The resulting string. * * Side Effects: * None. The old string must be freed by the caller */ Buffer * Var_Subst(const char *str, GNode *ctxt, Boolean err) { Boolean errorReported; Buffer *buf; /* Buffer for forming things */ /* * Set TRUE if an error has already been reported to prevent a * plethora of messages when recursing. XXXHB this comment sounds * wrong. */ errorReported = FALSE; buf = Buf_Init(0); while (str[0] != '\0') { if ((str[0] == '$') && (str[1] == '$')) { /* * A dollar sign may be escaped with another dollar * sign. In such a case, we skip over the escape * character and store the dollar sign into the * buffer directly. */ str++; Buf_AddByte(buf, (Byte)str[0]); str++; } else if (str[0] == '$') { /* Variable invocation. */ VarParser subvp = { str, str, ctxt, err, TRUE }; char *rval; Boolean rfree; rval = VarParse(&subvp, &rfree); /* * When we come down here, val should either point to * the value of this variable, suitably modified, or * be NULL. Length should be the total length of the * potential variable invocation (from $ to end * character...) */ if (rval == var_Error || rval == varNoError) { /* * If performing old-time variable * substitution, skip over the variable and * continue with the substitution. Otherwise, * store the dollar sign and advance str so * we continue with the string... */ if (oldVars) { str = subvp.ptr; } else if (err) { /* * If variable is undefined, complain * and skip the variable. The * complaint will stop us from doing * anything when the file is parsed. */ if (!errorReported) { Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"", subvp.ptr - subvp.input, str); } errorReported = TRUE; str = subvp.ptr; } else { Buf_AddByte(buf, (Byte)str[0]); str++; } } else { /* * Copy all the characters from the variable * value straight into the new string. */ Buf_Append(buf, rval); if (rfree) { free(rval); } str = subvp.ptr; } } else { Buf_AddByte(buf, (Byte)str[0]); str++; } } return (buf); } /** * Substitute for all variables except if it is the same as 'var', * in the given string in the given context. If err is TRUE, * Parse_Error will be called when an undefined variable is * encountered. * * Results: * The resulting string. * * Side Effects: * None. The old string must be freed by the caller */ Buffer * Var_SubstOnly(const char *var, const char *str, Boolean err) { GNode *ctxt = VAR_GLOBAL; Boolean errorReported; Buffer *buf; /* Buffer for forming things */ /* * Set TRUE if an error has already been reported to prevent a * plethora of messages when recursing. XXXHB this comment sounds * wrong. */ errorReported = FALSE; buf = Buf_Init(0); while (str[0] != '\0') { if (str[0] == '$') { int skip; skip = match_var(str, var); if (skip > 0) { Buf_AddBytes(buf, skip, str); str += skip; } else { /* Variable invocation. */ VarParser subvp = { str, str, ctxt, err, TRUE }; char *rval; Boolean rfree; rval = VarParse(&subvp, &rfree); /* * When we get down here, rval should either * point to the value of this variable, or be * NULL. */ if (rval == var_Error || rval == varNoError) { /* * If performing old-time variable * substitution, skip over the * variable and continue with the * substitution. Otherwise, store the * dollar sign and advance str so we * continue with the string... */ if (oldVars) { str = subvp.ptr; } else if (err) { /* * If variable is undefined, * complain and skip the * variable. The complaint * will stop us from doing * anything when the file is * parsed. */ if (!errorReported) { Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"", subvp.ptr - subvp.input, str); } errorReported = TRUE; str = subvp.ptr; } else { Buf_AddByte(buf, (Byte)str[0]); str++; } } else { /* * Copy all the characters from the * variable value straight into the * new string. */ Buf_Append(buf, rval); if (rfree) { free(rval); } str = subvp.ptr; } } } else { Buf_AddByte(buf, (Byte)str[0]); str++; } } return (buf); } /** * Initialize the module * * Side Effects: * The VAR_CMD and VAR_GLOBAL contexts are created */ void Var_Init(char **env) { char **ptr; VAR_CMD = Targ_NewGN("Command"); VAR_ENV = Targ_NewGN("Environment"); VAR_GLOBAL = Targ_NewGN("Global"); /* * Copy user environment variables into ENV context. */ for (ptr = env; *ptr != NULL; ++ptr) { char *tmp = estrdup(*ptr); const char *name = tmp; char *sep = strchr(name, '='); const char *value = sep + 1; if (sep != NULL) { *sep = '\0'; VarAdd(name, value, VAR_ENV); } free(tmp); } } /** * Print all variables in global and command line contexts. */ void Var_Dump(void) { const LstNode *ln; const Var *v; printf("#*** Global Variables:\n"); LST_FOREACH(ln, &VAR_GLOBAL->context) { v = Lst_Datum(ln); printf("%-16s = %s\n", v->name, Buf_Data(v->val)); } printf("#*** Command-line Variables:\n"); LST_FOREACH(ln, &VAR_CMD->context) { v = Lst_Datum(ln); printf("%-16s = %s\n", v->name, Buf_Data(v->val)); } } /** * Print the values of any variables requested by * the user. */ void Var_Print(Lst *vlist, Boolean expandVars) { LstNode *n; char *name; LST_FOREACH(n, vlist) { name = Lst_Datum(n); if (expandVars) { char *value; char *v; if (*name == '$') { v = name; } else { v = emalloc(strlen(name) + 1 + 3); sprintf(v, "${%s}", name); } value = Buf_Peel(Var_Subst(v, VAR_GLOBAL, FALSE)); printf("%s\n", value); if (v != name) free(v); free(value); } else { const char *value = Var_Value(name, VAR_GLOBAL); printf("%s\n", value != NULL ? value : ""); } } } freebsd-buildutils-10.0/src/usr.bin/make/GNode.h0000644000000000000000000001665111677315120016355 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef GNode_h_39503bf2 #define GNode_h_39503bf2 #include "lst.h" #include "util.h" struct Suff; /* * The structure for an individual graph node. Each node has several * pieces of data associated with it. */ typedef struct GNode { char *name; /* The target's name */ char *path; /* The full pathname of the target file */ /* * The type of operator used to define the sources (qv. parse.c) * * The OP_ constants are used when parsing a dependency line as a way of * communicating to other parts of the program the way in which a target * should be made. These constants are bitwise-OR'ed together and * placed in the 'type' field of each node. Any node that has * a 'type' field which satisfies the OP_NOP function was never never on * the lefthand side of an operator, though it may have been on the * righthand side... */ int type; #define OP_DEPENDS 0x00000001 /* Execution of commands depends on * kids (:) */ #define OP_FORCE 0x00000002 /* Always execute commands (!) */ #define OP_DOUBLEDEP 0x00000004 /* Execution of commands depends on * kids per line (::) */ #define OP_OPMASK (OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP) #define OP_OPTIONAL 0x00000008 /* Don't care if the target doesn't * exist and can't be created */ #define OP_USE 0x00000010 /* * Use associated commands for * parents */ #define OP_EXEC 0x00000020 /* Target is never out of date, but * always execute commands anyway. * Its time doesn't matter, so it has * none...sort of */ #define OP_IGNORE 0x00000040 /* * Ignore errors when creating the node */ #define OP_PRECIOUS 0x00000080 /* Don't remove the target when * interrupted */ #define OP_SILENT 0x00000100 /* Don't echo commands when executed */ #define OP_MAKE 0x00000200 /* * Target is a recurrsive make so its * commands should always be executed * when it is out of date, regardless * of the state of the -n or -t flags */ #define OP_JOIN 0x00000400 /* Target is out-of-date only if any of * its children was out-of-date */ #define OP_INVISIBLE 0x00004000 /* The node is invisible to its parents. * I.e. it doesn't show up in the * parents's local variables. */ #define OP_NOTMAIN 0x00008000 /* The node is exempt from normal 'main * target' processing in parse.c */ #define OP_PHONY 0x00010000 /* Not a file target; run always */ /* Attributes applied by PMake */ #define OP_TRANSFORM 0x80000000 /* The node is a transformation rule */ #define OP_MEMBER 0x40000000 /* Target is a member of an archive */ #define OP_LIB 0x20000000 /* Target is a library */ #define OP_ARCHV 0x10000000 /* Target is an archive construct */ #define OP_HAS_COMMANDS 0x08000000 /* Target has all the commands it * should. Used when parsing to catch * multiple commands for a target */ #define OP_SAVE_CMDS 0x04000000 /* Saving commands on .END (Compat) */ #define OP_DEPS_FOUND 0x02000000 /* Already processed by Suff_FindDeps */ /* * OP_NOP will return TRUE if the node with the given type was not the * object of a dependency operator */ #define OP_NOP(t) (((t) & OP_OPMASK) == 0x00000000) int order; /* Its wait weight */ Boolean make; /* TRUE if this target needs to be remade */ /* Set to reflect the state of processing on this node */ enum { UNMADE, /* Not examined yet */ /* * Target is already being made. Indicates a cycle in the graph. * (compat mode only) */ BEINGMADE, MADE, /* Was out-of-date and has been made */ UPTODATE, /* Was already up-to-date */ /* * An error occurred while it was being * made (used only in compat mode) */ ERROR, /* * The target was aborted due to an * error making an inferior (compat). */ ABORTED, /* * Marked as potentially being part of a graph cycle. If we * come back to a node marked this way, it is printed and * 'made' is changed to ENDCYCLE. */ CYCLE, /* * The cycle has been completely printed. Go back and * unmark all its members. */ ENDCYCLE } made; /* TRUE if one of this target's children was made */ Boolean childMade; int unmade; /* The number of unmade children */ int mtime; /* Its modification time */ int cmtime; /* Modification time of its youngest child */ struct GNode *cmtime_gn;/* Youngest child */ /* * Links to parents for which this is an implied source, if any. (nodes * that depend on this, as gleaned from the transformation rules. */ Lst iParents; /* List of nodes of the same name created by the :: operator */ Lst cohorts; /* Lst of nodes for which this is a source (that depend on this one) */ Lst parents; /* List of nodes on which this depends */ Lst children; /* * List of nodes that must be made (if they're made) after this node is, * but that do not depend on this node, in the normal sense. */ Lst successors; /* * List of nodes that must be made (if they're made) before this node * can be, but that do no enter into the datedness of this node. */ Lst preds; /* * List of ``local'' variables that are specific to this target * and this target only (qv. var.c [$@ $< $?, etc.]) */ Lst context; /* * List of strings that are commands to be given to a shell * to create this target. */ Lst commands; /* current command executing in compat mode */ LstNode *compat_command; /* * Suffix for the node (determined by Suff_FindDeps and opaque to * everyone but the Suff module) */ struct Suff *suffix; } GNode; #endif /* GNode_h_39503bf2 */ freebsd-buildutils-10.0/src/usr.bin/make/parse.c0000644000000000000000000017276211320235400016457 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)parse.c 8.3 (Berkeley) 3/19/94 */ #include __FBSDID("$FreeBSD$"); /*- * parse.c -- * Functions to parse a makefile. * * Most important structures are kept in Lsts. Directories for * the #include "..." function are kept in the 'parseIncPath' Lst, while * those for the #include <...> are kept in the 'sysIncPath' Lst. The * targets currently being defined are kept in the 'targets' Lst. * * Interface: * * Parse_File Function used to parse a makefile. It must * be given the name of the file, which should * already have been opened, and a function * to call to read a character from the file. * * Parse_IsVar Returns TRUE if the given line is a * variable assignment. Used by MainParseArgs * to determine if an argument is a target * or a variable assignment. Used internally * for pretty much the same thing... * * Parse_Error Function called when an error occurs in * parsing. Used by the variable and * conditional modules. * * Parse_MainName Returns a Lst of the main target to create. */ #include #include #include #include #include #include #include "arch.h" #include "buf.h" #include "cond.h" #include "config.h" #include "dir.h" #include "for.h" #include "globals.h" #include "GNode.h" #include "hash_tables.h" #include "job.h" #include "make.h" #include "parse.h" #include "pathnames.h" #include "shell.h" #include "str.h" #include "suff.h" #include "targ.h" #include "util.h" #include "var.h" /* * These values are returned by ParsePopInput to tell Parse_File whether to * CONTINUE parsing, i.e. it had only reached the end of an include file, * or if it's DONE. */ #define CONTINUE 1 #define DONE 0 /* targets we're working on */ static Lst targets = Lst_Initializer(targets); /* true if currently in a dependency line or its commands */ static Boolean inLine; static int fatals = 0; /* * The main target to create. This is the first target on the * first dependency line in the first makefile. */ static GNode *mainNode; /* * Definitions for handling #include specifications */ struct IFile { char *fname; /* name of previous file */ int lineno; /* saved line number */ FILE *F; /* the open stream */ char *str; /* the string when parsing a string */ char *ptr; /* the current pointer when parsing a string */ TAILQ_ENTRY(IFile) link;/* stack the files */ }; /* stack of IFiles generated by * #includes */ static TAILQ_HEAD(, IFile) includes = TAILQ_HEAD_INITIALIZER(includes); /* access current file */ #define CURFILE (TAILQ_FIRST(&includes)) /* list of directories for "..." includes */ struct Path parseIncPath = TAILQ_HEAD_INITIALIZER(parseIncPath); /* list of directories for <...> includes */ struct Path sysIncPath = TAILQ_HEAD_INITIALIZER(sysIncPath); /* * specType contains the SPECial TYPE of the current target. It is * Not if the target is unspecial. If it *is* special, however, the children * are linked as children of the parent but not vice versa. This variable is * set in ParseDoDependency */ typedef enum { Begin, /* .BEGIN */ Default, /* .DEFAULT */ End, /* .END */ ExportVar, /* .EXPORTVAR */ Ignore, /* .IGNORE */ Includes, /* .INCLUDES */ Interrupt, /* .INTERRUPT */ Libs, /* .LIBS */ MFlags, /* .MFLAGS or .MAKEFLAGS */ Main, /* .MAIN and we don't have anyth. user-spec. to make */ Not, /* Not special */ NotParallel, /* .NOTPARALELL */ Null, /* .NULL */ Order, /* .ORDER */ Parallel, /* .PARALLEL */ ExPath, /* .PATH */ Phony, /* .PHONY */ Posix, /* .POSIX */ MakefileDeps, /* .MAKEFILEDEPS */ Precious, /* .PRECIOUS */ ExShell, /* .SHELL */ Silent, /* .SILENT */ SingleShell, /* .SINGLESHELL */ Suffixes, /* .SUFFIXES */ Wait, /* .WAIT */ Warn, /* .WARN */ Attribute /* Generic attribute */ } ParseSpecial; static ParseSpecial specType; static int waiting; /* * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER * seen, then set to each successive source on the line. */ static GNode *predecessor; /* * The parseKeywords table is searched using binary search when deciding * if a target or source is special. The 'spec' field is the ParseSpecial * type of the keyword ("Not" if the keyword isn't special as a target) while * the 'op' field is the operator to apply to the list of targets if the * keyword is used as a source ("0" if the keyword isn't special as a source) */ static const struct keyword { const char *name; /* Name of keyword */ ParseSpecial spec; /* Type when used as a target */ int op; /* Operator when used as a source */ } parseKeywords[] = { /* KEYWORD-START-TAG */ { ".BEGIN", Begin, 0 }, { ".DEFAULT", Default, 0 }, { ".END", End, 0 }, { ".EXEC", Attribute, OP_EXEC }, { ".EXPORTVAR", ExportVar, 0 }, { ".IGNORE", Ignore, OP_IGNORE }, { ".INCLUDES", Includes, 0 }, { ".INTERRUPT", Interrupt, 0 }, { ".INVISIBLE", Attribute, OP_INVISIBLE }, { ".JOIN", Attribute, OP_JOIN }, { ".LIBS", Libs, 0 }, { ".MAIN", Main, 0 }, { ".MAKE", Attribute, OP_MAKE }, { ".MAKEFILEDEPS", MakefileDeps, 0 }, { ".MAKEFLAGS", MFlags, 0 }, { ".MFLAGS", MFlags, 0 }, { ".NOTMAIN", Attribute, OP_NOTMAIN }, { ".NOTPARALLEL", NotParallel, 0 }, { ".NO_PARALLEL", NotParallel, 0 }, { ".NULL", Null, 0 }, { ".OPTIONAL", Attribute, OP_OPTIONAL }, { ".ORDER", Order, 0 }, { ".PARALLEL", Parallel, 0 }, { ".PATH", ExPath, 0 }, { ".PHONY", Phony, OP_PHONY }, { ".POSIX", Posix, 0 }, { ".PRECIOUS", Precious, OP_PRECIOUS }, { ".RECURSIVE", Attribute, OP_MAKE }, { ".SHELL", ExShell, 0 }, { ".SILENT", Silent, OP_SILENT }, { ".SINGLESHELL", SingleShell, 0 }, { ".SUFFIXES", Suffixes, 0 }, { ".USE", Attribute, OP_USE }, { ".WAIT", Wait, 0 }, { ".WARN", Warn, 0 }, /* KEYWORD-END-TAG */ }; #define NKEYWORDS (sizeof(parseKeywords) / sizeof(parseKeywords[0])) static void parse_include(char *, int, int); static void parse_sinclude(char *, int, int); static void parse_message(char *, int, int); static void parse_undef(char *, int, int); static void parse_for(char *, int, int); static void parse_endfor(char *, int, int); static const struct directive { const char *name; int code; Boolean skip_flag; /* execute even when skipped */ void (*func)(char *, int, int); } directives[] = { /* DIRECTIVES-START-TAG */ { "elif", COND_ELIF, TRUE, Cond_If }, { "elifdef", COND_ELIFDEF, TRUE, Cond_If }, { "elifmake", COND_ELIFMAKE, TRUE, Cond_If }, { "elifndef", COND_ELIFNDEF, TRUE, Cond_If }, { "elifnmake", COND_ELIFNMAKE, TRUE, Cond_If }, { "else", COND_ELSE, TRUE, Cond_Else }, { "endfor", 0, FALSE, parse_endfor }, { "endif", COND_ENDIF, TRUE, Cond_Endif }, { "error", 1, FALSE, parse_message }, { "for", 0, FALSE, parse_for }, { "if", COND_IF, TRUE, Cond_If }, { "ifdef", COND_IFDEF, TRUE, Cond_If }, { "ifmake", COND_IFMAKE, TRUE, Cond_If }, { "ifndef", COND_IFNDEF, TRUE, Cond_If }, { "ifnmake", COND_IFNMAKE, TRUE, Cond_If }, { "include", 0, FALSE, parse_include }, { "sinclude", 0, FALSE, parse_sinclude }, { "undef", 0, FALSE, parse_undef }, { "warning", 0, FALSE, parse_message }, /* DIRECTIVES-END-TAG */ }; #define NDIRECTS (sizeof(directives) / sizeof(directives[0])) /*- * ParseFindKeyword * Look in the table of keywords for one matching the given string. * * Results: * The pointer to keyword table entry or NULL. */ static const struct keyword * ParseFindKeyword(const char *str) { int kw; kw = keyword_hash(str, strlen(str)); if (kw < 0 || kw >= (int)NKEYWORDS || strcmp(str, parseKeywords[kw].name) != 0) return (NULL); return (&parseKeywords[kw]); } /*- * Parse_Error -- * Error message abort function for parsing. Prints out the context * of the error (line number and file) as well as the message with * two optional arguments. * * Results: * None * * Side Effects: * "fatals" is incremented if the level is PARSE_FATAL. */ /* VARARGS */ void Parse_Error(int type, const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (CURFILE != NULL) fprintf(stderr, "\"%s\", line %d: ", CURFILE->fname, CURFILE->lineno); if (type == PARSE_WARNING) fprintf(stderr, "warning: "); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); fflush(stderr); if (type == PARSE_FATAL) fatals += 1; } /** * ParsePushInput * * Push a new input source onto the input stack. If ptr is NULL * the fullname is used to fopen the file. If it is not NULL, * ptr is assumed to point to the string to be parsed. If opening the * file fails, the fullname is freed. */ static void ParsePushInput(char *fullname, FILE *fp, char *ptr, int lineno) { struct IFile *nf; nf = emalloc(sizeof(*nf)); nf->fname = fullname; nf->lineno = lineno; if (ptr == NULL) { /* the input source is a file */ if ((nf->F = fp) == NULL) { nf->F = fopen(fullname, "r"); if (nf->F == NULL) { Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); free(fullname); free(nf); return; } } nf->str = nf->ptr = NULL; Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); } else { nf->str = nf->ptr = ptr; nf->F = NULL; } TAILQ_INSERT_HEAD(&includes, nf, link); } /** * ParsePopInput * Called when EOF is reached in the current file. If we were reading * an include file, the includes stack is popped and things set up * to go back to reading the previous file at the previous location. * * Results: * CONTINUE if there's more to do. DONE if not. * * Side Effects: * The old curFile.F is closed. The includes list is shortened. * curFile.lineno, curFile.F, and curFile.fname are changed if * CONTINUE is returned. */ static int ParsePopInput(void) { struct IFile *ifile; /* the state on the top of the includes stack */ assert(!TAILQ_EMPTY(&includes)); ifile = TAILQ_FIRST(&includes); TAILQ_REMOVE(&includes, ifile, link); free(ifile->fname); if (ifile->F != NULL) { fclose(ifile->F); Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); } if (ifile->str != NULL) { free(ifile->str); } free(ifile); return (TAILQ_EMPTY(&includes) ? DONE : CONTINUE); } /** * parse_warn * Parse the .WARN pseudo-target. */ static void parse_warn(char *line) { ArgArray aa; int i; brk_string(&aa, line, TRUE); for (i = 1; i < aa.argc; i++) Main_ParseWarn(aa.argv[i], 0); } /*- *--------------------------------------------------------------------- * ParseLinkSrc -- * Link the parent nodes to their new child. Used by * ParseDoDependency. If the specType isn't 'Not', the parent * isn't linked as a parent of the child. * * Side Effects: * New elements are added to the parents lists of cgn and the * children list of cgn. the unmade field of pgn is updated * to reflect the additional child. *--------------------------------------------------------------------- */ static void ParseLinkSrc(Lst *parents, GNode *cgn) { LstNode *ln; GNode *pgn; LST_FOREACH(ln, parents) { pgn = Lst_Datum(ln); if (Lst_Member(&pgn->children, cgn) == NULL) { Lst_AtEnd(&pgn->children, cgn); if (specType == Not) { Lst_AtEnd(&cgn->parents, pgn); } pgn->unmade += 1; } } } /*- *--------------------------------------------------------------------- * ParseDoOp -- * Apply the parsed operator to all target nodes. Used in * ParseDoDependency once all targets have been found and their * operator parsed. If the previous and new operators are incompatible, * a major error is taken. * * Side Effects: * The type field of the node is altered to reflect any new bits in * the op. *--------------------------------------------------------------------- */ static void ParseDoOp(int op) { GNode *cohort; LstNode *ln; GNode *gn; LST_FOREACH(ln, &targets) { gn = Lst_Datum(ln); /* * If the dependency mask of the operator and the node don't * match and the node has actually had an operator applied to * it before, and the operator actually has some dependency * information in it, complain. */ if ((op & OP_OPMASK) != (gn->type & OP_OPMASK) && !OP_NOP(gn->type) && !OP_NOP(op)) { Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name); return; } if (op == OP_DOUBLEDEP && (gn->type & OP_OPMASK) == OP_DOUBLEDEP) { /* * If the node was the object of a :: operator, we need * to create a new instance of it for the children and * commands on this dependency line. The new instance * is placed on the 'cohorts' list of the initial one * (note the initial one is not on its own cohorts list) * and the new instance is linked to all parents of the * initial instance. */ cohort = Targ_NewGN(gn->name); /* * Duplicate links to parents so graph traversal is * simple. Perhaps some type bits should be duplicated? * * Make the cohort invisible as well to avoid * duplicating it into other variables. True, parents * of this target won't tend to do anything with their * local variables, but better safe than sorry. */ ParseLinkSrc(&gn->parents, cohort); cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; Lst_AtEnd(&gn->cohorts, cohort); /* * Replace the node in the targets list with the * new copy */ Lst_Replace(ln, cohort); gn = cohort; } /* * We don't want to nuke any previous flags (whatever they were) * so we just OR the new operator into the old */ gn->type |= op; } } /*- *--------------------------------------------------------------------- * ParseDoSrc -- * Given the name of a source, figure out if it is an attribute * and apply it to the targets if it is. Else decide if there is * some attribute which should be applied *to* the source because * of some special target and apply it if so. Otherwise, make the * source be a child of the targets in the list 'targets' * * Results: * None * * Side Effects: * Operator bits may be added to the list of targets or to the source. * The targets may have a new source added to their lists of children. *--------------------------------------------------------------------- */ static void ParseDoSrc(int tOp, char *src, Lst *allsrc) { GNode *gn = NULL; const struct keyword *kw; if (src[0] == '.' && isupper ((unsigned char)src[1])) { if ((kw = ParseFindKeyword(src)) != NULL) { if (kw->op != 0) { ParseDoOp(kw->op); return; } if (kw->spec == Wait) { waiting++; return; } } } switch (specType) { case Main: /* * If we have noted the existence of a .MAIN, it means we need * to add the sources of said target to the list of things * to create. The string 'src' is likely to be free, so we * must make a new copy of it. Note that this will only be * invoked if the user didn't specify a target on the command * line. This is to allow #ifmake's to succeed, or something... */ Lst_AtEnd(&create, estrdup(src)); /* * Add the name to the .TARGETS variable as well, so the user * can employ that, if desired. */ Var_Append(".TARGETS", src, VAR_GLOBAL); return; case Order: /* * Create proper predecessor/successor links between the * previous source and the current one. */ gn = Targ_FindNode(src, TARG_CREATE); if (predecessor != NULL) { Lst_AtEnd(&predecessor->successors, gn); Lst_AtEnd(&gn->preds, predecessor); } /* * The current source now becomes the predecessor for the next * one. */ predecessor = gn; break; default: /* * If the source is not an attribute, we need to find/create * a node for it. After that we can apply any operator to it * from a special target or link it to its parents, as * appropriate. * * In the case of a source that was the object of a :: operator, * the attribute is applied to all of its instances (as kept in * the 'cohorts' list of the node) or all the cohorts are linked * to all the targets. */ gn = Targ_FindNode(src, TARG_CREATE); if (tOp) { gn->type |= tOp; } else { ParseLinkSrc(&targets, gn); } if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { GNode *cohort; LstNode *ln; for (ln = Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Succ(ln)) { cohort = Lst_Datum(ln); if (tOp) { cohort->type |= tOp; } else { ParseLinkSrc(&targets, cohort); } } } break; } gn->order = waiting; Lst_AtEnd(allsrc, gn); if (waiting) { LstNode *ln; GNode *p; /* * Check if GNodes needs to be synchronized. * This has to be when two nodes are on different sides of a * .WAIT directive. */ LST_FOREACH(ln, allsrc) { p = Lst_Datum(ln); if (p->order >= gn->order) break; /* * XXX: This can cause loops, and loops can cause * unmade targets, but checking is tedious, and the * debugging output can show the problem */ Lst_AtEnd(&p->successors, gn); Lst_AtEnd(&gn->preds, p); } } } /*- *--------------------------------------------------------------------- * ParseDoDependency -- * Parse the dependency line in line. * * Results: * None * * Side Effects: * The nodes of the sources are linked as children to the nodes of the * targets. Some nodes may be created. * * We parse a dependency line by first extracting words from the line and * finding nodes in the list of all targets with that name. This is done * until a character is encountered which is an operator character. Currently * these are only ! and :. At this point the operator is parsed and the * pointer into the line advanced until the first source is encountered. * The parsed operator is applied to each node in the 'targets' list, * which is where the nodes found for the targets are kept, by means of * the ParseDoOp function. * The sources are read in much the same way as the targets were except * that now they are expanded using the wildcarding scheme of the C-Shell * and all instances of the resulting words in the list of all targets * are found. Each of the resulting nodes is then linked to each of the * targets as one of its children. * Certain targets are handled specially. These are the ones detailed * by the specType variable. * The storing of transformation rules is also taken care of here. * A target is recognized as a transformation rule by calling * Suff_IsTransform. If it is a transformation rule, its node is gotten * from the suffix module via Suff_AddTransform rather than the standard * Targ_FindNode in the target module. *--------------------------------------------------------------------- */ static void ParseDoDependency(char *line) { char *cp; /* our current position */ char *lstart = line; /* original input line */ GNode *gn; /* a general purpose temporary node */ int op; /* the operator on the line */ char savec; /* a place to save a character */ Lst paths; /* Search paths to alter when parsing .PATH targets */ int tOp; /* operator from special target */ LstNode *ln; const struct keyword *kw; tOp = 0; specType = Not; waiting = 0; Lst_Init(&paths); do { for (cp = line; *cp && !isspace((unsigned char)*cp) && *cp != '('; cp++) { if (*cp == '$') { /* * Must be a dynamic source (would have been * expanded otherwise), so call the Var module * to parse the puppy so we can safely advance * beyond it...There should be no errors in this * as they would have been discovered in the * initial Var_Subst and we wouldn't be here. */ size_t length = 0; Boolean freeIt; char *result; result = Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt); if (freeIt) { free(result); } cp += length - 1; } else if (*cp == '!' || *cp == ':') { /* * We don't want to end a word on ':' or '!' if * there is a better match later on in the * string (greedy matching). * This allows the user to have targets like: * fie::fi:fo: fum * foo::bar: * where "fie::fi:fo" and "foo::bar" are the * targets. In real life this is used for perl5 * library man pages where "::" separates an * object from its class. Ie: * "File::Spec::Unix". This behaviour is also * consistent with other versions of make. */ char *p = cp + 1; if (*cp == ':' && *p == ':') p++; /* Found the best match already. */ if (*p == '\0' || isspace(*p)) break; p += strcspn(p, "!:"); /* No better match later on... */ if (*p == '\0') break; } continue; } if (*cp == '(') { /* * Archives must be handled specially to make sure the * OP_ARCHV flag is set in their 'type' field, for one * thing, and because things like "archive(file1.o * file2.o file3.o)" are permissible. Arch_ParseArchive * will set 'line' to be the first non-blank after the * archive-spec. It creates/finds nodes for the members * and places them on the given list, returning TRUE * if all went well and FALSE if there was an error in * the specification. On error, line should remain * untouched. */ if (!Arch_ParseArchive(&line, &targets, VAR_CMD)) { Parse_Error(PARSE_FATAL, "Error in archive specification: \"%s\"", line); return; } else { cp = line; continue; } } savec = *cp; if (!*cp) { /* * Ending a dependency line without an operator is a * Bozo no-no. As a heuristic, this is also often * triggered by undetected conflicts from cvs/rcs * merges. */ if (strncmp(line, "<<<<<<", 6) == 0 || strncmp(line, "||||||", 6) == 0 || strncmp(line, "======", 6) == 0 || strncmp(line, ">>>>>>", 6) == 0) { Parse_Error(PARSE_FATAL, "Makefile appears to " "contain unresolved cvs/rcs/??? merge " "conflicts"); } else Parse_Error(PARSE_FATAL, lstart[0] == '.' ? "Unknown directive" : "Need an operator"); return; } *cp = '\0'; /* * Have a word in line. See if it's a special target and set * specType to match it. */ if (*line == '.' && isupper((unsigned char)line[1])) { /* * See if the target is a special target that must have * it or its sources handled specially. */ if ((kw = ParseFindKeyword(line)) != NULL) { if (specType == ExPath && kw->spec != ExPath) { Parse_Error(PARSE_FATAL, "Mismatched special targets"); return; } specType = kw->spec; tOp = kw->op; /* * Certain special targets have special * semantics: * .PATH Have to set the dirSearchPath * variable too * .MAIN Its sources are only used if * nothing has been specified to * create. * .DEFAULT Need to create a node to hang * commands on, but we don't want * it in the graph, nor do we want * it to be the Main Target, so we * create it, set OP_NOTMAIN and * add it to the list, setting * DEFAULT to the new node for * later use. We claim the node is * A transformation rule to make * life easier later, when we'll * use Make_HandleUse to actually * apply the .DEFAULT commands. * .PHONY The list of targets * .BEGIN * .END * .INTERRUPT Are not to be considered the * main target. * .NOTPARALLEL Make only one target at a time. * .SINGLESHELL Create a shell for each * command. * .ORDER Must set initial predecessor * to NULL */ switch (specType) { case ExPath: Lst_AtEnd(&paths, &dirSearchPath); break; case Main: if (!Lst_IsEmpty(&create)) { specType = Not; } break; case Begin: case End: case Interrupt: gn = Targ_FindNode(line, TARG_CREATE); gn->type |= OP_NOTMAIN; Lst_AtEnd(&targets, gn); break; case Default: gn = Targ_NewGN(".DEFAULT"); gn->type |= (OP_NOTMAIN|OP_TRANSFORM); Lst_AtEnd(&targets, gn); DEFAULT = gn; break; case NotParallel: jobLimit = 1; break; case SingleShell: compatMake = 1; break; case Order: predecessor = NULL; break; default: break; } } else if (strncmp(line, ".PATH", 5) == 0) { /* * .PATH has to be handled specially. * Call on the suffix module to give us a path * to modify. */ struct Path *path; specType = ExPath; path = Suff_GetPath(&line[5]); if (path == NULL) { Parse_Error(PARSE_FATAL, "Suffix '%s' " "not defined (yet)", &line[5]); return; } else Lst_AtEnd(&paths, path); } } /* * Have word in line. Get or create its node and stick it at * the end of the targets list */ if (specType == Not && *line != '\0') { /* target names to be found and added to targets list */ Lst curTargs = Lst_Initializer(curTargs); if (Dir_HasWildcards(line)) { /* * Targets are to be sought only in the current * directory, so create an empty path for the * thing. Note we need to use Path_Clear in the * destruction of the path as the Dir module * could have added a directory to the path... */ struct Path emptyPath = TAILQ_HEAD_INITIALIZER(emptyPath); Path_Expand(line, &emptyPath, &curTargs); Path_Clear(&emptyPath); } else { /* * No wildcards, but we want to avoid code * duplication, so create a list with the word * on it. */ Lst_AtEnd(&curTargs, line); } while (!Lst_IsEmpty(&curTargs)) { char *targName = Lst_DeQueue(&curTargs); if (!Suff_IsTransform (targName)) { gn = Targ_FindNode(targName, TARG_CREATE); } else { gn = Suff_AddTransform(targName); } Lst_AtEnd(&targets, gn); } } else if (specType == ExPath && *line != '.' && *line != '\0'){ Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line); } *cp = savec; /* * If it is a special type and not .PATH, it's the only * target we allow on this line... */ if (specType != Not && specType != ExPath) { Boolean warnFlag = FALSE; while (*cp != '!' && *cp != ':' && *cp) { if (*cp != ' ' && *cp != '\t') { warnFlag = TRUE; } cp++; } if (warnFlag) { Parse_Error(PARSE_WARNING, "Extra target ignored"); } } else { while (*cp && isspace((unsigned char)*cp)) { cp++; } } line = cp; } while (*line != '!' && *line != ':' && *line); if (!Lst_IsEmpty(&targets)) { switch (specType) { default: Parse_Error(PARSE_WARNING, "Special and mundane " "targets don't mix. Mundane ones ignored"); break; case Default: case Begin: case End: case Interrupt: /* * These four create nodes on which to hang commands, so * targets shouldn't be empty... */ case Not: /* * Nothing special here -- targets can be empty if it * wants. */ break; } } /* * Have now parsed all the target names. Must parse the operator next. * The result is left in op. */ if (*cp == '!') { op = OP_FORCE; } else if (*cp == ':') { if (cp[1] == ':') { op = OP_DOUBLEDEP; cp++; } else { op = OP_DEPENDS; } } else { Parse_Error(PARSE_FATAL, lstart[0] == '.' ? "Unknown directive" : "Missing dependency operator"); return; } cp++; /* Advance beyond operator */ ParseDoOp(op); /* * Get to the first source */ while (*cp && isspace((unsigned char)*cp)) { cp++; } line = cp; /* * Several special targets take different actions if present with no * sources: * a .SUFFIXES line with no sources clears out all old suffixes * a .PRECIOUS line makes all targets precious * a .IGNORE line ignores errors for all targets * a .SILENT line creates silence when making all targets * a .PATH removes all directories from the search path(s). */ if (!*line) { switch (specType) { case Suffixes: Suff_ClearSuffixes(); break; case Precious: allPrecious = TRUE; break; case Ignore: ignoreErrors = TRUE; break; case Silent: beSilent = TRUE; break; case ExPath: LST_FOREACH(ln, &paths) Path_Clear(Lst_Datum(ln)); break; case MakefileDeps: mfAutoDeps = TRUE; break; case Posix: is_posix = TRUE; Var_SetGlobal("%POSIX", "1003.2"); break; default: break; } } else if (specType == MFlags) { /* * Call on functions in main.c to deal with these arguments and * set the initial character to a null-character so the loop to * get sources won't get anything */ Main_ParseArgLine(line, 0); *line = '\0'; } else if (specType == Warn) { parse_warn(line); *line = '\0'; } else if (specType == ExShell) { if (!Shell_Parse(line)) { Parse_Error(PARSE_FATAL, "improper shell specification"); return; } *line = '\0'; } else if (specType == NotParallel || specType == SingleShell) { *line = '\0'; } /* * NOW GO FOR THE SOURCES */ if (specType == Suffixes || specType == ExPath || specType == Includes || specType == Libs || specType == Null) { while (*line) { /* * If the target was one that doesn't take files as its * sources but takes something like suffixes, we take * each space-separated word on the line as a something * and deal with it accordingly. * * If the target was .SUFFIXES, we take each source as * a suffix and add it to the list of suffixes * maintained by the Suff module. * * If the target was a .PATH, we add the source as a * directory to search on the search path. * * If it was .INCLUDES, the source is taken to be the * suffix of files which will be #included and whose * search path should be present in the .INCLUDES * variable. * * If it was .LIBS, the source is taken to be the * suffix of files which are considered libraries and * whose search path should be present in the .LIBS * variable. * * If it was .NULL, the source is the suffix to use * when a file has no valid suffix. */ char savech; while (*cp && !isspace((unsigned char)*cp)) { cp++; } savech = *cp; *cp = '\0'; switch (specType) { case Suffixes: Suff_AddSuffix(line); break; case ExPath: LST_FOREACH(ln, &paths) Path_AddDir(Lst_Datum(ln), line); break; case Includes: Suff_AddInclude(line); break; case Libs: Suff_AddLib(line); break; case Null: Suff_SetNull(line); break; default: break; } *cp = savech; if (savech != '\0') { cp++; } while (*cp && isspace((unsigned char)*cp)) { cp++; } line = cp; } Lst_Destroy(&paths, NOFREE); } else if (specType == ExportVar) { Var_SetEnv(line, VAR_GLOBAL); } else { /* list of sources in order */ Lst curSrcs = Lst_Initializer(curSrc); while (*line) { /* * The targets take real sources, so we must beware of * archive specifications (i.e. things with left * parentheses in them) and handle them accordingly. */ while (*cp && !isspace((unsigned char)*cp)) { if (*cp == '(' && cp > line && cp[-1] != '$') { /* * Only stop for a left parenthesis if * it isn't at the start of a word * (that'll be for variable changes * later) and isn't preceded by a dollar * sign (a dynamic source). */ break; } else { cp++; } } if (*cp == '(') { GNode *gnp; /* list of archive source names after exp. */ Lst sources = Lst_Initializer(sources); if (!Arch_ParseArchive(&line, &sources, VAR_CMD)) { Parse_Error(PARSE_FATAL, "Error in " "source archive spec \"%s\"", line); return; } while (!Lst_IsEmpty(&sources)) { gnp = Lst_DeQueue(&sources); ParseDoSrc(tOp, gnp->name, &curSrcs); } cp = line; } else { if (*cp) { *cp = '\0'; cp += 1; } ParseDoSrc(tOp, line, &curSrcs); } while (*cp && isspace((unsigned char)*cp)) { cp++; } line = cp; } Lst_Destroy(&curSrcs, NOFREE); } if (mainNode == NULL) { /* * If we have yet to decide on a main target to make, in the * absence of any user input, we want the first target on * the first dependency line that is actually a real target * (i.e. isn't a .USE or .EXEC rule) to be made. */ LST_FOREACH(ln, &targets) { gn = Lst_Datum(ln); if ((gn->type & (OP_NOTMAIN | OP_USE | OP_EXEC | OP_TRANSFORM)) == 0) { mainNode = gn; Targ_SetMain(gn); break; } } } } /*- *--------------------------------------------------------------------- * Parse_IsVar -- * Return TRUE if the passed line is a variable assignment. A variable * assignment consists of a single word followed by optional whitespace * followed by either a += or an = operator. * This function is used both by the Parse_File function and main when * parsing the command-line arguments. * * Results: * TRUE if it is. FALSE if it ain't * * Side Effects: * none *--------------------------------------------------------------------- */ Boolean Parse_IsVar(char *line) { Boolean wasSpace = FALSE; /* set TRUE if found a space */ Boolean haveName = FALSE; /* Set TRUE if have a variable name */ int level = 0; #define ISEQOPERATOR(c) \ ((c) == '+' || (c) == ':' || (c) == '?' || (c) == '!') /* * Skip to variable name */ for (; *line == ' ' || *line == '\t'; line++) continue; for (; *line != '=' || level != 0; line++) { switch (*line) { case '\0': /* * end-of-line -- can't be a variable assignment. */ return (FALSE); case ' ': case '\t': /* * there can be as much white space as desired so long * as there is only one word before the operator */ wasSpace = TRUE; break; case '(': case '{': level++; break; case '}': case ')': level--; break; default: if (wasSpace && haveName) { if (ISEQOPERATOR(*line)) { /* * We must have a finished word */ if (level != 0) return (FALSE); /* * When an = operator [+?!:] is found, * the next character must be an = or * it ain't a valid assignment. */ if (line[1] == '=') return (haveName); #ifdef SUNSHCMD /* * This is a shell command */ if (strncmp(line, ":sh", 3) == 0) return (haveName); #endif } /* * This is the start of another word, so not * assignment. */ return (FALSE); } else { haveName = TRUE; wasSpace = FALSE; } break; } } return (haveName); } /*- *--------------------------------------------------------------------- * Parse_DoVar -- * Take the variable assignment in the passed line and do it in the * global context. * * Note: There is a lexical ambiguity with assignment modifier characters * in variable names. This routine interprets the character before the = * as a modifier. Therefore, an assignment like * C++=/usr/bin/CC * is interpreted as "C+ +=" instead of "C++ =". * * Results: * none * * Side Effects: * the variable structure of the given variable name is altered in the * global context. *--------------------------------------------------------------------- */ void Parse_DoVar(char *line, GNode *ctxt) { char *cp; /* pointer into line */ enum { VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL } type; /* Type of assignment */ char *opc; /* ptr to operator character to * null-terminate the variable name */ /* * Skip to variable name */ while (*line == ' ' || *line == '\t') { line++; } /* * Skip to operator character, nulling out whitespace as we go */ for (cp = line + 1; *cp != '='; cp++) { if (isspace((unsigned char)*cp)) { *cp = '\0'; } } opc = cp - 1; /* operator is the previous character */ *cp++ = '\0'; /* nuke the = */ /* * Check operator type */ switch (*opc) { case '+': type = VAR_APPEND; *opc = '\0'; break; case '?': /* * If the variable already has a value, we don't do anything. */ *opc = '\0'; if (Var_Exists(line, ctxt)) { return; } else { type = VAR_NORMAL; } break; case ':': type = VAR_SUBST; *opc = '\0'; break; case '!': type = VAR_SHELL; *opc = '\0'; break; default: #ifdef SUNSHCMD while (*opc != ':') { if (opc == line) break; else --opc; } if (strncmp(opc, ":sh", 3) == 0) { type = VAR_SHELL; *opc = '\0'; break; } #endif type = VAR_NORMAL; break; } while (isspace((unsigned char)*cp)) { cp++; } if (type == VAR_APPEND) { Var_Append(line, cp, ctxt); } else if (type == VAR_SUBST) { /* * Allow variables in the old value to be undefined, but leave * their invocation alone -- this is done by forcing oldVars * to be false. * XXX: This can cause recursive variables, but that's not * hard to do, and this allows someone to do something like * * CFLAGS = $(.INCLUDES) * CFLAGS := -I.. $(CFLAGS) * * And not get an error. */ Boolean oldOldVars = oldVars; oldVars = FALSE; /* * make sure that we set the variable the first time to nothing * so that it gets substituted! */ if (!Var_Exists(line, ctxt)) Var_Set(line, "", ctxt); cp = Buf_Peel(Var_Subst(cp, ctxt, FALSE)); oldVars = oldOldVars; Var_Set(line, cp, ctxt); free(cp); } else if (type == VAR_SHELL) { /* * TRUE if the command needs to be freed, i.e. * if any variable expansion was performed */ Boolean freeCmd = FALSE; Buffer *buf; const char *error; if (strchr(cp, '$') != NULL) { /* * There's a dollar sign in the command, so perform * variable expansion on the whole thing. The * resulting string will need freeing when we're done, * so set freeCmd to TRUE. */ cp = Buf_Peel(Var_Subst(cp, VAR_CMD, TRUE)); freeCmd = TRUE; } buf = Cmd_Exec(cp, &error); Var_Set(line, Buf_Data(buf), ctxt); Buf_Destroy(buf, TRUE); if (error) Parse_Error(PARSE_WARNING, error, cp); if (freeCmd) free(cp); } else { /* * Normal assignment -- just do it. */ Var_Set(line, cp, ctxt); } if (strcmp(line, MAKE_JOB_PREFIX) == 0) Job_SetPrefix(); } /*- *----------------------------------------------------------------------- * ParseHasCommands -- * Callback procedure for Parse_File when destroying the list of * targets on the last dependency line. Marks a target as already * having commands if it does, to keep from having shell commands * on multiple dependency lines. * * Results: * None * * Side Effects: * OP_HAS_COMMANDS may be set for the target. * *----------------------------------------------------------------------- */ static void ParseHasCommands(void *gnp) { GNode *gn = gnp; if (!Lst_IsEmpty(&gn->commands)) { gn->type |= OP_HAS_COMMANDS; } } /*- *----------------------------------------------------------------------- * Parse_AddIncludeDir -- * Add a directory to the path searched for included makefiles * bracketed by double-quotes. Used by functions in main.c * * Results: * None. * * Side Effects: * The directory is appended to the list. * *----------------------------------------------------------------------- */ void Parse_AddIncludeDir(char *dir) { Path_AddDir(&parseIncPath, dir); } /*- *--------------------------------------------------------------------- * Parse_FromString -- * Start Parsing from the given string * * Results: * None * * Side Effects: * A structure is added to the includes Lst and readProc, curFile.lineno, * curFile.fname and curFile.F are altered for the new file *--------------------------------------------------------------------- */ void Parse_FromString(char *str, int lineno) { DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno)); ParsePushInput(estrdup(CURFILE->fname), NULL, str, lineno); } #ifdef SYSVINCLUDE /*- *--------------------------------------------------------------------- * ParseTraditionalInclude -- * Push to another file. * * The input is the line minus the "include". The file name is * the string following the "include". * * Results: * None * * Side Effects: * A structure is added to the includes Lst and readProc, curFile.lineno, * curFile.fname and curFile.F are altered for the new file *--------------------------------------------------------------------- */ static void ParseTraditionalInclude(char *file) { char *fullname; /* full pathname of file */ char *cp; /* current position in file spec */ /* * Skip over whitespace */ while (*file == ' ' || *file == '\t') { file++; } if (*file == '\0') { Parse_Error(PARSE_FATAL, "Filename missing from \"include\""); return; } /* * Skip to end of line or next whitespace */ for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) { continue; } *cp = '\0'; /* * Substitute for any variables in the file name before trying to * find the thing. */ file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE)); /* * Now we know the file's name, we attempt to find the durn thing. * Search for it first on the -I search path, then on the .PATH * search path, if not found in a -I directory. */ fullname = Path_FindFile(file, &parseIncPath); if (fullname == NULL) { fullname = Path_FindFile(file, &dirSearchPath); } if (fullname == NULL) { /* * Still haven't found the makefile. Look for it on the system * path as a last resort. */ fullname = Path_FindFile(file, &sysIncPath); } if (fullname == NULL) { Parse_Error(PARSE_FATAL, "Could not find %s", file); /* XXXHB free(file) */ return; } /* XXXHB free(file) */ /* * We set up the name of the file to be the absolute * name of the include file so error messages refer to the right * place. */ ParsePushInput(fullname, NULL, NULL, 0); } #endif /*- *--------------------------------------------------------------------- * ParseReadc -- * Read a character from the current file * * Results: * The character that was read * * Side Effects: *--------------------------------------------------------------------- */ static int ParseReadc(void) { if (CURFILE->F != NULL) return (fgetc(CURFILE->F)); if (CURFILE->str != NULL && *CURFILE->ptr != '\0') return (*CURFILE->ptr++); return (EOF); } /*- *--------------------------------------------------------------------- * ParseUnreadc -- * Put back a character to the current file * * Results: * None. * * Side Effects: *--------------------------------------------------------------------- */ static void ParseUnreadc(int c) { if (CURFILE->F != NULL) { ungetc(c, CURFILE->F); return; } if (CURFILE->str != NULL) { *--(CURFILE->ptr) = c; return; } } /* ParseSkipLine(): * Grab the next line unless it begins with a dot (`.') and we're told to * ignore such lines. */ static char * ParseSkipLine(int skip, int keep_newline) { char *line; int c, lastc; Buffer *buf; buf = Buf_Init(MAKE_BSIZE); do { Buf_Clear(buf); lastc = '\0'; while (((c = ParseReadc()) != '\n' || lastc == '\\') && c != EOF) { if (skip && c == '#' && lastc != '\\') { /* * let a comment be terminated even by an * escaped \n. This is consistent to comment * handling in ParseReadLine */ while ((c = ParseReadc()) != '\n' && c != EOF) ; break; } if (c == '\n') { if (keep_newline) Buf_AddByte(buf, (Byte)c); else Buf_ReplaceLastByte(buf, (Byte)' '); CURFILE->lineno++; while ((c = ParseReadc()) == ' ' || c == '\t') continue; if (c == EOF) break; } Buf_AddByte(buf, (Byte)c); lastc = c; } if (c == EOF) { Parse_Error(PARSE_FATAL, "Unclosed conditional/for loop"); Buf_Destroy(buf, TRUE); return (NULL); } CURFILE->lineno++; Buf_AddByte(buf, (Byte)'\0'); line = Buf_Data(buf); } while (skip == 1 && line[0] != '.'); Buf_Destroy(buf, FALSE); return (line); } /*- *--------------------------------------------------------------------- * ParseReadLine -- * Read an entire line from the input file. Called only by Parse_File. * To facilitate escaped newlines and what have you, a character is * buffered in 'lastc', which is '\0' when no characters have been * read. When we break out of the loop, c holds the terminating * character and lastc holds a character that should be added to * the line (unless we don't read anything but a terminator). * * Results: * A line w/o its newline * * Side Effects: * Only those associated with reading a character *--------------------------------------------------------------------- */ static char * ParseReadLine(void) { Buffer *buf; /* Buffer for current line */ int c; /* the current character */ int lastc; /* The most-recent character */ Boolean semiNL; /* treat semi-colons as newlines */ Boolean ignDepOp; /* TRUE if should ignore dependency operators * for the purposes of setting semiNL */ Boolean ignComment; /* TRUE if should ignore comments (in a * shell command */ char *line; /* Result */ char *ep; /* to strip trailing blanks */ again: semiNL = FALSE; ignDepOp = FALSE; ignComment = FALSE; lastc = '\0'; /* * Handle tab at the beginning of the line. A leading tab (shell * command) forces us to ignore comments and dependency operators and * treat semi-colons as semi-colons (by leaving semiNL FALSE). * This also discards completely blank lines. */ for (;;) { c = ParseReadc(); if (c == EOF) { if (ParsePopInput() == DONE) { /* End of all inputs - return NULL */ return (NULL); } continue; } if (c == '\t') { ignComment = ignDepOp = TRUE; lastc = c; break; } if (c != '\n') { ParseUnreadc(c); break; } CURFILE->lineno++; } buf = Buf_Init(MAKE_BSIZE); while (((c = ParseReadc()) != '\n' || lastc == '\\') && c != EOF) { test_char: switch (c) { case '\n': /* * Escaped newline: read characters until a * non-space or an unescaped newline and * replace them all by a single space. This is * done by storing the space over the backslash * and dropping through with the next nonspace. * If it is a semi-colon and semiNL is TRUE, * it will be recognized as a newline in the * code below this... */ CURFILE->lineno++; lastc = ' '; while ((c = ParseReadc()) == ' ' || c == '\t') { continue; } if (c == EOF || c == '\n') { goto line_read; } else { /* * Check for comments, semiNL's, etc. -- * easier than ParseUnreadc(c); * continue; */ goto test_char; } /*NOTREACHED*/ break; case ';': /* * Semi-colon: Need to see if it should be * interpreted as a newline */ if (semiNL) { /* * To make sure the command that may * be following this semi-colon begins * with a tab, we push one back into the * input stream. This will overwrite the * semi-colon in the buffer. If there is * no command following, this does no * harm, since the newline remains in * the buffer and the * whole line is ignored. */ ParseUnreadc('\t'); goto line_read; } break; case '=': if (!semiNL) { /* * Haven't seen a dependency operator * before this, so this must be a * variable assignment -- don't pay * attention to dependency operators * after this. */ ignDepOp = TRUE; } else if (lastc == ':' || lastc == '!') { /* * Well, we've seen a dependency * operator already, but it was the * previous character, so this is really * just an expanded variable assignment. * Revert semi-colons to being just * semi-colons again and ignore any more * dependency operators. * * XXX: Note that a line like * "foo : a:=b" will blow up, but who'd * write a line like that anyway? */ ignDepOp = TRUE; semiNL = FALSE; } break; case '#': if (!ignComment) { if (lastc != '\\') { /* * If the character is a hash * mark and it isn't escaped * (or we're being compatible), * the thing is a comment. * Skip to the end of the line. */ do { c = ParseReadc(); } while (c != '\n' && c != EOF); goto line_read; } else { /* * Don't add the backslash. * Just let the # get copied * over. */ lastc = c; continue; } } break; case ':': case '!': if (!ignDepOp) { /* * A semi-colon is recognized as a * newline only on dependency lines. * Dependency lines are lines with a * colon or an exclamation point. * Ergo... */ semiNL = TRUE; } break; default: break; } /* * Copy in the previous character (there may be none if this * was the first character) and save this one in * lastc. */ if (lastc != '\0') Buf_AddByte(buf, (Byte)lastc); lastc = c; } line_read: CURFILE->lineno++; if (lastc != '\0') { Buf_AddByte(buf, (Byte)lastc); } Buf_AddByte(buf, (Byte)'\0'); line = Buf_Peel(buf); /* * Strip trailing blanks and tabs from the line. * Do not strip a blank or tab that is preceded by * a '\' */ ep = line; while (*ep) ++ep; while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) { if (ep > line + 1 && ep[-2] == '\\') break; --ep; } *ep = 0; if (line[0] == '\0') { /* empty line - just ignore */ free(line); goto again; } return (line); } /*- *----------------------------------------------------------------------- * ParseFinishLine -- * Handle the end of a dependency group. * * Results: * Nothing. * * Side Effects: * inLine set FALSE. 'targets' list destroyed. * *----------------------------------------------------------------------- */ static void ParseFinishLine(void) { const LstNode *ln; if (inLine) { LST_FOREACH(ln, &targets) { if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM) Suff_EndTransform(Lst_Datum(ln)); } Lst_Destroy(&targets, ParseHasCommands); inLine = FALSE; } } /** * xparse_include * Parse an .include directive and push the file onto the input stack. * The input is the line minus the .include. A file spec is a string * enclosed in <> or "". The former is looked for only in sysIncPath. * The latter in . and the directories specified by -I command line * options */ static void xparse_include(char *file, int sinclude) { char *fullname; /* full pathname of file */ char endc; /* the character which ends the file spec */ char *cp; /* current position in file spec */ Boolean isSystem; /* TRUE if makefile is a system makefile */ char *prefEnd, *Fname; char *newName; /* * Skip to delimiter character so we know where to look */ while (*file == ' ' || *file == '\t') { file++; } if (*file != '"' && *file != '<') { Parse_Error(PARSE_FATAL, ".include filename must be delimited by '\"' or '<'"); return; } /* * Set the search path on which to find the include file based on the * characters which bracket its name. Angle-brackets imply it's * a system Makefile while double-quotes imply it's a user makefile */ if (*file == '<') { isSystem = TRUE; endc = '>'; } else { isSystem = FALSE; endc = '"'; } /* * Skip to matching delimiter */ for (cp = ++file; *cp != endc; cp++) { if (*cp == '\0') { Parse_Error(PARSE_FATAL, "Unclosed .include filename. '%c' expected", endc); return; } } *cp = '\0'; /* * Substitute for any variables in the file name before trying to * find the thing. */ file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE)); /* * Now we know the file's name and its search path, we attempt to * find the durn thing. A return of NULL indicates the file don't * exist. */ if (!isSystem) { /* * Include files contained in double-quotes are first searched * for relative to the including file's location. We don't want * to cd there, of course, so we just tack on the old file's * leading path components and call Path_FindFile to see if * we can locate the beast. */ /* Make a temporary copy of this, to be safe. */ Fname = estrdup(CURFILE->fname); prefEnd = strrchr(Fname, '/'); if (prefEnd != NULL) { *prefEnd = '\0'; if (file[0] == '/') newName = estrdup(file); else newName = str_concat(Fname, file, STR_ADDSLASH); fullname = Path_FindFile(newName, &parseIncPath); if (fullname == NULL) { fullname = Path_FindFile(newName, &dirSearchPath); } free(newName); *prefEnd = '/'; } else { fullname = NULL; } free(Fname); if (fullname == NULL) { /* * Makefile wasn't found in same directory as included * makefile. Search for it first on the -I search path, * then on the .PATH search path, if not found in a -I * directory. * XXX: Suffix specific? */ fullname = Path_FindFile(file, &parseIncPath); if (fullname == NULL) { fullname = Path_FindFile(file, &dirSearchPath); } } } else { fullname = NULL; } if (fullname == NULL) { /* * System makefile or still haven't found the makefile. * Look for it on the system path. */ fullname = Path_FindFile(file, &sysIncPath); } if (fullname == NULL) { *cp = endc; if (!sinclude) Parse_Error(PARSE_FATAL, "Could not find %s", file); else Main_AddSourceMakefile(file); free(file); return; } Main_AddSourceMakefile(fullname); free(file); /* * We set up the name of the file to be the absolute * name of the include file so error messages refer to the right * place. */ ParsePushInput(fullname, NULL, NULL, 0); DEBUGF(DIR, (".include %s\n", fullname)); } static void parse_include(char *file, int code __unused, int lineno __unused) { xparse_include(file, 0); } static void parse_sinclude(char *file, int code __unused, int lineno __unused) { xparse_include(file, 1); } /** * parse_message * Parse a .warning or .error directive * * The input is the line minus the ".error"/".warning". We substitute * variables, print the message and exit(1) (for .error) or just print * a warning if the directive is malformed. */ static void parse_message(char *line, int iserror, int lineno __unused) { if (!isspace((u_char)*line)) { Parse_Error(PARSE_WARNING, "invalid syntax: .%s%s", iserror ? "error" : "warning", line); return; } while (isspace((u_char)*line)) line++; line = Buf_Peel(Var_Subst(line, VAR_CMD, FALSE)); Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line); free(line); if (iserror) { /* Terminate immediately. */ exit(1); } } /** * parse_undef * Parse an .undef directive. */ static void parse_undef(char *line, int code __unused, int lineno __unused) { char *cp; while (isspace((u_char)*line)) line++; for (cp = line; !isspace((u_char)*cp) && *cp != '\0'; cp++) { ; } *cp = '\0'; cp = Buf_Peel(Var_Subst(line, VAR_CMD, FALSE)); Var_Delete(cp, VAR_GLOBAL); free(cp); } /** * parse_for * Parse a .for directive. */ static void parse_for(char *line, int code __unused, int lineno) { if (!For_For(line)) { /* syntax error */ return; } line = NULL; /* * Skip after the matching endfor. */ do { free(line); line = ParseSkipLine(0, 1); if (line == NULL) { Parse_Error(PARSE_FATAL, "Unexpected end of file in for loop.\n"); return; } } while (For_Eval(line)); free(line); /* execute */ For_Run(lineno); } /** * parse_endfor * Parse endfor. This may only happen if there was no matching .for. */ static void parse_endfor(char *line __unused, int code __unused, int lineno __unused) { Parse_Error(PARSE_FATAL, "for-less endfor"); } /** * parse_directive * Got a line starting with a '.'. Check if this is a directive * and parse it. * * return: * TRUE if line was a directive, FALSE otherwise. */ static Boolean parse_directive(char *line) { char *start; char *cp; int dir; /* * Get the keyword: * .[[:space:]]*\([[:alpha:]][[:alnum:]_]*\).* * \1 is the keyword. */ for (start = line; isspace((u_char)*start); start++) { ; } if (!isalpha((u_char)*start)) { return (FALSE); } cp = start + 1; while (isalnum((u_char)*cp) || *cp == '_') { cp++; } dir = directive_hash(start, cp - start); if (dir < 0 || dir >= (int)NDIRECTS || (size_t)(cp - start) != strlen(directives[dir].name) || strncmp(start, directives[dir].name, cp - start) != 0) { /* not actually matched */ return (FALSE); } if (!skipLine || directives[dir].skip_flag) (*directives[dir].func)(cp, directives[dir].code, CURFILE->lineno); return (TRUE); } /*- *--------------------------------------------------------------------- * Parse_File -- * Parse a file into its component parts, incorporating it into the * current dependency graph. This is the main function and controls * almost every other function in this module * * Results: * None * * Side Effects: * Loads. Nodes are added to the list of all targets, nodes and links * are added to the dependency graph. etc. etc. etc. *--------------------------------------------------------------------- */ void Parse_File(const char *name, FILE *stream) { char *cp; /* pointer into the line */ char *line; /* the line we're working on */ inLine = FALSE; fatals = 0; ParsePushInput(estrdup(name), stream, NULL, 0); while ((line = ParseReadLine()) != NULL) { if (*line == '.' && parse_directive(line + 1)) { /* directive consumed */ goto nextLine; } if (skipLine || *line == '#') { /* Skipping .if block or comment. */ goto nextLine; } if (*line == '\t') { /* * If a line starts with a tab, it can only * hope to be a creation command. */ for (cp = line + 1; isspace((unsigned char)*cp); cp++) { continue; } if (*cp) { if (inLine) { LstNode *ln; GNode *gn; /* * So long as it's not a blank * line and we're actually in a * dependency spec, add the * command to the list of * commands of all targets in * the dependency spec. */ LST_FOREACH(ln, &targets) { gn = Lst_Datum(ln); /* * if target already * supplied, ignore * commands */ if (!(gn->type & OP_HAS_COMMANDS)) Lst_AtEnd(&gn->commands, cp); else Parse_Error(PARSE_WARNING, "duplicate script " "for target \"%s\" ignored", gn->name); } continue; } else { Parse_Error(PARSE_FATAL, "Unassociated shell command \"%s\"", cp); } } #ifdef SYSVINCLUDE } else if (strncmp(line, "include", 7) == 0 && isspace((unsigned char)line[7]) && strchr(line, ':') == NULL) { /* * It's an S3/S5-style "include". */ ParseTraditionalInclude(line + 7); goto nextLine; #endif } else if (Parse_IsVar(line)) { ParseFinishLine(); Parse_DoVar(line, VAR_GLOBAL); } else { /* * We now know it's a dependency line so it * needs to have all variables expanded before * being parsed. Tell the variable module to * complain if some variable is undefined... * To make life easier on novices, if the line * is indented we first make sure the line has * a dependency operator in it. If it doesn't * have an operator and we're in a dependency * line's script, we assume it's actually a * shell command and add it to the current * list of targets. XXX this comment seems wrong. */ cp = line; if (isspace((unsigned char)line[0])) { while (*cp != '\0' && isspace((unsigned char)*cp)) { cp++; } if (*cp == '\0') { goto nextLine; } } ParseFinishLine(); cp = Buf_Peel(Var_Subst(line, VAR_CMD, TRUE)); free(line); line = cp; /* * Need a non-circular list for the target nodes */ Lst_Destroy(&targets, NOFREE); inLine = TRUE; ParseDoDependency(line); } nextLine: free(line); } ParseFinishLine(); /* * Make sure conditionals are clean */ Cond_End(); if (fatals) errx(1, "fatal errors encountered -- cannot continue"); } /*- *----------------------------------------------------------------------- * Parse_MainName -- * Return a Lst of the main target to create for main()'s sake. If * no such target exists, we Punt with an obnoxious error message. * * Results: * A Lst of the single node to create. * * Side Effects: * None. * *----------------------------------------------------------------------- */ void Parse_MainName(Lst *listmain) { if (mainNode == NULL) { Punt("no target to make."); /*NOTREACHED*/ } else if (mainNode->type & OP_DOUBLEDEP) { Lst_AtEnd(listmain, mainNode); Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW); } else Lst_AtEnd(listmain, mainNode); } freebsd-buildutils-10.0/src/usr.bin/make/suff.c0000644000000000000000000015513311135403240016304 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)suff.c 8.4 (Berkeley) 3/21/94 */ #include __FBSDID("$FreeBSD$"); /*- * suff.c -- * Functions to maintain suffix lists and find implicit dependents * using suffix transformation rules * * Interface: * Suff_Init Initialize all things to do with suffixes. * * Suff_DoPaths This function is used to make life easier * when searching for a file according to its * suffix. It takes the global search path, * as defined using the .PATH: target, and appends * its directories to the path of each of the * defined suffixes, as specified using * .PATH: targets. In addition, all * directories given for suffixes labeled as * include files or libraries, using the .INCLUDES * or .LIBS targets, are played with using * Dir_MakeFlags to create the .INCLUDES and * .LIBS global variables. * * Suff_ClearSuffixes Clear out all the suffixes and defined * transformations. * * Suff_IsTransform Return TRUE if the passed string is the lhs * of a transformation rule. * * Suff_AddSuffix Add the passed string as another known suffix. * * Suff_GetPath Return the search path for the given suffix. * * Suff_AddInclude Mark the given suffix as denoting an include * file. * * Suff_AddLib Mark the given suffix as denoting a library. * * Suff_AddTransform Add another transformation to the suffix * graph. Returns GNode suitable for framing, I * mean, tacking commands, attributes, etc. on. * * Suff_SetNull Define the suffix to consider the suffix of * any file that doesn't have a known one. * * Suff_FindDeps Find implicit sources for and the location of * a target based on its suffix. Returns the * bottom-most node added to the graph or NULL * if the target had no implicit sources. */ #include #include #include #include #include "arch.h" #include "buf.h" #include "config.h" #include "dir.h" #include "globals.h" #include "GNode.h" #include "lst.h" #include "make.h" #include "parse.h" #include "str.h" #include "suff.h" #include "targ.h" #include "util.h" #include "var.h" /* Lst of suffixes */ static Lst sufflist = Lst_Initializer(sufflist); /* Lst of suffixes to be cleaned */ static Lst suffClean = Lst_Initializer(suffClean); /* Lst of sources */ static Lst srclist = Lst_Initializer(srclist); /* Lst of transformation rules */ static Lst transforms = Lst_Initializer(transforms); /* Counter for assigning suffix numbers */ static int sNum = 0; /* * Structure describing an individual suffix. */ typedef struct Suff { char *name; /* The suffix itself */ int nameLen; /* Length of the suffix */ short flags; /* Type of suffix */ #define SUFF_INCLUDE 0x01 /* One which is #include'd */ #define SUFF_LIBRARY 0x02 /* One which contains a library */ #define SUFF_NULL 0x04 /* The empty suffix */ struct Path searchPath; /* Path for files with this suffix */ int sNum; /* The suffix number */ int refCount; /* Reference count of list membership */ Lst parents; /* Suffixes we have a transformation to */ Lst children; /* Suffixes we have a transformation from */ Lst ref; /* List of lists this suffix is referenced */ } Suff; /* * Structure used in the search for implied sources. */ typedef struct Src { char *file; /* The file to look for */ char *pref; /* Prefix from which file was formed */ Suff *suff; /* The suffix on the file */ struct Src *parent; /* The Src for which this is a source */ GNode *node; /* The node describing the file */ int children; /* Count of existing children (so we don't free * this thing too early or never nuke it) */ #ifdef DEBUG_SRC Lst cp; /* Debug; children list */ #endif } Src; /* The NULL suffix for this run */ static Suff *suffNull; /* The empty suffix required for POSIX single-suffix transformation rules */ static Suff *emptySuff; static void SuffFindDeps(GNode *, Lst *); /*- *----------------------------------------------------------------------- * SuffSuffIsSuffix -- * See if suff is a suffix of str. * * Results: * NULL if it ain't, pointer to character in str before suffix if * it is. * * Side Effects: * None *----------------------------------------------------------------------- */ static char * SuffSuffIsSuffix(const Suff *s, char *str) { const char *p1; /* Pointer into suffix name */ char *p2; /* Pointer into string being examined */ size_t len; len = strlen(str); p1 = s->name + s->nameLen; p2 = str + len; while (p1 >= s->name && len > 0 && *p1 == *p2) { p1--; p2--; len--; } return (p1 == s->name - 1 ? p2 : NULL); } /*- *----------------------------------------------------------------------- * SuffSuffFind -- * Find a suffix given its name. * * Results: * The suffix or NULL. * * Side Effects: * None *----------------------------------------------------------------------- */ static Suff * SuffSuffFind(const char *s) { LstNode *ln; LST_FOREACH(ln, &sufflist) { if (strcmp(s, ((const Suff *)Lst_Datum(ln))->name) == 0) return (Lst_Datum(ln)); } return (NULL); } /*- *----------------------------------------------------------------------- * SuffTransFind * Find a transform. * * Results: * transform or NULL. * * Side Effects: * None *----------------------------------------------------------------------- */ static GNode * SuffTransFind(const char *name) { LstNode *ln; LST_FOREACH(ln, &transforms) { if (strcmp(name, ((const GNode *)Lst_Datum(ln))->name) == 0) return (Lst_Datum(ln)); } return (NULL); } /*********** Maintenance Functions ************/ #if 0 /* * Keep this function for now until it is clear why a .SUFFIXES: doesn't * actually delete the suffixes but just puts them on the suffClean list. */ /*- *----------------------------------------------------------------------- * SuffFree -- * Free up all memory associated with the given suffix structure. * * Results: * none * * Side Effects: * the suffix entry is detroyed *----------------------------------------------------------------------- */ static void SuffFree(void *sp) { Suff *s = sp; if (s == suffNull) suffNull = NULL; if (s == emptySuff) emptySuff = NULL; Lst_Destroy(&s->ref, NOFREE); Lst_Destroy(&s->children, NOFREE); Lst_Destroy(&s->parents, NOFREE); Lst_Destroy(&s->searchPath, Dir_Destroy); free(s->name); free(s); } #endif /*- *----------------------------------------------------------------------- * SuffRemove -- * Remove the suffix into the list * * Results: * None * * Side Effects: * The reference count for the suffix is decremented *----------------------------------------------------------------------- */ static void SuffRemove(Lst *l, Suff *s) { LstNode *ln = Lst_Member(l, s); if (ln != NULL) { Lst_Remove(l, ln); s->refCount--; } } /*- *----------------------------------------------------------------------- * SuffInsert -- * Insert the suffix into the list keeping the list ordered by suffix * numbers. * * Results: * None * * Side Effects: * The reference count of the suffix is incremented *----------------------------------------------------------------------- */ static void SuffInsert(Lst *l, Suff *s) { LstNode *ln; /* current element in l we're examining */ Suff *s2; /* the suffix descriptor in this element */ s2 = NULL; for (ln = Lst_First(l); ln != NULL; ln = Lst_Succ(ln)) { s2 = Lst_Datum(ln); if (s2->sNum >= s->sNum) break; } if (s2 == NULL) { DEBUGF(SUFF, ("inserting an empty list?...")); } DEBUGF(SUFF, ("inserting %s(%d)...", s->name, s->sNum)); if (ln == NULL) { DEBUGF(SUFF, ("at end of list\n")); Lst_AtEnd(l, s); s->refCount++; Lst_AtEnd(&s->ref, l); } else if (s2->sNum != s->sNum) { DEBUGF(SUFF, ("before %s(%d)\n", s2->name, s2->sNum)); Lst_Insert(l, ln, s); s->refCount++; Lst_AtEnd(&s->ref, l); } else { DEBUGF(SUFF, ("already there\n")); } } /*- *----------------------------------------------------------------------- * Suff_ClearSuffixes -- * This is gross. Nuke the list of suffixes but keep all transformation * rules around. The transformation graph is destroyed in this process, * but we leave the list of rules so when a new graph is formed the rules * will remain. * This function is called from the parse module when a * .SUFFIXES:\n line is encountered. * * Results: * none * * Side Effects: * the sufflist and its graph nodes are destroyed *----------------------------------------------------------------------- */ void Suff_ClearSuffixes(void) { Lst_Concat(&suffClean, &sufflist, LST_CONCLINK); sNum = 1; suffNull = emptySuff; /* * Clear suffNull's children list (the other suffixes are built new, but * suffNull is used as is). * NOFREE is used because all suffixes are are on the suffClean list. * suffNull should not have parents. */ Lst_Destroy(&suffNull->children, NOFREE); } /*- *----------------------------------------------------------------------- * SuffParseTransform -- * Parse a transformation string to find its two component suffixes. * * Results: * TRUE if the string is a valid transformation and FALSE otherwise. * * Side Effects: * The passed pointers are overwritten. * *----------------------------------------------------------------------- */ static Boolean SuffParseTransform(char *str, Suff **srcPtr, Suff **targPtr) { LstNode *srcLn; /* element in suffix list of trans source*/ Suff *src; /* Source of transformation */ char *str2; /* Extra pointer (maybe target suffix) */ LstNode *singleLn; /* element in suffix list of any suffix * that exactly matches str */ Suff *single = NULL; /* Source of possible transformation to * null suffix */ singleLn = NULL; /* * Loop looking first for a suffix that matches the start of the * string and then for one that exactly matches the rest of it. If * we can find two that meet these criteria, we've successfully * parsed the string. */ srcLn = Lst_First(&sufflist); for (;;) { /* advance to next possible suffix */ while (srcLn != NULL) { src = Lst_Datum(srcLn); if (strncmp(str, src->name, strlen(src->name)) == 0) break; srcLn = LST_NEXT(srcLn); } if (srcLn == NULL) { /* * Ran out of source suffixes -- no such rule */ if (singleLn != NULL) { /* * Not so fast Mr. Smith! There was a suffix * that encompassed the entire string, so we * assume it was a transformation to the null * suffix (thank you POSIX). We still prefer to * find a double rule over a singleton, hence we * leave this check until the end. * * XXX: Use emptySuff over suffNull? */ *srcPtr = single; *targPtr = suffNull; return (TRUE); } return (FALSE); } str2 = str + src->nameLen; if (*str2 == '\0') { single = src; singleLn = srcLn; } else { *targPtr = SuffSuffFind(str2); if (*targPtr != NULL) { *srcPtr = src; return (TRUE); } } /* next one */ srcLn = LST_NEXT(srcLn); } } /*- *----------------------------------------------------------------------- * Suff_IsTransform -- * Return TRUE if the given string is a transformation rule * * * Results: * TRUE if the string is a concatenation of two known suffixes. * FALSE otherwise * * Side Effects: * None *----------------------------------------------------------------------- */ Boolean Suff_IsTransform(char *str) { Suff *src, *targ; return (SuffParseTransform(str, &src, &targ)); } /*- *----------------------------------------------------------------------- * Suff_AddTransform -- * Add the transformation rule described by the line to the * list of rules and place the transformation itself in the graph * * Results: * The node created for the transformation in the transforms list * * Side Effects: * The node is placed on the end of the transforms Lst and links are * made between the two suffixes mentioned in the target name *----------------------------------------------------------------------- */ GNode * Suff_AddTransform(char *line) { GNode *gn; /* GNode of transformation rule */ Suff *s; /* source suffix */ Suff *t; /* target suffix */ s = t = NULL; /* silence gcc */ gn = SuffTransFind(line); if (gn == NULL) { /* * Make a new graph node for the transformation. * It will be filled in by the Parse module. */ gn = Targ_NewGN(line); Lst_AtEnd(&transforms, gn); } else { /* * New specification for transformation rule. Just nuke the * old list of commands so they can be filled in again... * We don't actually free the commands themselves, because a * given command can be attached to several different * transformations. */ Lst_Destroy(&gn->commands, NOFREE); Lst_Destroy(&gn->children, NOFREE); } gn->type = OP_TRANSFORM; SuffParseTransform(line, &s, &t); /* * link the two together in the proper relationship and order */ DEBUGF(SUFF, ("defining transformation from `%s' to `%s'\n", s->name, t->name)); SuffInsert(&t->children, s); SuffInsert(&s->parents, t); return (gn); } /*- *----------------------------------------------------------------------- * Suff_EndTransform -- * Handle the finish of a transformation definition, removing the * transformation from the graph if it has neither commands nor * sources. This is called from the Parse module at the end of * a dependency block. * * Side Effects: * If the node has no commands or children, the children and parents * lists of the affected suffices are altered. * *----------------------------------------------------------------------- */ void Suff_EndTransform(const GNode *gn) { Suff *s, *t; if (!Lst_IsEmpty(&gn->commands) || !Lst_IsEmpty(&gn->children)) { DEBUGF(SUFF, ("transformation %s complete\n", gn->name)); return; } /* * SuffParseTransform() may fail for special rules which are not * actual transformation rules (e.g., .DEFAULT). */ if (!SuffParseTransform(gn->name, &s, &t)) return; DEBUGF(SUFF, ("deleting transformation from `%s' to `%s'\n", s->name, t->name)); /* * Remove the source from the target's children list. We check * for a NULL return to handle a beanhead saying something like * .c.o .c.o: * * We'll be called twice when the next target is seen, but .c * and .o are only linked once... */ SuffRemove(&t->children, s); /* * Remove the target from the source's parents list */ SuffRemove(&s->parents, t); } /*- *----------------------------------------------------------------------- * SuffRebuildGraph -- * Called from Suff_AddSuffix via LST_FOREACH to search through the * list of existing transformation rules and rebuild the transformation * graph when it has been destroyed by Suff_ClearSuffixes. If the * given rule is a transformation involving this suffix and another, * existing suffix, the proper relationship is established between * the two. * * Side Effects: * The appropriate links will be made between this suffix and * others if transformation rules exist for it. * *----------------------------------------------------------------------- */ static void SuffRebuildGraph(const GNode *transform, Suff *s) { char *cp; Suff *s2 = NULL; /* * First see if it is a transformation from this suffix. */ if (strncmp(transform->name, s->name, strlen(s->name)) == 0) { cp = transform->name + strlen(s->name); if (cp[0] == '\0') /* null rule */ s2 = suffNull; else s2 = SuffSuffFind(cp); if (s2 != NULL) { /* * Found target. Link in and return, since it can't be * anything else. */ SuffInsert(&s2->children, s); SuffInsert(&s->parents, s2); return; } } /* * Not from, maybe to? */ cp = SuffSuffIsSuffix(s, transform->name); if (cp != NULL) { /* * Null-terminate the source suffix in order to find it. */ cp[1] = '\0'; s2 = SuffSuffFind(transform->name); /* * Replace the start of the target suffix */ cp[1] = s->name[0]; if (s2 != NULL) { /* * Found it -- establish the proper relationship */ SuffInsert(&s->children, s2); SuffInsert(&s2->parents, s); } } } /*- *----------------------------------------------------------------------- * Suff_AddSuffix -- * Add the suffix in string to the end of the list of known suffixes. * Should we restructure the suffix graph? Make doesn't... * * Results: * None * * Side Effects: * A GNode is created for the suffix and a Suff structure is created and * added to the suffixes list unless the suffix was already known. *----------------------------------------------------------------------- */ void Suff_AddSuffix(char *str) { Suff *s; /* new suffix descriptor */ LstNode *ln; if (SuffSuffFind(str) != NULL) /* * Already known */ return; s = emalloc(sizeof(Suff)); s->name = estrdup(str); s->nameLen = strlen(s->name); TAILQ_INIT(&s->searchPath); Lst_Init(&s->children); Lst_Init(&s->parents); Lst_Init(&s->ref); s->sNum = sNum++; s->flags = 0; s->refCount = 0; Lst_AtEnd(&sufflist, s); /* * Look for any existing transformations from or to this suffix. * XXX: Only do this after a Suff_ClearSuffixes? */ LST_FOREACH(ln, &transforms) SuffRebuildGraph(Lst_Datum(ln), s); } /*- *----------------------------------------------------------------------- * Suff_GetPath -- * Return the search path for the given suffix, if it's defined. * * Results: * The searchPath for the desired suffix or NULL if the suffix isn't * defined. * * Side Effects: * None *----------------------------------------------------------------------- */ struct Path * Suff_GetPath(char *sname) { Suff *s; s = SuffSuffFind(sname); if (s == NULL) return (NULL); return (&s->searchPath); } /*- *----------------------------------------------------------------------- * Suff_DoPaths -- * Extend the search paths for all suffixes to include the default * search path. * * Results: * None. * * Side Effects: * The searchPath field of all the suffixes is extended by the * directories in dirSearchPath. If paths were specified for the * ".h" suffix, the directories are stuffed into a global variable * called ".INCLUDES" with each directory preceded by a -I. The same * is done for the ".a" suffix, except the variable is called * ".LIBS" and the flag is -L. *----------------------------------------------------------------------- */ void Suff_DoPaths(void) { Suff *s; LstNode *ln; char *ptr; struct Path inIncludes; /* Cumulative .INCLUDES path */ struct Path inLibs; /* Cumulative .LIBS path */ TAILQ_INIT(&inIncludes); TAILQ_INIT(&inLibs); for (ln = Lst_First(&sufflist); ln != NULL; ln = Lst_Succ(ln)) { s = Lst_Datum(ln); #ifdef INCLUDES if (s->flags & SUFF_INCLUDE) { Path_Concat(&inIncludes, &s->searchPath); } #endif /* INCLUDES */ #ifdef LIBRARIES if (s->flags & SUFF_LIBRARY) { Path_Concat(&inLibs, &s->searchPath); } #endif /* LIBRARIES */ Path_Concat(&s->searchPath, &dirSearchPath); } ptr = Path_MakeFlags("-I", &inIncludes); Var_SetGlobal(".INCLUDES", ptr); free(ptr); ptr = Path_MakeFlags("-L", &inLibs); Var_SetGlobal(".LIBS", ptr); free(ptr); Path_Clear(&inIncludes); Path_Clear(&inLibs); } /*- *----------------------------------------------------------------------- * Suff_AddInclude -- * Add the given suffix as a type of file which gets included. * Called from the parse module when a .INCLUDES line is parsed. * The suffix must have already been defined. * * Results: * None. * * Side Effects: * The SUFF_INCLUDE bit is set in the suffix's flags field * *----------------------------------------------------------------------- */ void Suff_AddInclude(char *sname) { Suff *s; if ((s = SuffSuffFind(sname)) != NULL) s->flags |= SUFF_INCLUDE; } /*- *----------------------------------------------------------------------- * Suff_AddLib -- * Add the given suffix as a type of file which is a library. * Called from the parse module when parsing a .LIBS line. The * suffix must have been defined via .SUFFIXES before this is * called. * * Results: * None. * * Side Effects: * The SUFF_LIBRARY bit is set in the suffix's flags field * *----------------------------------------------------------------------- */ void Suff_AddLib(char *sname) { Suff *s; if ((s = SuffSuffFind(sname)) != NULL) s->flags |= SUFF_LIBRARY; } /* * Create a new Src structure */ static Src * SuffSrcCreate(char *file, char *prefix, Suff *suff, Src *parent, GNode *node) { Src *s; s = emalloc(sizeof(*s)); s->file = file; s->pref = prefix; s->suff = suff; s->parent = parent; s->node = node; s->children = 0; #ifdef DEBUG_SRC Lst_Init(&s->cp); #endif return (s); } /********** Implicit Source Search Functions *********/ /*- *----------------------------------------------------------------------- * SuffAddLevel -- * Add all the children of targ as Src structures to the given list: * Add a suffix as a Src structure to the given list with its parent * being the given Src structure. If the suffix is the null suffix, * the prefix is used unaltered as the file name in the Src structure. * * Results: * None * * Side Effects: * Lots of structures are created and added to the list *----------------------------------------------------------------------- */ static void SuffAddLevel(Lst *l, Src *targ) { LstNode *ln; Suff *suff; Src *s2; #ifdef DEBUG_SRC const LstNode *ln1; #endif LST_FOREACH(ln, &targ->suff->children) { suff = Lst_Datum(ln); if ((suff->flags & SUFF_NULL) && *suff->name != '\0') { /* * If the suffix has been marked as the NULL suffix, * also create a Src structure for a file with no suffix * attached. Two birds, and all that... */ s2 = SuffSrcCreate(estrdup(targ->pref), targ->pref, suff, targ, NULL); suff->refCount++; targ->children += 1; Lst_AtEnd(l, s2); #ifdef DEBUG_SRC Lst_AtEnd(&targ->cp, s2); printf("1 add %p %p to %p:", targ, s2, l); LST_FOREACH(ln1, l) printf("%p ", (const void *)Lst_Datum(ln1)); printf("\n"); #endif } s2 = SuffSrcCreate(str_concat(targ->pref, suff->name, 0), targ->pref, suff, targ, NULL); suff->refCount++; targ->children += 1; Lst_AtEnd(l, s2); #ifdef DEBUG_SRC Lst_AtEnd(&targ->cp, s2); printf("2 add %p %p to %p:", targ, s2, l); LST_FOREACH(ln1, l) printf("%p ", (const void *)Lst_Datum(ln1)); printf("\n"); #endif } } /*- *---------------------------------------------------------------------- * SuffRemoveSrc -- * Free all src structures in list that don't have a reference count * XXX this actually frees only the first of these. * * Results: * True if a src was removed * * Side Effects: * The memory is free'd. *---------------------------------------------------------------------- */ static int SuffRemoveSrc(Lst *l) { LstNode *ln, *ln1; Src *s; int t = 0; #ifdef DEBUG_SRC printf("cleaning %lx: ", (unsigned long) l); LST_FOREACH(ln, l) printf("%p ", (const void *)Lst_Datum(ln)); printf("\n"); #endif for (ln = Lst_First(l); ln != NULL; ln = ln1) { ln1 = Lst_Succ(ln); s = (Src *)Lst_Datum(ln); if (s->children == 0) { free(s->file); if (!s->parent) free(s->pref); else { #ifdef DEBUG_SRC LstNode *ln = Lst_Member(&s->parent->cp, s); if (ln != NULL) Lst_Remove(&s->parent->cp, ln); #endif --s->parent->children; } #ifdef DEBUG_SRC printf("free: [l=%p] p=%p %d\n", l, s, s->children); Lst_Destroy(&s->cp, NOFREE); #endif Lst_Remove(l, ln); free(s); t |= 1; return (TRUE); } #ifdef DEBUG_SRC else { const LstNode *tln; printf("keep: [l=%p] p=%p %d: ", l, s, s->children); LST_FOREACH(tln, &s->cp) printf("%p ", (const void *)Lst_Datum(tln)); printf("\n"); } #endif } return (t); } /*- *----------------------------------------------------------------------- * SuffFindThem -- * Find the first existing file/target in the list srcs * * Results: * The lowest structure in the chain of transformations * * Side Effects: * None *----------------------------------------------------------------------- */ static Src * SuffFindThem(Lst *srcs, Lst *slst) { Src *s; /* current Src */ Src *rs; /* returned Src */ char *ptr; rs = NULL; while (!Lst_IsEmpty (srcs)) { s = Lst_DeQueue(srcs); DEBUGF(SUFF, ("\ttrying %s...", s->file)); /* * A file is considered to exist if either a node exists in the * graph for it or the file actually exists. */ if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) { #ifdef DEBUG_SRC printf("remove %p from %p\n", s, srcs); #endif rs = s; break; } if ((ptr = Path_FindFile(s->file, &s->suff->searchPath)) != NULL) { rs = s; #ifdef DEBUG_SRC printf("remove %p from %p\n", s, srcs); #endif free(ptr); break; } DEBUGF(SUFF, ("not there\n")); SuffAddLevel(srcs, s); Lst_AtEnd(slst, s); } if (rs) { DEBUGF(SUFF, ("got it\n")); } return (rs); } /*- *----------------------------------------------------------------------- * SuffFindCmds -- * See if any of the children of the target in the Src structure is * one from which the target can be transformed. If there is one, * a Src structure is put together for it and returned. * * Results: * The Src structure of the "winning" child, or NULL if no such beast. * * Side Effects: * A Src structure may be allocated. * *----------------------------------------------------------------------- */ static Src * SuffFindCmds(Src *targ, Lst *slst) { LstNode *ln; /* General-purpose list node */ GNode *t; /* Target GNode */ GNode *s; /* Source GNode */ int prefLen;/* The length of the defined prefix */ Suff *suff; /* Suffix on matching beastie */ Src *ret; /* Return value */ char *cp; t = targ->node; prefLen = strlen(targ->pref); for (ln = Lst_First(&t->children); ln != NULL; ln = Lst_Succ(ln)) { s = Lst_Datum(ln); cp = strrchr(s->name, '/'); if (cp == NULL) { cp = s->name; } else { cp++; } if (strncmp(cp, targ->pref, prefLen) == 0) { /* * The node matches the prefix ok, see if it has * a known suffix. */ suff = SuffSuffFind(&cp[prefLen]); if (suff != NULL) { /* * It even has a known suffix, see if there's * a transformation defined between the node's * suffix and the target's suffix. * * XXX: Handle multi-stage transformations * here, too. */ if (Lst_Member(&suff->parents, targ->suff) != NULL) { /* * Hot Damn! Create a new Src structure * to describe this transformation * (making sure to duplicate the * source node's name so Suff_FindDeps * can free it again (ick)), and return * the new structure. */ ret = SuffSrcCreate(estrdup(s->name), targ->pref, suff, targ, s); suff->refCount++; targ->children += 1; #ifdef DEBUG_SRC printf("3 add %p %p\n", &targ, ret); Lst_AtEnd(&targ->cp, ret); #endif Lst_AtEnd(slst, ret); DEBUGF(SUFF, ("\tusing existing source " "%s\n", s->name)); return (ret); } } } } return (NULL); } /*- * The child node contains variable references. Expand them and return * a list of expansions. */ static void SuffExpandVariables(GNode *parent, GNode *child, Lst *members) { Buffer *buf; char *cp; char *start; Lst_Init(members); DEBUGF(SUFF, ("Expanding \"%s\"...", child->name)); buf = Var_Subst(child->name, parent, TRUE); cp = Buf_Data(buf); if (child->type & OP_ARCHV) { /* * Node was an archive(member) target, so we * want to call on the Arch module to find the * nodes for us, expanding variables in the * parent's context. */ Arch_ParseArchive(&cp, members, parent); Buf_Destroy(buf, TRUE); return; } /* * Break the result into a vector of strings whose nodes we can find, * then add those nodes to the members list. Unfortunately, we can't use * brk_string b/c it doesn't understand about variable specifications * with spaces in them... XXX */ for (start = cp; *start == ' ' || *start == '\t'; start++) ; for (cp = start; *cp != '\0'; cp++) { if (*cp == ' ' || *cp == '\t') { /* * White-space -- terminate element, find the node, * add it, skip any further spaces. */ *cp++ = '\0'; Lst_AtEnd(members, Targ_FindNode(start, TARG_CREATE)); while (*cp == ' ' || *cp == '\t') { cp++; } /* * Adjust cp for increment at * start of loop, but set start * to first non-space. */ start = cp--; } else if (*cp == '$') { /* * Start of a variable spec -- contact variable module * to find the end so we can skip over it. */ char *junk; size_t len = 0; Boolean doFree; junk = Var_Parse(cp, parent, TRUE, &len, &doFree); if (junk != var_Error) { cp += len - 1; } if (doFree) { free(junk); } } else if (*cp == '\\' && *cp != '\0') { /* * Escaped something -- skip over it */ cp++; } } if (cp != start) { /* * Stuff left over -- add it to the * list too */ Lst_AtEnd(members, Targ_FindNode(start, TARG_CREATE)); } Buf_Destroy(buf, TRUE); } /*- * The child node contains wildcards. Expand them and return a list of * expansions. */ static void SuffExpandWildcards(GNode *child, Lst *members) { char *cp; Lst exp; /* List of expansions */ LstNode *ln; struct Path *path; /* Search path along which to expand */ Lst_Init(members); /* * Find a path along which to expand the word. * * If the word has a known suffix, use that path. * If it has no known suffix and we're allowed to use the null * suffix, use its path. * Else use the default system search path. */ LST_FOREACH(ln, &sufflist) { if (SuffSuffIsSuffix(Lst_Datum(ln), child->name) != NULL) break; } DEBUGF(SUFF, ("Wildcard expanding \"%s\"...", child->name)); if (ln != NULL) { Suff *s = Lst_Datum(ln); DEBUGF(SUFF, ("suffix is \"%s\"...", s->name)); path = &s->searchPath; } else { /* * Use default search path */ path = &dirSearchPath; } /* * Expand the word along the chosen path */ Lst_Init(&exp); Path_Expand(child->name, path, &exp); while (!Lst_IsEmpty(&exp)) { /* * Fetch next expansion off the list and find its GNode */ cp = Lst_DeQueue(&exp); DEBUGF(SUFF, ("%s...", cp)); Lst_AtEnd(members, Targ_FindNode(cp, TARG_CREATE)); } } /*- *----------------------------------------------------------------------- * SuffExpandChildren -- * Expand the names of any children of a given node that contain * variable invocations or file wildcards into actual targets. * * Results: * == 0 (continue) * * Side Effects: * The expanded node is removed from the parent's list of children, * and the parent's unmade counter is decremented, but other nodes * may be added. * *----------------------------------------------------------------------- */ static void SuffExpandChildren(GNode *parent, LstNode *current) { GNode *cchild; /* current child */ GNode *gn; LstNode *prev; /* node after which to append new source */ Lst members; /* expanded nodes */ if (current == NULL) { /* start from begin of parent's children list */ current = Lst_First(&parent->children); } while (current != NULL) { cchild = Lst_Datum(current); /* * First do variable expansion -- this takes precedence over * wildcard expansion. If the result contains wildcards, they'll * be gotten to later since the resulting words are tacked * instead of the current child onto the children list. * * XXXHB what if cchild contains lib.a(t1.o t2.o t3.o) but * no $? */ if (strchr(cchild->name, '$') != NULL) { SuffExpandVariables(parent, cchild, &members); } else if (Dir_HasWildcards(cchild->name)) { SuffExpandWildcards(cchild, &members); } else { /* nothing special just advance to next child */ current = LST_NEXT(current); continue; } /* * New nodes effectively take the place of the child, * so place them after the child */ prev = current; /* * Add all new elements to the parent node if they aren't * already children of it. */ while(!Lst_IsEmpty(&members)) { gn = Lst_DeQueue(&members); DEBUGF(SUFF, ("%s...", gn->name)); if (Lst_Member(&parent->children, gn) == NULL) { Lst_Append(&parent->children, prev, gn); prev = Lst_Succ(prev); Lst_AtEnd(&gn->parents, parent); parent->unmade++; } } /* * Now the source is expanded, remove it from the list * of children to keep it from being processed. * Advance to the next child. */ prev = current; current = LST_NEXT(current); parent->unmade--; Lst_Remove(&parent->children, prev); DEBUGF(SUFF, ("\n")); } } /*- *----------------------------------------------------------------------- * SuffApplyTransform -- * Apply a transformation rule, given the source and target nodes * and suffixes. * * Results: * TRUE if successful, FALSE if not. * * Side Effects: * The source and target are linked and the commands from the * transformation are added to the target node's commands list. * All attributes but OP_DEPMASK and OP_TRANSFORM are applied * to the target. The target also inherits all the sources for * the transformation rule. * *----------------------------------------------------------------------- */ static Boolean SuffApplyTransform(GNode *tGn, GNode *sGn, Suff *t, Suff *s) { LstNode *ln; /* General node */ char *tname; /* Name of transformation rule */ GNode *gn; /* Node for same */ if (Lst_Member(&tGn->children, sGn) == NULL) { /* * Not already linked, so form the proper links between the * target and source. */ Lst_AtEnd(&tGn->children, sGn); Lst_AtEnd(&sGn->parents, tGn); tGn->unmade += 1; } if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) { /* * When a :: node is used as the implied source of a node, * we have to link all its cohorts in as sources as well. Only * the initial sGn gets the target in its iParents list, however * as that will be sufficient to get the .IMPSRC variable set * for tGn */ for (ln = Lst_First(&sGn->cohorts); ln != NULL; ln = Lst_Succ(ln)) { gn = Lst_Datum(ln); if (Lst_Member(&tGn->children, gn) == NULL) { /* * Not already linked, so form the proper * links between the target and source. */ Lst_AtEnd(&tGn->children, gn); Lst_AtEnd(&gn->parents, tGn); tGn->unmade += 1; } } } /* * Locate the transformation rule itself */ tname = str_concat(s->name, t->name, 0); gn = SuffTransFind(tname); free(tname); if (gn == NULL) { /* * Not really such a transformation rule (can happen when we're * called to link an OP_MEMBER and OP_ARCHV node), so return * FALSE. */ return (FALSE); } DEBUGF(SUFF, ("\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name)); /* * Record last child for expansion purposes */ ln = Lst_Last(&tGn->children); /* * Pass the buck to Make_HandleUse to apply the rule */ Make_HandleUse(gn, tGn); /* * Deal with wildcards and variables in any acquired sources */ ln = Lst_Succ(ln); if (ln != NULL) { SuffExpandChildren(tGn, ln); } /* * Keep track of another parent to which this beast is transformed so * the .IMPSRC variable can be set correctly for the parent. */ Lst_AtEnd(&sGn->iParents, tGn); return (TRUE); } /*- *----------------------------------------------------------------------- * SuffFindArchiveDeps -- * Locate dependencies for an OP_ARCHV node. * * Results: * None * * Side Effects: * Same as Suff_FindDeps * *----------------------------------------------------------------------- */ static void SuffFindArchiveDeps(GNode *gn, Lst *slst) { char *eoarch; /* End of archive portion */ char *eoname; /* End of member portion */ char *name; /* Start of member's name */ GNode *mem; /* Node for member */ Suff *ms; /* Suffix descriptor for member */ static const char *copy[] = { TARGET, /* Must be first */ PREFIX, /* Must be second */ }; /* * The node is an archive(member) pair. so we must find a * suffix for both of them. */ eoarch = strchr(gn->name, '('); eoname = strchr(eoarch, ')'); *eoname = '\0'; /* Nuke parentheses during suffix search */ *eoarch = '\0'; /* So a suffix can be found */ name = eoarch + 1; /* * To simplify things, call Suff_FindDeps recursively on the member now, * so we can simply compare the member's .PREFIX and .TARGET variables * to locate its suffix. This allows us to figure out the suffix to * use for the archive without having to do a quadratic search over the * suffix list, backtracking for each one... */ mem = Targ_FindNode(name, TARG_CREATE); SuffFindDeps(mem, slst); /* * Create the link between the two nodes right off */ if (Lst_Member(&gn->children, mem) == NULL) { Lst_AtEnd(&gn->children, mem); Lst_AtEnd(&mem->parents, gn); gn->unmade += 1; } /* * Copy in the variables from the member node to this one. */ Var_Set(copy[1], Var_Value(copy[1], mem), gn); Var_Set(copy[0], Var_Value(copy[0], mem), gn); ms = mem->suffix; if (ms == NULL) { /* * Didn't know what it was -- use .NULL suffix if not in * make mode */ DEBUGF(SUFF, ("using null suffix\n")); ms = suffNull; } /* * Set the other two local variables required for this target. */ Var_Set(MEMBER, name, gn); Var_Set(ARCHIVE, gn->name, gn); if (ms != NULL) { /* * Member has a known suffix, so look for a transformation rule * from it to a possible suffix of the archive. Rather than * searching through the entire list, we just look at suffixes * to which the member's suffix may be transformed... */ LstNode *ln; /* * Use first matching suffix... */ LST_FOREACH(ln, &ms->parents) { if (SuffSuffIsSuffix(Lst_Datum(ln), gn->name) != NULL) break; } if (ln != NULL) { /* * Got one -- apply it */ if (!SuffApplyTransform(gn, mem, Lst_Datum(ln), ms)) { DEBUGF(SUFF, ("\tNo transformation from " "%s -> %s\n", ms->name, ((Suff *)Lst_Datum(ln))->name)); } } } /* * Replace the opening and closing parens now we've no need * of the separate pieces. */ *eoarch = '('; *eoname = ')'; /* * Pretend gn appeared to the left of a dependency operator so * the user needn't provide a transformation from the member to the * archive. */ if (OP_NOP(gn->type)) { gn->type |= OP_DEPENDS; } /* * Flag the member as such so we remember to look in the archive for * its modification time. */ mem->type |= OP_MEMBER; } /*- *----------------------------------------------------------------------- * SuffFindNormalDeps -- * Locate implicit dependencies for regular targets. * * Results: * None. * * Side Effects: * Same as Suff_FindDeps... * *----------------------------------------------------------------------- */ static void SuffFindNormalDeps(GNode *gn, Lst *slst) { char *eoname; /* End of name */ char *sopref; /* Start of prefix */ LstNode *ln; /* Next suffix node to check */ Lst srcs; /* List of sources at which to look */ Lst targs; /* List of targets to which things can be * transformed. They all have the same file, * but different suff and pref fields */ Src *bottom; /* Start of found transformation path */ Src *src; /* General Src pointer */ char *pref; /* Prefix to use */ Src *targ; /* General Src target pointer */ eoname = gn->name + strlen(gn->name); sopref = gn->name; /* * Begin at the beginning... */ ln = Lst_First(&sufflist); Lst_Init(&srcs); Lst_Init(&targs); /* * We're caught in a catch-22 here. On the one hand, we want to use any * transformation implied by the target's sources, but we can't examine * the sources until we've expanded any variables/wildcards they may * hold, and we can't do that until we've set up the target's local * variables and we can't do that until we know what the proper suffix * for the target is (in case there are two suffixes one of which is a * suffix of the other) and we can't know that until we've found its * implied source, which we may not want to use if there's an existing * source that implies a different transformation. * * In an attempt to get around this, which may not work all the time, * but should work most of the time, we look for implied sources first, * checking transformations to all possible suffixes of the target, * use what we find to set the target's local variables, expand the * children, then look for any overriding transformations they imply. * Should we find one, we discard the one we found before. */ while (ln != NULL) { /* * Look for next possible suffix... */ while (ln != NULL) { if (SuffSuffIsSuffix(Lst_Datum(ln), gn->name) != NULL) break; ln = LST_NEXT(ln); } if (ln != NULL) { int prefLen; /* Length of the prefix */ Src *target; /* * Allocate a Src structure to which things can be * transformed */ target = SuffSrcCreate(estrdup(gn->name), NULL, Lst_Datum(ln), NULL, gn); target->suff->refCount++; /* * Allocate room for the prefix, whose end is found * by subtracting the length of the suffix from * the end of the name. */ prefLen = (eoname - target->suff->nameLen) - sopref; assert(prefLen >= 0); target->pref = emalloc(prefLen + 1); memcpy(target->pref, sopref, prefLen); target->pref[prefLen] = '\0'; /* * Add nodes from which the target can be made */ SuffAddLevel(&srcs, target); /* * Record the target so we can nuke it */ Lst_AtEnd(&targs, target); /* * Search from this suffix's successor... */ ln = Lst_Succ(ln); } } /* * Handle target of unknown suffix... */ if (Lst_IsEmpty(&targs) && suffNull != NULL) { DEBUGF(SUFF, ("\tNo known suffix on %s. Using .NULL suffix\n", gn->name)); targ = SuffSrcCreate(estrdup(gn->name), estrdup(sopref), suffNull, NULL, gn); targ->suff->refCount++; /* * Only use the default suffix rules if we don't have commands * or dependencies defined for this gnode */ if (Lst_IsEmpty(&gn->commands) && Lst_IsEmpty(&gn->children)) SuffAddLevel(&srcs, targ); else { DEBUGF(SUFF, ("not ")); } DEBUGF(SUFF, ("adding suffix rules\n")); Lst_AtEnd(&targs, targ); } /* * Using the list of possible sources built up from the target * suffix(es), try and find an existing file/target that matches. */ bottom = SuffFindThem(&srcs, slst); if (bottom == NULL) { /* * No known transformations -- use the first suffix found for * setting the local variables. */ if (!Lst_IsEmpty(&targs)) { targ = Lst_Datum(Lst_First(&targs)); } else { targ = NULL; } } else { /* * Work up the transformation path to find the suffix of the * target to which the transformation was made. */ for (targ = bottom; targ->parent != NULL; targ = targ->parent) continue; } /* * The .TARGET variable we always set to be the name at this point, * since it's only set to the path if the thing is only a source and * if it's only a source, it doesn't matter what we put here as far * as expanding sources is concerned, since it has none... */ Var_Set(TARGET, gn->name, gn); pref = (targ != NULL) ? targ->pref : gn->name; Var_Set(PREFIX, pref, gn); /* * Now we've got the important local variables set, expand any sources * that still contain variables or wildcards in their names. */ SuffExpandChildren(gn, NULL); if (targ == NULL) { DEBUGF(SUFF, ("\tNo valid suffix on %s\n", gn->name)); sfnd_abort: /* * Deal with finding the thing on the default search path if the * node is only a source (not on the lhs of a dependency * operator or [XXX] it has neither children or commands). */ if (OP_NOP(gn->type) || (Lst_IsEmpty(&gn->children) && Lst_IsEmpty(&gn->commands))) { gn->path = Path_FindFile(gn->name, (targ == NULL ? &dirSearchPath : &targ->suff->searchPath)); if (gn->path != NULL) { char *ptr; Var_Set(TARGET, gn->path, gn); if (targ != NULL) { /* * Suffix known for the thing -- trim * the suffix off the path to form the * proper .PREFIX variable. */ int savep = strlen(gn->path) - targ->suff->nameLen; char savec; if (gn->suffix) gn->suffix->refCount--; gn->suffix = targ->suff; gn->suffix->refCount++; savec = gn->path[savep]; gn->path[savep] = '\0'; if ((ptr = strrchr(gn->path, '/')) != NULL) ptr++; else ptr = gn->path; Var_Set(PREFIX, ptr, gn); gn->path[savep] = savec; } else { /* * The .PREFIX gets the full path if * the target has no known suffix. */ if (gn->suffix) gn->suffix->refCount--; gn->suffix = NULL; if ((ptr = strrchr(gn->path, '/')) != NULL) ptr++; else ptr = gn->path; Var_Set(PREFIX, ptr, gn); } } } else { /* * Not appropriate to search for the thing -- set the * path to be the name so Dir_MTime won't go * grovelling for it. */ if (gn->suffix) gn->suffix->refCount--; gn->suffix = (targ == NULL) ? NULL : targ->suff; if (gn->suffix) gn->suffix->refCount++; free(gn->path); gn->path = estrdup(gn->name); } goto sfnd_return; } /* * If the suffix indicates that the target is a library, mark that in * the node's type field. */ if (targ->suff->flags & SUFF_LIBRARY) { gn->type |= OP_LIB; } /* * Check for overriding transformation rule implied by sources */ if (!Lst_IsEmpty(&gn->children)) { src = SuffFindCmds(targ, slst); if (src != NULL) { /* * Free up all the Src structures in the * transformation path up to, but not including, * the parent node. */ while (bottom && bottom->parent != NULL) { if (Lst_Member(slst, bottom) == NULL) { Lst_AtEnd(slst, bottom); } bottom = bottom->parent; } bottom = src; } } if (bottom == NULL) { /* * No idea from where it can come -- return now. */ goto sfnd_abort; } /* * We now have a list of Src structures headed by 'bottom' and linked * via their 'parent' pointers. What we do next is create links between * source and target nodes (which may or may not have been created) * and set the necessary local variables in each target. The * commands for each target are set from the commands of the * transformation rule used to get from the src suffix to the targ * suffix. Note that this causes the commands list of the original * node, gn, to be replaced by the commands of the final * transformation rule. Also, the unmade field of gn is incremented. * Etc. */ if (bottom->node == NULL) { bottom->node = Targ_FindNode(bottom->file, TARG_CREATE); } for (src = bottom; src->parent != NULL; src = src->parent) { targ = src->parent; if (src->node->suffix) src->node->suffix->refCount--; src->node->suffix = src->suff; src->node->suffix->refCount++; if (targ->node == NULL) { targ->node = Targ_FindNode(targ->file, TARG_CREATE); } SuffApplyTransform(targ->node, src->node, targ->suff, src->suff); if (targ->node != gn) { /* * Finish off the dependency-search process for any * nodes between bottom and gn (no point in questing * around the filesystem for their implicit source * when it's already known). Note that the node can't * have any sources that need expanding, since * SuffFindThem will stop on an existing * node, so all we need to do is set the standard and * System V variables. */ targ->node->type |= OP_DEPS_FOUND; Var_Set(PREFIX, targ->pref, targ->node); Var_Set(TARGET, targ->node->name, targ->node); } } if (gn->suffix) gn->suffix->refCount--; gn->suffix = src->suff; gn->suffix->refCount++; /* * So Dir_MTime doesn't go questing for it... */ free(gn->path); gn->path = estrdup(gn->name); /* * Nuke the transformation path and the Src structures left over in the * two lists. */ sfnd_return: if (bottom) if (Lst_Member(slst, bottom) == NULL) Lst_AtEnd(slst, bottom); while (SuffRemoveSrc(&srcs) || SuffRemoveSrc(&targs)) continue; Lst_Concat(slst, &srcs, LST_CONCLINK); Lst_Concat(slst, &targs, LST_CONCLINK); } /*- *----------------------------------------------------------------------- * Suff_FindDeps -- * Find implicit sources for the target described by the graph node * gn * * Results: * Nothing. * * Side Effects: * Nodes are added to the graph below the passed-in node. The nodes * are marked to have their IMPSRC variable filled in. The * PREFIX variable is set for the given node and all its * implied children. * * Notes: * The path found by this target is the shortest path in the * transformation graph, which may pass through non-existent targets, * to an existing target. The search continues on all paths from the * root suffix until a file is found. I.e. if there's a path * .o -> .c -> .l -> .l,v from the root and the .l,v file exists but * the .c and .l files don't, the search will branch out in * all directions from .o and again from all the nodes on the * next level until the .l,v node is encountered. * *----------------------------------------------------------------------- */ void Suff_FindDeps(GNode *gn) { SuffFindDeps(gn, &srclist); while (SuffRemoveSrc(&srclist)) continue; } static void SuffFindDeps(GNode *gn, Lst *slst) { if (gn->type & OP_DEPS_FOUND) { /* * If dependencies already found, no need to do it again... */ return; } else { gn->type |= OP_DEPS_FOUND; } DEBUGF(SUFF, ("SuffFindDeps (%s)\n", gn->name)); if (gn->type & OP_ARCHV) { SuffFindArchiveDeps(gn, slst); } else if (gn->type & OP_LIB) { /* * If the node is a library, it is the arch module's job to find * it and set the TARGET variable accordingly. We merely provide * the search path, assuming all libraries end in ".a" (if the * suffix hasn't been defined, there's nothing we can do for it, * so we just set the TARGET variable to the node's name in order * to give it a value). */ Suff *s; s = SuffSuffFind(LIBSUFF); if (gn->suffix) gn->suffix->refCount--; if (s != NULL) { gn->suffix = s; gn->suffix->refCount++; Arch_FindLib(gn, &s->searchPath); } else { gn->suffix = NULL; Var_Set(TARGET, gn->name, gn); } /* * Because a library (-lfoo) target doesn't follow the standard * filesystem conventions, we don't set the regular variables for * the thing. .PREFIX is simply made empty... */ Var_Set(PREFIX, "", gn); } else { SuffFindNormalDeps(gn, slst); } } /*- *----------------------------------------------------------------------- * Suff_SetNull -- * Define which suffix is the null suffix. * * Results: * None. * * Side Effects: * 'suffNull' is altered. * * Notes: * Need to handle the changing of the null suffix gracefully so the * old transformation rules don't just go away. * *----------------------------------------------------------------------- */ void Suff_SetNull(char *name) { Suff *s; if ((s = SuffSuffFind(name)) == NULL) { Parse_Error(PARSE_WARNING, "Desired null suffix %s " "not defined.", name); return; } if (suffNull != NULL) { suffNull->flags &= ~SUFF_NULL; } s->flags |= SUFF_NULL; /* * XXX: Here's where the transformation mangling * would take place */ suffNull = s; } /*- *----------------------------------------------------------------------- * Suff_Init -- * Initialize suffixes module * * Results: * None * * Side Effects: * Many *----------------------------------------------------------------------- */ void Suff_Init(void) { sNum = 0; /* * Create null suffix for single-suffix rules (POSIX). The thing doesn't * actually go on the suffix list or everyone will think that's its * suffix. */ emptySuff = suffNull = emalloc(sizeof(Suff)); suffNull->name = estrdup(""); suffNull->nameLen = 0; TAILQ_INIT(&suffNull->searchPath); Path_Concat(&suffNull->searchPath, &dirSearchPath); Lst_Init(&suffNull->children); Lst_Init(&suffNull->parents); Lst_Init(&suffNull->ref); suffNull->sNum = sNum++; suffNull->flags = SUFF_NULL; suffNull->refCount = 1; } /********************* DEBUGGING FUNCTIONS **********************/ void Suff_PrintAll(void) { const LstNode *ln; const LstNode *tln; const GNode *gn; const Suff *s; static const struct flag2str suff_flags[] = { { SUFF_INCLUDE, "INCLUDE" }, { SUFF_LIBRARY, "LIBRARY" }, { SUFF_NULL, "NULL" }, { 0, NULL } }; printf("#*** Suffixes:\n"); LST_FOREACH(ln, &sufflist) { s = Lst_Datum(ln); printf("# `%s' [%d] ", s->name, s->refCount); if (s->flags != 0) { printf(" "); print_flags(stdout, suff_flags, s->flags, 1); } printf("\n#\tTo: "); LST_FOREACH(tln, &s->parents) printf("`%s' ", ((const Suff *)Lst_Datum(tln))->name); printf("\n#\tFrom: "); LST_FOREACH(tln, &s->children) printf("`%s' ", ((const Suff *)Lst_Datum(tln))->name); printf("\n#\tSearch Path: "); Path_Print(&s->searchPath); printf("\n"); } printf("#*** Transformations:\n"); LST_FOREACH(ln, &transforms) { gn = Lst_Datum(ln); printf("%-16s: ", gn->name); Targ_PrintType(gn->type); printf("\n"); LST_FOREACH(tln, &gn->commands) printf("\t%s\n", (const char *)Lst_Datum(tln)); printf("\n"); } } freebsd-buildutils-10.0/src/usr.bin/make/str.h0000644000000000000000000000647510244355130016166 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef str_h_44db59e6 #define str_h_44db59e6 #include "util.h" struct Buffer; /** * An array of c-strings. The pointers stored in argv, point to * strings stored in buffer. */ typedef struct ArgArray { int size; /* size of argv array */ int argc; /* strings referenced in argv */ char **argv; /* array of string pointers */ size_t len; /* size of buffer */ char *buffer; /* data buffer */ } ArgArray; /* * These constants are all used by the Str_Concat function to decide how the * final string should look. If STR_ADDSPACE is given, a space will be * placed between the two strings. If STR_ADDSLASH is given, a '/' will * be used instead of a space. If neither is given, no intervening characters * will be placed between the two strings in the final output. */ #define STR_ADDSPACE 0x01 /* add a space when Str_Concat'ing */ #define STR_ADDSLASH 0x04 /* add a slash when Str_Concat'ing */ void ArgArray_Init(ArgArray *); void ArgArray_Done(ArgArray *); char *str_concat(const char *, const char *, int); void brk_string(ArgArray *, const char [], Boolean); char *MAKEFLAGS_quote(const char *); void MAKEFLAGS_break(ArgArray *, const char []); int Str_Match(const char *, const char *); const char *Str_SYSVMatch(const char *, const char *, int *); void Str_SYSVSubst(struct Buffer *, const char *, const char *, int); #endif /* str_h_44db59e6 */ freebsd-buildutils-10.0/src/usr.bin/make/main.c0000644000000000000000000010125712057176443016303 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)main.c 8.3 (Berkeley) 3/19/94 */ #ifndef lint #if 0 static char copyright[] = "@(#) Copyright (c) 1988, 1989, 1990, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); /* * main.c * The main file for this entire program. Exit routines etc * reside here. * * Utility functions defined in this file: * Main_ParseArgLine * Takes a line of arguments, breaks them and * treats them as if they were given when first * invoked. Used by the parse module to implement * the .MFLAGS target. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "arch.h" #include "buf.h" #include "config.h" #include "dir.h" #include "globals.h" #include "GNode.h" #include "job.h" #include "make.h" #include "parse.h" #include "pathnames.h" #include "shell.h" #include "str.h" #include "suff.h" #include "targ.h" #include "util.h" #include "var.h" extern char **environ; /* XXX what header declares this variable? */ #define WANT_ENV_MKLVL 1 #define MKLVL_MAXVAL 500 #define MKLVL_ENVVAR "__MKLVL__" /* ordered list of makefiles to read */ static Lst makefiles = Lst_Initializer(makefiles); /* ordered list of source makefiles */ static Lst source_makefiles = Lst_Initializer(source_makefiles); /* list of variables to print */ static Lst variables = Lst_Initializer(variables); static Boolean expandVars; /* fully expand printed variables */ static Boolean noBuiltins; /* -r flag */ static Boolean forceJobs; /* -j argument given */ static char *curdir; /* startup directory */ static char *objdir; /* where we chdir'ed to */ static char **save_argv; /* saved argv */ static char *save_makeflags;/* saved MAKEFLAGS */ /* (-E) vars to override from env */ Lst envFirstVars = Lst_Initializer(envFirstVars); /* Targets to be made */ Lst create = Lst_Initializer(create); Boolean allPrecious; /* .PRECIOUS given on line by itself */ Boolean is_posix; /* .POSIX target seen */ Boolean mfAutoDeps; /* .MAKEFILEDEPS target seen */ Boolean remakingMakefiles; /* True if remaking makefiles is in progress */ Boolean beSilent; /* -s flag */ Boolean beVerbose; /* -v flag */ Boolean beQuiet; /* -Q flag */ Boolean compatMake; /* -B argument */ int debug; /* -d flag */ Boolean ignoreErrors; /* -i flag */ int jobLimit; /* -j argument */ int makeErrors; /* Number of targets not remade due to errors */ Boolean jobsRunning; /* TRUE if the jobs might be running */ Boolean keepgoing; /* -k flag */ Boolean noExecute; /* -n flag */ Boolean printGraphOnly; /* -p flag */ Boolean queryFlag; /* -q flag */ Boolean touchFlag; /* -t flag */ Boolean usePipes; /* !-P flag */ uint32_t warn_cmd; /* command line warning flags */ uint32_t warn_flags; /* actual warning flags */ uint32_t warn_nocmd; /* command line no-warning flags */ time_t now; /* Time at start of make */ struct GNode *DEFAULT; /* .DEFAULT node */ static struct { const char *foreign_name; const char *freebsd_name; } arch_aliases[] = { { "x86_64", "amd64" }, { "mipsel", "mips" }, }; /** * Exit with usage message. */ static void usage(void) { fprintf(stderr, "usage: make [-BPSXeiknpqrstv] [-C directory] [-D variable]\n" "\t[-d flags] [-E variable] [-f makefile] [-I directory]\n" "\t[-j max_jobs] [-m directory] [-V variable]\n" "\t[variable=value] [target ...]\n"); exit(2); } /** * MFLAGS_append * Append a flag with an optional argument to MAKEFLAGS and MFLAGS */ static void MFLAGS_append(const char *flag, char *arg) { char *str; Var_Append(".MAKEFLAGS", flag, VAR_GLOBAL); if (arg != NULL) { str = MAKEFLAGS_quote(arg); Var_Append(".MAKEFLAGS", str, VAR_GLOBAL); free(str); } Var_Append("MFLAGS", flag, VAR_GLOBAL); if (arg != NULL) { str = MAKEFLAGS_quote(arg); Var_Append("MFLAGS", str, VAR_GLOBAL); free(str); } } /** * Main_ParseWarn * * Handle argument to warning option. */ int Main_ParseWarn(const char *arg, int iscmd) { int i, neg; static const struct { const char *option; uint32_t flag; } options[] = { { "dirsyntax", WARN_DIRSYNTAX }, { NULL, 0 } }; neg = 0; if (arg[0] == 'n' && arg[1] == 'o') { neg = 1; arg += 2; } for (i = 0; options[i].option != NULL; i++) if (strcmp(arg, options[i].option) == 0) break; if (options[i].option == NULL) /* unknown option */ return (-1); if (iscmd) { if (!neg) { warn_cmd |= options[i].flag; warn_nocmd &= ~options[i].flag; warn_flags |= options[i].flag; } else { warn_nocmd |= options[i].flag; warn_cmd &= ~options[i].flag; warn_flags &= ~options[i].flag; } } else { if (!neg) { warn_flags |= (options[i].flag & ~warn_nocmd); } else { warn_flags &= ~(options[i].flag | warn_cmd); } } return (0); } /** * Open and parse the given makefile. * * Results: * TRUE if ok. FALSE if couldn't open file. */ static Boolean ReadMakefile(const char p[]) { char *fname, *fnamesave; /* makefile to read */ FILE *stream; char *name, path[MAXPATHLEN]; char *MAKEFILE; int setMAKEFILE; /* XXX - remove this once constification is done */ fnamesave = fname = estrdup(p); if (!strcmp(fname, "-")) { Parse_File("(stdin)", stdin); Var_SetGlobal("MAKEFILE", ""); } else { setMAKEFILE = strcmp(fname, ".depend"); /* if we've chdir'd, rebuild the path name */ if (curdir != objdir && *fname != '/') { snprintf(path, MAXPATHLEN, "%s/%s", curdir, fname); /* * XXX The realpath stuff breaks relative includes * XXX in some cases. The problem likely is in * XXX parse.c where it does special things in * XXX ParseDoInclude if the file is relative * XXX or absolute and not a system file. There * XXX it assumes that if the current file that's * XXX being included is absolute, that any files * XXX that it includes shouldn't do the -I path * XXX stuff, which is inconsistent with historical * XXX behavior. However, I can't penetrate the mists * XXX further, so I'm putting this workaround in * XXX here until such time as the underlying bug * XXX can be fixed. */ #if THIS_BREAKS_THINGS if (realpath(path, path) != NULL && (stream = fopen(path, "r")) != NULL) { MAKEFILE = fname; fname = path; goto found; } } else if (realpath(fname, path) != NULL) { MAKEFILE = fname; fname = path; if ((stream = fopen(fname, "r")) != NULL) goto found; } #else if ((stream = fopen(path, "r")) != NULL) { MAKEFILE = fname; fname = path; goto found; } } else { MAKEFILE = fname; if ((stream = fopen(fname, "r")) != NULL) goto found; } #endif /* look in -I and system include directories. */ name = Path_FindFile(fname, &parseIncPath); if (!name) name = Path_FindFile(fname, &sysIncPath); if (!name || !(stream = fopen(name, "r"))) { free(fnamesave); return (FALSE); } MAKEFILE = fname = name; /* * set the MAKEFILE variable desired by System V fans -- the * placement of the setting here means it gets set to the last * makefile specified, as it is set by SysV make. */ found: if (setMAKEFILE) Var_SetGlobal("MAKEFILE", MAKEFILE); Parse_File(fname, stream); } free(fnamesave); return (TRUE); } /** * Open and parse the given makefile. * If open is successful add it to the list of makefiles. * * Results: * TRUE if ok. FALSE if couldn't open file. */ static Boolean TryReadMakefile(const char p[]) { char *data; LstNode *last = Lst_Last(&source_makefiles); if (!ReadMakefile(p)) return (FALSE); data = estrdup(p); if (last == NULL) { LstNode *first = Lst_First(&source_makefiles); Lst_Insert(&source_makefiles, first, data); } else Lst_Append(&source_makefiles, last, estrdup(p)); return (TRUE); } /** * MainParseArgs * Parse a given argument vector. Called from main() and from * Main_ParseArgLine() when the .MAKEFLAGS target is used. * * XXX: Deal with command line overriding .MAKEFLAGS in makefile * * Side Effects: * Various global and local flags will be set depending on the flags * given */ static void MainParseArgs(int argc, char **argv) { int c; Boolean found_dd = FALSE; char found_dir[MAXPATHLEN + 1]; /* for searching for sys.mk */ rearg: optind = 1; /* since we're called more than once */ optreset = 1; #define OPTFLAGS "ABC:D:d:E:ef:I:ij:km:nPpQqrSstV:vXx:" for (;;) { if ((optind < argc) && strcmp(argv[optind], "--") == 0) { found_dd = TRUE; } if ((c = getopt(argc, argv, OPTFLAGS)) == -1) { break; } switch(c) { case 'A': arch_fatal = FALSE; MFLAGS_append("-A", NULL); break; case 'B': compatMake = TRUE; MFLAGS_append("-B", NULL); unsetenv("MAKE_JOBS_FIFO"); break; case 'C': if (chdir(optarg) == -1) err(1, "chdir %s", optarg); if (getcwd(curdir, MAXPATHLEN) == NULL) err(2, NULL); break; case 'D': Var_SetGlobal(optarg, "1"); MFLAGS_append("-D", optarg); break; case 'd': { char *modules = optarg; for (; *modules; ++modules) switch (*modules) { case 'A': debug = ~0; break; case 'a': debug |= DEBUG_ARCH; break; case 'c': debug |= DEBUG_COND; break; case 'd': debug |= DEBUG_DIR; break; case 'f': debug |= DEBUG_FOR; break; case 'g': if (modules[1] == '1') { debug |= DEBUG_GRAPH1; ++modules; } else if (modules[1] == '2') { debug |= DEBUG_GRAPH2; ++modules; } break; case 'j': debug |= DEBUG_JOB; break; case 'l': debug |= DEBUG_LOUD; break; case 'm': debug |= DEBUG_MAKE; break; case 's': debug |= DEBUG_SUFF; break; case 't': debug |= DEBUG_TARG; break; case 'v': debug |= DEBUG_VAR; break; default: warnx("illegal argument to d option " "-- %c", *modules); usage(); } MFLAGS_append("-d", optarg); break; } case 'E': Lst_AtEnd(&envFirstVars, estrdup(optarg)); MFLAGS_append("-E", optarg); break; case 'e': checkEnvFirst = TRUE; MFLAGS_append("-e", NULL); break; case 'f': Lst_AtEnd(&makefiles, estrdup(optarg)); break; case 'I': Parse_AddIncludeDir(optarg); MFLAGS_append("-I", optarg); break; case 'i': ignoreErrors = TRUE; MFLAGS_append("-i", NULL); break; case 'j': { char *endptr; forceJobs = TRUE; jobLimit = strtol(optarg, &endptr, 10); if (jobLimit <= 0 || *endptr != '\0') { warnx("illegal number, -j argument -- %s", optarg); usage(); } MFLAGS_append("-j", optarg); break; } case 'k': keepgoing = TRUE; MFLAGS_append("-k", NULL); break; case 'm': /* look for magic parent directory search string */ if (strncmp(".../", optarg, 4) == 0) { if (!Dir_FindHereOrAbove(curdir, optarg + 4, found_dir, sizeof(found_dir))) break; /* nothing doing */ Path_AddDir(&sysIncPath, found_dir); } else { Path_AddDir(&sysIncPath, optarg); } MFLAGS_append("-m", optarg); break; case 'n': noExecute = TRUE; MFLAGS_append("-n", NULL); break; case 'P': usePipes = FALSE; MFLAGS_append("-P", NULL); break; case 'p': printGraphOnly = TRUE; debug |= DEBUG_GRAPH1; break; case 'Q': beQuiet = TRUE; beVerbose = FALSE; MFLAGS_append("-Q", NULL); break; case 'q': queryFlag = TRUE; /* Kind of nonsensical, wot? */ MFLAGS_append("-q", NULL); break; case 'r': noBuiltins = TRUE; MFLAGS_append("-r", NULL); break; case 'S': keepgoing = FALSE; MFLAGS_append("-S", NULL); break; case 's': beSilent = TRUE; MFLAGS_append("-s", NULL); break; case 't': touchFlag = TRUE; MFLAGS_append("-t", NULL); break; case 'V': Lst_AtEnd(&variables, estrdup(optarg)); MFLAGS_append("-V", optarg); break; case 'v': beVerbose = TRUE; beQuiet = FALSE; MFLAGS_append("-v", NULL); break; case 'X': expandVars = FALSE; break; case 'x': if (Main_ParseWarn(optarg, 1) != -1) MFLAGS_append("-x", optarg); break; default: case '?': usage(); } } argv += optind; argc -= optind; oldVars = TRUE; /* * Parse the rest of the arguments. * o Check for variable assignments and perform them if so. * o Check for more flags and restart getopt if so. * o Anything else is taken to be a target and added * to the end of the "create" list. */ for (; *argv != NULL; ++argv, --argc) { if (Parse_IsVar(*argv)) { char *ptr = MAKEFLAGS_quote(*argv); char *v = estrdup(*argv); Var_Append(".MAKEFLAGS", ptr, VAR_GLOBAL); Parse_DoVar(v, VAR_CMD); free(ptr); free(v); } else if ((*argv)[0] == '-') { if ((*argv)[1] == '\0') { /* * (*argv) is a single dash, so we * just ignore it. */ } else if (found_dd) { /* * Double dash has been found, ignore * any more options. But what do we do * with it? For now treat it like a target. */ Lst_AtEnd(&create, estrdup(*argv)); } else { /* * (*argv) is a -flag, so backup argv and * argc. getopt() expects options to start * in the 2nd position. */ argc++; argv--; goto rearg; } } else if ((*argv)[0] == '\0') { Punt("illegal (null) argument."); } else { Lst_AtEnd(&create, estrdup(*argv)); } } } /** * Main_ParseArgLine * Used by the parse module when a .MFLAGS or .MAKEFLAGS target * is encountered and by main() when reading the .MAKEFLAGS envariable. * Takes a line of arguments and breaks it into its * component words and passes those words and the number of them to the * MainParseArgs function. * The line should have all its leading whitespace removed. * * Side Effects: * Only those that come from the various arguments. */ void Main_ParseArgLine(char *line, int mflags) { ArgArray aa; if (line == NULL) return; for (; *line == ' '; ++line) continue; if (!*line) return; if (mflags) MAKEFLAGS_break(&aa, line); else brk_string(&aa, line, TRUE); MainParseArgs(aa.argc, aa.argv); ArgArray_Done(&aa); } static char * chdir_verify_path(const char *path, char *obpath) { struct stat sb; if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { if (chdir(path) == -1 || getcwd(obpath, MAXPATHLEN) == NULL) { warn("warning: %s", path); return (NULL); } return (obpath); } return (NULL); } /** * In lieu of a good way to prevent every possible looping in make(1), stop * there from being more than MKLVL_MAXVAL processes forked by make(1), to * prevent a forkbomb from happening, in a dumb and mechanical way. * * Side Effects: * Creates or modifies environment variable MKLVL_ENVVAR via setenv(). */ static void check_make_level(void) { #ifdef WANT_ENV_MKLVL char *value = getenv(MKLVL_ENVVAR); int level = (value == NULL) ? 0 : atoi(value); if (level < 0) { errx(2, "Invalid value for recursion level (%d).", level); } else if (level > MKLVL_MAXVAL) { errx(2, "Max recursion level (%d) exceeded.", MKLVL_MAXVAL); } else { char new_value[32]; sprintf(new_value, "%d", level + 1); setenv(MKLVL_ENVVAR, new_value, 1); } #endif /* WANT_ENV_MKLVL */ } /** * Main_AddSourceMakefile * Add a file to the list of source makefiles */ void Main_AddSourceMakefile(const char *name) { Lst_AtEnd(&source_makefiles, estrdup(name)); } /** * Remake_Makefiles * Remake all the makefiles */ static void Remake_Makefiles(void) { Lst cleanup; LstNode *ln; int error_cnt = 0; int remade_cnt = 0; Compat_InstallSignalHandlers(); if (curdir != objdir) { if (chdir(curdir) < 0) Fatal("Failed to change directory to %s.", curdir); } Lst_Init(&cleanup); LST_FOREACH(ln, &source_makefiles) { LstNode *ln2; struct GNode *gn; const char *name = Lst_Datum(ln); Boolean saveTouchFlag = touchFlag; Boolean saveQueryFlag = queryFlag; Boolean saveNoExecute = noExecute; int mtime; /* * Create node */ gn = Targ_FindNode(name, TARG_CREATE); DEBUGF(MAKE, ("Checking %s...", gn->name)); Suff_FindDeps(gn); /* * -t, -q and -n has no effect unless the makefile is * specified as one of the targets explicitly in the * command line */ LST_FOREACH(ln2, &create) { if (!strcmp(gn->name, Lst_Datum(ln2))) { /* found as a target */ break; } } if (ln2 == NULL) { touchFlag = FALSE; queryFlag = FALSE; noExecute = FALSE; } /* * Check and remake the makefile */ mtime = Dir_MTime(gn); remakingMakefiles = TRUE; Compat_Make(gn, gn); remakingMakefiles = FALSE; /* * Restore -t, -q and -n behaviour */ touchFlag = saveTouchFlag; queryFlag = saveQueryFlag; noExecute = saveNoExecute; /* * Compat_Make will leave the 'made' field of gn * in one of the following states: * UPTODATE gn was already up-to-date * MADE gn was recreated successfully * ERROR An error occurred while gn was being created * ABORTED gn was not remade because one of its inferiors * could not be made due to errors. */ if (gn->made == MADE) { if (mtime != Dir_MTime(gn)) { DEBUGF(MAKE, ("%s updated (%d -> %d).\n", gn->name, mtime, gn->mtime)); remade_cnt++; } else { DEBUGF(MAKE, ("%s not updated: skipping restart.\n", gn->name)); } } else if (gn->made == ERROR) error_cnt++; else if (gn->made == ABORTED) { printf("`%s' not remade because of errors.\n", gn->name); error_cnt++; } else if (gn->made == UPTODATE) { Lst_EnQueue(&cleanup, gn); } } if (error_cnt > 0) Fatal("Failed to remake Makefiles."); if (remade_cnt > 0) { DEBUGF(MAKE, ("Restarting `%s'.\n", save_argv[0])); /* * Some of makefiles were remade -- restart from clean state */ if (save_makeflags != NULL) setenv("MAKEFLAGS", save_makeflags, 1); else unsetenv("MAKEFLAGS"); if (execvp(save_argv[0], save_argv) < 0) { Fatal("Can't restart `%s': %s.", save_argv[0], strerror(errno)); } } while (!Lst_IsEmpty(&cleanup)) { GNode *gn = Lst_DeQueue(&cleanup); gn->unmade = 0; gn->make = FALSE; gn->made = UNMADE; gn->childMade = FALSE; gn->mtime = gn->cmtime = 0; gn->cmtime_gn = NULL; LST_FOREACH(ln, &gn->children) { GNode *cgn = Lst_Datum(ln); gn->unmade++; Lst_EnQueue(&cleanup, cgn); } } if (curdir != objdir) { if (chdir(objdir) < 0) Fatal("Failed to change directory to %s.", objdir); } } /** * main * The main function, for obvious reasons. Initializes variables * and a few modules, then parses the arguments give it in the * environment and on the command line. Reads the system makefile * followed by either Makefile, makefile or the file given by the * -f argument. Sets the .MAKEFLAGS PMake variable based on all the * flags it has received by then uses either the Make or the Compat * module to create the initial list of targets. * * Results: * If -q was given, exits -1 if anything was out-of-date. Else it exits * 0. * * Side Effects: * The program exits when done. Targets are created. etc. etc. etc. */ int main(int argc, char **argv) { const char *machine; const char *machine_arch; const char *machine_cpu; Boolean outOfDate = TRUE; /* FALSE if all targets up to date */ const char *p; const char *pathp; const char *path; char mdpath[MAXPATHLEN]; char obpath[MAXPATHLEN]; char cdpath[MAXPATHLEN]; char found_dir[MAXPATHLEN + 1]; /* for searching for sys.mk */ char *cp = NULL, *start; save_argv = argv; save_makeflags = getenv("MAKEFLAGS"); if (save_makeflags != NULL) save_makeflags = estrdup(save_makeflags); /* * Initialize file global variables. */ expandVars = TRUE; noBuiltins = FALSE; /* Read the built-in rules */ forceJobs = FALSE; /* No -j flag */ curdir = cdpath; /* * Initialize program global variables. */ beSilent = FALSE; /* Print commands as executed */ ignoreErrors = FALSE; /* Pay attention to non-zero returns */ noExecute = FALSE; /* Execute all commands */ printGraphOnly = FALSE; /* Don't stop after printing graph */ keepgoing = FALSE; /* Stop on error */ allPrecious = FALSE; /* Remove targets when interrupted */ queryFlag = FALSE; /* This is not just a check-run */ touchFlag = FALSE; /* Actually update targets */ usePipes = TRUE; /* Catch child output in pipes */ debug = 0; /* No debug verbosity, please. */ jobsRunning = FALSE; jobLimit = DEFMAXJOBS; compatMake = FALSE; /* No compat mode */ check_make_level(); #ifdef RLIMIT_NOFILE /* * get rid of resource limit on file descriptors */ { struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) == -1) { err(2, "getrlimit"); } rl.rlim_cur = rl.rlim_max; if (setrlimit(RLIMIT_NOFILE, &rl) == -1) { err(2, "setrlimit"); } } #endif /* * Get the name of this type of MACHINE from utsname * so we can share an executable for similar machines. * (i.e. m68k: amiga hp300, mac68k, sun3, ...) * * Note that both MACHINE and MACHINE_ARCH are decided at * run-time. */ if ((machine = getenv("MACHINE")) == NULL) { static struct utsname utsname; unsigned int i; if (uname(&utsname) == -1) err(2, "uname"); machine = utsname.machine; /* Canonicalize non-FreeBSD naming conventions */ for (i = 0; i < sizeof(arch_aliases) / sizeof(arch_aliases[0]); i++) if (!strcmp(machine, arch_aliases[i].foreign_name)) { machine = arch_aliases[i].freebsd_name; break; } } if ((machine_arch = getenv("MACHINE_ARCH")) == NULL) { #ifdef MACHINE_ARCH machine_arch = MACHINE_ARCH; #else machine_arch = "unknown"; #endif } /* * Set machine_cpu to the minimum supported CPU revision based * on the target architecture, if not already set. */ if ((machine_cpu = getenv("MACHINE_CPU")) == NULL) { if (!strcmp(machine_arch, "i386")) machine_cpu = "i486"; else machine_cpu = "unknown"; } /* * Initialize the parsing, directory and variable modules to prepare * for the reading of inclusion paths and variable settings on the * command line */ Proc_Init(); Dir_Init(); /* Initialize directory structures so -I flags * can be processed correctly */ Var_Init(environ); /* As well as the lists of variables for * parsing arguments */ /* * Initialize the Shell so that we have a shell for != assignments * on the command line. */ Shell_Init(); /* * Initialize various variables. * MAKE also gets this name, for compatibility * .MAKEFLAGS gets set to the empty string just in case. * MFLAGS also gets initialized empty, for compatibility. */ Var_SetGlobal("MAKE", argv[0]); Var_SetGlobal(".MAKEFLAGS", ""); Var_SetGlobal("MFLAGS", ""); Var_SetGlobal("MACHINE", machine); Var_SetGlobal("MACHINE_ARCH", machine_arch); Var_SetGlobal("MACHINE_CPU", machine_cpu); #ifdef MAKE_VERSION Var_SetGlobal("MAKE_VERSION", MAKE_VERSION); #endif Var_SetGlobal(".newline", "\n"); /* handy for :@ loops */ { char tmp[64]; snprintf(tmp, sizeof(tmp), "%u", getpid()); Var_SetGlobal(".MAKE.PID", tmp); snprintf(tmp, sizeof(tmp), "%u", getppid()); Var_SetGlobal(".MAKE.PPID", tmp); } Job_SetPrefix(); /* * Find where we are... */ if (getcwd(curdir, MAXPATHLEN) == NULL) err(2, NULL); /* * First snag things out of the MAKEFLAGS environment * variable. Then parse the command line arguments. */ Main_ParseArgLine(getenv("MAKEFLAGS"), 1); MainParseArgs(argc, argv); /* * Verify that cwd is sane (after -C may have changed it). */ { struct stat sa; if (stat(curdir, &sa) == -1) err(2, "%s", curdir); } /* * The object directory location is determined using the * following order of preference: * * 1. MAKEOBJDIRPREFIX`cwd` * 2. MAKEOBJDIR * 3. PATH_OBJDIR.${MACHINE} * 4. PATH_OBJDIR * 5. PATH_OBJDIRPREFIX`cwd` * * If one of the first two fails, use the current directory. * If the remaining three all fail, use the current directory. * * Once things are initted, * have to add the original directory to the search path, * and modify the paths for the Makefiles appropriately. The * current directory is also placed as a variable for make scripts. */ if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) { if (!(path = getenv("MAKEOBJDIR"))) { path = PATH_OBJDIR; pathp = PATH_OBJDIRPREFIX; snprintf(mdpath, MAXPATHLEN, "%s.%s", path, machine); if (!(objdir = chdir_verify_path(mdpath, obpath))) if (!(objdir=chdir_verify_path(path, obpath))) { snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir); if (!(objdir=chdir_verify_path(mdpath, obpath))) objdir = curdir; } } else if (!(objdir = chdir_verify_path(path, obpath))) objdir = curdir; } else { snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir); if (!(objdir = chdir_verify_path(mdpath, obpath))) objdir = curdir; } Dir_InitDot(); /* Initialize the "." directory */ if (objdir != curdir) Path_AddDir(&dirSearchPath, curdir); Var_SetGlobal(".ST_EXPORTVAR", "YES"); Var_SetGlobal(".CURDIR", curdir); Var_SetGlobal(".OBJDIR", objdir); if (getenv("MAKE_JOBS_FIFO") != NULL) forceJobs = TRUE; /* * Be compatible if user did not specify -j and did not explicitly * turned compatibility on */ if (!compatMake && !forceJobs) compatMake = TRUE; /* * Initialize target and suffix modules in preparation for * parsing the makefile(s) */ Targ_Init(); Suff_Init(); DEFAULT = NULL; time(&now); /* * Set up the .TARGETS variable to contain the list of targets to be * created. If none specified, make the variable empty -- the parser * will fill the thing in with the default or .MAIN target. */ if (Lst_IsEmpty(&create)) { Var_SetGlobal(".TARGETS", ""); } else { LstNode *ln; for (ln = Lst_First(&create); ln != NULL; ln = Lst_Succ(ln)) { char *name = Lst_Datum(ln); Var_Append(".TARGETS", name, VAR_GLOBAL); } } /* * If no user-supplied system path was given (through the -m option) * add the directories from the DEFSYSPATH (more than one may be given * as dir1:...:dirn) to the system include path. */ if (TAILQ_EMPTY(&sysIncPath)) { char defsyspath[] = PATH_DEFSYSPATH; char *syspath = getenv("MAKESYSPATH"); /* * If no user-supplied system path was given (thru -m option) * add the directories from the DEFSYSPATH (more than one may * be given as dir1:...:dirn) to the system include path. */ if (syspath == NULL || *syspath == '\0') syspath = defsyspath; else syspath = estrdup(syspath); for (start = syspath; *start != '\0'; start = cp) { for (cp = start; *cp != '\0' && *cp != ':'; cp++) continue; if (*cp == ':') { *cp++ = '\0'; } /* look for magic parent directory search string */ if (strncmp(".../", start, 4) == 0) { if (Dir_FindHereOrAbove(curdir, start + 4, found_dir, sizeof(found_dir))) { Path_AddDir(&sysIncPath, found_dir); } } else { Path_AddDir(&sysIncPath, start); } } if (syspath != defsyspath) free(syspath); } /* * Read in the built-in rules first, followed by the specified * makefile, if it was (makefile != (char *) NULL), or the default * Makefile and makefile, in that order, if it wasn't. */ if (!noBuiltins) { /* Path of sys.mk */ Lst sysMkPath = Lst_Initializer(sysMkPath); LstNode *ln; char defsysmk[] = PATH_DEFSYSMK; Path_Expand(defsysmk, &sysIncPath, &sysMkPath); if (Lst_IsEmpty(&sysMkPath)) Fatal("make: no system rules (%s).", PATH_DEFSYSMK); LST_FOREACH(ln, &sysMkPath) { if (!ReadMakefile(Lst_Datum(ln))) break; } if (ln != NULL) Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); Lst_Destroy(&sysMkPath, free); } if (!Lst_IsEmpty(&makefiles)) { LstNode *ln; LST_FOREACH(ln, &makefiles) { if (!TryReadMakefile(Lst_Datum(ln))) break; } if (ln != NULL) Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); } else if (!TryReadMakefile("BSDmakefile")) if (!TryReadMakefile("makefile")) TryReadMakefile("Makefile"); ReadMakefile(".depend"); /* Install all the flags into the MAKEFLAGS envariable. */ if (((p = Var_Value(".MAKEFLAGS", VAR_GLOBAL)) != NULL) && *p) setenv("MAKEFLAGS", p, 1); else setenv("MAKEFLAGS", "", 1); /* * For compatibility, look at the directories in the VPATH variable * and add them to the search path, if the variable is defined. The * variable's value is in the same format as the PATH envariable, i.e. * ::... */ if (Var_Exists("VPATH", VAR_CMD)) { /* * GCC stores string constants in read-only memory, but * Var_Subst will want to write this thing, so store it * in an array */ static char VPATH[] = "${VPATH}"; Buffer *buf; char *vpath; char *ptr; char savec; buf = Var_Subst(VPATH, VAR_CMD, FALSE); vpath = Buf_Data(buf); do { /* skip to end of directory */ for (ptr = vpath; *ptr != ':' && *ptr != '\0'; ptr++) ; /* Save terminator character so know when to stop */ savec = *ptr; *ptr = '\0'; /* Add directory to search path */ Path_AddDir(&dirSearchPath, vpath); vpath = ptr + 1; } while (savec != '\0'); Buf_Destroy(buf, TRUE); } /* * Now that all search paths have been read for suffixes et al, it's * time to add the default search path to their lists... */ Suff_DoPaths(); /* print the initial graph, if the user requested it */ if (DEBUG(GRAPH1)) Targ_PrintGraph(1); /* print the values of any variables requested by the user */ if (Lst_IsEmpty(&variables) && !printGraphOnly) { /* * Since the user has not requested that any variables * be printed, we can build targets. * * Have read the entire graph and need to make a list of targets * to create. If none was given on the command line, we consult * the parsing module to find the main target(s) to create. */ Lst targs = Lst_Initializer(targs); if (!is_posix && mfAutoDeps) { /* * Check if any of the makefiles are out-of-date. */ Remake_Makefiles(); } if (Lst_IsEmpty(&create)) Parse_MainName(&targs); else Targ_FindList(&targs, &create, TARG_CREATE); if (compatMake) { /* * Compat_Init will take care of creating * all the targets as well as initializing * the module. */ Compat_Run(&targs); outOfDate = 0; } else { /* * Initialize job module before traversing * the graph, now that any .BEGIN and .END * targets have been read. This is done * only if the -q flag wasn't given (to * prevent the .BEGIN from being executed * should it exist). */ if (!queryFlag) { Job_Init(jobLimit); jobsRunning = TRUE; } /* Traverse the graph, checking on all the targets */ outOfDate = Make_Run(&targs); } Lst_Destroy(&targs, NOFREE); } else { Var_Print(&variables, expandVars); } Lst_Destroy(&variables, free); Lst_Destroy(&makefiles, free); Lst_Destroy(&source_makefiles, free); Lst_Destroy(&create, free); /* print the graph now it's been processed if the user requested it */ if (DEBUG(GRAPH2)) Targ_PrintGraph(2); if (queryFlag) return (outOfDate); if (makeErrors != 0) Finish(makeErrors); return (0); } freebsd-buildutils-10.0/src/usr.bin/make/pathnames.h0000644000000000000000000000421510214313356017325 0ustar /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)pathnames.h 8.2 (Berkeley) 4/28/95 * $FreeBSD$ */ #ifndef pathnames_h_235b888a #define pathnames_h_235b888a #ifndef PATH_OBJDIR #define PATH_OBJDIR "obj" #endif /* ! PATH_OBJDIR */ #ifndef PATH_OBJDIRPREFIX #define PATH_OBJDIRPREFIX "/usr/obj" #endif /* ! PATH_OBJDIRPREFIX */ #ifndef PATH_DEFSHELLDIR #define PATH_DEFSHELLDIR "/bin" #endif /* ! PATH_DEFSHELLDIR */ #ifndef PATH_DEFSYSMK #define PATH_DEFSYSMK "sys.mk" #endif /* ! PATH_DEFSYSMK */ #ifndef PATH_DEFSYSPATH #define PATH_DEFSYSPATH "/usr/share/mk" #endif /* ! PATH_DEFSYSPATH */ #endif /* pathnames_h_235b888a */ freebsd-buildutils-10.0/src/usr.bin/make/cond.h0000644000000000000000000000506310226422452016273 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef cond_h_6e96ad7c #define cond_h_6e96ad7c /* * Values returned by Cond_Eval. */ #define COND_PARSE 0 /* Parse the next lines */ #define COND_SKIP 1 /* Skip the next lines */ #define COND_INVALID 2 /* Not a conditional statement */ enum { COND_IF, COND_IFDEF, COND_IFNDEF, COND_IFMAKE, COND_IFNMAKE, COND_ELSE, COND_ELIF, COND_ELIFDEF, COND_ELIFNDEF, COND_ELIFMAKE, COND_ELIFNMAKE, COND_ENDIF, }; void Cond_If(char *, int, int); void Cond_Else(char *, int, int); void Cond_Endif(char *, int, int); void Cond_End(void); extern Boolean skipLine; #endif /* cond_h_6e96ad7c */ freebsd-buildutils-10.0/src/usr.bin/make/shell.c0000644000000000000000000003377210244644173016470 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include "parse.h" #include "pathnames.h" #include "shell.h" #include "util.h" /* * Descriptions for various shells. What the list of builtins should contain * is debatable: either all builtins or only those which may specified on * a single line without use of meta-characters. For correct makefiles that * contain only correct command lines there is no difference. But if a command * line, for example, is: 'if -foo bar' and there is an executable named 'if' * in the path, the first possibility would execute that 'if' while in the * second case the shell would give an error. Histerically only a small * subset of the builtins and no reserved words where given in the list which * corresponds roughly to the first variant. So go with this but add missing * words. */ #define CSH_BUILTINS \ "alias cd eval exec exit read set ulimit unalias " \ "umask unset wait" #define SH_BUILTINS \ "alias cd eval exec exit read set ulimit unalias " \ "umask unset wait" #define CSH_META "#=|^(){};&<>*?[]:$`\\@\n" #define SH_META "#=|^(){};&<>*?[]:$`\\\n" static const char *const shells_init[] = { /* * CSH description. The csh can do echo control by playing * with the setting of the 'echo' shell variable. Sadly, * however, it is unable to do error control nicely. */ "name=csh path='" PATH_DEFSHELLDIR "/csh' " "quiet='unset verbose' echo='set verbose' filter='unset verbose' " "hasErrCtl=N check='echo \"%s\"\n' ignore='csh -c \"%s || exit 0\"' " "echoFlag=v errFlag=e " "meta='" CSH_META "' builtins='" CSH_BUILTINS "'", /* * SH description. Echo control is also possible and, under * sun UNIX anyway, one can even control error checking. */ "name=sh path='" PATH_DEFSHELLDIR "/sh' " "quiet='set -' echo='set -v' filter='set -' " "hasErrCtl=Y check='set -e' ignore='set +e' " "echoFlag=v errFlag=e " "meta='" SH_META "' builtins='" SH_BUILTINS "'", /* * KSH description. The Korn shell has a superset of * the Bourne shell's functionality. There are probably builtins * missing here. */ "name=ksh path='" PATH_DEFSHELLDIR "/ksh' " "quiet='set -' echo='set -v' filter='set -' " "hasErrCtl=Y check='set -e' ignore='set +e' " "echoFlag=v errFlag=e " "meta='" SH_META "' builtins='" SH_BUILTINS "' unsetenv=T", NULL }; /* * This is the shell to which we pass all commands in the Makefile. * It is set by the Job_ParseShell function. */ struct Shell *commandShell; /* * This is the list of all known shells. */ static struct Shells shells = TAILQ_HEAD_INITIALIZER(shells); void ShellDump(const struct Shell *) __unused; /** * Helper function for sorting the builtin list alphabetically. */ static int sort_builtins(const void *p1, const void *p2) { return (strcmp(*(const char* const*)p1, *(const char* const*)p2)); } /** * Free a shell structure and all associated strings. */ static void ShellFree(struct Shell *sh) { if (sh != NULL) { free(sh->name); free(sh->path); free(sh->echoOff); free(sh->echoOn); free(sh->noPrint); free(sh->errCheck); free(sh->ignErr); free(sh->echo); free(sh->exit); ArgArray_Done(&sh->builtins); free(sh->meta); free(sh); } } /** * Dump a shell specification to stderr. */ void ShellDump(const struct Shell *sh) { int i; fprintf(stderr, "Shell %p:\n", sh); fprintf(stderr, " name='%s' path='%s'\n", sh->name, sh->path); fprintf(stderr, " hasEchoCtl=%d echoOff='%s' echoOn='%s'\n", sh->hasEchoCtl, sh->echoOff, sh->echoOn); fprintf(stderr, " noPrint='%s'\n", sh->noPrint); fprintf(stderr, " hasErrCtl=%d errCheck='%s' ignErr='%s'\n", sh->hasErrCtl, sh->errCheck, sh->ignErr); fprintf(stderr, " echo='%s' exit='%s'\n", sh->echo, sh->exit); fprintf(stderr, " builtins=%d\n", sh->builtins.argc - 1); for (i = 1; i < sh->builtins.argc; i++) fprintf(stderr, " '%s'", sh->builtins.argv[i]); fprintf(stderr, "\n meta='%s'\n", sh->meta); fprintf(stderr, " unsetenv=%d\n", sh->unsetenv); } /** * Parse a shell specification line and return the new Shell structure. * In case of an error a message is printed and NULL is returned. */ static struct Shell * ShellParseSpec(const char *spec, Boolean *fullSpec) { ArgArray aa; struct Shell *sh; char *eq; char *keyw; int arg; *fullSpec = FALSE; sh = emalloc(sizeof(*sh)); memset(sh, 0, sizeof(*sh)); ArgArray_Init(&sh->builtins); /* * Parse the specification by keyword but skip the first word */ brk_string(&aa, spec, TRUE); for (arg = 1; arg < aa.argc; arg++) { /* * Split keyword and value */ keyw = aa.argv[arg]; if ((eq = strchr(keyw, '=')) == NULL) { Parse_Error(PARSE_FATAL, "missing '=' in shell " "specification keyword '%s'", keyw); ArgArray_Done(&aa); ShellFree(sh); return (NULL); } *eq++ = '\0'; if (strcmp(keyw, "path") == 0) { free(sh->path); sh->path = estrdup(eq); } else if (strcmp(keyw, "name") == 0) { free(sh->name); sh->name = estrdup(eq); } else if (strcmp(keyw, "quiet") == 0) { free(sh->echoOff); sh->echoOff = estrdup(eq); *fullSpec = TRUE; } else if (strcmp(keyw, "echo") == 0) { free(sh->echoOn); sh->echoOn = estrdup(eq); *fullSpec = TRUE; } else if (strcmp(keyw, "filter") == 0) { free(sh->noPrint); sh->noPrint = estrdup(eq); *fullSpec = TRUE; } else if (strcmp(keyw, "echoFlag") == 0) { free(sh->echo); sh->echo = estrdup(eq); *fullSpec = TRUE; } else if (strcmp(keyw, "errFlag") == 0) { free(sh->exit); sh->exit = estrdup(eq); *fullSpec = TRUE; } else if (strcmp(keyw, "hasErrCtl") == 0) { sh->hasErrCtl = (*eq == 'Y' || *eq == 'y' || *eq == 'T' || *eq == 't'); *fullSpec = TRUE; } else if (strcmp(keyw, "check") == 0) { free(sh->errCheck); sh->errCheck = estrdup(eq); *fullSpec = TRUE; } else if (strcmp(keyw, "ignore") == 0) { free(sh->ignErr); sh->ignErr = estrdup(eq); *fullSpec = TRUE; } else if (strcmp(keyw, "builtins") == 0) { ArgArray_Done(&sh->builtins); brk_string(&sh->builtins, eq, TRUE); qsort(sh->builtins.argv + 1, sh->builtins.argc - 1, sizeof(char *), sort_builtins); *fullSpec = TRUE; } else if (strcmp(keyw, "meta") == 0) { free(sh->meta); sh->meta = estrdup(eq); *fullSpec = TRUE; } else if (strcmp(keyw, "unsetenv") == 0) { sh->unsetenv = (*eq == 'Y' || *eq == 'y' || *eq == 'T' || *eq == 't'); *fullSpec = TRUE; } else { Parse_Error(PARSE_FATAL, "unknown keyword in shell " "specification '%s'", keyw); ArgArray_Done(&aa); ShellFree(sh); return (NULL); } } ArgArray_Done(&aa); /* * Some checks (could be more) */ if (*fullSpec) { if ((sh->echoOn != NULL) ^ (sh->echoOff != NULL)) { Parse_Error(PARSE_FATAL, "Shell must have either both " "echoOff and echoOn or none of them"); ShellFree(sh); return (NULL); } if (sh->echoOn != NULL && sh->echoOff != NULL) sh->hasEchoCtl = TRUE; } return (sh); } /** * Parse the builtin shell specifications and put them into the shell * list. Then select the default shell to be the current shell. This * is called from main() before any parsing (including MAKEFLAGS and * command line) is done. */ void Shell_Init(void) { int i; struct Shell *sh; Boolean fullSpec; for (i = 0; shells_init[i] != NULL; i++) { sh = ShellParseSpec(shells_init[i], &fullSpec); TAILQ_INSERT_TAIL(&shells, sh, link); if (strcmp(sh->name, DEFSHELLNAME) == 0) commandShell = sh; } } /** * Find a matching shell in 'shells' given its final component. * * Results: * A pointer to a freshly allocated Shell structure with the contents * from static description or NULL if no shell with the given name * is found. */ static struct Shell * ShellMatch(const char *name) { struct Shell *sh; TAILQ_FOREACH(sh, &shells, link) if (strcmp(sh->name, name) == 0) return (sh); return (NULL); } /** * Parse a shell specification and set up commandShell appropriately. * * Results: * TRUE if the specification was correct. FALSE otherwise. * * Side Effects: * commandShell points to a Shell structure. * created from the shell spec). * * Notes: * A shell specification consists of a .SHELL target, with dependency * operator, followed by a series of blank-separated words. Double * quotes can be used to use blanks in words. A backslash escapes * anything (most notably a double-quote and a space) and * provides the functionality it does in C. Each word consists of * keyword and value separated by an equal sign. There should be no * unnecessary spaces in the word. The keywords are as follows: * name Name of shell. * path Location of shell. Overrides "name" if given * quiet Command to turn off echoing. * echo Command to turn echoing on * filter Result of turning off echoing that shouldn't be * printed. * echoFlag Flag to turn echoing on at the start * errFlag Flag to turn error checking on at the start * hasErrCtl True if shell has error checking control * check Command to turn on error checking if hasErrCtl * is TRUE or template of command to echo a command * for which error checking is off if hasErrCtl is * FALSE. * ignore Command to turn off error checking if hasErrCtl * is TRUE or template of command to execute a * command so as to ignore any errors it returns if * hasErrCtl is FALSE. * builtins A space separated list of builtins. If one * of these builtins is detected when make wants * to execute a command line, the command line is * handed to the shell. Otherwise make may try to * execute the command directly. If this list is empty * it is assumed, that the command must always be * handed over to the shell. * meta The shell meta characters. If this is not specified * or empty, commands are alway passed to the shell. * Otherwise they are not passed when they contain * neither a meta character nor a builtin command. * unsetenv Unsetenv("ENV") before executing anything. */ Boolean Shell_Parse(const char line[]) { Boolean fullSpec; struct Shell *sh; struct Shell *match; /* parse the specification */ if ((sh = ShellParseSpec(line, &fullSpec)) == NULL) return (FALSE); if (sh->path == NULL) { /* * If no path was given, the user wants one of the pre-defined * shells, yes? So we find the one s/he wants with the help of * JobMatchShell and set things up the right way. */ if (sh->name == NULL) { Parse_Error(PARSE_FATAL, "Neither path nor name specified"); ShellFree(sh); return (FALSE); } if (fullSpec) { /* * XXX May want to merge sh into match. But this * require ShellParseSpec to return information * which attributes actuall have been specified. */ Parse_Error(PARSE_FATAL, "No path specified"); ShellFree(sh); return (FALSE); } if ((match = ShellMatch(sh->name)) == NULL) { Parse_Error(PARSE_FATAL, "%s: no matching shell", sh->name); ShellFree(sh); return (FALSE); } ShellFree(sh); commandShell = match; return (TRUE); } /* * The user provided a path. If s/he gave nothing else * (fullSpec is FALSE), try and find a matching shell in the * ones we know of. Else we just take the specification at its * word and copy it to a new location. In either case, we need * to record the path the user gave for the shell. */ if (sh->name == NULL) { /* get the base name as the name */ if ((sh->name = strrchr(sh->path, '/')) == NULL) { sh->name = estrdup(sh->path); } else { sh->name = estrdup(sh->name + 1); } } if (!fullSpec) { if ((match = ShellMatch(sh->name)) == NULL) { Parse_Error(PARSE_FATAL, "%s: no matching shell", sh->name); ShellFree(sh); return (FALSE); } /* set the patch on the matching shell */ free(match->path); match->path = sh->path; sh->path = NULL; ShellFree(sh); commandShell = match; return (TRUE); } TAILQ_INSERT_HEAD(&shells, sh, link); /* set the new shell */ commandShell = sh; return (TRUE); } freebsd-buildutils-10.0/src/usr.bin/make/proc.h0000644000000000000000000000367010244645456016330 0ustar /*- * Copyright (C) 2005 Max Okumoto. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef proc_h_458845848 #define proc_h_458845848 /** * Information used to create a new process. */ typedef struct ProcStuff { int in; /* stdin for new process */ int out; /* stdout for new process */ int err; /* stderr for new process */ int merge_errors; /* true if stderr is redirected to stdin */ int pgroup; /* true if new process a process leader */ int searchpath; /* true if binary should be found via $PATH */ char **argv; int argv_free; /* release argv after use */ int errCheck; pid_t child_pid; } ProcStuff; void Proc_Exec(const ProcStuff *) __dead2; #endif /* proc_h_458845848 */ freebsd-buildutils-10.0/src/usr.bin/make/make.c0000644000000000000000000006003211312423505016252 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)make.c 8.1 (Berkeley) 6/6/93 */ #include __FBSDID("$FreeBSD$"); /* * make.c * The functions which perform the examination of targets and * their suitability for creation * * Interface: * Make_Run Initialize things for the module and recreate * whatever needs recreating. Returns TRUE if * work was (or would have been) done and FALSE * otherwise. * * Make_Update Update all parents of a given child. Performs * various bookkeeping chores like the updating * of the cmtime field of the parent, filling * of the IMPSRC context variable, etc. It will * place the parent on the toBeMade queue if it should be. * * Make_TimeStamp Function to set the parent's cmtime field * based on a child's modification time. * * Make_DoAllVar Set up the various local variables for a * target, including the .ALLSRC variable, making * sure that any variable that needs to exist * at the very least has the empty value. * * Make_OODate Determine if a target is out-of-date. * * Make_HandleUse See if a child is a .USE node for a parent * and perform the .USE actions if so. */ #include "arch.h" #include "config.h" #include "dir.h" #include "globals.h" #include "GNode.h" #include "job.h" #include "make.h" #include "parse.h" #include "suff.h" #include "targ.h" #include "util.h" #include "var.h" /* The current fringe of the graph. These are nodes which await examination * by MakeOODate. It is added to by Make_Update and subtracted from by * MakeStartJobs */ static Lst toBeMade = Lst_Initializer(toBeMade); /* * Number of nodes to be processed. If this is non-zero when Job_Empty() * returns TRUE, there's a cycle in the graph. */ static int numNodes; static Boolean MakeStartJobs(void); /** * Make_TimeStamp * Set the cmtime field of a parent node based on the mtime stamp in its * child. Called from MakeOODate via LST_FOREACH. * * Results: * Always returns 0. * * Side Effects: * The cmtime of the parent node will be changed if the mtime * field of the child is greater than it. */ int Make_TimeStamp(GNode *pgn, GNode *cgn) { if (cgn->mtime > pgn->cmtime) { pgn->cmtime = cgn->mtime; pgn->cmtime_gn = cgn; } return (0); } /** * Make_OODate * See if a given node is out of date with respect to its sources. * Used by Make_Run when deciding which nodes to place on the * toBeMade queue initially and by Make_Update to screen out USE and * EXEC nodes. In the latter case, however, any other sort of node * must be considered out-of-date since at least one of its children * will have been recreated. * * Results: * TRUE if the node is out of date. FALSE otherwise. * * Side Effects: * The mtime field of the node and the cmtime field of its parents * will/may be changed. */ Boolean Make_OODate(GNode *gn) { Boolean oodate; LstNode *ln; /* * Certain types of targets needn't even be sought as their datedness * doesn't depend on their modification time... */ if ((gn->type & (OP_JOIN | OP_USE | OP_EXEC)) == 0) { Dir_MTime(gn); if (gn->mtime != 0) { DEBUGF(MAKE, ("modified %s...", Targ_FmtTime(gn->mtime))); } else { DEBUGF(MAKE, ("non-existent...")); } } /* * A target is remade in one of the following circumstances: * its modification time is smaller than that of its youngest child * and it would actually be run (has commands or type OP_NOP) * it's the object of a force operator * it has no children, was on the lhs of an operator and doesn't * exist already. * * Libraries are only considered out-of-date if the archive module says * they are. * * These weird rules are brought to you by Backward-Compatibility and * the strange people who wrote 'Make'. */ if (gn->type & OP_USE) { /* * If the node is a USE node it is *never* out of date * no matter *what*. */ DEBUGF(MAKE, (".USE node...")); oodate = FALSE; } else if (gn->type & OP_LIB) { DEBUGF(MAKE, ("library...")); /* * always out of date if no children and :: target */ oodate = Arch_LibOODate(gn) || ((gn->cmtime == 0) && (gn->type & OP_DOUBLEDEP)); } else if (gn->type & OP_JOIN) { /* * A target with the .JOIN attribute is only considered * out-of-date if any of its children was out-of-date. */ DEBUGF(MAKE, (".JOIN node...")); oodate = gn->childMade; } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) { /* * A node which is the object of the force (!) operator or * which has the .EXEC attribute is always considered * out-of-date. */ if (gn->type & OP_FORCE) { DEBUGF(MAKE, ("! operator...")); } else if (gn->type & OP_PHONY) { DEBUGF(MAKE, (".PHONY node...")); } else { DEBUGF(MAKE, (".EXEC node...")); } if (remakingMakefiles) { DEBUGF(MAKE, ("skipping (remaking makefiles)...")); oodate = FALSE; } else { oodate = TRUE; } } else if (gn->mtime < gn->cmtime || (gn->cmtime == 0 && (gn->mtime == 0 || (gn->type & OP_DOUBLEDEP)))) { /* * A node whose modification time is less than that of its * youngest child or that has no children (cmtime == 0) and * either doesn't exist (mtime == 0) or was the object of a * :: operator is out-of-date. Why? Because that's the way * Make does it. */ if (gn->mtime < gn->cmtime) { DEBUGF(MAKE, ("modified before source (%s)...", gn->cmtime_gn ? gn->cmtime_gn->path : "???")); oodate = TRUE; } else if (gn->mtime == 0) { DEBUGF(MAKE, ("non-existent and no sources...")); if (remakingMakefiles && Lst_IsEmpty(&gn->commands)) { DEBUGF(MAKE, ("skipping (no commands and remaking makefiles)...")); oodate = FALSE; } else { oodate = TRUE; } } else { DEBUGF(MAKE, (":: operator and no sources...")); if (remakingMakefiles) { DEBUGF(MAKE, ("skipping (remaking makefiles)...")); oodate = FALSE; } else { oodate = TRUE; } } } else oodate = FALSE; /* * If the target isn't out-of-date, the parents need to know its * modification time. Note that targets that appear to be out-of-date * but aren't, because they have no commands and aren't of type OP_NOP, * have their mtime stay below their children's mtime to keep parents * from thinking they're out-of-date. */ if (!oodate) { LST_FOREACH(ln, &gn->parents) if (Make_TimeStamp(Lst_Datum(ln), gn)) break; } return (oodate); } /** * Make_HandleUse * Function called by Make_Run and SuffApplyTransform on the downward * pass to handle .USE and transformation nodes. A callback function * for LST_FOREACH, it implements the .USE and transformation * functionality by copying the node's commands, type flags * and children to the parent node. Should be called before the * children are enqueued to be looked at. * * A .USE node is much like an explicit transformation rule, except * its commands are always added to the target node, even if the * target already has commands. * * Results: * returns 0. * * Side Effects: * Children and commands may be added to the parent and the parent's * type may be changed. * *----------------------------------------------------------------------- */ int Make_HandleUse(GNode *cgn, GNode *pgn) { GNode *gn; /* A child of the .USE node */ LstNode *ln; /* An element in the children list */ if (cgn->type & (OP_USE | OP_TRANSFORM)) { if ((cgn->type & OP_USE) || Lst_IsEmpty(&pgn->commands)) { /* * .USE or transformation and target has no commands -- * append the child's commands to the parent. */ Lst_Concat(&pgn->commands, &cgn->commands, LST_CONCNEW); } for (ln = Lst_First(&cgn->children); ln != NULL; ln = Lst_Succ(ln)) { gn = Lst_Datum(ln); if (Lst_Member(&pgn->children, gn) == NULL) { Lst_AtEnd(&pgn->children, gn); Lst_AtEnd(&gn->parents, pgn); pgn->unmade += 1; } } pgn->type |= cgn->type & ~(OP_OPMASK | OP_USE | OP_TRANSFORM); /* * This child node is now "made", so we decrement the count of * unmade children in the parent... We also remove the child * from the parent's list to accurately reflect the number of * decent children the parent has. This is used by Make_Run to * decide whether to queue the parent or examine its children... */ if (cgn->type & OP_USE) { pgn->unmade--; } } return (0); } /** * Make_Update * Perform update on the parents of a node. Used by JobFinish once * a node has been dealt with and by MakeStartJobs if it finds an * up-to-date node. * * Results: * Always returns 0 * * Side Effects: * The unmade field of pgn is decremented and pgn may be placed on * the toBeMade queue if this field becomes 0. * * If the child was made, the parent's childMade field will be set true * and its cmtime set to now. * * If the child wasn't made, the cmtime field of the parent will be * altered if the child's mtime is big enough. * * Finally, if the child is the implied source for the parent, the * parent's IMPSRC variable is set appropriately. */ void Make_Update(GNode *cgn) { GNode *pgn; /* the parent node */ const char *cname; /* the child's name */ LstNode *ln; /* Element in parents and iParents lists */ const char *cpref; cname = Var_Value(TARGET, cgn); /* * If the child was actually made, see what its modification time is * now -- some rules won't actually update the file. If the file still * doesn't exist, make its mtime now. */ if (cgn->made != UPTODATE) { #ifndef RECHECK /* * We can't re-stat the thing, but we can at least take care * of rules where a target depends on a source that actually * creates the target, but only if it has changed, e.g. * * parse.h : parse.o * * parse.o : parse.y * yacc -d parse.y * cc -c y.tab.c * mv y.tab.o parse.o * cmp -s y.tab.h parse.h || mv y.tab.h parse.h * * In this case, if the definitions produced by yacc haven't * changed from before, parse.h won't have been updated and * cgn->mtime will reflect the current modification time for * parse.h. This is something of a kludge, I admit, but it's a * useful one.. * XXX: People like to use a rule like * * FRC: * * To force things that depend on FRC to be made, so we have to * check for gn->children being empty as well... */ if (!Lst_IsEmpty(&cgn->commands) || Lst_IsEmpty(&cgn->children)) { cgn->mtime = now; } #else /* * This is what Make does and it's actually a good thing, as it * allows rules like * * cmp -s y.tab.h parse.h || cp y.tab.h parse.h * * to function as intended. Unfortunately, thanks to the * stateless nature of NFS (by which I mean the loose coupling * of two clients using the same file from a common server), * there are times when the modification time of a file created * on a remote machine will not be modified before the local * stat() implied by the Dir_MTime occurs, thus leading us to * believe that the file is unchanged, wreaking havoc with * files that depend on this one. * * I have decided it is better to make too much than to make too * little, so this stuff is commented out unless you're sure * it's ok. * -- ardeb 1/12/88 */ /* * Christos, 4/9/92: If we are saving commands pretend that * the target is made now. Otherwise archives with ... rules * don't work! */ if (noExecute || (cgn->type & OP_SAVE_CMDS) || Dir_MTime(cgn) == 0) { cgn->mtime = now; } DEBUGF(MAKE, ("update time: %s\n", Targ_FmtTime(cgn->mtime))); #endif } for (ln = Lst_First(&cgn->parents); ln != NULL; ln = Lst_Succ(ln)) { pgn = Lst_Datum(ln); if (pgn->make) { pgn->unmade -= 1; if (!(cgn->type & (OP_EXEC | OP_USE))) { if (cgn->made == MADE) pgn->childMade = TRUE; Make_TimeStamp(pgn, cgn); } if (pgn->unmade == 0) { /* * Queue the node up -- any unmade predecessors * will be dealt with in MakeStartJobs. */ Lst_EnQueue(&toBeMade, pgn); } else if (pgn->unmade < 0) { Error("Graph cycles through %s", pgn->name); } } } /* * Deal with successor nodes. If any is marked for making and has an * unmade count of 0, has not been made and isn't in the examination * queue, it means we need to place it in the queue as it restrained * itself before. */ for (ln = Lst_First(&cgn->successors); ln != NULL; ln = Lst_Succ(ln)) { GNode *succ = Lst_Datum(ln); if (succ->make && succ->unmade == 0 && succ->made == UNMADE && Lst_Member(&toBeMade, succ) == NULL) { Lst_EnQueue(&toBeMade, succ); } } /* * Set the .PREFIX and .IMPSRC variables for all the implied parents * of this node. */ cpref = Var_Value(PREFIX, cgn); for (ln = Lst_First(&cgn->iParents); ln != NULL; ln = Lst_Succ(ln)) { pgn = Lst_Datum(ln); if (pgn->make) { Var_Set(IMPSRC, cname, pgn); Var_Set(PREFIX, cpref, pgn); } } } /** * Make_DoAllVar * Set up the ALLSRC and OODATE variables. Sad to say, it must be * done separately, rather than while traversing the graph. This is * because Make defined OODATE to contain all sources whose modification * times were later than that of the target, *not* those sources that * were out-of-date. Since in both compatibility and native modes, * the modification time of the parent isn't found until the child * has been dealt with, we have to wait until now to fill in the * variable. As for ALLSRC, the ordering is important and not * guaranteed when in native mode, so it must be set here, too. * * Side Effects: * The ALLSRC and OODATE variables of the given node is filled in. * If the node is a .JOIN node, its TARGET variable will be set to * match its ALLSRC variable. */ void Make_DoAllVar(GNode *gn) { LstNode *ln; GNode *cgn; const char *child; LST_FOREACH(ln, &gn->children) { /* * Add the child's name to the ALLSRC and OODATE variables of * the given node. The child is added only if it has not been * given the .EXEC, .USE or .INVISIBLE attributes. .EXEC and * .USE children are very rarely going to be files, so... * * A child is added to the OODATE variable if its modification * time is later than that of its parent, as defined by Make, * except if the parent is a .JOIN node. In that case, it is * only added to the OODATE variable if it was actually made * (since .JOIN nodes don't have modification times, the * comparison is rather unfair...). */ cgn = Lst_Datum(ln); if ((cgn->type & (OP_EXEC | OP_USE | OP_INVISIBLE)) == 0) { if (OP_NOP(cgn->type)) { /* * this node is only source; use the specific * pathname for it */ child = cgn->path ? cgn->path : cgn->name; } else child = Var_Value(TARGET, cgn); Var_Append(ALLSRC, child, gn); if (gn->type & OP_JOIN) { if (cgn->made == MADE) { Var_Append(OODATE, child, gn); } } else if (gn->mtime < cgn->mtime || (cgn->mtime >= now && cgn->made == MADE)) { /* * It goes in the OODATE variable if the parent * is younger than the child or if the child has * been modified more recently than the start of * the make. This is to keep pmake from getting * confused if something else updates the parent * after the make starts (shouldn't happen, I * know, but sometimes it does). In such a case, * if we've updated the kid, the parent is * likely to have a modification time later than * that of the kid and anything that relies on * the OODATE variable will be hosed. * * XXX: This will cause all made children to * go in the OODATE variable, even if they're * not touched, if RECHECK isn't defined, since * cgn->mtime is set to now in Make_Update. * According to some people, this is good... */ Var_Append(OODATE, child, gn); } } } if (!Var_Exists (OODATE, gn)) { Var_Set(OODATE, "", gn); } if (!Var_Exists (ALLSRC, gn)) { Var_Set(ALLSRC, "", gn); } if (gn->type & OP_JOIN) { Var_Set(TARGET, Var_Value(ALLSRC, gn), gn); } } /** * MakeStartJobs * Start as many jobs as possible. * * Results: * If the query flag was given to pmake, no job will be started, * but as soon as an out-of-date target is found, this function * returns TRUE. At all other times, this function returns FALSE. * * Side Effects: * Nodes are removed from the toBeMade queue and job table slots * are filled. */ static Boolean MakeStartJobs(void) { GNode *gn; while (!Lst_IsEmpty(&toBeMade) && !Job_Full()) { gn = Lst_DeQueue(&toBeMade); DEBUGF(MAKE, ("Examining %s...", gn->name)); /* * Make sure any and all predecessors that are going to be made, * have been. */ if (!Lst_IsEmpty(&gn->preds)) { LstNode *ln; for (ln = Lst_First(&gn->preds); ln != NULL; ln = Lst_Succ(ln)){ GNode *pgn = Lst_Datum(ln); if (pgn->make && pgn->made == UNMADE) { DEBUGF(MAKE, ("predecessor %s not made " "yet.\n", pgn->name)); break; } } /* * If ln isn't NULL, there's a predecessor as yet * unmade, so we just drop this node on the floor. * When the node in question has been made, it will * notice this node as being ready to make but as yet * unmade and will place the node on the queue. */ if (ln != NULL) { continue; } } numNodes--; if (Make_OODate(gn)) { DEBUGF(MAKE, ("out-of-date\n")); if (queryFlag) { return (TRUE); } Make_DoAllVar(gn); Job_Make(gn); } else { DEBUGF(MAKE, ("up-to-date\n")); gn->made = UPTODATE; if (gn->type & OP_JOIN) { /* * Even for an up-to-date .JOIN node, we need * it to have its context variables so * references to it get the correct value for * .TARGET when building up the context * variables of its parent(s)... */ Make_DoAllVar(gn); } Make_Update(gn); } } return (FALSE); } /** * MakePrintStatus * Print the status of a top-level node, viz. it being up-to-date * already or not created due to an error in a lower level. * Callback function for Make_Run via LST_FOREACH. If gn->unmade is * nonzero and that is meant to imply a cycle in the graph, then * cycle is TRUE. * * Side Effects: * A message may be printed. */ static void MakePrintStatus(GNode *gn, Boolean cycle) { LstNode *ln; if (gn->made == UPTODATE) { printf("`%s' is up to date.\n", gn->name); } else if (gn->unmade != 0) { if (cycle) { /* * If printing cycles and came to one that has unmade * children, print out the cycle by recursing on its * children. Note a cycle like: * a : b * b : c * c : b * will cause this to erroneously complain about a * being in the cycle, but this is a good approximation. */ if (gn->made == CYCLE) { Error("Graph cycles through `%s'", gn->name); gn->made = ENDCYCLE; LST_FOREACH(ln, &gn->children) MakePrintStatus(Lst_Datum(ln), TRUE); gn->made = UNMADE; } else if (gn->made != ENDCYCLE) { gn->made = CYCLE; LST_FOREACH(ln, &gn->children) MakePrintStatus(Lst_Datum(ln), TRUE); } } else { printf("`%s' not remade because of errors.\n", gn->name); } } } /** * Make_Run * Initialize the nodes to remake and the list of nodes which are * ready to be made by doing a breadth-first traversal of the graph * starting from the nodes in the given list. Once this traversal * is finished, all the 'leaves' of the graph are in the toBeMade * queue. * Using this queue and the Job module, work back up the graph, * calling on MakeStartJobs to keep the job table as full as * possible. * * Results: * TRUE if work was done. FALSE otherwise. * * Side Effects: * The make field of all nodes involved in the creation of the given * targets is set to 1. The toBeMade list is set to contain all the * 'leaves' of these subgraphs. */ Boolean Make_Run(Lst *targs) { GNode *gn; /* a temporary pointer */ GNode *cgn; Lst examine; /* List of targets to examine */ LstNode *ln; Lst_Init(&examine); Lst_Duplicate(&examine, targs, NOCOPY); numNodes = 0; /* * Make an initial downward pass over the graph, marking nodes to be * made as we go down. We call Suff_FindDeps to find where a node is and * to get some children for it if it has none and also has no commands. * If the node is a leaf, we stick it on the toBeMade queue to * be looked at in a minute, otherwise we add its children to our queue * and go on about our business. */ while (!Lst_IsEmpty(&examine)) { gn = Lst_DeQueue(&examine); if (!gn->make) { gn->make = TRUE; numNodes++; /* * Apply any .USE rules before looking for implicit * dependencies to make sure everything has commands * that should... */ LST_FOREACH(ln, &gn->children) if (Make_HandleUse(Lst_Datum(ln), gn)) break; Suff_FindDeps(gn); if (gn->unmade != 0) { LST_FOREACH(ln, &gn->children) { cgn = Lst_Datum(ln); if (!cgn->make && !(cgn->type & OP_USE)) Lst_EnQueue(&examine, cgn); } } else { Lst_EnQueue(&toBeMade, gn); } } } if (queryFlag) { /* * We wouldn't do any work unless we could start some jobs in * the next loop... (we won't actually start any, of course, * this is just to see if any of the targets was out of date) */ return (MakeStartJobs()); } else { /* * Initialization. At the moment, no jobs are running and * until some get started, nothing will happen since the * remaining upward traversal of the graph is performed by the * routines in job.c upon the finishing of a job. So we fill * the Job table as much as we can before going into our loop. */ MakeStartJobs(); } /* * Main Loop: The idea here is that the ending of jobs will take * care of the maintenance of data structures and the waiting for output * will cause us to be idle most of the time while our children run as * much as possible. Because the job table is kept as full as possible, * the only time when it will be empty is when all the jobs which need * running have been run, so that is the end condition of this loop. * Note that the Job module will exit if there were any errors unless * the keepgoing flag was given. */ while (!Job_Empty()) { Job_CatchOutput(!Lst_IsEmpty(&toBeMade)); Job_CatchChildren(!usePipes); MakeStartJobs(); } Job_Finish(); /* * Print the final status of each target. E.g. if it wasn't made * because some inferior reported an error. */ LST_FOREACH(ln, targs) MakePrintStatus(Lst_Datum(ln), (makeErrors == 0) && (numNodes != 0)); return (TRUE); } freebsd-buildutils-10.0/src/usr.bin/make/util.c0000644000000000000000000001370710241127775016333 0ustar /*- * Copyright (c) 2002 Juli Mallett. All rights reserved. * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)main.c 8.3 (Berkeley) 3/19/94 */ #include __FBSDID("$FreeBSD$"); /*- * util.c -- * General utilitarian routines for make(1). */ #include #include #include #include #include #include #include #include #include "globals.h" #include "job.h" #include "targ.h" #include "util.h" static void enomem(void) __dead2; /*- * Debug -- * Print a debugging message given its format. * * Results: * None. * * Side Effects: * The message is printed. */ /* VARARGS */ void Debug(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fflush(stderr); } /*- * Print a debugging message given its format and append the current * errno description. Terminate with a newline. */ /* VARARGS */ void DebugM(const char *fmt, ...) { va_list ap; int e = errno; va_start(ap, fmt); vfprintf(stderr, fmt, ap); fprintf(stderr, ": %s\n", strerror(e)); va_end(ap); fflush(stderr); } /*- * Error -- * Print an error message given its format. * * Results: * None. * * Side Effects: * The message is printed. */ /* VARARGS */ void Error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); fflush(stderr); } /*- * Fatal -- * Produce a Fatal error message. If jobs are running, waits for them * to finish. * * Results: * None * * Side Effects: * The program exits */ /* VARARGS */ void Fatal(const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (jobsRunning) Job_Wait(); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); fflush(stderr); if (DEBUG(GRAPH2)) Targ_PrintGraph(2); exit(2); /* Not 1 so -q can distinguish error */ } /* * Punt -- * Major exception once jobs are being created. Kills all jobs, prints * a message and exits. * * Results: * None * * Side Effects: * All children are killed indiscriminately and the program Lib_Exits */ /* VARARGS */ void Punt(const char *fmt, ...) { va_list ap; va_start(ap, fmt); fprintf(stderr, "make: "); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); fflush(stderr); DieHorribly(); } /*- * DieHorribly -- * Exit without giving a message. * * Results: * None * * Side Effects: * A big one... */ void DieHorribly(void) { if (jobsRunning) Job_AbortAll(); if (DEBUG(GRAPH2)) Targ_PrintGraph(2); exit(2); /* Not 1, so -q can distinguish error */ } /* * Finish -- * Called when aborting due to errors in child shell to signal * abnormal exit, with the number of errors encountered in Make_Make. * * Results: * None * * Side Effects: * The program exits */ void Finish(int errors) { Fatal("%d error%s", errors, errors == 1 ? "" : "s"); } /* * emalloc -- * malloc, but die on error. */ void * emalloc(size_t len) { void *p; if ((p = malloc(len)) == NULL) enomem(); return (p); } /* * estrdup -- * strdup, but die on error. */ char * estrdup(const char *str) { char *p; if ((p = strdup(str)) == NULL) enomem(); return (p); } /* * erealloc -- * realloc, but die on error. */ void * erealloc(void *ptr, size_t size) { if ((ptr = realloc(ptr, size)) == NULL) enomem(); return (ptr); } /* * enomem -- * die when out of memory. */ static void enomem(void) { err(2, NULL); } /* * enunlink -- * Remove a file carefully, avoiding directories. */ int eunlink(const char *file) { struct stat st; if (lstat(file, &st) == -1) return (-1); if (S_ISDIR(st.st_mode)) { errno = EISDIR; return (-1); } return (unlink(file)); } /* * Convert a flag word to a printable thing and print it */ void print_flags(FILE *fp, const struct flag2str *tab, u_int flags, int par) { int first = 1; if (par) fprintf(fp, "("); while (tab->str != NULL) { if (flags & tab->flag) { if (!first) fprintf(fp, par ? "|" : " "); first = 0; fprintf(fp, "%s", tab->str); } tab++; } if (par) fprintf(fp, ")"); } freebsd-buildutils-10.0/src/usr.bin/make/dir.h0000644000000000000000000000552211320435022016117 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)dir.h 8.2 (Berkeley) 4/28/95 * $FreeBSD$ */ #ifndef dir_h_6002e3b8 #define dir_h_6002e3b8 #include #include "hash.h" struct GNode; struct Lst; struct Dir; struct PathElement; TAILQ_HEAD(Path, PathElement); void Dir_Init(void); void Dir_InitDot(void); Boolean Dir_HasWildcards(const char *); int Dir_FindHereOrAbove(char *, char *, char *, int); int Dir_MTime(struct GNode *); void Dir_PrintDirectories(void); struct Dir *Path_AddDir(struct Path *, const char *); void Path_Clear(struct Path *); void Path_Concat(struct Path *, const struct Path *); void Path_Duplicate(struct Path *, const struct Path *); void Path_Expand(char *, struct Path *, struct Lst *); char *Path_FindFile(char *, struct Path *); char *Path_MakeFlags(const char *, const struct Path *); void Path_Print(const struct Path *); #endif /* dir_h_6002e3b8 */ freebsd-buildutils-10.0/src/usr.bin/make/hash.c0000644000000000000000000002351010241065354016264 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)hash.c 8.1 (Berkeley) 6/6/93 */ #include __FBSDID("$FreeBSD$"); /* hash.c -- * * This module contains routines to manipulate a hash table. * See hash.h for a definition of the structure of the hash * table. Hash tables grow automatically as the amount of * information increases. */ #include #include #include #include "hash.h" #include "util.h" /* * Forward references to local procedures that are used before they're * defined: */ static void RebuildTable(Hash_Table *); /* * The following defines the ratio of # entries to # buckets * at which we rebuild the table to make it larger. */ #define rebuildLimit 8 /* *--------------------------------------------------------- * * Hash_InitTable -- * * Set up the hash table t with a given number of buckets, or a * reasonable default if the number requested is less than or * equal to zero. Hash tables will grow in size as needed. * * * Results: * None. * * Side Effects: * Memory is allocated for the initial bucket area. * *--------------------------------------------------------- */ void Hash_InitTable(Hash_Table *t, int numBuckets) { int i; struct Hash_Entry **hp; /* * Round up the size to a power of two. */ if (numBuckets <= 0) i = 16; else { for (i = 2; i < numBuckets; i <<= 1) continue; } t->numEntries = 0; t->size = i; t->mask = i - 1; t->bucketPtr = hp = emalloc(sizeof(*hp) * i); while (--i >= 0) *hp++ = NULL; } /* *--------------------------------------------------------- * * Hash_DeleteTable -- * * This routine removes everything from a hash table * and frees up the memory space it occupied (except for * the space in the Hash_Table structure). * * Results: * None. * * Side Effects: * Lots of memory is freed up. * *--------------------------------------------------------- */ void Hash_DeleteTable(Hash_Table *t) { struct Hash_Entry **hp, *h, *nexth = NULL; int i; for (hp = t->bucketPtr, i = t->size; --i >= 0;) { for (h = *hp++; h != NULL; h = nexth) { nexth = h->next; free(h); } } free(t->bucketPtr); /* * Set up the hash table to cause memory faults on any future access * attempts until re-initialization. */ t->bucketPtr = NULL; } /* *--------------------------------------------------------- * * Hash_FindEntry -- * * Searches a hash table for an entry corresponding to key. * * Results: * The return value is a pointer to the entry for key, * if key was present in the table. If key was not * present, NULL is returned. * * Side Effects: * None. * *--------------------------------------------------------- */ Hash_Entry * Hash_FindEntry(const Hash_Table *t, const char *key) { Hash_Entry *e; unsigned h; const char *p; for (h = 0, p = key; *p;) h = (h << 5) - h + *p++; p = key; for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next) if (e->namehash == h && strcmp(e->name, p) == 0) return (e); return (NULL); } /* *--------------------------------------------------------- * * Hash_CreateEntry -- * * Searches a hash table for an entry corresponding to * key. If no entry is found, then one is created. * * Results: * The return value is a pointer to the entry. If *newPtr * isn't NULL, then *newPtr is filled in with TRUE if a * new entry was created, and FALSE if an entry already existed * with the given key. * * Side Effects: * Memory may be allocated, and the hash buckets may be modified. *--------------------------------------------------------- */ Hash_Entry * Hash_CreateEntry(Hash_Table *t, const char *key, Boolean *newPtr) { Hash_Entry *e; unsigned int h; const char *p; int keylen; struct Hash_Entry **hp; /* * Hash the key. As a side effect, save the length (strlen) of the * key in case we need to create the entry. */ for (h = 0, p = key; *p;) h = (h << 5) - h + *p++; keylen = p - key; p = key; for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next) { if (e->namehash == h && strcmp(e->name, p) == 0) { if (newPtr != NULL) *newPtr = FALSE; return (e); } } /* * The desired entry isn't there. Before allocating a new entry, * expand the table if necessary (and this changes the resulting * bucket chain). */ if (t->numEntries >= rebuildLimit * t->size) RebuildTable(t); e = emalloc(sizeof(*e) + keylen); hp = &t->bucketPtr[h & t->mask]; e->next = *hp; *hp = e; e->clientData = NULL; e->namehash = h; strcpy(e->name, p); t->numEntries++; if (newPtr != NULL) *newPtr = TRUE; return (e); } /* *--------------------------------------------------------- * * Hash_DeleteEntry -- * * Delete the given hash table entry and free memory associated with * it. * * Results: * None. * * Side Effects: * Hash chain that entry lives in is modified and memory is freed. * *--------------------------------------------------------- */ void Hash_DeleteEntry(Hash_Table *t, Hash_Entry *e) { Hash_Entry **hp, *p; if (e == NULL) return; for (hp = &t->bucketPtr[e->namehash & t->mask]; (p = *hp) != NULL; hp = &p->next) { if (p == e) { *hp = p->next; free(p); t->numEntries--; return; } } write(STDERR_FILENO, "bad call to Hash_DeleteEntry\n", 29); abort(); } /* *--------------------------------------------------------- * * Hash_EnumFirst -- * This procedure sets things up for a complete search * of all entries recorded in the hash table. * * Results: * The return value is the address of the first entry in * the hash table, or NULL if the table is empty. * * Side Effects: * The information in searchPtr is initialized so that successive * calls to Hash_Next will return successive HashEntry's * from the table. * *--------------------------------------------------------- */ Hash_Entry * Hash_EnumFirst(const Hash_Table *t, Hash_Search *searchPtr) { searchPtr->tablePtr = t; searchPtr->nextIndex = 0; searchPtr->hashEntryPtr = NULL; return (Hash_EnumNext(searchPtr)); } /* *--------------------------------------------------------- * * Hash_EnumNext -- * This procedure returns successive entries in the hash table. * * Results: * The return value is a pointer to the next HashEntry * in the table, or NULL when the end of the table is * reached. * * Side Effects: * The information in searchPtr is modified to advance to the * next entry. * *--------------------------------------------------------- */ Hash_Entry * Hash_EnumNext(Hash_Search *searchPtr) { Hash_Entry *e; const Hash_Table *t = searchPtr->tablePtr; /* * The hashEntryPtr field points to the most recently returned * entry, or is NULL if we are starting up. If not NULL, we have * to start at the next one in the chain. */ e = searchPtr->hashEntryPtr; if (e != NULL) e = e->next; /* * If the chain ran out, or if we are starting up, we need to * find the next nonempty chain. */ while (e == NULL) { if (searchPtr->nextIndex >= t->size) return (NULL); e = t->bucketPtr[searchPtr->nextIndex++]; } searchPtr->hashEntryPtr = e; return (e); } /* *--------------------------------------------------------- * * RebuildTable -- * This local routine makes a new hash table that * is larger than the old one. * * Results: * None. * * Side Effects: * The entire hash table is moved, so any bucket numbers * from the old table are invalid. * *--------------------------------------------------------- */ static void RebuildTable(Hash_Table *t) { Hash_Entry *e, *next = NULL, **hp, **xp; int i, mask; Hash_Entry **oldhp; int oldsize; oldhp = t->bucketPtr; oldsize = i = t->size; i <<= 1; t->size = i; t->mask = mask = i - 1; t->bucketPtr = hp = emalloc(sizeof(*hp) * i); while (--i >= 0) *hp++ = NULL; for (hp = oldhp, i = oldsize; --i >= 0;) { for (e = *hp++; e != NULL; e = next) { next = e->next; xp = &t->bucketPtr[e->namehash & mask]; e->next = *xp; *xp = e; } } free(oldhp); } freebsd-buildutils-10.0/src/usr.bin/make/targ.h0000644000000000000000000000602610200624544016303 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef targ_h_6ded1830 #define targ_h_6ded1830 #include /* * The TARG_ constants are used when calling the Targ_FindNode and * Targ_FindList functions in targ.c. They simply tell the functions what to * do if the desired node(s) is (are) not found. If the TARG_CREATE constant * is given, a new, empty node will be created for the target, placed in the * table of all targets and its address returned. If TARG_NOCREATE is given, * a NULL pointer will be returned. */ #define TARG_CREATE 0x01 /* create node if not found */ #define TARG_NOCREATE 0x00 /* don't create it */ struct GNode; struct Lst; void Targ_Init(void); struct GNode *Targ_NewGN(const char *); struct GNode *Targ_FindNode(const char *, int); void Targ_FindList(struct Lst *, struct Lst *, int); Boolean Targ_Ignore(struct GNode *); Boolean Targ_Silent(struct GNode *); Boolean Targ_Precious(struct GNode *); void Targ_SetMain(struct GNode *); int Targ_PrintCmd(void *, void *); char *Targ_FmtTime(time_t); void Targ_PrintType(int); void Targ_PrintGraph(int); #endif /* targ_h_6ded1830 */ freebsd-buildutils-10.0/src/usr.bin/make/buf.c0000644000000000000000000001370111677315120016121 0ustar /*- * Copyright (c) 2005 Max Okumoto * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)buf.c 8.1 (Berkeley) 6/6/93 */ #include __FBSDID("$FreeBSD$"); /* * buf.c * Functions for automatically-expanded buffers. */ #include #include #include "buf.h" #include "util.h" /** * Returns the number of bytes in the buffer. Doesn't include the * null-terminating byte. */ size_t Buf_Size(const Buffer *buf) { return (buf->end - buf->buf); } /** * Returns a reference to the data contained in the buffer. * * @note Adding data to the Buffer object may invalidate the reference. */ char * Buf_Data(const Buffer *bp) { return (bp->buf); } /** * Expand the buffer to hold the number of additional bytes, plus * space to store a terminating NULL byte. */ static inline void BufExpand(Buffer *bp, size_t nb) { size_t len = Buf_Size(bp); size_t size; if (bp->size < len + nb + 1) { size = bp->size + MAX(nb + 1, BUF_ADD_INC); bp->size = size; bp->buf = erealloc(bp->buf, size); bp->end = bp->buf + len; } } /** * Add a single byte to the buffer. */ void Buf_AddByte(Buffer *bp, Byte byte) { BufExpand(bp, 1); *bp->end = byte; bp->end++; *bp->end = '\0'; } /** * Add bytes to the buffer. */ void Buf_AddBytes(Buffer *bp, size_t len, const Byte *bytes) { BufExpand(bp, len); memcpy(bp->end, bytes, len); bp->end += len; *bp->end = '\0'; } /** * Get a reference to the internal buffer. * * len: * Pointer to where we return the number of bytes in the internal buffer. * * Returns: * return A pointer to the data. */ Byte * Buf_GetAll(Buffer *bp, size_t *len) { if (len != NULL) *len = Buf_Size(bp); return (bp->buf); } /** * Get the contents of a buffer and destroy the buffer. If the buffer * is NULL, return NULL. * * Returns: * the pointer to the data. */ char * Buf_Peel(Buffer *bp) { char *ret; if (bp == NULL) return (NULL); ret = bp->buf; free(bp); return (ret); } /** * Initialize a buffer. If no initial size is given, a reasonable * default is used. * * Returns: * A buffer object to be given to other functions in this library. * * Side Effects: * Space is allocated for the Buffer object and a internal buffer. */ Buffer * Buf_Init(size_t size) { Buffer *bp; /* New Buffer */ if (size <= 0) size = BUF_DEF_SIZE; bp = emalloc(sizeof(*bp)); bp->size = size; bp->buf = emalloc(size); bp->end = bp->buf; *bp->end = '\0'; return (bp); } /** * Destroy a buffer, and optionally free its data, too. * * Side Effects: * Space for the Buffer object and possibly the internal buffer * is de-allocated. */ void Buf_Destroy(Buffer *buf, Boolean freeData) { if (freeData) free(buf->buf); free(buf); } /** * Replace the last byte in a buffer. If the buffer was empty * initially, then a new byte will be added. */ void Buf_ReplaceLastByte(Buffer *bp, Byte byte) { if (bp->end == bp->buf) { Buf_AddByte(bp, byte); } else { *(bp->end - 1) = byte; } } /** * Append characters in str to Buffer object */ void Buf_Append(Buffer *bp, const char str[]) { Buf_AddBytes(bp, strlen(str), str); } /** * Append characters in buf to Buffer object */ void Buf_AppendBuf(Buffer *bp, const Buffer *buf) { Buf_AddBytes(bp, Buf_Size(buf), buf->buf); } /** * Append characters between str and end to Buffer object. */ void Buf_AppendRange(Buffer *bp, const char str[], const char *end) { Buf_AddBytes(bp, end - str, str); } /** * Convert newlines in buffer to spaces. The trailing newline is * removed. */ void Buf_StripNewlines(Buffer *bp) { char *ptr = bp->end; /* * If there is anything in the buffer, remove the last * newline character. */ if (ptr != bp->buf) { if (*(ptr - 1) == '\n') { /* shorten buffer */ *(ptr - 1) = '\0'; --bp->end; } --ptr; } /* Convert newline characters to a space characters. */ while (ptr != bp->buf) { if (*ptr == '\n') { *ptr = ' '; } --ptr; } } /** * Clear the contents of the buffer. */ void Buf_Clear(Buffer *bp) { bp->end = bp->buf; *bp->end = '\0'; } freebsd-buildutils-10.0/src/usr.bin/make/Makefile0000644000000000000000000001047312145247426016650 0ustar # @(#)Makefile 5.2 (Berkeley) 12/28/90 # $Id: Makefile,v 1.6 1994/06/30 05:33:39 cgd Exp $ # $FreeBSD$ .include PROG= make CFLAGS+=-I${.CURDIR} SRCS= arch.c buf.c cond.c dir.c for.c hash.c hash_tables.c job.c \ lst.c main.c make.c parse.c proc.c shell.c str.c suff.c targ.c \ util.c var.c .if !defined(MK_SHARED_TOOLCHAIN) || ${MK_SHARED_TOOLCHAIN} == "no" NO_SHARED?= YES .endif # Version has the RYYYYMMDDX format, where R is from RELENG_ CFLAGS+=-DMAKE_VERSION=\"10201205300\" # There is no obvious performance improvement currently. # CFLAGS+=-DUSE_KQUEUE # Make object files which depend on preprocessor symbols defined in # the Makefile which are not compilation options but rather configuration # options dependend on the Makefile. main.c needs MAKE_VERSION while # shell.c uses DEFSHELLNAME. This will cause recompilation in the case # the definition is changed in the makefile. It will of course not cause # recompilation if one does 'make MAKE_SHELL=csh'. main.o shell.o: ${MAKEFILE} # Directive and keyword tables. We use hash tables. These hash tables have been # generated with mph (ports/devel/mph) # If you change the directives or keywords (adding, deleting, reordering) you # need to create new tables and hash functions (directive_hash, keyword_hash). # # The following changes have been made to the generated code: # # o prefix the names of the g, T0 and T1 arrays with 'directive_' # resp. 'keyword_'. # # o make the type of the tables 'const [un]signed char' (if you change # anything make sure that the numbers fit into a char). # # o make the hash function use the length for termination, # not the trailing '\0', via the -l flag in emitc and some editing # (only for directive_hash). LOCALBASE ?= /usr/local MPH ?= ${LOCALBASE}/bin/mph EMITC ?= ${LOCALBASE}/bin/emitc .PRECIOUS: hash hash: ( echo '/*' ; \ echo ' * DO NOT EDIT' ; \ echo ' * $$''FreeBSD$$' ; \ echo -n ' * auto-generated from ' ; \ sed -nEe '/\$$FreeBSD/s/^.*\$$(.*)\$$.*$$/\1/p' \ ${.CURDIR}/parse.c ; \ echo ' * DO NOT EDIT' ; \ echo ' */' ; \ echo '#include ' ; \ echo ; \ echo '#include "hash_tables.h"' ; \ echo ; \ cat ${.CURDIR}/parse.c | sed \ -e '1,/DIRECTIVES-START-TAG/d' \ -e '/DIRECTIVES-END-TAG/,$$d' \ -e 's/^[^"]*"\([^"]*\)".*$$/\1/' | \ ${MPH} -d2 -m1 | ${EMITC} -l -s | \ sed \ -e 's/^static int g\[\]/static const signed char directive_g[]/' \ -e 's/^static int T0\[\]/static const u_char directive_T0[]/' \ -e 's/^static int T1\[\]/static const u_char directive_T1[]/' \ -e '/^#define uchar unsigned char/d' \ -e 's/uchar/u_char/g' \ -e 's/^hash(/directive_hash(/' \ -e 's/; \*kp;/; kp < key + len;/' \ -e 's/int len)/size_t len)/' \ -e 's/= T0\[/= directive_T0\[/' \ -e 's/= T1\[/= directive_T1\[/' \ -e 's/g\[f/directive_g[f/g' ; \ cat ${.CURDIR}/parse.c | sed \ -e '1,/KEYWORD-START-TAG/d' \ -e '/KEYWORD-END-TAG/,$$d' \ -e 's/^[^"]*"\([^"]*\)".*$$/\1/' | \ ${MPH} -d2 -m1 | ${EMITC} -l -s | \ sed \ -e 's/^static int g\[\]/static const signed char keyword_g[]/' \ -e 's/^static int T0\[\]/static const u_char keyword_T0[]/' \ -e 's/^static int T1\[\]/static const u_char keyword_T1[]/' \ -e '/^#define uchar unsigned char/d' \ -e 's/uchar/u_char/g' \ -e 's/^hash(/keyword_hash(/' \ -e 's/int len)/size_t len)/' \ -e 's/= T0\[/= keyword_T0\[/' \ -e 's/= T1\[/= keyword_T1\[/' \ -e 's/g\[f/keyword_g[f/g' \ ) > ${.CURDIR}/hash_tables.c # Set the shell which make(1) uses. Bourne is the default, but a decent # Korn shell works fine, and much faster. Using the C shell for this # will almost certainly break everything, but it's Unix tradition to # allow you to shoot yourself in the foot if you want to :-) MAKE_SHELL?= sh .if ${MAKE_SHELL} == "csh" || ${MAKE_SHELL} == "sh" || ${MAKE_SHELL} == "ksh" CFLAGS+= -DDEFSHELLNAME=\"${MAKE_SHELL}\" .else .error "MAKE_SHELL must be set to one of \"csh\", \"sh\" or \"ksh\"." .endif .if defined(MK_BMAKE) && ${MK_BMAKE} != "no" # if we are here we don't want this called 'make' PROG= fmake fmake.1: make.1 cp ${.ALLSRC} ${.TARGET} .endif .include freebsd-buildutils-10.0/src/usr.bin/make/job.c0000644000000000000000000024622112165165412016124 0ustar /*- * Copyright (c) 1988, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1988, 1989 by Adam de Boor * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)job.c 8.2 (Berkeley) 3/19/94 */ #include __FBSDID("$FreeBSD$"); /*- * job.c -- * handle the creation etc. of our child processes. * * Interface: * Job_Make Start the creation of the given target. * * Job_CatchChildren * Check for and handle the termination of any children. * This must be called reasonably frequently to keep the * whole make going at a decent clip, since job table * entries aren't removed until their process is caught * this way. Its single argument is TRUE if the function * should block waiting for a child to terminate. * * Job_CatchOutput Print any output our children have produced. Should * also be called fairly frequently to keep the user * informed of what's going on. If no output is waiting, * it will block for a time given by the SEL_* constants, * below, or until output is ready. * * Job_Init Called to intialize this module. in addition, any * commands attached to the .BEGIN target are executed * before this function returns. Hence, the makefile must * have been parsed before this function is called. * * Job_Full Return TRUE if the job table is filled. * * Job_Empty Return TRUE if the job table is completely empty. * * Job_Finish Perform any final processing which needs doing. This * includes the execution of any commands which have * been/were attached to the .END target. It should only * be called when the job table is empty. * * Job_AbortAll Abort all currently running jobs. It doesn't handle * output or do anything for the jobs, just kills them. * It should only be called in an emergency, as it were. * * Job_CheckCommands * Verify that the commands for a target are ok. Provide * them if necessary and possible. * * Job_Touch Update a target without really updating it. * * Job_Wait Wait for all currently-running jobs to finish. * * compat.c -- * The routines in this file implement the full-compatibility * mode of PMake. Most of the special functionality of PMake * is available in this mode. Things not supported: * - different shells. * - friendly variable substitution. * * Interface: * Compat_Run Initialize things for this module and recreate * thems as need creatin' */ #include #include #include #include #ifdef USE_KQUEUE #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include "arch.h" #include "buf.h" #include "config.h" #include "dir.h" #include "globals.h" #include "GNode.h" #include "job.h" #include "make.h" #include "parse.h" #include "proc.h" #include "shell.h" #include "str.h" #include "suff.h" #include "targ.h" #include "util.h" #include "var.h" #define TMPPAT "makeXXXXXXXXXX" #ifndef USE_KQUEUE /* * The SEL_ constants determine the maximum amount of time spent in select * before coming out to see if a child has finished. SEL_SEC is the number of * seconds and SEL_USEC is the number of micro-seconds */ #define SEL_SEC 2 #define SEL_USEC 0 #endif /* !USE_KQUEUE */ /* * Job Table definitions. * * The job "table" is kept as a linked Lst in 'jobs', with the number of * active jobs maintained in the 'nJobs' variable. At no time will this * exceed the value of 'maxJobs', initialized by the Job_Init function. * * When a job is finished, the Make_Update function is called on each of the * parents of the node which was just remade. This takes care of the upward * traversal of the dependency graph. */ #define JOB_BUFSIZE 1024 typedef struct Job { pid_t pid; /* The child's process ID */ struct GNode *node; /* The target the child is making */ /* * A LstNode for the first command to be saved after the job completes. * This is NULL if there was no "..." in the job's commands. */ LstNode *tailCmds; /* * An FILE* for writing out the commands. This is only * used before the job is actually started. */ FILE *cmdFILE; /* * A word of flags which determine how the module handles errors, * echoing, etc. for the job */ short flags; /* Flags to control treatment of job */ #define JOB_IGNERR 0x001 /* Ignore non-zero exits */ #define JOB_SILENT 0x002 /* no output */ #define JOB_SPECIAL 0x004 /* Target is a special one. i.e. run it locally * if we can't export it and maxLocal is 0 */ #define JOB_IGNDOTS 0x008 /* Ignore "..." lines when processing * commands */ #define JOB_FIRST 0x020 /* Job is first job for the node */ #define JOB_RESTART 0x080 /* Job needs to be completely restarted */ #define JOB_RESUME 0x100 /* Job needs to be resumed b/c it stopped, * for some reason */ #define JOB_CONTINUING 0x200 /* We are in the process of resuming this job. * Used to avoid infinite recursion between * JobFinish and JobRestart */ /* union for handling shell's output */ union { /* * This part is used when usePipes is true. * The output is being caught via a pipe and the descriptors * of our pipe, an array in which output is line buffered and * the current position in that buffer are all maintained for * each job. */ struct { /* * Input side of pipe associated with * job's output channel */ int op_inPipe; /* * Output side of pipe associated with job's * output channel */ int op_outPipe; /* * Buffer for storing the output of the * job, line by line */ char op_outBuf[JOB_BUFSIZE + 1]; /* Current position in op_outBuf */ int op_curPos; } o_pipe; /* * If usePipes is false the output is routed to a temporary * file and all that is kept is the name of the file and the * descriptor open to the file. */ struct { /* Name of file to which shell output was rerouted */ char of_outFile[PATH_MAX]; /* * Stream open to the output file. Used to funnel all * from a single job to one file while still allowing * multiple shell invocations */ int of_outFd; } o_file; } output; /* Data for tracking a shell's output */ TAILQ_ENTRY(Job) link; /* list link */ } Job; #define outPipe output.o_pipe.op_outPipe #define inPipe output.o_pipe.op_inPipe #define outBuf output.o_pipe.op_outBuf #define curPos output.o_pipe.op_curPos #define outFile output.o_file.of_outFile #define outFd output.o_file.of_outFd TAILQ_HEAD(JobList, Job); /* * error handling variables */ static int aborting = 0; /* why is the make aborting? */ #define ABORT_ERROR 1 /* Because of an error */ #define ABORT_INTERRUPT 2 /* Because it was interrupted */ #define ABORT_WAIT 3 /* Waiting for jobs to finish */ /* * XXX: Avoid SunOS bug... FILENO() is fp->_file, and file * is a char! So when we go above 127 we turn negative! */ #define FILENO(a) ((unsigned)fileno(a)) /* * post-make command processing. The node postCommands is really just the * .END target but we keep it around to avoid having to search for it * all the time. */ static GNode *postCommands; /* * The number of commands actually printed for a target. Should this * number be 0, no shell will be executed. */ static int numCommands; /* * Return values from JobStart. */ #define JOB_RUNNING 0 /* Job is running */ #define JOB_ERROR 1 /* Error in starting the job */ #define JOB_FINISHED 2 /* The job is already finished */ #define JOB_STOPPED 3 /* The job is stopped */ /* * The maximum number of jobs that may run. This is initialize from the * -j argument for the leading make and from the FIFO for sub-makes. */ static int maxJobs; static int nJobs; /* The number of children currently running */ /* The structures that describe them */ static struct JobList jobs = TAILQ_HEAD_INITIALIZER(jobs); static Boolean jobFull; /* Flag to tell when the job table is full. It * is set TRUE when (1) the total number of * running jobs equals the maximum allowed */ #ifdef USE_KQUEUE static int kqfd; /* File descriptor obtained by kqueue() */ #else static fd_set outputs; /* Set of descriptors of pipes connected to * the output channels of children */ #endif static GNode *lastNode; /* The node for which output was most recently * produced. */ static const char *targFmt; /* Format string to use to head output from a * job when it's not the most-recent job heard * from */ static char *targPrefix = NULL; /* What we print at the start of targFmt */ #define TARG_FMT "%s %s ---\n" /* Default format */ #define MESSAGE(fp, gn) \ fprintf(fp, targFmt, targPrefix, gn->name); /* * When JobStart attempts to run a job but isn't allowed to * or when Job_CatchChildren detects a job that has * been stopped somehow, the job is placed on the stoppedJobs queue to be run * when the next job finishes. * * Lst of Job structures describing jobs that were stopped due to * concurrency limits or externally */ static struct JobList stoppedJobs = TAILQ_HEAD_INITIALIZER(stoppedJobs); static int fifoFd; /* Fd of our job fifo */ static char fifoName[] = "/tmp/make_fifo_XXXXXXXXX"; static int fifoMaster; static volatile sig_atomic_t interrupted; #if defined(USE_PGRP) && defined(SYSV) # define KILL(pid, sig) killpg(-(pid), (sig)) #else # if defined(USE_PGRP) # define KILL(pid, sig) killpg((pid), (sig)) # else # define KILL(pid, sig) kill((pid), (sig)) # endif #endif /* * Grmpf... There is no way to set bits of the wait structure * anymore with the stupid W*() macros. I liked the union wait * stuff much more. So, we devise our own macros... This is * really ugly, use dramamine sparingly. You have been warned. */ #define W_SETMASKED(st, val, fun) \ { \ int sh = (int)~0; \ int mask = fun(sh); \ \ for (sh = 0; ((mask >> sh) & 1) == 0; sh++) \ continue; \ *(st) = (*(st) & ~mask) | ((val) << sh); \ } #define W_SETTERMSIG(st, val) W_SETMASKED(st, val, WTERMSIG) #define W_SETEXITSTATUS(st, val) W_SETMASKED(st, val, WEXITSTATUS) static void JobRestart(Job *); static int JobStart(GNode *, int, Job *); static void JobDoOutput(Job *, Boolean); static void JobInterrupt(int, int); static void JobRestartJobs(void); static int Compat_RunCommand(LstNode *, struct GNode *); static GNode *curTarg = NULL; static GNode *ENDNode; /** * Create a fifo file with a uniq filename, and returns a file * descriptor to that fifo. */ static int mkfifotemp(char *template) { char *start; char *pathend; char *ptr; const unsigned char padchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; if (template[0] == '\0') { errno = EINVAL; /* bad input string */ return (-1); } /* Find end of template string. */ pathend = strchr(template, '\0'); ptr = pathend - 1; /* * Starting from the end of the template replace spaces with 'X' in * them with random characters until there are no more 'X'. */ while (ptr >= template && *ptr == 'X') { uint32_t rand_num = #if __FreeBSD_version < 800041 arc4random() % (sizeof(padchar) - 1); #else arc4random_uniform(sizeof(padchar) - 1); #endif *ptr-- = padchar[rand_num]; } start = ptr + 1; /* Check the target directory. */ for (; ptr > template; --ptr) { if (*ptr == '/') { struct stat sbuf; *ptr = '\0'; if (stat(template, &sbuf) != 0) return (-1); if (!S_ISDIR(sbuf.st_mode)) { errno = ENOTDIR; return (-1); } *ptr = '/'; break; } } for (;;) { if (mkfifo(template, 0600) == 0) { int fd; if ((fd = open(template, O_RDWR, 0600)) < 0) { unlink(template); return (-1); } else { return (fd); } } else { if (errno != EEXIST) { return (-1); } } /* * If we have a collision, cycle through the space of * filenames. */ for (ptr = start;;) { char *pad; if (*ptr == '\0' || ptr == pathend) return (-1); pad = strchr(padchar, *ptr); if (pad == NULL || *++pad == '\0') { *ptr++ = padchar[0]; } else { *ptr++ = *pad; break; } } } /*NOTREACHED*/ } static void catch_child(int sig __unused) { } /** */ void Proc_Init(void) { /* * Catch SIGCHLD so that we get kicked out of select() when we * need to look at a child. This is only known to matter for the * -j case (perhaps without -P). * * XXX this is intentionally misplaced. */ struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; sa.sa_handler = catch_child; sigaction(SIGCHLD, &sa, NULL); } /** * Wait for child process to terminate. */ static int ProcWait(ProcStuff *ps) { pid_t pid; int status; /* * Wait for the process to exit. */ for (;;) { pid = wait(&status); if (pid == -1 && errno != EINTR) { Fatal("error in wait: %d", pid); /* NOTREACHED */ } if (pid == ps->child_pid) { break; } if (interrupted) { break; } } return (status); } /** * JobCatchSignal * Got a signal. Set global variables and hope that someone will * handle it. */ static void JobCatchSig(int signo) { interrupted = signo; } /** * JobPassSig -- * Pass a signal on to all local jobs if * USE_PGRP is defined, then die ourselves. * * Side Effects: * We die by the same signal. */ static void JobPassSig(int signo) { Job *job; sigset_t nmask, omask; struct sigaction act; sigemptyset(&nmask); sigaddset(&nmask, signo); sigprocmask(SIG_SETMASK, &nmask, &omask); DEBUGF(JOB, ("JobPassSig(%d) called.\n", signo)); TAILQ_FOREACH(job, &jobs, link) { DEBUGF(JOB, ("JobPassSig passing signal %d to child %jd.\n", signo, (intmax_t)job->pid)); KILL(job->pid, signo); } /* * Deal with proper cleanup based on the signal received. We only run * the .INTERRUPT target if the signal was in fact an interrupt. * The other three termination signals are more of a "get out *now*" * command. */ if (signo == SIGINT) { JobInterrupt(TRUE, signo); } else if (signo == SIGHUP || signo == SIGTERM || signo == SIGQUIT) { JobInterrupt(FALSE, signo); } /* * Leave gracefully if SIGQUIT, rather than core dumping. */ if (signo == SIGQUIT) { signo = SIGINT; } /* * Send ourselves the signal now we've given the message to everyone * else. Note we block everything else possible while we're getting * the signal. This ensures that all our jobs get continued when we * wake up before we take any other signal. * XXX this comment seems wrong. */ act.sa_handler = SIG_DFL; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(signo, &act, NULL); DEBUGF(JOB, ("JobPassSig passing signal to self, mask = %x.\n", ~0 & ~(1 << (signo - 1)))); signal(signo, SIG_DFL); KILL(getpid(), signo); signo = SIGCONT; TAILQ_FOREACH(job, &jobs, link) { DEBUGF(JOB, ("JobPassSig passing signal %d to child %jd.\n", signo, (intmax_t)job->pid)); KILL(job->pid, signo); } sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL); act.sa_handler = JobPassSig; sigaction(signo, &act, NULL); } /** * JobPrintCommand -- * Put out another command for the given job. If the command starts * with an @ or a - we process it specially. In the former case, * so long as the -s and -n flags weren't given to make, we stick * a shell-specific echoOff command in the script. In the latter, * we ignore errors for the entire job, unless the shell has error * control. * If the command is just "..." we take all future commands for this * job to be commands to be executed once the entire graph has been * made and return non-zero to signal that the end of the commands * was reached. These commands are later attached to the postCommands * node and executed by Job_Finish when all things are done. * This function is called from JobStart via LST_FOREACH. * * Results: * Always 0, unless the command was "..." * * Side Effects: * If the command begins with a '-' and the shell has no error control, * the JOB_IGNERR flag is set in the job descriptor. * If the command is "..." and we're not ignoring such things, * tailCmds is set to the successor node of the cmd. * numCommands is incremented if the command is actually printed. */ static int JobPrintCommand(LstNode *cmdNode, Job *job) { Boolean noSpecials; /* true if we shouldn't worry about * inserting special commands into * the input stream. */ Boolean shutUp = FALSE; /* true if we put a no echo command * into the command file */ Boolean errOff = FALSE; /* true if we turned error checking * off before printing the command * and need to turn it back on */ const char *cmdTemplate;/* Template to use when printing the command */ char *cmd; /* Expanded command */ noSpecials = (noExecute && !(job->node->type & OP_MAKE)); #define DBPRINTF(fmt, arg) \ DEBUGF(JOB, (fmt, arg)); \ fprintf(job->cmdFILE, fmt, arg); \ fflush(job->cmdFILE); /* * For debugging, we replace each command with the result of expanding * the variables in the command. */ cmd = Buf_Peel(Var_Subst(Lst_Datum(cmdNode), job->node, FALSE)); if (strcmp(cmd, "...") == 0) { free(cmd); job->node->type |= OP_SAVE_CMDS; if ((job->flags & JOB_IGNDOTS) == 0) { job->tailCmds = Lst_Succ(cmdNode); return (1); } return (0); } Lst_Replace(cmdNode, cmd); /* * Check for leading @', -' or +'s to control echoing, error checking, * and execution on -n. */ while (*cmd == '@' || *cmd == '-' || *cmd == '+') { switch (*cmd) { case '@': shutUp = DEBUG(LOUD) ? FALSE : TRUE; break; case '-': errOff = TRUE; break; case '+': if (noSpecials) { /* * We're not actually exececuting anything... * but this one needs to be - use compat mode * just for it. */ Compat_RunCommand(cmdNode, job->node); return (0); } break; } cmd++; } while (isspace((unsigned char)*cmd)) cmd++; /* * Ignore empty commands */ if (*cmd == '\0') { return (0); } cmdTemplate = "%s\n"; numCommands += 1; if (shutUp) { if (!(job->flags & JOB_SILENT) && !noSpecials && commandShell->hasEchoCtl) { DBPRINTF("%s\n", commandShell->echoOff); } else { shutUp = FALSE; } } if (errOff) { if (!(job->flags & JOB_IGNERR) && !noSpecials) { if (commandShell->hasErrCtl) { /* * We don't want the error-control commands * showing up either, so we turn off echoing * while executing them. We could put another * field in the shell structure to tell * JobDoOutput to look for this string too, * but why make it any more complex than * it already is? */ if (!(job->flags & JOB_SILENT) && !shutUp && commandShell->hasEchoCtl) { DBPRINTF("%s\n", commandShell->echoOff); DBPRINTF("%s\n", commandShell->ignErr); DBPRINTF("%s\n", commandShell->echoOn); } else { DBPRINTF("%s\n", commandShell->ignErr); } } else if (commandShell->ignErr && *commandShell->ignErr != '\0') { /* * The shell has no error control, so we need to * be weird to get it to ignore any errors from * the command. If echoing is turned on, we turn * it off and use the errCheck template to echo * the command. Leave echoing off so the user * doesn't see the weirdness we go through to * ignore errors. Set cmdTemplate to use the * weirdness instead of the simple "%s\n" * template. */ if (!(job->flags & JOB_SILENT) && !shutUp && commandShell->hasEchoCtl) { DBPRINTF("%s\n", commandShell->echoOff); DBPRINTF(commandShell->errCheck, cmd); shutUp = TRUE; } cmdTemplate = commandShell->ignErr; /* * The error ignoration (hee hee) is already * taken care of by the ignErr template, so * pretend error checking is still on. */ errOff = FALSE; } else { errOff = FALSE; } } else { errOff = FALSE; } } DBPRINTF(cmdTemplate, cmd); if (errOff) { /* * If echoing is already off, there's no point in issuing the * echoOff command. Otherwise we issue it and pretend it was on * for the whole command... */ if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl) { DBPRINTF("%s\n", commandShell->echoOff); shutUp = TRUE; } DBPRINTF("%s\n", commandShell->errCheck); } if (shutUp) { DBPRINTF("%s\n", commandShell->echoOn); } return (0); } /** * JobClose -- * Called to close both input and output pipes when a job is finished. * * Side Effects: * The file descriptors associated with the job are closed. */ static void JobClose(Job *job) { if (usePipes) { #if !defined(USE_KQUEUE) FD_CLR(job->inPipe, &outputs); #endif if (job->outPipe != job->inPipe) { close(job->outPipe); } JobDoOutput(job, TRUE); close(job->inPipe); } else { close(job->outFd); JobDoOutput(job, TRUE); } } /** * JobFinish -- * Do final processing for the given job including updating * parents and starting new jobs as available/necessary. Note * that we pay no attention to the JOB_IGNERR flag here. * This is because when we're called because of a noexecute flag * or something, jstat.w_status is 0 and when called from * Job_CatchChildren, the status is zeroed if it s/b ignored. * * Side Effects: * Some nodes may be put on the toBeMade queue. * Final commands for the job are placed on postCommands. * * If we got an error and are aborting (aborting == ABORT_ERROR) and * the job list is now empty, we are done for the day. * If we recognized an error (makeErrors !=0), we set the aborting flag * to ABORT_ERROR so no more jobs will be started. */ static void JobFinish(Job *job, int *status) { Boolean done; LstNode *ln; if (WIFEXITED(*status)) { int job_status = WEXITSTATUS(*status); JobClose(job); /* * Deal with ignored errors in -B mode. We need to * print a message telling of the ignored error as * well as setting status.w_status to 0 so the next * command gets run. To do this, we set done to be * TRUE if in -B mode and the job exited non-zero. */ if (job_status == 0) { done = FALSE; } else { if (job->flags & JOB_IGNERR) { done = TRUE; } else { /* * If it exited non-zero and either we're * doing things our way or we're not ignoring * errors, the job is finished. Similarly, if * the shell died because of a signal the job * is also finished. In these cases, finish * out the job's output before printing the * exit status... */ done = TRUE; if (job->cmdFILE != NULL && job->cmdFILE != stdout) { fclose(job->cmdFILE); } } } } else if (WIFSIGNALED(*status)) { if (WTERMSIG(*status) == SIGCONT) { /* * No need to close things down or anything. */ done = FALSE; } else { /* * If it exited non-zero and either we're * doing things our way or we're not ignoring * errors, the job is finished. Similarly, if * the shell died because of a signal the job * is also finished. In these cases, finish * out the job's output before printing the * exit status... */ JobClose(job); if (job->cmdFILE != NULL && job->cmdFILE != stdout) { fclose(job->cmdFILE); } done = TRUE; } } else { /* * No need to close things down or anything. */ done = FALSE; } if (WIFEXITED(*status)) { if (done || DEBUG(JOB)) { FILE *out; if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) { /* * If output is going to a file and this job * is ignoring errors, arrange to have the * exit status sent to the output file as * well. */ out = fdopen(job->outFd, "w"); if (out == NULL) Punt("Cannot fdopen"); } else { out = stdout; } DEBUGF(JOB, ("Process %jd exited.\n", (intmax_t)job->pid)); if (WEXITSTATUS(*status) == 0) { if (DEBUG(JOB)) { if (usePipes && job->node != lastNode) { MESSAGE(out, job->node); lastNode = job->node; } fprintf(out, "*** [%s] Completed successfully\n", job->node->name); } } else { if (usePipes && job->node != lastNode) { MESSAGE(out, job->node); lastNode = job->node; } fprintf(out, "*** [%s] Error code %d%s\n", job->node->name, WEXITSTATUS(*status), (job->flags & JOB_IGNERR) ? " (ignored)" : ""); if (job->flags & JOB_IGNERR) { *status = 0; } } fflush(out); } } else if (WIFSIGNALED(*status)) { if (done || DEBUG(JOB) || (WTERMSIG(*status) == SIGCONT)) { FILE *out; if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) { /* * If output is going to a file and this job * is ignoring errors, arrange to have the * exit status sent to the output file as * well. */ out = fdopen(job->outFd, "w"); if (out == NULL) Punt("Cannot fdopen"); } else { out = stdout; } if (WTERMSIG(*status) == SIGCONT) { /* * If the beastie has continued, shift the * Job from the stopped list to the running * one (or re-stop it if concurrency is * exceeded) and go and get another child. */ if (job->flags & (JOB_RESUME | JOB_RESTART)) { if (usePipes && job->node != lastNode) { MESSAGE(out, job->node); lastNode = job->node; } fprintf(out, "*** [%s] Continued\n", job->node->name); } if (!(job->flags & JOB_CONTINUING)) { DEBUGF(JOB, ("Warning: process %jd was not " "continuing.\n", (intmax_t) job->pid)); } job->flags &= ~JOB_CONTINUING; TAILQ_INSERT_TAIL(&jobs, job, link); nJobs += 1; DEBUGF(JOB, ("Process %jd is continuing locally.\n", (intmax_t) job->pid)); if (nJobs == maxJobs) { jobFull = TRUE; DEBUGF(JOB, ("Job queue is full.\n")); } fflush(out); return; } else { if (usePipes && job->node != lastNode) { MESSAGE(out, job->node); lastNode = job->node; } fprintf(out, "*** [%s] Signal %d\n", job->node->name, WTERMSIG(*status)); fflush(out); } } } else { /* STOPPED */ FILE *out; if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) { /* * If output is going to a file and this job * is ignoring errors, arrange to have the * exit status sent to the output file as * well. */ out = fdopen(job->outFd, "w"); if (out == NULL) Punt("Cannot fdopen"); } else { out = stdout; } DEBUGF(JOB, ("Process %jd stopped.\n", (intmax_t) job->pid)); if (usePipes && job->node != lastNode) { MESSAGE(out, job->node); lastNode = job->node; } fprintf(out, "*** [%s] Stopped -- signal %d\n", job->node->name, WSTOPSIG(*status)); job->flags |= JOB_RESUME; TAILQ_INSERT_TAIL(&stoppedJobs, job, link); fflush(out); return; } /* * Now handle the -B-mode stuff. If the beast still isn't finished, * try and restart the job on the next command. If JobStart says it's * ok, it's ok. If there's an error, this puppy is done. */ if (compatMake && WIFEXITED(*status) && Lst_Succ(job->node->compat_command) != NULL) { switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) { case JOB_RUNNING: done = FALSE; break; case JOB_ERROR: done = TRUE; W_SETEXITSTATUS(status, 1); break; case JOB_FINISHED: /* * If we got back a JOB_FINISHED code, JobStart has * already called Make_Update and freed the job * descriptor. We set done to false here to avoid fake * cycles and double frees. JobStart needs to do the * update so we can proceed up the graph when given * the -n flag.. */ done = FALSE; break; default: break; } } else { done = TRUE; } if (done && aborting != ABORT_ERROR && aborting != ABORT_INTERRUPT && *status == 0) { /* * As long as we aren't aborting and the job didn't return a * non-zero status that we shouldn't ignore, we call * Make_Update to update the parents. In addition, any saved * commands for the node are placed on the .END target. */ for (ln = job->tailCmds; ln != NULL; ln = LST_NEXT(ln)) { Lst_AtEnd(&postCommands->commands, Buf_Peel( Var_Subst(Lst_Datum(ln), job->node, FALSE))); } job->node->made = MADE; Make_Update(job->node); free(job); } else if (*status != 0) { makeErrors++; free(job); } JobRestartJobs(); /* * Set aborting if any error. */ if (makeErrors && !keepgoing && aborting != ABORT_INTERRUPT) { /* * If we found any errors in this batch of children and the -k * flag wasn't given, we set the aborting flag so no more jobs * get started. */ aborting = ABORT_ERROR; } if (aborting == ABORT_ERROR && Job_Empty()) { /* * If we are aborting and the job table is now empty, we finish. */ Finish(makeErrors); } } /** * Job_Touch * Touch the given target. Called by JobStart when the -t flag was * given. Prints messages unless told to be silent. * * Side Effects: * The data modification of the file is changed. In addition, if the * file did not exist, it is created. */ void Job_Touch(GNode *gn, Boolean silent) { int streamID; /* ID of stream opened to do the touch */ struct utimbuf times; /* Times for utime() call */ if (gn->type & (OP_JOIN | OP_USE | OP_EXEC | OP_OPTIONAL)) { /* * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" * targets and, as such, shouldn't really be created. */ return; } if (!silent) { fprintf(stdout, "touch %s\n", gn->name); fflush(stdout); } if (noExecute) { return; } if (gn->type & OP_ARCHV) { Arch_Touch(gn); } else if (gn->type & OP_LIB) { Arch_TouchLib(gn); } else { char *file = gn->path ? gn->path : gn->name; times.actime = times.modtime = now; if (utime(file, ×) < 0) { streamID = open(file, O_RDWR | O_CREAT, 0666); if (streamID >= 0) { char c; /* * Read and write a byte to the file to change * the modification time, then close the file. */ if (read(streamID, &c, 1) == 1) { lseek(streamID, (off_t)0, SEEK_SET); write(streamID, &c, 1); } close(streamID); } else { fprintf(stdout, "*** couldn't touch %s: %s", file, strerror(errno)); fflush(stdout); } } } } /** * Job_CheckCommands * Make sure the given node has all the commands it needs. * * Results: * TRUE if the commands list is/was ok. * * Side Effects: * The node will have commands from the .DEFAULT rule added to it * if it needs them. */ Boolean Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) { if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) && (gn->type & OP_LIB) == 0) { /* * No commands. Look for .DEFAULT rule from which we might infer * commands. */ if (DEFAULT != NULL && !Lst_IsEmpty(&DEFAULT->commands)) { /* * Make only looks for a .DEFAULT if the node was * never the target of an operator, so that's what we * do too. If a .DEFAULT was given, we substitute its * commands for gn's commands and set the IMPSRC * variable to be the target's name The DEFAULT node * acts like a transformation rule, in that gn also * inherits any attributes or sources attached to * .DEFAULT itself. */ Make_HandleUse(DEFAULT, gn); Var_Set(IMPSRC, Var_Value(TARGET, gn), gn); } else if (Dir_MTime(gn) == 0) { /* * The node wasn't the target of an operator we have * no .DEFAULT rule to go on and the target doesn't * already exist. There's nothing more we can do for * this branch. If the -k flag wasn't given, we stop * in our tracks, otherwise we just don't update * this node's parents so they never get examined. */ static const char msg[] = "make: don't know how to make"; if (gn->type & OP_OPTIONAL) { fprintf(stdout, "%s %s(ignored)\n", msg, gn->name); fflush(stdout); } else if (keepgoing) { fprintf(stdout, "%s %s(continuing)\n", msg, gn->name); fflush(stdout); return (FALSE); } else { #ifndef WITHOUT_OLD_JOKE if (strcmp(gn->name,"love") == 0) (*abortProc)("Not war."); else #endif (*abortProc)("%s %s. Stop", msg, gn->name); return (FALSE); } } } return (TRUE); } /** * JobExec * Execute the shell for the given job. Called from JobStart and * JobRestart. * * Side Effects: * A shell is executed, outputs is altered and the Job structure added * to the job table. */ static void JobExec(Job *job, char **argv) { ProcStuff ps; if (DEBUG(JOB)) { int i; DEBUGF(JOB, ("Running %s\n", job->node->name)); DEBUGF(JOB, ("\tCommand: ")); for (i = 0; argv[i] != NULL; i++) { DEBUGF(JOB, ("%s ", argv[i])); } DEBUGF(JOB, ("\n")); } /* * Some jobs produce no output and it's disconcerting to have * no feedback of their running (since they produce no output, the * banner with their name in it never appears). This is an attempt to * provide that feedback, even if nothing follows it. */ if (lastNode != job->node && (job->flags & JOB_FIRST) && !(job->flags & JOB_SILENT)) { MESSAGE(stdout, job->node); lastNode = job->node; } ps.in = FILENO(job->cmdFILE); if (usePipes) { /* * Set up the child's output to be routed through the * pipe we've created for it. */ ps.out = job->outPipe; } else { /* * We're capturing output in a file, so we duplicate * the descriptor to the temporary file into the * standard output. */ ps.out = job->outFd; } ps.err = STDERR_FILENO; ps.merge_errors = 1; ps.pgroup = 1; ps.searchpath = 0; ps.argv = argv; ps.argv_free = 0; /* * Fork. Warning since we are doing vfork() instead of fork(), * do not allocate memory in the child process! */ if ((ps.child_pid = vfork()) == -1) { Punt("Cannot fork"); } else if (ps.child_pid == 0) { /* * Child */ if (fifoFd >= 0) close(fifoFd); Proc_Exec(&ps); /* NOTREACHED */ } /* * Parent */ job->pid = ps.child_pid; if (usePipes && (job->flags & JOB_FIRST)) { /* * The first time a job is run for a node, we set the * current position in the buffer to the beginning and * mark another stream to watch in the outputs mask. */ #ifdef USE_KQUEUE struct kevent kev[2]; #endif job->curPos = 0; #if defined(USE_KQUEUE) EV_SET(&kev[0], job->inPipe, EVFILT_READ, EV_ADD, 0, 0, job); EV_SET(&kev[1], job->pid, EVFILT_PROC, EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, NULL); if (kevent(kqfd, kev, 2, NULL, 0, NULL) != 0) { /* * kevent() will fail if the job is already * finished */ if (errno != EINTR && errno != EBADF && errno != ESRCH) Punt("kevent: %s", strerror(errno)); } #else FD_SET(job->inPipe, &outputs); #endif /* USE_KQUEUE */ } if (job->cmdFILE != NULL && job->cmdFILE != stdout) { fclose(job->cmdFILE); job->cmdFILE = NULL; } /* * Now the job is actually running, add it to the table. */ nJobs += 1; TAILQ_INSERT_TAIL(&jobs, job, link); if (nJobs == maxJobs) { jobFull = TRUE; } } /** * JobMakeArgv * Create the argv needed to execute the shell for a given job. */ static void JobMakeArgv(Job *job, char **argv) { int argc; static char args[10]; /* For merged arguments */ argv[0] = commandShell->name; argc = 1; if ((commandShell->exit && *commandShell->exit != '-') || (commandShell->echo && *commandShell->echo != '-')) { /* * At least one of the flags doesn't have a minus before it, so * merge them together. Have to do this because the *(&(@*#*&#$# * Bourne shell thinks its second argument is a file to source. * Grrrr. Note the ten-character limitation on the combined * arguments. */ sprintf(args, "-%s%s", (job->flags & JOB_IGNERR) ? "" : commandShell->exit ? commandShell->exit : "", (job->flags & JOB_SILENT) ? "" : commandShell->echo ? commandShell->echo : ""); if (args[1]) { argv[argc] = args; argc++; } } else { if (!(job->flags & JOB_IGNERR) && commandShell->exit) { argv[argc] = commandShell->exit; argc++; } if (!(job->flags & JOB_SILENT) && commandShell->echo) { argv[argc] = commandShell->echo; argc++; } } argv[argc] = NULL; } /** * JobRestart * Restart a job that stopped for some reason. The job must be neither * on the jobs nor on the stoppedJobs list. * * Side Effects: * jobFull will be set if the job couldn't be run. */ static void JobRestart(Job *job) { if (job->flags & JOB_RESTART) { /* * Set up the control arguments to the shell. This is based on * the flags set earlier for this job. If the JOB_IGNERR flag * is clear, the 'exit' flag of the commandShell is used to * cause it to exit upon receiving an error. If the JOB_SILENT * flag is clear, the 'echo' flag of the commandShell is used * to get it to start echoing as soon as it starts * processing commands. */ char *argv[4]; JobMakeArgv(job, argv); DEBUGF(JOB, ("Restarting %s...", job->node->name)); if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL)) { /* * Not allowed to run -- put it back on the hold * queue and mark the table full */ DEBUGF(JOB, ("holding\n")); TAILQ_INSERT_HEAD(&stoppedJobs, job, link); jobFull = TRUE; DEBUGF(JOB, ("Job queue is full.\n")); return; } else { /* * Job may be run locally. */ DEBUGF(JOB, ("running locally\n")); } JobExec(job, argv); } else { /* * The job has stopped and needs to be restarted. * Why it stopped, we don't know... */ DEBUGF(JOB, ("Resuming %s...", job->node->name)); if ((nJobs < maxJobs || ((job->flags & JOB_SPECIAL) && maxJobs == 0)) && nJobs != maxJobs) { /* * If we haven't reached the concurrency limit already * (or the job must be run and maxJobs is 0), it's ok * to resume it. */ Boolean error; int status; error = (KILL(job->pid, SIGCONT) != 0); if (!error) { /* * Make sure the user knows we've continued * the beast and actually put the thing in the * job table. */ job->flags |= JOB_CONTINUING; status = 0; W_SETTERMSIG(&status, SIGCONT); JobFinish(job, &status); job->flags &= ~(JOB_RESUME|JOB_CONTINUING); DEBUGF(JOB, ("done\n")); } else { Error("couldn't resume %s: %s", job->node->name, strerror(errno)); status = 0; W_SETEXITSTATUS(&status, 1); JobFinish(job, &status); } } else { /* * Job cannot be restarted. Mark the table as full and * place the job back on the list of stopped jobs. */ DEBUGF(JOB, ("table full\n")); TAILQ_INSERT_HEAD(&stoppedJobs, job, link); jobFull = TRUE; DEBUGF(JOB, ("Job queue is full.\n")); } } } /** * JobStart * Start a target-creation process going for the target described * by the graph node gn. * * Results: * JOB_ERROR if there was an error in the commands, JOB_FINISHED * if there isn't actually anything left to do for the job and * JOB_RUNNING if the job has been started. * * Side Effects: * A new Job node is created and added to the list of running * jobs. PMake is forked and a child shell created. */ static int JobStart(GNode *gn, int flags, Job *previous) { Job *job; /* new job descriptor */ char *argv[4]; /* Argument vector to shell */ Boolean cmdsOK; /* true if the nodes commands were all right */ Boolean noExec; /* Set true if we decide not to run the job */ int tfd; /* File descriptor for temp file */ LstNode *ln; char tfile[PATH_MAX]; const char *tdir; if (interrupted) { JobPassSig(interrupted); return (JOB_ERROR); } if (previous != NULL) { previous->flags &= ~(JOB_FIRST | JOB_IGNERR | JOB_SILENT); job = previous; } else { job = emalloc(sizeof(Job)); flags |= JOB_FIRST; } job->node = gn; job->tailCmds = NULL; /* * Set the initial value of the flags for this job based on the global * ones and the node's attributes... Any flags supplied by the caller * are also added to the field. */ job->flags = 0; if (Targ_Ignore(gn)) { job->flags |= JOB_IGNERR; } if (Targ_Silent(gn)) { job->flags |= JOB_SILENT; } job->flags |= flags; /* * Check the commands now so any attributes from .DEFAULT have a chance * to migrate to the node. */ if (!compatMake && (job->flags & JOB_FIRST)) { cmdsOK = Job_CheckCommands(gn, Error); } else { cmdsOK = TRUE; } if ((tdir = getenv("TMPDIR")) == NULL) tdir = _PATH_TMP; /* * If the -n flag wasn't given, we open up OUR (not the child's) * temporary file to stuff commands in it. The thing is rd/wr so we * don't need to reopen it to feed it to the shell. If the -n flag * *was* given, we just set the file to be stdout. Cute, huh? */ if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) { /* * We're serious here, but if the commands were bogus, we're * also dead... */ if (!cmdsOK) { DieHorribly(); } snprintf(tfile, sizeof(tfile), "%s/%s", tdir, TMPPAT); if ((tfd = mkstemp(tfile)) == -1) Punt("Cannot create temp file: %s", strerror(errno)); job->cmdFILE = fdopen(tfd, "w+"); eunlink(tfile); if (job->cmdFILE == NULL) { close(tfd); Punt("Could not open %s", tfile); } fcntl(FILENO(job->cmdFILE), F_SETFD, 1); /* * Send the commands to the command file, flush all its * buffers then rewind and remove the thing. */ noExec = FALSE; /* * Used to be backwards; replace when start doing multiple * commands per shell. */ if (compatMake) { /* * Be compatible: If this is the first time for this * node, verify its commands are ok and open the * commands list for sequential access by later * invocations of JobStart. Once that is done, we take * the next command off the list and print it to the * command file. If the command was an ellipsis, note * that there's nothing more to execute. */ if (job->flags & JOB_FIRST) gn->compat_command = Lst_First(&gn->commands); else gn->compat_command = Lst_Succ(gn->compat_command); if (gn->compat_command == NULL || JobPrintCommand(gn->compat_command, job)) noExec = TRUE; if (noExec && !(job->flags & JOB_FIRST)) { /* * If we're not going to execute anything, the * job is done and we need to close down the * various file descriptors we've opened for * output, then call JobDoOutput to catch the * final characters or send the file to the * screen... Note that the i/o streams are only * open if this isn't the first job. Note also * that this could not be done in * Job_CatchChildren b/c it wasn't clear if * there were more commands to execute or not... */ JobClose(job); } } else { /* * We can do all the commands at once. hooray for sanity */ numCommands = 0; LST_FOREACH(ln, &gn->commands) { if (JobPrintCommand(ln, job)) break; } /* * If we didn't print out any commands to the shell * script, there's not much point in executing the * shell, is there? */ if (numCommands == 0) { noExec = TRUE; } } } else if (noExecute) { /* * Not executing anything -- just print all the commands to * stdout in one fell swoop. This will still set up * job->tailCmds correctly. */ if (lastNode != gn) { MESSAGE(stdout, gn); lastNode = gn; } job->cmdFILE = stdout; /* * Only print the commands if they're ok, but don't die if * they're not -- just let the user know they're bad and keep * going. It doesn't do any harm in this case and may do * some good. */ if (cmdsOK) { LST_FOREACH(ln, &gn->commands) { if (JobPrintCommand(ln, job)) break; } } /* * Don't execute the shell, thank you. */ noExec = TRUE; } else { /* * Just touch the target and note that no shell should be * executed. Set cmdFILE to stdout to make life easier. Check * the commands, too, but don't die if they're no good -- it * does no harm to keep working up the graph. */ job->cmdFILE = stdout; Job_Touch(gn, job->flags & JOB_SILENT); noExec = TRUE; } /* * If we're not supposed to execute a shell, don't. */ if (noExec) { /* * Unlink and close the command file if we opened one */ if (job->cmdFILE != stdout) { if (job->cmdFILE != NULL) fclose(job->cmdFILE); } else { fflush(stdout); } /* * We only want to work our way up the graph if we aren't here * because the commands for the job were no good. */ if (cmdsOK) { if (aborting == 0) { for (ln = job->tailCmds; ln != NULL; ln = LST_NEXT(ln)) { Lst_AtEnd(&postCommands->commands, Buf_Peel(Var_Subst(Lst_Datum(ln), job->node, FALSE))); } job->node->made = MADE; Make_Update(job->node); } free(job); return(JOB_FINISHED); } else { free(job); return(JOB_ERROR); } } else { fflush(job->cmdFILE); } /* * Set up the control arguments to the shell. This is based on the flags * set earlier for this job. */ JobMakeArgv(job, argv); /* * If we're using pipes to catch output, create the pipe by which we'll * get the shell's output. If we're using files, print out that we're * starting a job and then set up its temporary-file name. */ if (!compatMake || (job->flags & JOB_FIRST)) { if (usePipes) { int fd[2]; if (pipe(fd) == -1) Punt("Cannot create pipe: %s", strerror(errno)); job->inPipe = fd[0]; job->outPipe = fd[1]; fcntl(job->inPipe, F_SETFD, 1); fcntl(job->outPipe, F_SETFD, 1); } else { fprintf(stdout, "Remaking `%s'\n", gn->name); fflush(stdout); snprintf(job->outFile, sizeof(job->outFile), "%s/%s", tdir, TMPPAT); if ((job->outFd = mkstemp(job->outFile)) == -1) Punt("cannot create temp file: %s", strerror(errno)); fcntl(job->outFd, F_SETFD, 1); } } if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL) && maxJobs != 0) { /* * We've hit the limit of concurrency, so put the job on hold * until some other job finishes. Note that the special jobs * (.BEGIN, .INTERRUPT and .END) may be run even when the * limit has been reached (e.g. when maxJobs == 0). */ jobFull = TRUE; DEBUGF(JOB, ("Can only run job locally.\n")); job->flags |= JOB_RESTART; TAILQ_INSERT_TAIL(&stoppedJobs, job, link); } else { if (nJobs >= maxJobs) { /* * If we're running this job as a special case * (see above), at least say the table is full. */ jobFull = TRUE; DEBUGF(JOB, ("Local job queue is full.\n")); } JobExec(job, argv); } return (JOB_RUNNING); } static char * JobOutput(Job *job, char *cp, char *endp, int msg) { char *ecp; if (commandShell->noPrint) { ecp = strstr(cp, commandShell->noPrint); while (ecp != NULL) { if (cp != ecp) { *ecp = '\0'; if (msg && job->node != lastNode) { MESSAGE(stdout, job->node); lastNode = job->node; } /* * The only way there wouldn't be a newline * after this line is if it were the last in * the buffer. However, since the non-printable * comes after it, there must be a newline, so * we don't print one. */ fprintf(stdout, "%s", cp); fflush(stdout); } cp = ecp + strlen(commandShell->noPrint); if (cp != endp) { /* * Still more to print, look again after * skipping the whitespace following the * non-printable command.... */ cp++; while (*cp == ' ' || *cp == '\t' || *cp == '\n') { cp++; } ecp = strstr(cp, commandShell->noPrint); } else { return (cp); } } } return (cp); } /** * JobDoOutput * This function is called at different times depending on * whether the user has specified that output is to be collected * via pipes or temporary files. In the former case, we are called * whenever there is something to read on the pipe. We collect more * output from the given job and store it in the job's outBuf. If * this makes up a line, we print it tagged by the job's identifier, * as necessary. * If output has been collected in a temporary file, we open the * file and read it line by line, transferring it to our own * output channel until the file is empty. At which point we * remove the temporary file. * In both cases, however, we keep our figurative eye out for the * 'noPrint' line for the shell from which the output came. If * we recognize a line, we don't print it. If the command is not * alone on the line (the character after it is not \0 or \n), we * do print whatever follows it. * * Side Effects: * curPos may be shifted as may the contents of outBuf. */ static void JobDoOutput(Job *job, Boolean finish) { Boolean gotNL = FALSE; /* true if got a newline */ Boolean fbuf; /* true if our buffer filled up */ int nr; /* number of bytes read */ int i; /* auxiliary index into outBuf */ int max; /* limit for i (end of current data) */ int nRead; /* (Temporary) number of bytes read */ FILE *oFILE; /* Stream pointer to shell's output file */ char inLine[132]; if (usePipes) { /* * Read as many bytes as will fit in the buffer. */ end_loop: gotNL = FALSE; fbuf = FALSE; nRead = read(job->inPipe, &job->outBuf[job->curPos], JOB_BUFSIZE - job->curPos); /* * Check for interrupt here too, because the above read may * block when the child process is stopped. In this case the * interrupt will unblock it (we don't use SA_RESTART). */ if (interrupted) JobPassSig(interrupted); if (nRead < 0) { DEBUGF(JOB, ("JobDoOutput(piperead)")); nr = 0; } else { nr = nRead; } /* * If we hit the end-of-file (the job is dead), we must flush * its remaining output, so pretend we read a newline if * there's any output remaining in the buffer. * Also clear the 'finish' flag so we stop looping. */ if (nr == 0 && job->curPos != 0) { job->outBuf[job->curPos] = '\n'; nr = 1; finish = FALSE; } else if (nr == 0) { finish = FALSE; } /* * Look for the last newline in the bytes we just got. If there * is one, break out of the loop with 'i' as its index and * gotNL set TRUE. */ max = job->curPos + nr; for (i = job->curPos + nr - 1; i >= job->curPos; i--) { if (job->outBuf[i] == '\n') { gotNL = TRUE; break; } else if (job->outBuf[i] == '\0') { /* * Why? */ job->outBuf[i] = ' '; } } if (!gotNL) { job->curPos += nr; if (job->curPos == JOB_BUFSIZE) { /* * If we've run out of buffer space, we have * no choice but to print the stuff. sigh. */ fbuf = TRUE; i = job->curPos; } } if (gotNL || fbuf) { /* * Need to send the output to the screen. Null terminate * it first, overwriting the newline character if there * was one. So long as the line isn't one we should * filter (according to the shell description), we print * the line, preceded by a target banner if this target * isn't the same as the one for which we last printed * something. The rest of the data in the buffer are * then shifted down to the start of the buffer and * curPos is set accordingly. */ job->outBuf[i] = '\0'; if (i >= job->curPos) { char *cp; cp = JobOutput(job, job->outBuf, &job->outBuf[i], FALSE); /* * There's still more in that buffer. This time, * though, we know there's no newline at the * end, so we add one of our own free will. */ if (*cp != '\0') { if (job->node != lastNode) { MESSAGE(stdout, job->node); lastNode = job->node; } fprintf(stdout, "%s%s", cp, gotNL ? "\n" : ""); fflush(stdout); } } if (i < max - 1) { /* shift the remaining characters down */ memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1)); job->curPos = max - (i + 1); } else { /* * We have written everything out, so we just * start over from the start of the buffer. * No copying. No nothing. */ job->curPos = 0; } } if (finish) { /* * If the finish flag is true, we must loop until we hit * end-of-file on the pipe. This is guaranteed to happen * eventually since the other end of the pipe is now * closed (we closed it explicitly and the child has * exited). When we do get an EOF, finish will be set * FALSE and we'll fall through and out. */ goto end_loop; } } else { /* * We've been called to retrieve the output of the job from the * temporary file where it's been squirreled away. This consists * of opening the file, reading the output line by line, being * sure not to print the noPrint line for the shell we used, * then close and remove the temporary file. Very simple. * * Change to read in blocks and do FindSubString type things * as for pipes? That would allow for "@echo -n..." */ oFILE = fopen(job->outFile, "r"); if (oFILE != NULL) { fprintf(stdout, "Results of making %s:\n", job->node->name); fflush(stdout); while (fgets(inLine, sizeof(inLine), oFILE) != NULL) { char *cp, *endp, *oendp; cp = inLine; oendp = endp = inLine + strlen(inLine); if (endp[-1] == '\n') { *--endp = '\0'; } cp = JobOutput(job, inLine, endp, FALSE); /* * There's still more in that buffer. This time, * though, we know there's no newline at the * end, so we add one of our own free will. */ fprintf(stdout, "%s", cp); fflush(stdout); if (endp != oendp) { fprintf(stdout, "\n"); fflush(stdout); } } fclose(oFILE); eunlink(job->outFile); } } } /** * Job_CatchChildren * Handle the exit of a child. Called from Make_Make. * * Side Effects: * The job descriptor is removed from the list of children. * * Notes: * We do waits, blocking or not, according to the wisdom of our * caller, until there are no more children to report. For each * job, call JobFinish to finish things off. This will take care of * putting jobs on the stoppedJobs queue. */ void Job_CatchChildren(Boolean block) { pid_t pid; /* pid of dead child */ Job *job; /* job descriptor for dead child */ int status; /* Exit/termination status */ /* * Don't even bother if we know there's no one around. */ if (nJobs == 0) { return; } for (;;) { pid = waitpid(-1, &status, (block ? 0 : WNOHANG) | WUNTRACED); if (pid <= 0) break; DEBUGF(JOB, ("Process %jd exited or stopped.\n", (intmax_t)pid)); TAILQ_FOREACH(job, &jobs, link) { if (job->pid == pid) break; } if (job == NULL) { if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGCONT)) { TAILQ_FOREACH(job, &jobs, link) { if (job->pid == pid) break; } if (job == NULL) { Error("Resumed child (%jd) " "not in table", (intmax_t)pid); continue; } TAILQ_REMOVE(&stoppedJobs, job, link); } else { Error("Child (%jd) not in table?", (intmax_t)pid); continue; } } else { TAILQ_REMOVE(&jobs, job, link); nJobs -= 1; if (fifoFd >= 0 && maxJobs > 1) { write(fifoFd, "+", 1); maxJobs--; if (nJobs >= maxJobs) jobFull = TRUE; else jobFull = FALSE; } else { DEBUGF(JOB, ("Job queue is no longer full.\n")); jobFull = FALSE; } } JobFinish(job, &status); } if (interrupted) JobPassSig(interrupted); } /** * Job_CatchOutput * Catch the output from our children, if we're using * pipes do so. Otherwise just block time until we get a * signal(most likely a SIGCHLD) since there's no point in * just spinning when there's nothing to do and the reaping * of a child can wait for a while. * * Side Effects: * Output is read from pipes if we're piping. * ----------------------------------------------------------------------- */ void #ifdef USE_KQUEUE Job_CatchOutput(int flag __unused) #else Job_CatchOutput(int flag) #endif { int nfds; #ifdef USE_KQUEUE #define KEV_SIZE 4 struct kevent kev[KEV_SIZE]; int i; #else struct timeval timeout; fd_set readfds; Job *job; #endif fflush(stdout); if (usePipes) { #ifdef USE_KQUEUE if ((nfds = kevent(kqfd, NULL, 0, kev, KEV_SIZE, NULL)) == -1) { if (errno != EINTR) Punt("kevent: %s", strerror(errno)); if (interrupted) JobPassSig(interrupted); } else { for (i = 0; i < nfds; i++) { if (kev[i].flags & EV_ERROR) { warnc(kev[i].data, "kevent"); continue; } switch (kev[i].filter) { case EVFILT_READ: JobDoOutput(kev[i].udata, FALSE); break; case EVFILT_PROC: /* * Just wake up and let * Job_CatchChildren() collect the * terminated job. */ break; } } } #else readfds = outputs; timeout.tv_sec = SEL_SEC; timeout.tv_usec = SEL_USEC; if (flag && jobFull && fifoFd >= 0) FD_SET(fifoFd, &readfds); nfds = select(FD_SETSIZE, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timeout); if (nfds <= 0) { if (interrupted) JobPassSig(interrupted); return; } if (fifoFd >= 0 && FD_ISSET(fifoFd, &readfds)) { if (--nfds <= 0) return; } job = TAILQ_FIRST(&jobs); while (nfds != 0 && job != NULL) { if (FD_ISSET(job->inPipe, &readfds)) { JobDoOutput(job, FALSE); nfds--; } job = TAILQ_NEXT(job, link); } #endif /* !USE_KQUEUE */ } } /** * Job_Make * Start the creation of a target. Basically a front-end for * JobStart used by the Make module. * * Side Effects: * Another job is started. */ void Job_Make(GNode *gn) { JobStart(gn, 0, NULL); } void Job_SetPrefix(void) { if (targPrefix) { free(targPrefix); } else if (!Var_Exists(MAKE_JOB_PREFIX, VAR_GLOBAL)) { Var_SetGlobal(MAKE_JOB_PREFIX, "---"); } targPrefix = Var_Subst("${" MAKE_JOB_PREFIX "}", VAR_GLOBAL, 0)->buf; } /** * Job_Init * Initialize the process module, given a maximum number of jobs. * * Side Effects: * lists and counters are initialized */ void Job_Init(int maxproc) { GNode *begin; /* node for commands to do at the very start */ const char *env; struct sigaction sa; fifoFd = -1; env = getenv("MAKE_JOBS_FIFO"); if (env == NULL && maxproc > 1) { /* * We did not find the environment variable so we are the * leader. Create the fifo, open it, write one char per * allowed job into the pipe. */ fifoFd = mkfifotemp(fifoName); if (fifoFd < 0) { env = NULL; } else { fifoMaster = 1; fcntl(fifoFd, F_SETFL, O_NONBLOCK); env = fifoName; setenv("MAKE_JOBS_FIFO", env, 1); while (maxproc-- > 0) { write(fifoFd, "+", 1); } /* The master make does not get a magic token */ jobFull = TRUE; maxJobs = 0; } } else if (env != NULL) { /* * We had the environment variable so we are a slave. * Open fifo and give ourselves a magic token which represents * the token our parent make has grabbed to start his make * process. Otherwise the sub-makes would gobble up tokens and * the proper number of tokens to specify to -j would depend * on the depth of the tree and the order of execution. */ fifoFd = open(env, O_RDWR, 0); if (fifoFd >= 0) { fcntl(fifoFd, F_SETFL, O_NONBLOCK); maxJobs = 1; jobFull = FALSE; } } if (fifoFd < 0) { maxJobs = maxproc; jobFull = FALSE; } else { } nJobs = 0; aborting = 0; makeErrors = 0; lastNode = NULL; if ((maxJobs == 1 && fifoFd < 0) || !beVerbose || is_posix || beQuiet) { /* * If only one job can run at a time, there's no need for a * banner, no is there? */ targFmt = ""; } else { targFmt = TARG_FMT; } /* * Catch the four signals that POSIX specifies if they aren't ignored. * JobCatchSignal will just set global variables and hope someone * else is going to handle the interrupt. */ sa.sa_handler = JobCatchSig; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (signal(SIGINT, SIG_IGN) != SIG_IGN) { sigaction(SIGINT, &sa, NULL); } if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { sigaction(SIGHUP, &sa, NULL); } if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { sigaction(SIGQUIT, &sa, NULL); } if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { sigaction(SIGTERM, &sa, NULL); } /* * There are additional signals that need to be caught and passed if * either the export system wants to be told directly of signals or if * we're giving each job its own process group (since then it won't get * signals from the terminal driver as we own the terminal) */ #if defined(USE_PGRP) if (signal(SIGTSTP, SIG_IGN) != SIG_IGN) { sigaction(SIGTSTP, &sa, NULL); } if (signal(SIGTTOU, SIG_IGN) != SIG_IGN) { sigaction(SIGTTOU, &sa, NULL); } if (signal(SIGTTIN, SIG_IGN) != SIG_IGN) { sigaction(SIGTTIN, &sa, NULL); } if (signal(SIGWINCH, SIG_IGN) != SIG_IGN) { sigaction(SIGWINCH, &sa, NULL); } #endif #ifdef USE_KQUEUE if ((kqfd = kqueue()) == -1) { Punt("kqueue: %s", strerror(errno)); } #endif begin = Targ_FindNode(".BEGIN", TARG_NOCREATE); if (begin != NULL) { JobStart(begin, JOB_SPECIAL, (Job *)NULL); while (nJobs) { Job_CatchOutput(0); Job_CatchChildren(!usePipes); } } postCommands = Targ_FindNode(".END", TARG_CREATE); } /** * Job_Full * See if the job table is full. It is considered full if it is OR * if we are in the process of aborting OR if we have * reached/exceeded our local quota. This prevents any more jobs * from starting up. * * Results: * TRUE if the job table is full, FALSE otherwise */ Boolean Job_Full(void) { char c; int i; if (aborting) return (aborting); if (fifoFd >= 0 && jobFull) { i = read(fifoFd, &c, 1); if (i > 0) { maxJobs++; jobFull = FALSE; } } return (jobFull); } /** * Job_Empty * See if the job table is empty. Because the local concurrency may * be set to 0, it is possible for the job table to become empty, * while the list of stoppedJobs remains non-empty. In such a case, * we want to restart as many jobs as we can. * * Results: * TRUE if it is. FALSE if it ain't. */ Boolean Job_Empty(void) { if (nJobs == 0) { if (!TAILQ_EMPTY(&stoppedJobs) && !aborting) { /* * The job table is obviously not full if it has no * jobs in it...Try and restart the stopped jobs. */ jobFull = FALSE; JobRestartJobs(); return (FALSE); } else { return (TRUE); } } else { return (FALSE); } } /** * JobInterrupt * Handle the receipt of an interrupt. * * Side Effects: * All children are killed. Another job will be started if the * .INTERRUPT target was given. */ static void JobInterrupt(int runINTERRUPT, int signo) { Job *job; /* job descriptor in that element */ GNode *interrupt; /* the node describing the .INTERRUPT target */ aborting = ABORT_INTERRUPT; TAILQ_FOREACH(job, &jobs, link) { if (!Targ_Precious(job->node)) { char *file = (job->node->path == NULL ? job->node->name : job->node->path); if (!noExecute && eunlink(file) != -1) { Error("*** %s removed", file); } } if (job->pid) { DEBUGF(JOB, ("JobInterrupt passing signal to child " "%jd.\n", (intmax_t)job->pid)); KILL(job->pid, signo); } } if (runINTERRUPT && !touchFlag) { /* * clear the interrupted flag because we would get an * infinite loop otherwise. */ interrupted = 0; interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); if (interrupt != NULL) { ignoreErrors = FALSE; JobStart(interrupt, JOB_IGNDOTS, (Job *)NULL); while (nJobs) { Job_CatchOutput(0); Job_CatchChildren(!usePipes); } } } if (fifoMaster) unlink(fifoName); } /** * Job_Finish * Do final processing such as the running of the commands * attached to the .END target. * * Results: * None. */ void Job_Finish(void) { if (postCommands != NULL && !Lst_IsEmpty(&postCommands->commands)) { if (makeErrors) { Error("Errors reported so .END ignored"); } else { JobStart(postCommands, JOB_SPECIAL | JOB_IGNDOTS, NULL); while (nJobs) { Job_CatchOutput(0); Job_CatchChildren(!usePipes); } } } if (fifoFd >= 0) { close(fifoFd); fifoFd = -1; if (fifoMaster) unlink(fifoName); } } /** * Job_Wait * Waits for all running jobs to finish and returns. Sets 'aborting' * to ABORT_WAIT to prevent other jobs from starting. * * Side Effects: * Currently running jobs finish. */ void Job_Wait(void) { aborting = ABORT_WAIT; while (nJobs != 0) { Job_CatchOutput(0); Job_CatchChildren(!usePipes); } aborting = 0; } /** * Job_AbortAll * Abort all currently running jobs without handling output or anything. * This function is to be called only in the event of a major * error. Most definitely NOT to be called from JobInterrupt. * * Side Effects: * All children are killed, not just the firstborn */ void Job_AbortAll(void) { Job *job; /* the job descriptor in that element */ int foo; aborting = ABORT_ERROR; if (nJobs) { TAILQ_FOREACH(job, &jobs, link) { /* * kill the child process with increasingly drastic * signals to make darn sure it's dead. */ KILL(job->pid, SIGINT); KILL(job->pid, SIGKILL); } } /* * Catch as many children as want to report in at first, then give up */ while (waitpid(-1, &foo, WNOHANG) > 0) ; } /** * JobRestartJobs * Tries to restart stopped jobs if there are slots available. * Note that this tries to restart them regardless of pending errors. * It's not good to leave stopped jobs lying around! * * Side Effects: * Resumes(and possibly migrates) jobs. */ static void JobRestartJobs(void) { Job *job; while (!jobFull && (job = TAILQ_FIRST(&stoppedJobs)) != NULL) { DEBUGF(JOB, ("Job queue is not full. " "Restarting a stopped job.\n")); TAILQ_REMOVE(&stoppedJobs, job, link); JobRestart(job); } } /** * Cmd_Exec * Execute the command in cmd, and return the output of that command * in a string. * * Results: * A string containing the output of the command, or the empty string * If error is not NULL, it contains the reason for the command failure * Any output sent to stderr in the child process is passed to stderr, * and not captured in the string. * * Side Effects: * The string must be freed by the caller. */ Buffer * Cmd_Exec(const char *cmd, const char **error) { int fds[2]; /* Pipe streams */ int status; /* command exit status */ Buffer *buf; /* buffer to store the result */ ssize_t rcnt; ProcStuff ps; *error = NULL; buf = Buf_Init(0); /* * Open a pipe for fetching its output */ if (pipe(fds) == -1) { *error = "Couldn't create pipe for \"%s\""; return (buf); } /* Set close-on-exec on read side of pipe. */ fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC); ps.in = STDIN_FILENO; ps.out = fds[1]; ps.err = STDERR_FILENO; ps.merge_errors = 0; ps.pgroup = 0; ps.searchpath = 0; /* Set up arguments for shell */ ps.argv = emalloc(4 * sizeof(char *)); ps.argv[0] = strdup(commandShell->name); ps.argv[1] = strdup("-c"); ps.argv[2] = strdup(cmd); ps.argv[3] = NULL; ps.argv_free = 1; /* * Fork. Warning since we are doing vfork() instead of fork(), * do not allocate memory in the child process! */ if ((ps.child_pid = vfork()) == -1) { *error = "Couldn't exec \"%s\""; return (buf); } else if (ps.child_pid == 0) { /* * Child */ Proc_Exec(&ps); /* NOTREACHED */ } free(ps.argv[2]); free(ps.argv[1]); free(ps.argv[0]); free(ps.argv); close(fds[1]); /* No need for the writing half of the pipe. */ do { char result[BUFSIZ]; rcnt = read(fds[0], result, sizeof(result)); if (rcnt != -1) Buf_AddBytes(buf, (size_t)rcnt, (Byte *)result); } while (rcnt > 0 || (rcnt == -1 && errno == EINTR)); if (rcnt == -1) *error = "Error reading shell's output for \"%s\""; /* * Close the input side of the pipe. */ close(fds[0]); status = ProcWait(&ps); if (status) *error = "\"%s\" returned non-zero status"; Buf_StripNewlines(buf); return (buf); } /* * Interrupt handler - set flag and defer handling to the main code */ static void CompatCatchSig(int signo) { interrupted = signo; } /*- *----------------------------------------------------------------------- * CompatInterrupt -- * Interrupt the creation of the current target and remove it if * it ain't precious. * * Results: * None. * * Side Effects: * The target is removed and the process exits. If .INTERRUPT exists, * its commands are run first WITH INTERRUPTS IGNORED.. * *----------------------------------------------------------------------- */ static void CompatInterrupt(int signo) { GNode *gn; sigset_t nmask, omask; LstNode *ln; sigemptyset(&nmask); sigaddset(&nmask, SIGINT); sigaddset(&nmask, SIGTERM); sigaddset(&nmask, SIGHUP); sigaddset(&nmask, SIGQUIT); sigprocmask(SIG_SETMASK, &nmask, &omask); /* prevent recursion in evaluation of .INTERRUPT */ interrupted = 0; if (curTarg != NULL && !Targ_Precious(curTarg)) { const char *file = Var_Value(TARGET, curTarg); if (!noExecute && eunlink(file) != -1) { printf("*** %s removed\n", file); } } /* * Run .INTERRUPT only if hit with interrupt signal */ if (signo == SIGINT) { gn = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); if (gn != NULL) { LST_FOREACH(ln, &gn->commands) { if (Compat_RunCommand(ln, gn)) break; } } } sigprocmask(SIG_SETMASK, &omask, NULL); if (signo == SIGQUIT) exit(signo); signal(signo, SIG_DFL); kill(getpid(), signo); } /** * shellneed * * Results: * Returns NULL if a specified line must be executed by the shell, * and an argument vector if it can be run via execvp(). * * Side Effects: * Uses brk_string so destroys the contents of argv. */ static char ** shellneed(ArgArray *aa, char *cmd) { char **p; int ret; if (commandShell->meta == NULL || commandShell->builtins.argc <= 1) /* use shell */ return (NULL); if (strpbrk(cmd, commandShell->meta) != NULL) return (NULL); /* * Break the command into words to form an argument * vector we can execute. */ brk_string(aa, cmd, TRUE); for (p = commandShell->builtins.argv + 1; *p != 0; p++) { if ((ret = strcmp(aa->argv[1], *p)) == 0) { /* found - use shell */ ArgArray_Done(aa); return (NULL); } if (ret < 0) { /* not found */ break; } } return (aa->argv + 1); } /** * Execute the next command for a target. If the command returns an * error, the node's made field is set to ERROR and creation stops. * The node from which the command came is also given. This is used * to execute the commands in compat mode and when executing commands * with the '+' flag in non-compat mode. In these modes each command * line should be executed by its own shell. We do some optimisation here: * if the shell description defines both a string of meta characters and * a list of builtins and the command line neither contains a meta character * nor starts with one of the builtins then we execute the command directly * without invoking a shell. * * Results: * 0 if the command succeeded, 1 if an error occurred. * * Side Effects: * The node's 'made' field may be set to ERROR. */ static int Compat_RunCommand(LstNode *cmdNode, GNode *gn) { ArgArray aa; char *cmd; /* Expanded command */ Boolean silent; /* Don't print command */ Boolean doit; /* Execute even in -n */ Boolean errCheck; /* Check errors */ int reason; /* Reason for child's death */ int status; /* Description of child's death */ char **av; /* Argument vector for thing to exec */ ProcStuff ps; silent = gn->type & OP_SILENT; errCheck = !(gn->type & OP_IGNORE); doit = FALSE; cmd = Buf_Peel(Var_Subst(Lst_Datum(cmdNode), gn, FALSE)); if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) { Lst_AtEnd(&ENDNode->commands, cmd); return (0); } else if (strcmp(cmd, "...") == 0) { free(cmd); gn->type |= OP_SAVE_CMDS; return (0); } Lst_Replace(cmdNode, cmd); while (*cmd == '@' || *cmd == '-' || *cmd == '+') { switch (*cmd) { case '@': silent = DEBUG(LOUD) ? FALSE : TRUE; break; case '-': errCheck = FALSE; break; case '+': doit = TRUE; break; } cmd++; } while (isspace((unsigned char)*cmd)) cmd++; /* * Ignore empty commands */ if (*cmd == '\0') { return (0); } /* * Print the command before echoing if we're not supposed to be quiet * for this one. We also print the command if -n given, but not if '+'. */ if (!silent || (noExecute && !doit)) { printf("%s\n", cmd); fflush(stdout); } /* * If we're not supposed to execute any commands, this is as far as * we go... */ if (!doit && noExecute) { return (0); } ps.in = STDIN_FILENO; ps.out = STDOUT_FILENO; ps.err = STDERR_FILENO; ps.merge_errors = 0; ps.pgroup = 0; ps.searchpath = 1; if ((av = shellneed(&aa, cmd)) == NULL) { /* * Shell meta character or shell builtin found - pass * command to shell. We give the shell the -e flag as * well as -c if it is supposed to exit when it hits an error. */ ps.argv = emalloc(4 * sizeof(char *)); ps.argv[0] = strdup(commandShell->path); ps.argv[1] = strdup(errCheck ? "-ec" : "-c"); ps.argv[2] = strdup(cmd); ps.argv[3] = NULL; ps.argv_free = 1; } else { ps.argv = av; ps.argv_free = 0; } ps.errCheck = errCheck; /* * Warning since we are doing vfork() instead of fork(), * do not allocate memory in the child process! */ if ((ps.child_pid = vfork()) == -1) { Fatal("Could not fork"); } else if (ps.child_pid == 0) { /* * Child */ Proc_Exec(&ps); /* NOTREACHED */ } else { if (ps.argv_free) { free(ps.argv[2]); free(ps.argv[1]); free(ps.argv[0]); free(ps.argv); } else { ArgArray_Done(&aa); } /* * we need to print out the command associated with this * Gnode in Targ_PrintCmd from Targ_PrintGraph when debugging * at level g2, in main(), Fatal() and DieHorribly(), * therefore do not free it when debugging. */ if (!DEBUG(GRAPH2)) { free(Lst_Datum(cmdNode)); Lst_Replace(cmdNode, NULL); } /* * The child is off and running. Now all we can do is wait... */ reason = ProcWait(&ps); if (interrupted) CompatInterrupt(interrupted); /* * Decode and report the reason child exited, then * indicate how we handled it. */ if (WIFEXITED(reason)) { status = WEXITSTATUS(reason); if (status == 0) { return (0); } else { printf("*** [%s] Error code %d", gn->name, status); } } else if (WIFSTOPPED(reason)) { status = WSTOPSIG(reason); } else { status = WTERMSIG(reason); printf("*** [%s] Signal %d", gn->name, status); } if (ps.errCheck) { gn->made = ERROR; if (keepgoing) { /* * Abort the current * target, but let * others continue. */ printf(" (continuing)\n"); } return (status); } else { /* * Continue executing * commands for this target. * If we return 0, this will * happen... */ printf(" (ignored)\n"); return (0); } } } /*- *----------------------------------------------------------------------- * Compat_Make -- * Make a target, given the parent, to abort if necessary. * * Side Effects: * If an error is detected and not being ignored, the process exits. * *----------------------------------------------------------------------- */ int Compat_Make(GNode *gn, GNode *pgn) { LstNode *ln; if (gn->type & OP_USE) { Make_HandleUse(gn, pgn); } else if (gn->made == UNMADE) { /* * First mark ourselves to be made, then apply whatever * transformations the suffix module thinks are necessary. * Once that's done, we can descend and make all our children. * If any of them has an error but the -k flag was given, our * 'make' field will be set FALSE again. This is our signal to * not attempt to do anything but abort our parent as well. */ gn->make = TRUE; gn->made = BEINGMADE; Suff_FindDeps(gn); LST_FOREACH(ln, &gn->children) Compat_Make(Lst_Datum(ln), gn); if (!gn->make) { gn->made = ABORTED; pgn->make = FALSE; return (0); } if (Lst_Member(&gn->iParents, pgn) != NULL) { Var_Set(IMPSRC, Var_Value(TARGET, gn), pgn); } /* * All the children were made ok. Now cmtime contains the * modification time of the newest child, we need to find out * if we exist and when we were modified last. The criteria for * datedness are defined by the Make_OODate function. */ DEBUGF(MAKE, ("Examining %s...", gn->name)); if (!Make_OODate(gn)) { gn->made = UPTODATE; DEBUGF(MAKE, ("up-to-date.\n")); return (0); } else { DEBUGF(MAKE, ("out-of-date.\n")); } /* * If the user is just seeing if something is out-of-date, * exit now to tell him/her "yes". */ if (queryFlag) { exit(1); } /* * We need to be re-made. We also have to make sure we've got * a $? variable. To be nice, we also define the $> variable * using Make_DoAllVar(). */ Make_DoAllVar(gn); /* * Alter our type to tell if errors should be ignored or things * should not be printed so Compat_RunCommand knows what to do. */ if (Targ_Ignore(gn)) { gn->type |= OP_IGNORE; } if (Targ_Silent(gn)) { gn->type |= OP_SILENT; } if (Job_CheckCommands(gn, Fatal)) { /* * Our commands are ok, but we still have to worry * about the -t flag... */ if (!touchFlag) { curTarg = gn; LST_FOREACH(ln, &gn->commands) { if (Compat_RunCommand(ln, gn)) break; } curTarg = NULL; } else { Job_Touch(gn, gn->type & OP_SILENT); } } else { gn->made = ERROR; } if (gn->made != ERROR) { /* * If the node was made successfully, mark it so, update * its modification time and timestamp all its parents. * Note that for .ZEROTIME targets, the timestamping * isn't done. This is to keep its state from affecting * that of its parent. */ gn->made = MADE; #ifndef RECHECK /* * We can't re-stat the thing, but we can at least take * care of rules where a target depends on a source that * actually creates the target, but only if it has * changed, e.g. * * parse.h : parse.o * * parse.o : parse.y * yacc -d parse.y * cc -c y.tab.c * mv y.tab.o parse.o * cmp -s y.tab.h parse.h || mv y.tab.h parse.h * * In this case, if the definitions produced by yacc * haven't changed from before, parse.h won't have been * updated and gn->mtime will reflect the current * modification time for parse.h. This is something of a * kludge, I admit, but it's a useful one.. * * XXX: People like to use a rule like * * FRC: * * To force things that depend on FRC to be made, so we * have to check for gn->children being empty as well... */ if (!Lst_IsEmpty(&gn->commands) || Lst_IsEmpty(&gn->children)) { gn->mtime = now; } #else /* * This is what Make does and it's actually a good * thing, as it allows rules like * * cmp -s y.tab.h parse.h || cp y.tab.h parse.h * * to function as intended. Unfortunately, thanks to * the stateless nature of NFS (and the speed of this * program), there are times when the modification time * of a file created on a remote machine will not be * modified before the stat() implied by the Dir_MTime * occurs, thus leading us to believe that the file * is unchanged, wreaking havoc with files that depend * on this one. * * I have decided it is better to make too much than to * make too little, so this stuff is commented out * unless you're sure it's ok. * -- ardeb 1/12/88 */ if (noExecute || Dir_MTime(gn) == 0) { gn->mtime = now; } if (gn->cmtime > gn->mtime) gn->mtime = gn->cmtime; DEBUGF(MAKE, ("update time: %s\n", Targ_FmtTime(gn->mtime))); #endif if (!(gn->type & OP_EXEC)) { pgn->childMade = TRUE; Make_TimeStamp(pgn, gn); } } else if (keepgoing) { pgn->make = FALSE; } else { printf("\n\nStop in %s.\n", Var_Value(".CURDIR", gn)); exit(1); } } else if (gn->made == ERROR) { /* * Already had an error when making this beastie. Tell the * parent to abort. */ pgn->make = FALSE; } else { if (Lst_Member(&gn->iParents, pgn) != NULL) { Var_Set(IMPSRC, Var_Value(TARGET, gn), pgn); } switch(gn->made) { case BEINGMADE: Error("Graph cycles through %s\n", gn->name); gn->made = ERROR; pgn->make = FALSE; break; case MADE: if ((gn->type & OP_EXEC) == 0) { pgn->childMade = TRUE; Make_TimeStamp(pgn, gn); } break; case UPTODATE: if ((gn->type & OP_EXEC) == 0) { Make_TimeStamp(pgn, gn); } break; default: break; } } return (0); } /*- * Install signal handlers for Compat_Run */ void Compat_InstallSignalHandlers(void) { if (signal(SIGINT, SIG_IGN) != SIG_IGN) { signal(SIGINT, CompatCatchSig); } if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { signal(SIGTERM, CompatCatchSig); } if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { signal(SIGHUP, CompatCatchSig); } if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { signal(SIGQUIT, CompatCatchSig); } } /*- *----------------------------------------------------------------------- * Compat_Run -- * Start making again, given a list of target nodes. * * Results: * None. * * Side Effects: * Guess what? * *----------------------------------------------------------------------- */ void Compat_Run(Lst *targs) { GNode *gn = NULL; /* Current root target */ LstNode *ln; Compat_InstallSignalHandlers(); ENDNode = Targ_FindNode(".END", TARG_CREATE); /* * If the user has defined a .BEGIN target, execute the commands * attached to it. */ if (!queryFlag) { gn = Targ_FindNode(".BEGIN", TARG_NOCREATE); if (gn != NULL) { LST_FOREACH(ln, &gn->commands) { if (Compat_RunCommand(ln, gn)) break; } if (gn->made == ERROR) { printf("\n\nStop.\n"); exit(1); } } } /* * For each entry in the list of targets to create, call Compat_Make on * it to create the thing. Compat_Make will leave the 'made' field of gn * in one of several states: * UPTODATE gn was already up-to-date * MADE gn was recreated successfully * ERROR An error occurred while gn was being created * ABORTED gn was not remade because one of its inferiors * could not be made due to errors. */ makeErrors = 0; while (!Lst_IsEmpty(targs)) { gn = Lst_DeQueue(targs); Compat_Make(gn, gn); if (gn->made == UPTODATE) { printf("`%s' is up to date.\n", gn->name); } else if (gn->made == ABORTED) { printf("`%s' not remade because of errors.\n", gn->name); makeErrors++; } else if (gn->made == ERROR) { makeErrors++; } } /* * If the user has defined a .END target, run its commands. */ if (makeErrors == 0) { LST_FOREACH(ln, &ENDNode->commands) { if (Compat_RunCommand(ln, ENDNode)) break; } } } freebsd-buildutils-10.0/src/usr.bin/make/hash_tables.c0000644000000000000000000000462410765767003017636 0ustar /* * DO NOT EDIT * $FreeBSD$ * auto-generated from FreeBSD: src/usr.bin/make/parse.c,v 1.114 2008/03/12 14:50:58 obrien Exp * DO NOT EDIT */ #include #include "hash_tables.h" /* * d=2 * n=40 * m=19 * c=2.09 * maxlen=1 * minklen=2 * maxklen=9 * minchar=97 * maxchar=119 * loop=0 * numiter=1 * seed= */ static const signed char directive_g[] = { 8, 0, 0, 5, 6, -1, 17, 15, 10, 6, -1, -1, 10, 0, 0, -1, 18, 2, 3, 0, 7, -1, -1, -1, 0, 14, -1, -1, 11, 16, -1, -1, 0, -1, 0, 0, 17, 0, -1, 1, }; static const u_char directive_T0[] = { 26, 14, 19, 35, 10, 34, 18, 27, 1, 17, 22, 37, 12, 12, 36, 21, 0, 6, 1, 25, 9, 4, 19, }; static const u_char directive_T1[] = { 25, 22, 19, 0, 2, 18, 33, 18, 30, 4, 30, 9, 21, 19, 16, 12, 35, 34, 4, 19, 9, 33, 16, }; int directive_hash(const u_char *key, size_t len) { unsigned f0, f1; const u_char *kp = key; if (len < 2 || len > 9) return -1; for (f0=f1=0; kp < key + len; ++kp) { if (*kp < 97 || *kp > 119) return -1; f0 += directive_T0[-97 + *kp]; f1 += directive_T1[-97 + *kp]; } f0 %= 40; f1 %= 40; return (directive_g[f0] + directive_g[f1]) % 19; } /* * d=2 * n=74 * m=35 * c=2.09 * maxlen=1 * minklen=4 * maxklen=13 * minchar=46 * maxchar=95 * loop=0 * numiter=4 * seed= */ static const signed char keyword_g[] = { 12, 18, 7, 25, 30, 5, -1, -1, -1, 7, -1, 0, 33, 0, 4, -1, -1, 13, 29, 0, -1, 28, -1, 28, -1, 0, -1, 27, 4, 34, -1, -1, -1, 30, 13, 10, -1, -1, 0, 10, 24, -1, -1, -1, 0, 6, 0, 0, -1, 23, -1, -1, -1, 0, -1, 23, -1, -1, 19, 4, -1, 31, 12, 16, -1, 20, 22, 9, 0, -1, -1, 9, 4, 0, }; static const u_char keyword_T0[] = { 34, 28, 50, 61, 14, 57, 48, 60, 20, 67, 60, 63, 0, 24, 28, 2, 49, 64, 18, 23, 36, 33, 40, 14, 38, 42, 71, 49, 2, 53, 53, 37, 7, 29, 24, 21, 12, 50, 59, 10, 43, 23, 0, 44, 47, 6, 46, 22, 48, 64, }; static const u_char keyword_T1[] = { 18, 67, 39, 60, 7, 70, 2, 26, 31, 18, 73, 47, 61, 17, 38, 50, 22, 52, 13, 55, 56, 32, 63, 4, 64, 55, 49, 21, 47, 67, 33, 66, 60, 73, 30, 68, 69, 32, 72, 4, 28, 49, 51, 15, 66, 68, 43, 67, 46, 56, }; int keyword_hash(const u_char *key, size_t len) { unsigned f0, f1; const u_char *kp = key; if (len < 4 || len > 13) return -1; for (f0=f1=0; *kp; ++kp) { if (*kp < 46 || *kp > 95) return -1; f0 += keyword_T0[-46 + *kp]; f1 += keyword_T1[-46 + *kp]; } f0 %= 74; f1 %= 74; return (keyword_g[f0] + keyword_g[f1]) % 35; } freebsd-buildutils-10.0/src/contrib/0000755000000000000000000000000012265500123014333 5ustar freebsd-buildutils-10.0/src/contrib/flex/0000755000000000000000000000000012265500133015272 5ustar freebsd-buildutils-10.0/src/contrib/flex/tables.h0000644000000000000000000000554212146741165016735 0ustar /* tables.h - tables serialization code * * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Vern Paxson. * * The United States Government has rights in this work pursuant * to contract no. DE-AC03-76SF00098 between the United States * Department of Energy and the University of California. * * This file is part of flex. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. */ #ifndef TABLES_H #define TABLES_H #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif /* Tables serialization API declarations. */ #include "tables_shared.h" struct yytbl_writer { FILE *out; flex_uint32_t total_written; /**< bytes written so far */ fpos_t th_ssize_pos; /**< position of th_ssize */ }; /* These are used by main.c, gen.c, etc. * tablesext - if true, create external tables * tablesfilename - filename for external tables * tablesname - name that goes in serialized data, e.g., "yytables" * tableswr - writer for external tables * tablesverify - true if tables-verify option specified * gentables - true if we should spit out the normal C tables */ extern bool tablesext, tablesverify,gentables; extern char *tablesfilename, *tablesname; extern struct yytbl_writer tableswr; int yytbl_writer_init (struct yytbl_writer *, FILE *); int yytbl_hdr_init (struct yytbl_hdr *th, const char *version_str, const char *name); int yytbl_data_init (struct yytbl_data *tbl, enum yytbl_id id); int yytbl_data_destroy (struct yytbl_data *td); int yytbl_hdr_fwrite (struct yytbl_writer *wr, const struct yytbl_hdr *th); int yytbl_data_fwrite (struct yytbl_writer *wr, struct yytbl_data *td); void yytbl_data_compress (struct yytbl_data *tbl); struct yytbl_data *mkftbl (void); #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif #endif /* vim:set expandtab cindent tabstop=4 softtabstop=4 shiftwidth=4 textwidth=0: */ freebsd-buildutils-10.0/src/contrib/flex/flexint.h0000644000000000000000000000276612146744056017143 0ustar /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined(__FreeBSD__) || \ (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ freebsd-buildutils-10.0/src/contrib/flex/FlexLexer.h0000644000000000000000000001411112146741165017351 0ustar // -*-C++-*- // FlexLexer.h -- define interfaces for lexical analyzer classes generated // by flex // Copyright (c) 1993 The Regents of the University of California. // All rights reserved. // // This code is derived from software contributed to Berkeley by // Kent Williams and Tom Epperly. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // Neither the name of the University nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR // IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE. // This file defines FlexLexer, an abstract class which specifies the // external interface provided to flex C++ lexer objects, and yyFlexLexer, // which defines a particular lexer class. // // If you want to create multiple lexer classes, you use the -P flag // to rename each yyFlexLexer to some other xxFlexLexer. You then // include in your other sources once per lexer class: // // #undef yyFlexLexer // #define yyFlexLexer xxFlexLexer // #include // // #undef yyFlexLexer // #define yyFlexLexer zzFlexLexer // #include // ... #ifndef __FLEX_LEXER_H // Never included before - need to define base class. #define __FLEX_LEXER_H #include # ifndef FLEX_STD # define FLEX_STD std:: # endif extern "C++" { struct yy_buffer_state; typedef int yy_state_type; class FlexLexer { public: virtual ~FlexLexer() { } const char* YYText() const { return yytext; } int YYLeng() const { return yyleng; } virtual void yy_switch_to_buffer( struct yy_buffer_state* new_buffer ) = 0; virtual struct yy_buffer_state* yy_create_buffer( FLEX_STD istream* s, int size ) = 0; virtual void yy_delete_buffer( struct yy_buffer_state* b ) = 0; virtual void yyrestart( FLEX_STD istream* s ) = 0; virtual int yylex() = 0; // Call yylex with new input/output sources. int yylex( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 ) { switch_streams( new_in, new_out ); return yylex(); } // Switch to new input/output streams. A nil stream pointer // indicates "keep the current one". virtual void switch_streams( FLEX_STD istream* new_in = 0, FLEX_STD ostream* new_out = 0 ) = 0; int lineno() const { return yylineno; } int debug() const { return yy_flex_debug; } void set_debug( int flag ) { yy_flex_debug = flag; } protected: char* yytext; int yyleng; int yylineno; // only maintained if you use %option yylineno int yy_flex_debug; // only has effect with -d or "%option debug" }; } #endif // FLEXLEXER_H #if defined(yyFlexLexer) || ! defined(yyFlexLexerOnce) // Either this is the first time through (yyFlexLexerOnce not defined), // or this is a repeated include to define a different flavor of // yyFlexLexer, as discussed in the flex manual. #define yyFlexLexerOnce extern "C++" { class yyFlexLexer : public FlexLexer { public: // arg_yyin and arg_yyout default to the cin and cout, but we // only make that assignment when initializing in yylex(). yyFlexLexer( FLEX_STD istream* arg_yyin = 0, FLEX_STD ostream* arg_yyout = 0 ); virtual ~yyFlexLexer(); void yy_switch_to_buffer( struct yy_buffer_state* new_buffer ); struct yy_buffer_state* yy_create_buffer( FLEX_STD istream* s, int size ); void yy_delete_buffer( struct yy_buffer_state* b ); void yyrestart( FLEX_STD istream* s ); void yypush_buffer_state( struct yy_buffer_state* new_buffer ); void yypop_buffer_state(); virtual int yylex(); virtual void switch_streams( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 ); virtual int yywrap(); protected: virtual int LexerInput( char* buf, int max_size ); virtual void LexerOutput( const char* buf, int size ); virtual void LexerError( const char* msg ); void yyunput( int c, char* buf_ptr ); int yyinput(); void yy_load_buffer_state(); void yy_init_buffer( struct yy_buffer_state* b, FLEX_STD istream* s ); void yy_flush_buffer( struct yy_buffer_state* b ); int yy_start_stack_ptr; int yy_start_stack_depth; int* yy_start_stack; void yy_push_state( int new_state ); void yy_pop_state(); int yy_top_state(); yy_state_type yy_get_previous_state(); yy_state_type yy_try_NUL_trans( yy_state_type current_state ); int yy_get_next_buffer(); FLEX_STD istream* yyin; // input source for default LexerInput FLEX_STD ostream* yyout; // output sink for default LexerOutput // yy_hold_char holds the character lost when yytext is formed. char yy_hold_char; // Number of characters read into yy_ch_buf. int yy_n_chars; // Points to current character in buffer. char* yy_c_buf_p; int yy_init; // whether we need to initialize int yy_start; // start state number // Flag which is used to allow yywrap()'s to do buffer switches // instead of setting up a fresh yyin. A bit of a hack ... int yy_did_buffer_switch_on_eof; size_t yy_buffer_stack_top; /**< index of top of stack. */ size_t yy_buffer_stack_max; /**< capacity of stack. */ struct yy_buffer_state ** yy_buffer_stack; /**< Stack as an array. */ void yyensure_buffer_stack(void); // The following are not always needed, but may be depending // on use of certain flex features (like REJECT or yymore()). yy_state_type yy_last_accepting_state; char* yy_last_accepting_cpos; yy_state_type* yy_state_buf; yy_state_type* yy_state_ptr; char* yy_full_match; int* yy_full_state; int yy_full_lp; int yy_lp; int yy_looking_for_trail_begin; int yy_more_flag; int yy_more_len; int yy_more_offset; int yy_prev_more_offset; }; } #endif // yyFlexLexer || ! yyFlexLexerOnce freebsd-buildutils-10.0/src/contrib/flex/gen.c0000644000000000000000000015457112146744056016240 0ustar /* gen - actual generation (writing) of flex scanners */ /* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */ /* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */ /* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #include "flexdef.h" #include "tables.h" /* declare functions that have forward references */ void gen_next_state PROTO ((int)); void genecs PROTO ((void)); void indent_put2s PROTO ((const char *, const char *)); void indent_puts PROTO ((const char *)); static int indent_level = 0; /* each level is 8 spaces */ #define indent_up() (++indent_level) #define indent_down() (--indent_level) #define set_indent(indent_val) indent_level = indent_val /* Almost everything is done in terms of arrays starting at 1, so provide * a null entry for the zero element of all C arrays. (The exception * to this is that the fast table representation generally uses the * 0 elements of its arrays, too.) */ static const char *get_int16_decl (void) { return (gentables) ? "static yyconst flex_int16_t %s[%d] =\n { 0,\n" : "static yyconst flex_int16_t * %s = 0;\n"; } static const char *get_int32_decl (void) { return (gentables) ? "static yyconst flex_int32_t %s[%d] =\n { 0,\n" : "static yyconst flex_int32_t * %s = 0;\n"; } static const char *get_state_decl (void) { return (gentables) ? "static yyconst yy_state_type %s[%d] =\n { 0,\n" : "static yyconst yy_state_type * %s = 0;\n"; } /* Indent to the current level. */ void do_indent () { int i = indent_level * 8; while (i >= 8) { outc ('\t'); i -= 8; } while (i > 0) { outc (' '); --i; } } /** Make the table for possible eol matches. * @return the newly allocated rule_can_match_eol table */ static struct yytbl_data *mkeoltbl (void) { int i; flex_int8_t *tdata = 0; struct yytbl_data *tbl; tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); yytbl_data_init (tbl, YYTD_ID_RULE_CAN_MATCH_EOL); tbl->td_flags = YYTD_DATA8; tbl->td_lolen = num_rules + 1; tbl->td_data = tdata = (flex_int8_t *) calloc (tbl->td_lolen, sizeof (flex_int8_t)); for (i = 1; i <= num_rules; i++) tdata[i] = rule_has_nl[i] ? 1 : 0; buf_prints (&yydmap_buf, "\t{YYTD_ID_RULE_CAN_MATCH_EOL, (void**)&yy_rule_can_match_eol, sizeof(%s)},\n", "flex_int32_t"); return tbl; } /* Generate the table for possible eol matches. */ static void geneoltbl (void) { int i; outn ("m4_ifdef( [[M4_YY_USE_LINENO]],[["); outn ("/* Table of booleans, true if rule could match eol. */"); out_str_dec (get_int32_decl (), "yy_rule_can_match_eol", num_rules + 1); if (gentables) { for (i = 1; i <= num_rules; i++) { out_dec ("%d, ", rule_has_nl[i] ? 1 : 0); /* format nicely, 20 numbers per line. */ if ((i % 20) == 19) out ("\n "); } out (" };\n"); } outn ("]])"); } /* Generate the code to keep backing-up information. */ void gen_backing_up () { if (reject || num_backing_up == 0) return; if (fullspd) indent_puts ("if ( yy_current_state[-1].yy_nxt )"); else indent_puts ("if ( yy_accept[yy_current_state] )"); indent_up (); indent_puts ("{"); indent_puts ("YY_G(yy_last_accepting_state) = yy_current_state;"); indent_puts ("YY_G(yy_last_accepting_cpos) = yy_cp;"); indent_puts ("}"); indent_down (); } /* Generate the code to perform the backing up. */ void gen_bu_action () { if (reject || num_backing_up == 0) return; set_indent (3); indent_puts ("case 0: /* must back up */"); indent_puts ("/* undo the effects of YY_DO_BEFORE_ACTION */"); indent_puts ("*yy_cp = YY_G(yy_hold_char);"); if (fullspd || fulltbl) indent_puts ("yy_cp = YY_G(yy_last_accepting_cpos) + 1;"); else /* Backing-up info for compressed tables is taken \after/ * yy_cp has been incremented for the next state. */ indent_puts ("yy_cp = YY_G(yy_last_accepting_cpos);"); indent_puts ("yy_current_state = YY_G(yy_last_accepting_state);"); indent_puts ("goto yy_find_action;"); outc ('\n'); set_indent (0); } /** mkctbl - make full speed compressed transition table * This is an array of structs; each struct a pair of integers. * You should call mkssltbl() immediately after this. * Then, I think, mkecstbl(). Arrrg. * @return the newly allocated trans table */ static struct yytbl_data *mkctbl (void) { int i; struct yytbl_data *tbl = 0; flex_int32_t *tdata = 0, curr = 0; int end_of_buffer_action = num_rules + 1; buf_prints (&yydmap_buf, "\t{YYTD_ID_TRANSITION, (void**)&yy_transition, sizeof(%s)},\n", ((tblend + numecs + 1) >= INT16_MAX || long_align) ? "flex_int32_t" : "flex_int16_t"); tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); yytbl_data_init (tbl, YYTD_ID_TRANSITION); tbl->td_flags = YYTD_DATA32 | YYTD_STRUCT; tbl->td_hilen = 0; tbl->td_lolen = tblend + numecs + 1; /* number of structs */ tbl->td_data = tdata = (flex_int32_t *) calloc (tbl->td_lolen * 2, sizeof (flex_int32_t)); /* We want the transition to be represented as the offset to the * next state, not the actual state number, which is what it currently * is. The offset is base[nxt[i]] - (base of current state)]. That's * just the difference between the starting points of the two involved * states (to - from). * * First, though, we need to find some way to put in our end-of-buffer * flags and states. We do this by making a state with absolutely no * transitions. We put it at the end of the table. */ /* We need to have room in nxt/chk for two more slots: One for the * action and one for the end-of-buffer transition. We now *assume* * that we're guaranteed the only character we'll try to index this * nxt/chk pair with is EOB, i.e., 0, so we don't have to make sure * there's room for jam entries for other characters. */ while (tblend + 2 >= current_max_xpairs) expand_nxt_chk (); while (lastdfa + 1 >= current_max_dfas) increase_max_dfas (); base[lastdfa + 1] = tblend + 2; nxt[tblend + 1] = end_of_buffer_action; chk[tblend + 1] = numecs + 1; chk[tblend + 2] = 1; /* anything but EOB */ /* So that "make test" won't show arb. differences. */ nxt[tblend + 2] = 0; /* Make sure every state has an end-of-buffer transition and an * action #. */ for (i = 0; i <= lastdfa; ++i) { int anum = dfaacc[i].dfaacc_state; int offset = base[i]; chk[offset] = EOB_POSITION; chk[offset - 1] = ACTION_POSITION; nxt[offset - 1] = anum; /* action number */ } for (i = 0; i <= tblend; ++i) { if (chk[i] == EOB_POSITION) { tdata[curr++] = 0; tdata[curr++] = base[lastdfa + 1] - i; } else if (chk[i] == ACTION_POSITION) { tdata[curr++] = 0; tdata[curr++] = nxt[i]; } else if (chk[i] > numecs || chk[i] == 0) { tdata[curr++] = 0; tdata[curr++] = 0; } else { /* verify, transition */ tdata[curr++] = chk[i]; tdata[curr++] = base[nxt[i]] - (i - chk[i]); } } /* Here's the final, end-of-buffer state. */ tdata[curr++] = chk[tblend + 1]; tdata[curr++] = nxt[tblend + 1]; tdata[curr++] = chk[tblend + 2]; tdata[curr++] = nxt[tblend + 2]; return tbl; } /** Make start_state_list table. * @return the newly allocated start_state_list table */ static struct yytbl_data *mkssltbl (void) { struct yytbl_data *tbl = 0; flex_int32_t *tdata = 0; flex_int32_t i; tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); yytbl_data_init (tbl, YYTD_ID_START_STATE_LIST); tbl->td_flags = YYTD_DATA32 | YYTD_PTRANS; tbl->td_hilen = 0; tbl->td_lolen = lastsc * 2 + 1; tbl->td_data = tdata = (flex_int32_t *) calloc (tbl->td_lolen, sizeof (flex_int32_t)); for (i = 0; i <= lastsc * 2; ++i) tdata[i] = base[i]; buf_prints (&yydmap_buf, "\t{YYTD_ID_START_STATE_LIST, (void**)&yy_start_state_list, sizeof(%s)},\n", "struct yy_trans_info*"); return tbl; } /* genctbl - generates full speed compressed transition table */ void genctbl () { int i; int end_of_buffer_action = num_rules + 1; /* Table of verify for transition and offset to next state. */ if (gentables) out_dec ("static yyconst struct yy_trans_info yy_transition[%d] =\n {\n", tblend + numecs + 1); else outn ("static yyconst struct yy_trans_info *yy_transition = 0;"); /* We want the transition to be represented as the offset to the * next state, not the actual state number, which is what it currently * is. The offset is base[nxt[i]] - (base of current state)]. That's * just the difference between the starting points of the two involved * states (to - from). * * First, though, we need to find some way to put in our end-of-buffer * flags and states. We do this by making a state with absolutely no * transitions. We put it at the end of the table. */ /* We need to have room in nxt/chk for two more slots: One for the * action and one for the end-of-buffer transition. We now *assume* * that we're guaranteed the only character we'll try to index this * nxt/chk pair with is EOB, i.e., 0, so we don't have to make sure * there's room for jam entries for other characters. */ while (tblend + 2 >= current_max_xpairs) expand_nxt_chk (); while (lastdfa + 1 >= current_max_dfas) increase_max_dfas (); base[lastdfa + 1] = tblend + 2; nxt[tblend + 1] = end_of_buffer_action; chk[tblend + 1] = numecs + 1; chk[tblend + 2] = 1; /* anything but EOB */ /* So that "make test" won't show arb. differences. */ nxt[tblend + 2] = 0; /* Make sure every state has an end-of-buffer transition and an * action #. */ for (i = 0; i <= lastdfa; ++i) { int anum = dfaacc[i].dfaacc_state; int offset = base[i]; chk[offset] = EOB_POSITION; chk[offset - 1] = ACTION_POSITION; nxt[offset - 1] = anum; /* action number */ } for (i = 0; i <= tblend; ++i) { if (chk[i] == EOB_POSITION) transition_struct_out (0, base[lastdfa + 1] - i); else if (chk[i] == ACTION_POSITION) transition_struct_out (0, nxt[i]); else if (chk[i] > numecs || chk[i] == 0) transition_struct_out (0, 0); /* unused slot */ else /* verify, transition */ transition_struct_out (chk[i], base[nxt[i]] - (i - chk[i])); } /* Here's the final, end-of-buffer state. */ transition_struct_out (chk[tblend + 1], nxt[tblend + 1]); transition_struct_out (chk[tblend + 2], nxt[tblend + 2]); if (gentables) outn (" };\n"); /* Table of pointers to start states. */ if (gentables) out_dec ("static yyconst struct yy_trans_info *yy_start_state_list[%d] =\n", lastsc * 2 + 1); else outn ("static yyconst struct yy_trans_info **yy_start_state_list =0;"); if (gentables) { outn (" {"); for (i = 0; i <= lastsc * 2; ++i) out_dec (" &yy_transition[%d],\n", base[i]); dataend (); } if (useecs) genecs (); } /* mkecstbl - Make equivalence-class tables. */ static struct yytbl_data *mkecstbl (void) { int i; struct yytbl_data *tbl = 0; flex_int32_t *tdata = 0; tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); yytbl_data_init (tbl, YYTD_ID_EC); tbl->td_flags |= YYTD_DATA32; tbl->td_hilen = 0; tbl->td_lolen = csize; tbl->td_data = tdata = (flex_int32_t *) calloc (tbl->td_lolen, sizeof (flex_int32_t)); for (i = 1; i < csize; ++i) { ecgroup[i] = ABS (ecgroup[i]); tdata[i] = ecgroup[i]; } buf_prints (&yydmap_buf, "\t{YYTD_ID_EC, (void**)&yy_ec, sizeof(%s)},\n", "flex_int32_t"); return tbl; } /* Generate equivalence-class tables. */ void genecs () { int i, j; int numrows; out_str_dec (get_int32_decl (), "yy_ec", csize); for (i = 1; i < csize; ++i) { ecgroup[i] = ABS (ecgroup[i]); mkdata (ecgroup[i]); } dataend (); if (trace) { fputs (_("\n\nEquivalence Classes:\n\n"), stderr); numrows = csize / 8; for (j = 0; j < numrows; ++j) { for (i = j; i < csize; i = i + numrows) { fprintf (stderr, "%4s = %-2d", readable_form (i), ecgroup[i]); putc (' ', stderr); } putc ('\n', stderr); } } } /* Generate the code to find the action number. */ void gen_find_action () { if (fullspd) indent_puts ("yy_act = yy_current_state[-1].yy_nxt;"); else if (fulltbl) indent_puts ("yy_act = yy_accept[yy_current_state];"); else if (reject) { indent_puts ("yy_current_state = *--YY_G(yy_state_ptr);"); indent_puts ("YY_G(yy_lp) = yy_accept[yy_current_state];"); outn ("goto find_rule; /* avoid `defined but not used' warning */"); outn ("find_rule: /* we branch to this label when backing up */"); indent_puts ("for ( ; ; ) /* until we find what rule we matched */"); indent_up (); indent_puts ("{"); indent_puts ("if ( YY_G(yy_lp) && YY_G(yy_lp) < yy_accept[yy_current_state + 1] )"); indent_up (); indent_puts ("{"); indent_puts ("yy_act = yy_acclist[YY_G(yy_lp)];"); if (variable_trailing_context_rules) { indent_puts ("if ( yy_act & YY_TRAILING_HEAD_MASK ||"); indent_puts (" YY_G(yy_looking_for_trail_begin) )"); indent_up (); indent_puts ("{"); indent_puts ("if ( yy_act == YY_G(yy_looking_for_trail_begin) )"); indent_up (); indent_puts ("{"); indent_puts ("YY_G(yy_looking_for_trail_begin) = 0;"); indent_puts ("yy_act &= ~YY_TRAILING_HEAD_MASK;"); indent_puts ("break;"); indent_puts ("}"); indent_down (); indent_puts ("}"); indent_down (); indent_puts ("else if ( yy_act & YY_TRAILING_MASK )"); indent_up (); indent_puts ("{"); indent_puts ("YY_G(yy_looking_for_trail_begin) = yy_act & ~YY_TRAILING_MASK;"); indent_puts ("YY_G(yy_looking_for_trail_begin) |= YY_TRAILING_HEAD_MASK;"); if (real_reject) { /* Remember matched text in case we back up * due to REJECT. */ indent_puts ("YY_G(yy_full_match) = yy_cp;"); indent_puts ("YY_G(yy_full_state) = YY_G(yy_state_ptr);"); indent_puts ("YY_G(yy_full_lp) = YY_G(yy_lp);"); } indent_puts ("}"); indent_down (); indent_puts ("else"); indent_up (); indent_puts ("{"); indent_puts ("YY_G(yy_full_match) = yy_cp;"); indent_puts ("YY_G(yy_full_state) = YY_G(yy_state_ptr);"); indent_puts ("YY_G(yy_full_lp) = YY_G(yy_lp);"); indent_puts ("break;"); indent_puts ("}"); indent_down (); indent_puts ("++YY_G(yy_lp);"); indent_puts ("goto find_rule;"); } else { /* Remember matched text in case we back up due to * trailing context plus REJECT. */ indent_up (); indent_puts ("{"); indent_puts ("YY_G(yy_full_match) = yy_cp;"); indent_puts ("break;"); indent_puts ("}"); indent_down (); } indent_puts ("}"); indent_down (); indent_puts ("--yy_cp;"); /* We could consolidate the following two lines with those at * the beginning, but at the cost of complaints that we're * branching inside a loop. */ indent_puts ("yy_current_state = *--YY_G(yy_state_ptr);"); indent_puts ("YY_G(yy_lp) = yy_accept[yy_current_state];"); indent_puts ("}"); indent_down (); } else { /* compressed */ indent_puts ("yy_act = yy_accept[yy_current_state];"); if (interactive && !reject) { /* Do the guaranteed-needed backing up to figure out * the match. */ indent_puts ("if ( yy_act == 0 )"); indent_up (); indent_puts ("{ /* have to back up */"); indent_puts ("yy_cp = YY_G(yy_last_accepting_cpos);"); indent_puts ("yy_current_state = YY_G(yy_last_accepting_state);"); indent_puts ("yy_act = yy_accept[yy_current_state];"); indent_puts ("}"); indent_down (); } } } /* mkftbl - make the full table and return the struct . * you should call mkecstbl() after this. */ struct yytbl_data *mkftbl (void) { int i; int end_of_buffer_action = num_rules + 1; struct yytbl_data *tbl; flex_int32_t *tdata = 0; tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); yytbl_data_init (tbl, YYTD_ID_ACCEPT); tbl->td_flags |= YYTD_DATA32; tbl->td_hilen = 0; /* it's a one-dimensional array */ tbl->td_lolen = lastdfa + 1; tbl->td_data = tdata = (flex_int32_t *) calloc (tbl->td_lolen, sizeof (flex_int32_t)); dfaacc[end_of_buffer_state].dfaacc_state = end_of_buffer_action; for (i = 1; i <= lastdfa; ++i) { int anum = dfaacc[i].dfaacc_state; tdata[i] = anum; if (trace && anum) fprintf (stderr, _("state # %d accepts: [%d]\n"), i, anum); } buf_prints (&yydmap_buf, "\t{YYTD_ID_ACCEPT, (void**)&yy_accept, sizeof(%s)},\n", long_align ? "flex_int32_t" : "flex_int16_t"); return tbl; } /* genftbl - generate full transition table */ void genftbl () { int i; int end_of_buffer_action = num_rules + 1; out_str_dec (long_align ? get_int32_decl () : get_int16_decl (), "yy_accept", lastdfa + 1); dfaacc[end_of_buffer_state].dfaacc_state = end_of_buffer_action; for (i = 1; i <= lastdfa; ++i) { int anum = dfaacc[i].dfaacc_state; mkdata (anum); if (trace && anum) fprintf (stderr, _("state # %d accepts: [%d]\n"), i, anum); } dataend (); if (useecs) genecs (); /* Don't have to dump the actual full table entries - they were * created on-the-fly. */ } /* Generate the code to find the next compressed-table state. */ void gen_next_compressed_state (char_map) char *char_map; { indent_put2s ("YY_CHAR yy_c = %s;", char_map); /* Save the backing-up info \before/ computing the next state * because we always compute one more state than needed - we * always proceed until we reach a jam state */ gen_backing_up (); indent_puts ("while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )"); indent_up (); indent_puts ("{"); indent_puts ("yy_current_state = (int) yy_def[yy_current_state];"); if (usemecs) { /* We've arrange it so that templates are never chained * to one another. This means we can afford to make a * very simple test to see if we need to convert to * yy_c's meta-equivalence class without worrying * about erroneously looking up the meta-equivalence * class twice */ do_indent (); /* lastdfa + 2 is the beginning of the templates */ out_dec ("if ( yy_current_state >= %d )\n", lastdfa + 2); indent_up (); indent_puts ("yy_c = yy_meta[(unsigned int) yy_c];"); indent_down (); } indent_puts ("}"); indent_down (); indent_puts ("yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];"); } /* Generate the code to find the next match. */ void gen_next_match () { /* NOTE - changes in here should be reflected in gen_next_state() and * gen_NUL_trans(). */ char *char_map = useecs ? "yy_ec[YY_SC_TO_UI(*yy_cp)] " : "YY_SC_TO_UI(*yy_cp)"; char *char_map_2 = useecs ? "yy_ec[YY_SC_TO_UI(*++yy_cp)] " : "YY_SC_TO_UI(*++yy_cp)"; if (fulltbl) { if (gentables) indent_put2s ("while ( (yy_current_state = yy_nxt[yy_current_state][ %s ]) > 0 )", char_map); else indent_put2s ("while ( (yy_current_state = yy_nxt[yy_current_state*YY_NXT_LOLEN + %s ]) > 0 )", char_map); indent_up (); if (num_backing_up > 0) { indent_puts ("{"); gen_backing_up (); outc ('\n'); } indent_puts ("++yy_cp;"); if (num_backing_up > 0) indent_puts ("}"); indent_down (); outc ('\n'); indent_puts ("yy_current_state = -yy_current_state;"); } else if (fullspd) { indent_puts ("{"); indent_puts ("yyconst struct yy_trans_info *yy_trans_info;\n"); indent_puts ("YY_CHAR yy_c;\n"); indent_put2s ("for ( yy_c = %s;", char_map); indent_puts (" (yy_trans_info = &yy_current_state[(unsigned int) yy_c])->"); indent_puts ("yy_verify == yy_c;"); indent_put2s (" yy_c = %s )", char_map_2); indent_up (); if (num_backing_up > 0) indent_puts ("{"); indent_puts ("yy_current_state += yy_trans_info->yy_nxt;"); if (num_backing_up > 0) { outc ('\n'); gen_backing_up (); indent_puts ("}"); } indent_down (); indent_puts ("}"); } else { /* compressed */ indent_puts ("do"); indent_up (); indent_puts ("{"); gen_next_state (false); indent_puts ("++yy_cp;"); indent_puts ("}"); indent_down (); do_indent (); if (interactive) out_dec ("while ( yy_base[yy_current_state] != %d );\n", jambase); else out_dec ("while ( yy_current_state != %d );\n", jamstate); if (!reject && !interactive) { /* Do the guaranteed-needed backing up to figure out * the match. */ indent_puts ("yy_cp = YY_G(yy_last_accepting_cpos);"); indent_puts ("yy_current_state = YY_G(yy_last_accepting_state);"); } } } /* Generate the code to find the next state. */ void gen_next_state (worry_about_NULs) int worry_about_NULs; { /* NOTE - changes in here should be reflected in gen_next_match() */ char char_map[256]; if (worry_about_NULs && !nultrans) { if (useecs) snprintf (char_map, sizeof(char_map), "(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : %d)", NUL_ec); else snprintf (char_map, sizeof(char_map), "(*yy_cp ? YY_SC_TO_UI(*yy_cp) : %d)", NUL_ec); } else strcpy (char_map, useecs ? "yy_ec[YY_SC_TO_UI(*yy_cp)] " : "YY_SC_TO_UI(*yy_cp)"); if (worry_about_NULs && nultrans) { if (!fulltbl && !fullspd) /* Compressed tables back up *before* they match. */ gen_backing_up (); indent_puts ("if ( *yy_cp )"); indent_up (); indent_puts ("{"); } if (fulltbl) { if (gentables) indent_put2s ("yy_current_state = yy_nxt[yy_current_state][%s];", char_map); else indent_put2s ("yy_current_state = yy_nxt[yy_current_state*YY_NXT_LOLEN + %s];", char_map); } else if (fullspd) indent_put2s ("yy_current_state += yy_current_state[%s].yy_nxt;", char_map); else gen_next_compressed_state (char_map); if (worry_about_NULs && nultrans) { indent_puts ("}"); indent_down (); indent_puts ("else"); indent_up (); indent_puts ("yy_current_state = yy_NUL_trans[yy_current_state];"); indent_down (); } if (fullspd || fulltbl) gen_backing_up (); if (reject) indent_puts ("*YY_G(yy_state_ptr)++ = yy_current_state;"); } /* Generate the code to make a NUL transition. */ void gen_NUL_trans () { /* NOTE - changes in here should be reflected in gen_next_match() */ /* Only generate a definition for "yy_cp" if we'll generate code * that uses it. Otherwise lint and the like complain. */ int need_backing_up = (num_backing_up > 0 && !reject); if (need_backing_up && (!nultrans || fullspd || fulltbl)) /* We're going to need yy_cp lying around for the call * below to gen_backing_up(). */ indent_puts ("char *yy_cp = YY_G(yy_c_buf_p);"); outc ('\n'); if (nultrans) { indent_puts ("yy_current_state = yy_NUL_trans[yy_current_state];"); indent_puts ("yy_is_jam = (yy_current_state == 0);"); } else if (fulltbl) { do_indent (); if (gentables) out_dec ("yy_current_state = yy_nxt[yy_current_state][%d];\n", NUL_ec); else out_dec ("yy_current_state = yy_nxt[yy_current_state*YY_NXT_LOLEN + %d];\n", NUL_ec); indent_puts ("yy_is_jam = (yy_current_state <= 0);"); } else if (fullspd) { do_indent (); out_dec ("int yy_c = %d;\n", NUL_ec); indent_puts ("yyconst struct yy_trans_info *yy_trans_info;\n"); indent_puts ("yy_trans_info = &yy_current_state[(unsigned int) yy_c];"); indent_puts ("yy_current_state += yy_trans_info->yy_nxt;"); indent_puts ("yy_is_jam = (yy_trans_info->yy_verify != yy_c);"); } else { char NUL_ec_str[20]; snprintf (NUL_ec_str, sizeof(NUL_ec_str), "%d", NUL_ec); gen_next_compressed_state (NUL_ec_str); do_indent (); out_dec ("yy_is_jam = (yy_current_state == %d);\n", jamstate); if (reject) { /* Only stack this state if it's a transition we * actually make. If we stack it on a jam, then * the state stack and yy_c_buf_p get out of sync. */ indent_puts ("if ( ! yy_is_jam )"); indent_up (); indent_puts ("*YY_G(yy_state_ptr)++ = yy_current_state;"); indent_down (); } } /* If we've entered an accepting state, back up; note that * compressed tables have *already* done such backing up, so * we needn't bother with it again. */ if (need_backing_up && (fullspd || fulltbl)) { outc ('\n'); indent_puts ("if ( ! yy_is_jam )"); indent_up (); indent_puts ("{"); gen_backing_up (); indent_puts ("}"); indent_down (); } } /* Generate the code to find the start state. */ void gen_start_state () { if (fullspd) { if (bol_needed) { indent_puts ("yy_current_state = yy_start_state_list[YY_G(yy_start) + YY_AT_BOL()];"); } else indent_puts ("yy_current_state = yy_start_state_list[YY_G(yy_start)];"); } else { indent_puts ("yy_current_state = YY_G(yy_start);"); if (bol_needed) indent_puts ("yy_current_state += YY_AT_BOL();"); if (reject) { /* Set up for storing up states. */ outn ("m4_ifdef( [[M4_YY_USES_REJECT]],\n[["); indent_puts ("YY_G(yy_state_ptr) = YY_G(yy_state_buf);"); indent_puts ("*YY_G(yy_state_ptr)++ = yy_current_state;"); outn ("]])"); } } } /* gentabs - generate data statements for the transition tables */ void gentabs () { int i, j, k, *accset, nacc, *acc_array, total_states; int end_of_buffer_action = num_rules + 1; struct yytbl_data *yyacc_tbl = 0, *yymeta_tbl = 0, *yybase_tbl = 0, *yydef_tbl = 0, *yynxt_tbl = 0, *yychk_tbl = 0, *yyacclist_tbl=0; flex_int32_t *yyacc_data = 0, *yybase_data = 0, *yydef_data = 0, *yynxt_data = 0, *yychk_data = 0, *yyacclist_data=0; flex_int32_t yybase_curr = 0, yyacclist_curr=0,yyacc_curr=0; acc_array = allocate_integer_array (current_max_dfas); nummt = 0; /* The compressed table format jams by entering the "jam state", * losing information about the previous state in the process. * In order to recover the previous state, we effectively need * to keep backing-up information. */ ++num_backing_up; if (reject) { /* Write out accepting list and pointer list. * First we generate the "yy_acclist" array. In the process, * we compute the indices that will go into the "yy_accept" * array, and save the indices in the dfaacc array. */ int EOB_accepting_list[2]; /* Set up accepting structures for the End Of Buffer state. */ EOB_accepting_list[0] = 0; EOB_accepting_list[1] = end_of_buffer_action; accsiz[end_of_buffer_state] = 1; dfaacc[end_of_buffer_state].dfaacc_set = EOB_accepting_list; out_str_dec (long_align ? get_int32_decl () : get_int16_decl (), "yy_acclist", MAX (numas, 1) + 1); buf_prints (&yydmap_buf, "\t{YYTD_ID_ACCLIST, (void**)&yy_acclist, sizeof(%s)},\n", long_align ? "flex_int32_t" : "flex_int16_t"); yyacclist_tbl = (struct yytbl_data*)calloc(1,sizeof(struct yytbl_data)); yytbl_data_init (yyacclist_tbl, YYTD_ID_ACCLIST); yyacclist_tbl->td_lolen = MAX(numas,1) + 1; yyacclist_tbl->td_data = yyacclist_data = (flex_int32_t *) calloc (yyacclist_tbl->td_lolen, sizeof (flex_int32_t)); yyacclist_curr = 1; j = 1; /* index into "yy_acclist" array */ for (i = 1; i <= lastdfa; ++i) { acc_array[i] = j; if (accsiz[i] != 0) { accset = dfaacc[i].dfaacc_set; nacc = accsiz[i]; if (trace) fprintf (stderr, _("state # %d accepts: "), i); for (k = 1; k <= nacc; ++k) { int accnum = accset[k]; ++j; if (variable_trailing_context_rules && !(accnum & YY_TRAILING_HEAD_MASK) && accnum > 0 && accnum <= num_rules && rule_type[accnum] == RULE_VARIABLE) { /* Special hack to flag * accepting number as part * of trailing context rule. */ accnum |= YY_TRAILING_MASK; } mkdata (accnum); yyacclist_data[yyacclist_curr++] = accnum; if (trace) { fprintf (stderr, "[%d]", accset[k]); if (k < nacc) fputs (", ", stderr); else putc ('\n', stderr); } } } } /* add accepting number for the "jam" state */ acc_array[i] = j; dataend (); if (tablesext) { yytbl_data_compress (yyacclist_tbl); if (yytbl_data_fwrite (&tableswr, yyacclist_tbl) < 0) flexerror (_("Could not write yyacclist_tbl")); yytbl_data_destroy (yyacclist_tbl); yyacclist_tbl = NULL; } } else { dfaacc[end_of_buffer_state].dfaacc_state = end_of_buffer_action; for (i = 1; i <= lastdfa; ++i) acc_array[i] = dfaacc[i].dfaacc_state; /* add accepting number for jam state */ acc_array[i] = 0; } /* Begin generating yy_accept */ /* Spit out "yy_accept" array. If we're doing "reject", it'll be * pointers into the "yy_acclist" array. Otherwise it's actual * accepting numbers. In either case, we just dump the numbers. */ /* "lastdfa + 2" is the size of "yy_accept"; includes room for C arrays * beginning at 0 and for "jam" state. */ k = lastdfa + 2; if (reject) /* We put a "cap" on the table associating lists of accepting * numbers with state numbers. This is needed because we tell * where the end of an accepting list is by looking at where * the list for the next state starts. */ ++k; out_str_dec (long_align ? get_int32_decl () : get_int16_decl (), "yy_accept", k); buf_prints (&yydmap_buf, "\t{YYTD_ID_ACCEPT, (void**)&yy_accept, sizeof(%s)},\n", long_align ? "flex_int32_t" : "flex_int16_t"); yyacc_tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); yytbl_data_init (yyacc_tbl, YYTD_ID_ACCEPT); yyacc_tbl->td_lolen = k; yyacc_tbl->td_data = yyacc_data = (flex_int32_t *) calloc (yyacc_tbl->td_lolen, sizeof (flex_int32_t)); yyacc_curr=1; for (i = 1; i <= lastdfa; ++i) { mkdata (acc_array[i]); yyacc_data[yyacc_curr++] = acc_array[i]; if (!reject && trace && acc_array[i]) fprintf (stderr, _("state # %d accepts: [%d]\n"), i, acc_array[i]); } /* Add entry for "jam" state. */ mkdata (acc_array[i]); yyacc_data[yyacc_curr++] = acc_array[i]; if (reject) { /* Add "cap" for the list. */ mkdata (acc_array[i]); yyacc_data[yyacc_curr++] = acc_array[i]; } dataend (); if (tablesext) { yytbl_data_compress (yyacc_tbl); if (yytbl_data_fwrite (&tableswr, yyacc_tbl) < 0) flexerror (_("Could not write yyacc_tbl")); yytbl_data_destroy (yyacc_tbl); yyacc_tbl = NULL; } /* End generating yy_accept */ if (useecs) { genecs (); if (tablesext) { struct yytbl_data *tbl; tbl = mkecstbl (); yytbl_data_compress (tbl); if (yytbl_data_fwrite (&tableswr, tbl) < 0) flexerror (_("Could not write ecstbl")); yytbl_data_destroy (tbl); tbl = 0; } } if (usemecs) { /* Begin generating yy_meta */ /* Write out meta-equivalence classes (used to index * templates with). */ flex_int32_t *yymecs_data = 0; yymeta_tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); yytbl_data_init (yymeta_tbl, YYTD_ID_META); yymeta_tbl->td_lolen = numecs + 1; yymeta_tbl->td_data = yymecs_data = (flex_int32_t *) calloc (yymeta_tbl->td_lolen, sizeof (flex_int32_t)); if (trace) fputs (_("\n\nMeta-Equivalence Classes:\n"), stderr); out_str_dec (get_int32_decl (), "yy_meta", numecs + 1); buf_prints (&yydmap_buf, "\t{YYTD_ID_META, (void**)&yy_meta, sizeof(%s)},\n", "flex_int32_t"); for (i = 1; i <= numecs; ++i) { if (trace) fprintf (stderr, "%d = %d\n", i, ABS (tecbck[i])); mkdata (ABS (tecbck[i])); yymecs_data[i] = ABS (tecbck[i]); } dataend (); if (tablesext) { yytbl_data_compress (yymeta_tbl); if (yytbl_data_fwrite (&tableswr, yymeta_tbl) < 0) flexerror (_ ("Could not write yymeta_tbl")); yytbl_data_destroy (yymeta_tbl); yymeta_tbl = NULL; } /* End generating yy_meta */ } total_states = lastdfa + numtemps; /* Begin generating yy_base */ out_str_dec ((tblend >= INT16_MAX || long_align) ? get_int32_decl () : get_int16_decl (), "yy_base", total_states + 1); buf_prints (&yydmap_buf, "\t{YYTD_ID_BASE, (void**)&yy_base, sizeof(%s)},\n", (tblend >= INT16_MAX || long_align) ? "flex_int32_t" : "flex_int16_t"); yybase_tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); yytbl_data_init (yybase_tbl, YYTD_ID_BASE); yybase_tbl->td_lolen = total_states + 1; yybase_tbl->td_data = yybase_data = (flex_int32_t *) calloc (yybase_tbl->td_lolen, sizeof (flex_int32_t)); yybase_curr = 1; for (i = 1; i <= lastdfa; ++i) { int d = def[i]; if (base[i] == JAMSTATE) base[i] = jambase; if (d == JAMSTATE) def[i] = jamstate; else if (d < 0) { /* Template reference. */ ++tmpuses; def[i] = lastdfa - d + 1; } mkdata (base[i]); yybase_data[yybase_curr++] = base[i]; } /* Generate jam state's base index. */ mkdata (base[i]); yybase_data[yybase_curr++] = base[i]; for (++i /* skip jam state */ ; i <= total_states; ++i) { mkdata (base[i]); yybase_data[yybase_curr++] = base[i]; def[i] = jamstate; } dataend (); if (tablesext) { yytbl_data_compress (yybase_tbl); if (yytbl_data_fwrite (&tableswr, yybase_tbl) < 0) flexerror (_("Could not write yybase_tbl")); yytbl_data_destroy (yybase_tbl); yybase_tbl = NULL; } /* End generating yy_base */ /* Begin generating yy_def */ out_str_dec ((total_states >= INT16_MAX || long_align) ? get_int32_decl () : get_int16_decl (), "yy_def", total_states + 1); buf_prints (&yydmap_buf, "\t{YYTD_ID_DEF, (void**)&yy_def, sizeof(%s)},\n", (total_states >= INT16_MAX || long_align) ? "flex_int32_t" : "flex_int16_t"); yydef_tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); yytbl_data_init (yydef_tbl, YYTD_ID_DEF); yydef_tbl->td_lolen = total_states + 1; yydef_tbl->td_data = yydef_data = (flex_int32_t *) calloc (yydef_tbl->td_lolen, sizeof (flex_int32_t)); for (i = 1; i <= total_states; ++i) { mkdata (def[i]); yydef_data[i] = def[i]; } dataend (); if (tablesext) { yytbl_data_compress (yydef_tbl); if (yytbl_data_fwrite (&tableswr, yydef_tbl) < 0) flexerror (_("Could not write yydef_tbl")); yytbl_data_destroy (yydef_tbl); yydef_tbl = NULL; } /* End generating yy_def */ /* Begin generating yy_nxt */ out_str_dec ((total_states >= INT16_MAX || long_align) ? get_int32_decl () : get_int16_decl (), "yy_nxt", tblend + 1); buf_prints (&yydmap_buf, "\t{YYTD_ID_NXT, (void**)&yy_nxt, sizeof(%s)},\n", (total_states >= INT16_MAX || long_align) ? "flex_int32_t" : "flex_int16_t"); yynxt_tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); yytbl_data_init (yynxt_tbl, YYTD_ID_NXT); yynxt_tbl->td_lolen = tblend + 1; yynxt_tbl->td_data = yynxt_data = (flex_int32_t *) calloc (yynxt_tbl->td_lolen, sizeof (flex_int32_t)); for (i = 1; i <= tblend; ++i) { /* Note, the order of the following test is important. * If chk[i] is 0, then nxt[i] is undefined. */ if (chk[i] == 0 || nxt[i] == 0) nxt[i] = jamstate; /* new state is the JAM state */ mkdata (nxt[i]); yynxt_data[i] = nxt[i]; } dataend (); if (tablesext) { yytbl_data_compress (yynxt_tbl); if (yytbl_data_fwrite (&tableswr, yynxt_tbl) < 0) flexerror (_("Could not write yynxt_tbl")); yytbl_data_destroy (yynxt_tbl); yynxt_tbl = NULL; } /* End generating yy_nxt */ /* Begin generating yy_chk */ out_str_dec ((total_states >= INT16_MAX || long_align) ? get_int32_decl () : get_int16_decl (), "yy_chk", tblend + 1); buf_prints (&yydmap_buf, "\t{YYTD_ID_CHK, (void**)&yy_chk, sizeof(%s)},\n", (total_states >= INT16_MAX || long_align) ? "flex_int32_t" : "flex_int16_t"); yychk_tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); yytbl_data_init (yychk_tbl, YYTD_ID_CHK); yychk_tbl->td_lolen = tblend + 1; yychk_tbl->td_data = yychk_data = (flex_int32_t *) calloc (yychk_tbl->td_lolen, sizeof (flex_int32_t)); for (i = 1; i <= tblend; ++i) { if (chk[i] == 0) ++nummt; mkdata (chk[i]); yychk_data[i] = chk[i]; } dataend (); if (tablesext) { yytbl_data_compress (yychk_tbl); if (yytbl_data_fwrite (&tableswr, yychk_tbl) < 0) flexerror (_("Could not write yychk_tbl")); yytbl_data_destroy (yychk_tbl); yychk_tbl = NULL; } /* End generating yy_chk */ flex_free ((void *) acc_array); } /* Write out a formatted string (with a secondary string argument) at the * current indentation level, adding a final newline. */ void indent_put2s (fmt, arg) const char *fmt, *arg; { do_indent (); out_str (fmt, arg); outn (""); } /* Write out a string at the current indentation level, adding a final * newline. */ void indent_puts (str) const char *str; { do_indent (); outn (str); } /* make_tables - generate transition tables and finishes generating output file */ void make_tables () { int i; int did_eof_rule = false; struct yytbl_data *yynultrans_tbl; skelout (); /* %% [2.0] - break point in skel */ /* First, take care of YY_DO_BEFORE_ACTION depending on yymore * being used. */ set_indent (1); if (yymore_used && !yytext_is_array) { indent_puts ("YY_G(yytext_ptr) -= YY_G(yy_more_len); \\"); indent_puts ("yyleng = (size_t) (yy_cp - YY_G(yytext_ptr)); \\"); } else indent_puts ("yyleng = (size_t) (yy_cp - yy_bp); \\"); /* Now also deal with copying yytext_ptr to yytext if needed. */ skelout (); /* %% [3.0] - break point in skel */ if (yytext_is_array) { if (yymore_used) indent_puts ("if ( yyleng + YY_G(yy_more_offset) >= YYLMAX ) \\"); else indent_puts ("if ( yyleng >= YYLMAX ) \\"); indent_up (); indent_puts ("YY_FATAL_ERROR( \"token too large, exceeds YYLMAX\" ); \\"); indent_down (); if (yymore_used) { indent_puts ("yy_flex_strncpy( &yytext[YY_G(yy_more_offset)], YY_G(yytext_ptr), yyleng + 1 M4_YY_CALL_LAST_ARG); \\"); indent_puts ("yyleng += YY_G(yy_more_offset); \\"); indent_puts ("YY_G(yy_prev_more_offset) = YY_G(yy_more_offset); \\"); indent_puts ("YY_G(yy_more_offset) = 0; \\"); } else { indent_puts ("yy_flex_strncpy( yytext, YY_G(yytext_ptr), yyleng + 1 M4_YY_CALL_LAST_ARG); \\"); } } set_indent (0); skelout (); /* %% [4.0] - break point in skel */ /* This is where we REALLY begin generating the tables. */ out_dec ("#define YY_NUM_RULES %d\n", num_rules); out_dec ("#define YY_END_OF_BUFFER %d\n", num_rules + 1); if (fullspd) { /* Need to define the transet type as a size large * enough to hold the biggest offset. */ int total_table_size = tblend + numecs + 1; char *trans_offset_type = (total_table_size >= INT16_MAX || long_align) ? "flex_int32_t" : "flex_int16_t"; set_indent (0); indent_puts ("struct yy_trans_info"); indent_up (); indent_puts ("{"); /* We require that yy_verify and yy_nxt must be of the same size int. */ indent_put2s ("%s yy_verify;", trans_offset_type); /* In cases where its sister yy_verify *is* a "yes, there is * a transition", yy_nxt is the offset (in records) to the * next state. In most cases where there is no transition, * the value of yy_nxt is irrelevant. If yy_nxt is the -1th * record of a state, though, then yy_nxt is the action number * for that state. */ indent_put2s ("%s yy_nxt;", trans_offset_type); indent_puts ("};"); indent_down (); } else { /* We generate a bogus 'struct yy_trans_info' data type * so we can guarantee that it is always declared in the skel. * This is so we can compile "sizeof(struct yy_trans_info)" * in any scanner. */ indent_puts ("/* This struct is not used in this scanner,"); indent_puts (" but its presence is necessary. */"); indent_puts ("struct yy_trans_info"); indent_up (); indent_puts ("{"); indent_puts ("flex_int32_t yy_verify;"); indent_puts ("flex_int32_t yy_nxt;"); indent_puts ("};"); indent_down (); } if (fullspd) { genctbl (); if (tablesext) { struct yytbl_data *tbl; tbl = mkctbl (); yytbl_data_compress (tbl); if (yytbl_data_fwrite (&tableswr, tbl) < 0) flexerror (_("Could not write ftbl")); yytbl_data_destroy (tbl); tbl = mkssltbl (); yytbl_data_compress (tbl); if (yytbl_data_fwrite (&tableswr, tbl) < 0) flexerror (_("Could not write ssltbl")); yytbl_data_destroy (tbl); tbl = 0; if (useecs) { tbl = mkecstbl (); yytbl_data_compress (tbl); if (yytbl_data_fwrite (&tableswr, tbl) < 0) flexerror (_ ("Could not write ecstbl")); yytbl_data_destroy (tbl); tbl = 0; } } } else if (fulltbl) { genftbl (); if (tablesext) { struct yytbl_data *tbl; tbl = mkftbl (); yytbl_data_compress (tbl); if (yytbl_data_fwrite (&tableswr, tbl) < 0) flexerror (_("Could not write ftbl")); yytbl_data_destroy (tbl); tbl = 0; if (useecs) { tbl = mkecstbl (); yytbl_data_compress (tbl); if (yytbl_data_fwrite (&tableswr, tbl) < 0) flexerror (_ ("Could not write ecstbl")); yytbl_data_destroy (tbl); tbl = 0; } } } else gentabs (); if (do_yylineno) { geneoltbl (); if (tablesext) { struct yytbl_data *tbl; tbl = mkeoltbl (); yytbl_data_compress (tbl); if (yytbl_data_fwrite (&tableswr, tbl) < 0) flexerror (_("Could not write eoltbl")); yytbl_data_destroy (tbl); tbl = 0; } } /* Definitions for backing up. We don't need them if REJECT * is being used because then we use an alternative backin-up * technique instead. */ if (num_backing_up > 0 && !reject) { if (!C_plus_plus && !reentrant) { indent_puts ("static yy_state_type yy_last_accepting_state;"); indent_puts ("static char *yy_last_accepting_cpos;\n"); } } if (nultrans) { flex_int32_t *yynultrans_data = 0; /* Begin generating yy_NUL_trans */ out_str_dec (get_state_decl (), "yy_NUL_trans", lastdfa + 1); buf_prints (&yydmap_buf, "\t{YYTD_ID_NUL_TRANS, (void**)&yy_NUL_trans, sizeof(%s)},\n", (fullspd) ? "struct yy_trans_info*" : "flex_int32_t"); yynultrans_tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); yytbl_data_init (yynultrans_tbl, YYTD_ID_NUL_TRANS); if (fullspd) yynultrans_tbl->td_flags |= YYTD_PTRANS; yynultrans_tbl->td_lolen = lastdfa + 1; yynultrans_tbl->td_data = yynultrans_data = (flex_int32_t *) calloc (yynultrans_tbl->td_lolen, sizeof (flex_int32_t)); for (i = 1; i <= lastdfa; ++i) { if (fullspd) { out_dec (" &yy_transition[%d],\n", base[i]); yynultrans_data[i] = base[i]; } else { mkdata (nultrans[i]); yynultrans_data[i] = nultrans[i]; } } dataend (); if (tablesext) { yytbl_data_compress (yynultrans_tbl); if (yytbl_data_fwrite (&tableswr, yynultrans_tbl) < 0) flexerror (_ ("Could not write yynultrans_tbl")); yytbl_data_destroy (yynultrans_tbl); yynultrans_tbl = NULL; } /* End generating yy_NUL_trans */ } if (!C_plus_plus && !reentrant) { indent_puts ("extern int yy_flex_debug;"); indent_put2s ("int yy_flex_debug = %s;\n", ddebug ? "1" : "0"); } if (ddebug) { /* Spit out table mapping rules to line numbers. */ out_str_dec (long_align ? get_int32_decl () : get_int16_decl (), "yy_rule_linenum", num_rules); for (i = 1; i < num_rules; ++i) mkdata (rule_linenum[i]); dataend (); } if (reject) { outn ("m4_ifdef( [[M4_YY_USES_REJECT]],\n[["); /* Declare state buffer variables. */ if (!C_plus_plus && !reentrant) { outn ("static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;"); outn ("static char *yy_full_match;"); outn ("static int yy_lp;"); } if (variable_trailing_context_rules) { if (!C_plus_plus && !reentrant) { outn ("static int yy_looking_for_trail_begin = 0;"); outn ("static int yy_full_lp;"); outn ("static int *yy_full_state;"); } out_hex ("#define YY_TRAILING_MASK 0x%x\n", (unsigned int) YY_TRAILING_MASK); out_hex ("#define YY_TRAILING_HEAD_MASK 0x%x\n", (unsigned int) YY_TRAILING_HEAD_MASK); } outn ("#define REJECT \\"); outn ("{ \\"); outn ("*yy_cp = YY_G(yy_hold_char); /* undo effects of setting up yytext */ \\"); outn ("yy_cp = YY_G(yy_full_match); /* restore poss. backed-over text */ \\"); if (variable_trailing_context_rules) { outn ("YY_G(yy_lp) = YY_G(yy_full_lp); /* restore orig. accepting pos. */ \\"); outn ("YY_G(yy_state_ptr) = YY_G(yy_full_state); /* restore orig. state */ \\"); outn ("yy_current_state = *YY_G(yy_state_ptr); /* restore curr. state */ \\"); } outn ("++YY_G(yy_lp); \\"); outn ("goto find_rule; \\"); outn ("}"); outn ("]])\n"); } else { outn ("/* The intent behind this definition is that it'll catch"); outn (" * any uses of REJECT which flex missed."); outn (" */"); outn ("#define REJECT reject_used_but_not_detected"); } if (yymore_used) { if (!C_plus_plus) { if (yytext_is_array) { if (!reentrant){ indent_puts ("static int yy_more_offset = 0;"); indent_puts ("static int yy_prev_more_offset = 0;"); } } else if (!reentrant) { indent_puts ("static int yy_more_flag = 0;"); indent_puts ("static int yy_more_len = 0;"); } } if (yytext_is_array) { indent_puts ("#define yymore() (YY_G(yy_more_offset) = yy_flex_strlen( yytext M4_YY_CALL_LAST_ARG))"); indent_puts ("#define YY_NEED_STRLEN"); indent_puts ("#define YY_MORE_ADJ 0"); indent_puts ("#define YY_RESTORE_YY_MORE_OFFSET \\"); indent_up (); indent_puts ("{ \\"); indent_puts ("YY_G(yy_more_offset) = YY_G(yy_prev_more_offset); \\"); indent_puts ("yyleng -= YY_G(yy_more_offset); \\"); indent_puts ("}"); indent_down (); } else { indent_puts ("#define yymore() (YY_G(yy_more_flag) = 1)"); indent_puts ("#define YY_MORE_ADJ YY_G(yy_more_len)"); indent_puts ("#define YY_RESTORE_YY_MORE_OFFSET"); } } else { indent_puts ("#define yymore() yymore_used_but_not_detected"); indent_puts ("#define YY_MORE_ADJ 0"); indent_puts ("#define YY_RESTORE_YY_MORE_OFFSET"); } if (!C_plus_plus) { if (yytext_is_array) { outn ("#ifndef YYLMAX"); outn ("#define YYLMAX 8192"); outn ("#endif\n"); if (!reentrant){ outn ("char yytext[YYLMAX];"); outn ("char *yytext_ptr;"); } } else { if(! reentrant) outn ("char *yytext;"); } } out (&action_array[defs1_offset]); line_directive_out (stdout, 0); skelout (); /* %% [5.0] - break point in skel */ if (!C_plus_plus) { if (use_read) { outn ("\terrno=0; \\"); outn ("\twhile ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \\"); outn ("\t{ \\"); outn ("\t\tif( errno != EINTR) \\"); outn ("\t\t{ \\"); outn ("\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\"); outn ("\t\t\tbreak; \\"); outn ("\t\t} \\"); outn ("\t\terrno=0; \\"); outn ("\t\tclearerr(yyin); \\"); outn ("\t}\\"); } else { outn ("\tif ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \\"); outn ("\t\t{ \\"); outn ("\t\tint c = '*'; \\"); outn ("\t\tsize_t n; \\"); outn ("\t\tfor ( n = 0; n < max_size && \\"); outn ("\t\t\t (c = getc( yyin )) != EOF && c != '\\n'; ++n ) \\"); outn ("\t\t\tbuf[n] = (char) c; \\"); outn ("\t\tif ( c == '\\n' ) \\"); outn ("\t\t\tbuf[n++] = (char) c; \\"); outn ("\t\tif ( c == EOF && ferror( yyin ) ) \\"); outn ("\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\"); outn ("\t\tresult = n; \\"); outn ("\t\t} \\"); outn ("\telse \\"); outn ("\t\t{ \\"); outn ("\t\terrno=0; \\"); outn ("\t\twhile ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \\"); outn ("\t\t\t{ \\"); outn ("\t\t\tif( errno != EINTR) \\"); outn ("\t\t\t\t{ \\"); outn ("\t\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\"); outn ("\t\t\t\tbreak; \\"); outn ("\t\t\t\t} \\"); outn ("\t\t\terrno=0; \\"); outn ("\t\t\tclearerr(yyin); \\"); outn ("\t\t\t} \\"); outn ("\t\t}\\"); } } skelout (); /* %% [6.0] - break point in skel */ indent_puts ("#define YY_RULE_SETUP \\"); indent_up (); if (bol_needed) { indent_puts ("if ( yyleng > 0 ) \\"); indent_up (); indent_puts ("YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \\"); indent_puts ("\t\t(yytext[yyleng - 1] == '\\n'); \\"); indent_down (); } indent_puts ("YY_USER_ACTION"); indent_down (); skelout (); /* %% [7.0] - break point in skel */ /* Copy prolog to output file. */ out (&action_array[prolog_offset]); line_directive_out (stdout, 0); skelout (); /* %% [8.0] - break point in skel */ set_indent (2); if (yymore_used && !yytext_is_array) { indent_puts ("YY_G(yy_more_len) = 0;"); indent_puts ("if ( YY_G(yy_more_flag) )"); indent_up (); indent_puts ("{"); indent_puts ("YY_G(yy_more_len) = YY_G(yy_c_buf_p) - YY_G(yytext_ptr);"); indent_puts ("YY_G(yy_more_flag) = 0;"); indent_puts ("}"); indent_down (); } skelout (); /* %% [9.0] - break point in skel */ gen_start_state (); /* Note, don't use any indentation. */ outn ("yy_match:"); gen_next_match (); skelout (); /* %% [10.0] - break point in skel */ set_indent (2); gen_find_action (); skelout (); /* %% [11.0] - break point in skel */ outn ("m4_ifdef( [[M4_YY_USE_LINENO]],[["); indent_puts ("if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )"); indent_up (); indent_puts ("{"); indent_puts ("yy_size_t yyl;"); do_indent (); out_str ("for ( yyl = %s; yyl < yyleng; ++yyl )\n", yymore_used ? (yytext_is_array ? "YY_G(yy_prev_more_offset)" : "YY_G(yy_more_len)") : "0"); indent_up (); indent_puts ("if ( yytext[yyl] == '\\n' )"); indent_up (); indent_puts ("M4_YY_INCR_LINENO();"); indent_down (); indent_down (); indent_puts ("}"); indent_down (); outn ("]])"); skelout (); /* %% [12.0] - break point in skel */ if (ddebug) { indent_puts ("if ( yy_flex_debug )"); indent_up (); indent_puts ("{"); indent_puts ("if ( yy_act == 0 )"); indent_up (); indent_puts (C_plus_plus ? "std::cerr << \"--scanner backing up\\n\";" : "fprintf( stderr, \"--scanner backing up\\n\" );"); indent_down (); do_indent (); out_dec ("else if ( yy_act < %d )\n", num_rules); indent_up (); if (C_plus_plus) { indent_puts ("std::cerr << \"--accepting rule at line \" << yy_rule_linenum[yy_act] <<"); indent_puts (" \"(\\\"\" << yytext << \"\\\")\\n\";"); } else { indent_puts ("fprintf( stderr, \"--accepting rule at line %ld (\\\"%s\\\")\\n\","); indent_puts (" (long)yy_rule_linenum[yy_act], yytext );"); } indent_down (); do_indent (); out_dec ("else if ( yy_act == %d )\n", num_rules); indent_up (); if (C_plus_plus) { indent_puts ("std::cerr << \"--accepting default rule (\\\"\" << yytext << \"\\\")\\n\";"); } else { indent_puts ("fprintf( stderr, \"--accepting default rule (\\\"%s\\\")\\n\","); indent_puts (" yytext );"); } indent_down (); do_indent (); out_dec ("else if ( yy_act == %d )\n", num_rules + 1); indent_up (); indent_puts (C_plus_plus ? "std::cerr << \"--(end of buffer or a NUL)\\n\";" : "fprintf( stderr, \"--(end of buffer or a NUL)\\n\" );"); indent_down (); do_indent (); outn ("else"); indent_up (); if (C_plus_plus) { indent_puts ("std::cerr << \"--EOF (start condition \" << YY_START << \")\\n\";"); } else { indent_puts ("fprintf( stderr, \"--EOF (start condition %d)\\n\", YY_START );"); } indent_down (); indent_puts ("}"); indent_down (); } /* Copy actions to output file. */ skelout (); /* %% [13.0] - break point in skel */ indent_up (); gen_bu_action (); out (&action_array[action_offset]); line_directive_out (stdout, 0); /* generate cases for any missing EOF rules */ for (i = 1; i <= lastsc; ++i) if (!sceof[i]) { do_indent (); out_str ("case YY_STATE_EOF(%s):\n", scname[i]); did_eof_rule = true; } if (did_eof_rule) { indent_up (); indent_puts ("yyterminate();"); indent_down (); } /* Generate code for handling NUL's, if needed. */ /* First, deal with backing up and setting up yy_cp if the scanner * finds that it should JAM on the NUL. */ skelout (); /* %% [14.0] - break point in skel */ set_indent (4); if (fullspd || fulltbl) indent_puts ("yy_cp = YY_G(yy_c_buf_p);"); else { /* compressed table */ if (!reject && !interactive) { /* Do the guaranteed-needed backing up to figure * out the match. */ indent_puts ("yy_cp = YY_G(yy_last_accepting_cpos);"); indent_puts ("yy_current_state = YY_G(yy_last_accepting_state);"); } else /* Still need to initialize yy_cp, though * yy_current_state was set up by * yy_get_previous_state(). */ indent_puts ("yy_cp = YY_G(yy_c_buf_p);"); } /* Generate code for yy_get_previous_state(). */ set_indent (1); skelout (); /* %% [15.0] - break point in skel */ gen_start_state (); set_indent (2); skelout (); /* %% [16.0] - break point in skel */ gen_next_state (true); set_indent (1); skelout (); /* %% [17.0] - break point in skel */ gen_NUL_trans (); skelout (); /* %% [18.0] - break point in skel */ skelout (); /* %% [19.0] - break point in skel */ /* Update BOL and yylineno inside of input(). */ if (bol_needed) { indent_puts ("YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\\n');"); if (do_yylineno) { indent_puts ("if ( YY_CURRENT_BUFFER_LVALUE->yy_at_bol )"); indent_up (); indent_puts ("M4_YY_INCR_LINENO();"); indent_down (); } } else if (do_yylineno) { indent_puts ("if ( c == '\\n' )"); indent_up (); indent_puts ("M4_YY_INCR_LINENO();"); indent_down (); } skelout (); /* Copy remainder of input to output. */ line_directive_out (stdout, 1); if (sectnum == 3) { OUT_BEGIN_CODE (); (void) flexscan (); /* copy remainder of input to output */ OUT_END_CODE (); } } freebsd-buildutils-10.0/src/contrib/flex/libyywrap.c0000644000000000000000000000215512146744056017477 0ustar /* libyywrap - flex run-time support library "yywrap" function */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ int yywrap (void); int yywrap (void) { return 1; } freebsd-buildutils-10.0/src/contrib/flex/flex.skl0000644000000000000000000025503212146744602016763 0ustar %# -*-C-*- vi: set ft=c: %# This file is processed in several stages. %# Here are the stages, as best as I can describe: %# %# 1. flex.skl is processed through GNU m4 during the %# pre-compilation stage of flex. Only macros starting %# with `m4preproc_' are processed, and quoting is normal. %# %# 2. The preprocessed skeleton is translated verbatim into a %# C array, saved as "skel.c" and compiled into the flex binary. %# %# 3. At runtime, the skeleton is generated and filtered (again) %# through m4. Macros beginning with `m4_' will be processed. %# The quoting is "[[" and "]]" so we don't interfere with %# user code. %# %# All generate macros for the m4 stage contain the text "m4" or "M4" %# in them. This is to distinguish them from CPP macros. %# The exception to this rule is YY_G, which is an m4 macro, %# but it needs to be remain short because it is used everywhere. %# /* A lexical scanner generated by flex */ %# Macros for preproc stage. m4preproc_changecom %# Macros for runtime processing stage. m4_changecom m4_changequote m4_changequote([[, ]]) %# %# Lines in this skeleton starting with a "%" character are "control lines" %# and affect the generation of the scanner. The possible control codes are %# listed and processed in misc.c. %# %# %# - A comment. The current line is omitted from the generated scanner. %# %if-c++-only - The following lines are printed for C++ scanners ONLY. %# %if-c-only - The following lines are NOT printed for C++ scanners. %# %if-c-or-c++ - The following lines are printed in BOTH C and C++ scanners. %# %if-reentrant - Print for reentrant scanners.(push) %# %if-not-reentrant - Print for non-reentrant scanners. (push) %# %if-bison-bridge - Print for bison-bridge. (push) %# %if-not-bison-bridge - Print for non-bison-bridge. (push) %# %endif - pop from the previous if code. %# %% - A stop-point, where code is inserted by flex. %# Each stop-point is numbered here and also in the code generator. %# (See gen.c, etc. for details.) %# %not-for-header - Begin code that should NOT appear in a ".h" file. %# %ok-for-header - %c and %e are used for building a header file. %# %if-tables-serialization %# %# All control-lines EXCEPT comment lines ("%#") will be inserted into %# the generated scanner as a C-style comment. This is to aid those who %# edit the skeleton. %# %not-for-header %if-c-only %if-not-reentrant m4_ifelse(M4_YY_PREFIX,yy,, #define yy_create_buffer M4_YY_PREFIX[[_create_buffer]] #define yy_delete_buffer M4_YY_PREFIX[[_delete_buffer]] #define yy_flex_debug M4_YY_PREFIX[[_flex_debug]] #define yy_init_buffer M4_YY_PREFIX[[_init_buffer]] #define yy_flush_buffer M4_YY_PREFIX[[_flush_buffer]] #define yy_load_buffer_state M4_YY_PREFIX[[_load_buffer_state]] #define yy_switch_to_buffer M4_YY_PREFIX[[_switch_to_buffer]] #define yyin M4_YY_PREFIX[[in]] #define yyleng M4_YY_PREFIX[[leng]] #define yylex M4_YY_PREFIX[[lex]] #define yylineno M4_YY_PREFIX[[lineno]] #define yyout M4_YY_PREFIX[[out]] #define yyrestart M4_YY_PREFIX[[restart]] #define yytext M4_YY_PREFIX[[text]] #define yywrap M4_YY_PREFIX[[wrap]] #define yyalloc M4_YY_PREFIX[[alloc]] #define yyrealloc M4_YY_PREFIX[[realloc]] #define yyfree M4_YY_PREFIX[[free]] ) %endif %endif %ok-for-header #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION FLEX_MAJOR_VERSION #define YY_FLEX_MINOR_VERSION FLEX_MINOR_VERSION #define YY_FLEX_SUBMINOR_VERSION FLEX_SUBMINOR_VERSION #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif %# Some negated symbols m4_ifdef( [[M4_YY_IN_HEADER]], , [[m4_define([[M4_YY_NOT_IN_HEADER]], [[]])]]) m4_ifdef( [[M4_YY_REENTRANT]], , [[m4_define([[M4_YY_NOT_REENTRANT]], [[]])]]) %# This is the m4 way to say "(stack_used || is_reentrant) m4_ifdef( [[M4_YY_STACK_USED]], [[m4_define([[M4_YY_HAS_START_STACK_VARS]])]]) m4_ifdef( [[M4_YY_REENTRANT]], [[m4_define([[M4_YY_HAS_START_STACK_VARS]])]]) %# Prefixes. %# The complexity here is necessary so that m4 preserves %# the argument lists to each C function. m4_ifdef( [[M4_YY_PREFIX]],, [[m4_define([[M4_YY_PREFIX]], [[yy]])]]) m4preproc_define(`M4_GEN_PREFIX', ``m4_define(yy[[$1]], [[M4_YY_PREFIX[[$1]]m4_ifelse($'`#,0,,[[($'`@)]])]])'') %if-c++-only /* The c++ scanner is a mess. The FlexLexer.h header file relies on the * following macro. This is required in order to pass the c++-multiple-scanners * test in the regression suite. We get reports that it breaks inheritance. * We will address this in a future release of flex, or omit the C++ scanner * altogether. */ #define yyFlexLexer M4_YY_PREFIX[[FlexLexer]] %endif %if-c-only M4_GEN_PREFIX(`_create_buffer') M4_GEN_PREFIX(`_delete_buffer') M4_GEN_PREFIX(`_scan_buffer') M4_GEN_PREFIX(`_scan_string') M4_GEN_PREFIX(`_scan_bytes') M4_GEN_PREFIX(`_init_buffer') M4_GEN_PREFIX(`_flush_buffer') M4_GEN_PREFIX(`_load_buffer_state') M4_GEN_PREFIX(`_switch_to_buffer') M4_GEN_PREFIX(`push_buffer_state') M4_GEN_PREFIX(`pop_buffer_state') M4_GEN_PREFIX(`ensure_buffer_stack') M4_GEN_PREFIX(`lex') M4_GEN_PREFIX(`restart') M4_GEN_PREFIX(`lex_init') M4_GEN_PREFIX(`lex_init_extra') M4_GEN_PREFIX(`lex_destroy') M4_GEN_PREFIX(`get_debug') M4_GEN_PREFIX(`set_debug') M4_GEN_PREFIX(`get_extra') M4_GEN_PREFIX(`set_extra') M4_GEN_PREFIX(`get_in') M4_GEN_PREFIX(`set_in') M4_GEN_PREFIX(`get_out') M4_GEN_PREFIX(`set_out') M4_GEN_PREFIX(`get_leng') M4_GEN_PREFIX(`get_text') M4_GEN_PREFIX(`get_lineno') M4_GEN_PREFIX(`set_lineno') m4_ifdef( [[M4_YY_REENTRANT]], [[ M4_GEN_PREFIX(`get_column') M4_GEN_PREFIX(`set_column') ]]) M4_GEN_PREFIX(`wrap') %endif m4_ifdef( [[M4_YY_BISON_LVAL]], [[ M4_GEN_PREFIX(`get_lval') M4_GEN_PREFIX(`set_lval') ]]) m4_ifdef( [[]], [[ M4_GEN_PREFIX(`get_lloc') M4_GEN_PREFIX(`set_lloc') ]]) M4_GEN_PREFIX(`alloc') M4_GEN_PREFIX(`realloc') M4_GEN_PREFIX(`free') %if-c-only m4_ifdef( [[M4_YY_NOT_REENTRANT]], [[ M4_GEN_PREFIX(`text') M4_GEN_PREFIX(`leng') M4_GEN_PREFIX(`in') M4_GEN_PREFIX(`out') M4_GEN_PREFIX(`_flex_debug') M4_GEN_PREFIX(`lineno') ]]) %endif m4_ifdef( [[M4_YY_TABLES_EXTERNAL]], [[ M4_GEN_PREFIX(`tables_fload') M4_GEN_PREFIX(`tables_destroy') M4_GEN_PREFIX(`TABLES_NAME') ]]) /* First, we deal with platform-specific or compiler-specific issues. */ #if defined(__FreeBSD__) #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS #endif #include #include #else #define __dead2 #endif /* begin standard C headers. */ %if-c-only #include #include #include #include %endif %if-tables-serialization #include #include %endif /* end standard C headers. */ %if-c-or-c++ m4preproc_include(`flexint.h') %endif %if-c++-only /* begin standard C++ headers. */ #include #include #include #include #include /* end standard C++ headers. */ %endif #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif %# For compilers that can not handle prototypes. %# e.g., %# The function prototype %# int foo(int x, char* y); %# %# ...should be written as %# int foo M4_YY_PARAMS(int x, char* y); %# %# ...which could possibly generate %# int foo (); %# m4_ifdef( [[M4_YY_NO_ANSI_FUNC_PROTOS]], [[ m4_define( [[M4_YY_PARAMS]], [[()]]) ]], [[ m4_define( [[M4_YY_PARAMS]], [[($*)]]) ]]) %not-for-header /* Returned upon end-of-file. */ #define YY_NULL 0 %ok-for-header %not-for-header /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) %ok-for-header %if-reentrant /* An opaque pointer. */ #ifndef YY_TYPEDEF_YY_SCANNER_T #define YY_TYPEDEF_YY_SCANNER_T typedef void* yyscan_t; #endif %# Declare yyguts variable m4_define( [[M4_YY_DECL_GUTS_VAR]], [[struct yyguts_t * yyg = (struct yyguts_t*)yyscanner]]) %# Perform a noop access on yyguts to prevent unused variable complains m4_define( [[M4_YY_NOOP_GUTS_VAR]], [[(void)yyg]]) %# For use wherever a Global is accessed or assigned. m4_define( [[YY_G]], [[yyg->$1]]) %# For use in function prototypes to append the additional argument. m4_define( [[M4_YY_PROTO_LAST_ARG]], [[, yyscan_t yyscanner]]) m4_define( [[M4_YY_PROTO_ONLY_ARG]], [[yyscan_t yyscanner]]) %# For use in function definitions to append the additional argument. m4_ifdef( [[M4_YY_NO_ANSI_FUNC_DEFS]], [[ m4_define( [[M4_YY_DEF_LAST_ARG]], [[, yyscanner]]) m4_define( [[M4_YY_DEF_ONLY_ARG]], [[yyscanner]]) ]], [[ m4_define( [[M4_YY_DEF_LAST_ARG]], [[, yyscan_t yyscanner]]) m4_define( [[M4_YY_DEF_ONLY_ARG]], [[yyscan_t yyscanner]]) ]]) m4_define( [[M4_YY_DECL_LAST_ARG]], [[yyscan_t yyscanner;]]) %# For use in function calls to pass the additional argument. m4_define( [[M4_YY_CALL_LAST_ARG]], [[, yyscanner]]) m4_define( [[M4_YY_CALL_ONLY_ARG]], [[yyscanner]]) %# For use in function documentation to adjust for additional argument. m4_define( [[M4_YY_DOC_PARAM]], [[@param yyscanner The scanner object.]]) /* For convenience, these vars (plus the bison vars far below) are macros in the reentrant scanner. */ #define yyin YY_G(yyin_r) #define yyout YY_G(yyout_r) #define yyextra YY_G(yyextra_r) #define yyleng YY_G(yyleng_r) #define yytext YY_G(yytext_r) #define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) #define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) #define yy_flex_debug YY_G(yy_flex_debug_r) m4_define( [[M4_YY_INCR_LINENO]], [[ do{ yylineno++; yycolumn=0; }while(0) ]]) %endif %if-not-reentrant m4_define( [[M4_YY_INCR_LINENO]], [[ yylineno++; ]]) %# Define these macros to be no-ops. m4_define( [[M4_YY_DECL_GUTS_VAR]], [[m4_dnl]]) m4_define( [[M4_YY_NOOP_GUTS_VAR]], [[m4_dnl]]) m4_define( [[YY_G]], [[($1)]]) m4_define( [[M4_YY_PROTO_LAST_ARG]]) m4_define( [[M4_YY_PROTO_ONLY_ARG]], [[void]]) m4_define( [[M4_YY_DEF_LAST_ARG]]) m4_ifdef( [[M4_YY_NO_ANSI_FUNC_DEFS]], [[ m4_define( [[M4_YY_DEF_ONLY_ARG]]) ]], [[ m4_define( [[M4_YY_DEF_ONLY_ARG]], [[void]]) ]]) m4_define([[M4_YY_DECL_LAST_ARG]]) m4_define([[M4_YY_CALL_LAST_ARG]]) m4_define([[M4_YY_CALL_ONLY_ARG]]) m4_define( [[M4_YY_DOC_PARAM]], [[]]) %endif m4_ifdef( [[M4_YY_NO_ANSI_FUNC_DEFS]], [[ %# For compilers that need traditional function definitions. %# e.g., %# The function prototype taking 2 arguments %# int foo (int x, char* y) %# %# ...should be written as %# int foo YYFARGS2(int,x, char*,y) %# %# ...which could possibly generate %# int foo (x,y,yyscanner) %# int x; %# char * y; %# yyscan_t yyscanner; %# %# Generate traditional function defs m4_define( [[YYFARGS0]], [[(M4_YY_DEF_ONLY_ARG) [[\]] M4_YY_DECL_LAST_ARG]]) m4_define( [[YYFARGS1]], [[($2 M4_YY_DEF_LAST_ARG) [[\]] $1 $2; [[\]] M4_YY_DECL_LAST_ARG]]) m4_define( [[YYFARGS2]], [[($2,$4 M4_YY_DEF_LAST_ARG) [[\]] $1 $2; [[\]] $3 $4; [[\]] M4_YY_DECL_LAST_ARG]]) m4_define( [[YYFARGS3]], [[($2,$4,$6 M4_YY_DEF_LAST_ARG) [[\]] $1 $2; [[\]] $3 $4; [[\]] $5 $6; [[\]] M4_YY_DECL_LAST_ARG]]) ]], [[ %# Generate C99 function defs. m4_define( [[YYFARGS0]], [[(M4_YY_DEF_ONLY_ARG)]]) m4_define( [[YYFARGS1]], [[($1 $2 M4_YY_DEF_LAST_ARG)]]) m4_define( [[YYFARGS2]], [[($1 $2, $3 $4 M4_YY_DEF_LAST_ARG)]]) m4_define( [[YYFARGS3]], [[($1 $2, $3 $4, $5 $6 M4_YY_DEF_LAST_ARG)]]) ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN YY_G(yy_start) = 1 + 2 * ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((YY_G(yy_start) - 1) / 2) #define YYSTATE YY_START ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin M4_YY_CALL_LAST_ARG ) ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ #define YY_END_OF_BUFFER_CHAR 0 ]]) /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 #endif m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) ]]) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif %if-not-reentrant extern yy_size_t yyleng; %endif %if-c-only %if-not-reentrant extern FILE *yyin, *yyout; %endif %endif m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ m4_ifdef( [[M4_YY_USE_LINENO]], [[ /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires * access to the local variable yy_act. Since yyless() is a macro, it would break * existing scanners that call yyless() from OUTSIDE yylex. * One obvious solution it to make yy_act a global. I tried that, and saw * a 5% performance hit in a non-yylineno scanner, because yy_act is * normally declared as a register variable-- so it is not worth it. */ #define YY_LESS_LINENO(n) \ do { \ int yyl;\ for ( yyl = n; yyl < yyleng; ++yyl )\ if ( yytext[yyl] == '\n' )\ --yylineno;\ }while(0) ]], [[ #define YY_LESS_LINENO(n) ]]) ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = YY_G(yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ YY_G(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ #define unput(c) yyunput( c, YY_G(yytext_ptr) M4_YY_CALL_LAST_ARG ) ]]) #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { %if-c-only FILE *yy_input_file; %endif %if-c++-only std::istream* yy_input_file; %endif char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ yy_size_t yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 ]]) }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ %if-c-only Standard (non-C++) definition %not-for-header %if-not-reentrant /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ %endif %ok-for-header %endif m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( YY_G(yy_buffer_stack) \ ? YY_G(yy_buffer_stack)[YY_G(yy_buffer_stack_top)] \ : NULL) #define yy_current_buffer YY_CURRENT_BUFFER ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE YY_G(yy_buffer_stack)[YY_G(yy_buffer_stack_top)] ]]) %if-c-only Standard (non-C++) definition %if-not-reentrant %not-for-header /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ yy_size_t yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; %ok-for-header %endif void yyrestart M4_YY_PARAMS( FILE *input_file M4_YY_PROTO_LAST_ARG ); void yy_switch_to_buffer M4_YY_PARAMS( YY_BUFFER_STATE new_buffer M4_YY_PROTO_LAST_ARG ); YY_BUFFER_STATE yy_create_buffer M4_YY_PARAMS( FILE *file, int size M4_YY_PROTO_LAST_ARG ); void yy_delete_buffer M4_YY_PARAMS( YY_BUFFER_STATE b M4_YY_PROTO_LAST_ARG ); void yy_flush_buffer M4_YY_PARAMS( YY_BUFFER_STATE b M4_YY_PROTO_LAST_ARG ); void yypush_buffer_state M4_YY_PARAMS( YY_BUFFER_STATE new_buffer M4_YY_PROTO_LAST_ARG ); void yypop_buffer_state M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ static void yyensure_buffer_stack M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); static void yy_load_buffer_state M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); static void yy_init_buffer M4_YY_PARAMS( YY_BUFFER_STATE b, FILE *file M4_YY_PROTO_LAST_ARG ); ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ #define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG) ]]) YY_BUFFER_STATE yy_scan_buffer M4_YY_PARAMS( char *base, yy_size_t size M4_YY_PROTO_LAST_ARG ); YY_BUFFER_STATE yy_scan_string M4_YY_PARAMS( yyconst char *yy_str M4_YY_PROTO_LAST_ARG ); YY_BUFFER_STATE yy_scan_bytes M4_YY_PARAMS( yyconst char *bytes, yy_size_t len M4_YY_PROTO_LAST_ARG ); %endif void *yyalloc M4_YY_PARAMS( yy_size_t M4_YY_PROTO_LAST_ARG ); void *yyrealloc M4_YY_PARAMS( void *, yy_size_t M4_YY_PROTO_LAST_ARG ); void yyfree M4_YY_PARAMS( void * M4_YY_PROTO_LAST_ARG ); m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ #define yy_new_buffer yy_create_buffer ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE M4_YY_CALL_LAST_ARG); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE M4_YY_CALL_LAST_ARG); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) ]]) %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ %% [1.5] DFA ]]) %if-c-only Standard (non-C++) definition m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ static yy_state_type yy_get_previous_state M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); static yy_state_type yy_try_NUL_trans M4_YY_PARAMS( yy_state_type current_state M4_YY_PROTO_LAST_ARG); static int yy_get_next_buffer M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); static void yy_fatal_error M4_YY_PARAMS( yyconst char msg[] M4_YY_PROTO_LAST_ARG ) __dead2; ]]) %endif m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ YY_G(yytext_ptr) = yy_bp; \ %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ YY_G(yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ YY_G(yy_c_buf_p) = yy_cp; ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ %% [4.0] data tables for the DFA and the user's section 1 definitions go here ]]) m4_ifdef( [[M4_YY_IN_HEADER]], [[#ifdef YY_HEADER_EXPORT_START_CONDITIONS]]) M4_YY_SC_DEFS m4_ifdef( [[M4_YY_IN_HEADER]], [[#endif]]) m4_ifdef( [[M4_YY_NO_UNISTD_H]],, [[ #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ %if-c-only #include %endif %if-c++-only #include %endif #endif ]]) m4_ifdef( [[M4_EXTRA_TYPE_DEFS]], [[ #define YY_EXTRA_TYPE M4_EXTRA_TYPE_DEFS ]], [[ #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif ]] ) %if-c-only Reentrant structure and macros (non-C++). %if-reentrant m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* Holds the entire state of the reentrant scanner. */ struct yyguts_t { /* User-defined. Not touched by flex. */ YY_EXTRA_TYPE yyextra_r; /* The rest are the same as the globals declared in the non-reentrant scanner. */ FILE *yyin_r, *yyout_r; size_t yy_buffer_stack_top; /**< index of top of stack. */ size_t yy_buffer_stack_max; /**< capacity of stack. */ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ char yy_hold_char; yy_size_t yy_n_chars; yy_size_t yyleng_r; char *yy_c_buf_p; int yy_init; int yy_start; int yy_did_buffer_switch_on_eof; int yy_start_stack_ptr; int yy_start_stack_depth; int *yy_start_stack; yy_state_type yy_last_accepting_state; char* yy_last_accepting_cpos; int yylineno_r; int yy_flex_debug_r; m4_ifdef( [[M4_YY_USES_REJECT]], [[ yy_state_type *yy_state_buf; yy_state_type *yy_state_ptr; char *yy_full_match; int yy_lp; /* These are only needed for trailing context rules, * but there's no conditional variable for that yet. */ int yy_looking_for_trail_begin; int yy_full_lp; int *yy_full_state; ]]) m4_ifdef( [[M4_YY_TEXT_IS_ARRAY]], [[ char yytext_r[YYLMAX]; char *yytext_ptr; int yy_more_offset; int yy_prev_more_offset; ]], [[ char *yytext_r; int yy_more_flag; int yy_more_len; ]]) m4_ifdef( [[M4_YY_BISON_LVAL]], [[ YYSTYPE * yylval_r; ]]) m4_ifdef( [[]], [[ YYLTYPE * yylloc_r; ]]) }; /* end struct yyguts_t */ ]]) %if-c-only m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ static int yy_init_globals M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) %endif %if-reentrant m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ m4_ifdef( [[M4_YY_BISON_LVAL]], [[ /* This must go here because YYSTYPE and YYLTYPE are included * from bison output in section 1.*/ # define yylval YY_G(yylval_r) ]]) m4_ifdef( [[]], [[ # define yylloc YY_G(yylloc_r) ]]) ]]) int yylex_init M4_YY_PARAMS(yyscan_t* scanner); int yylex_init_extra M4_YY_PARAMS( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); %endif %endif End reentrant structures and macros. /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ m4_ifdef( [[M4_YY_NO_DESTROY]],, [[ int yylex_destroy M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) m4_ifdef( [[M4_YY_NO_GET_DEBUG]],, [[ int yyget_debug M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) m4_ifdef( [[M4_YY_NO_SET_DEBUG]],, [[ void yyset_debug M4_YY_PARAMS( int debug_flag M4_YY_PROTO_LAST_ARG ); ]]) m4_ifdef( [[M4_YY_NO_GET_EXTRA]],, [[ YY_EXTRA_TYPE yyget_extra M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) m4_ifdef( [[M4_YY_NO_SET_EXTRA]],, [[ void yyset_extra M4_YY_PARAMS( YY_EXTRA_TYPE user_defined M4_YY_PROTO_LAST_ARG ); ]]) m4_ifdef( [[M4_YY_NO_GET_IN]],, [[ FILE *yyget_in M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) m4_ifdef( [[M4_YY_NO_SET_IN]],, [[ void yyset_in M4_YY_PARAMS( FILE * in_str M4_YY_PROTO_LAST_ARG ); ]]) m4_ifdef( [[M4_YY_NO_GET_OUT]],, [[ FILE *yyget_out M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) m4_ifdef( [[M4_YY_NO_SET_OUT]],, [[ void yyset_out M4_YY_PARAMS( FILE * out_str M4_YY_PROTO_LAST_ARG ); ]]) m4_ifdef( [[M4_YY_NO_GET_LENG]],, [[ yy_size_t yyget_leng M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) m4_ifdef( [[M4_YY_NO_GET_TEXT]],, [[ char *yyget_text M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) m4_ifdef( [[M4_YY_NO_GET_LINENO]],, [[ int yyget_lineno M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) m4_ifdef( [[M4_YY_NO_SET_LINENO]],, [[ void yyset_lineno M4_YY_PARAMS( int line_number M4_YY_PROTO_LAST_ARG ); ]]) m4_ifdef( [[M4_YY_REENTRANT]], [[ m4_ifdef( [[M4_YY_NO_GET_COLUMN]],, [[ int yyget_column M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) ]]) m4_ifdef( [[M4_YY_REENTRANT]], [[ m4_ifdef( [[M4_YY_NO_SET_COLUMN]],, [[ void yyset_column M4_YY_PARAMS( int column_no M4_YY_PROTO_LAST_ARG ); ]]) ]]) %if-bison-bridge m4_ifdef( [[M4_YY_NO_GET_LVAL]],, [[ YYSTYPE * yyget_lval M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) void yyset_lval M4_YY_PARAMS( YYSTYPE * yylval_param M4_YY_PROTO_LAST_ARG ); m4_ifdef( [[]], [[ m4_ifdef( [[M4_YY_NO_GET_LLOC]],, [[ YYLTYPE *yyget_lloc M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) m4_ifdef( [[M4_YY_NO_SET_LLOC]],, [[ void yyset_lloc M4_YY_PARAMS( YYLTYPE * yylloc_param M4_YY_PROTO_LAST_ARG ); ]]) ]]) %endif /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); #else extern int yywrap M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); #endif #endif %not-for-header m4_ifdef( [[M4_YY_NO_UNPUT]],, [[ #ifndef YY_NO_UNPUT static void yyunput M4_YY_PARAMS( int c, char *buf_ptr M4_YY_PROTO_LAST_ARG); #endif ]]) %ok-for-header %endif #ifndef yytext_ptr static void yy_flex_strncpy M4_YY_PARAMS( char *, yyconst char *, int M4_YY_PROTO_LAST_ARG); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen M4_YY_PARAMS( yyconst char * M4_YY_PROTO_LAST_ARG); #endif #ifndef YY_NO_INPUT %if-c-only Standard (non-C++) definition %not-for-header #ifdef __cplusplus static int yyinput M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); #else static int input M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); #endif %ok-for-header %endif #endif %if-c-only %# TODO: This is messy. m4_ifdef( [[M4_YY_STACK_USED]], [[ m4_ifdef( [[M4_YY_NOT_REENTRANT]], [[ m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ static int yy_start_stack_ptr = 0; static int yy_start_stack_depth = 0; static int *yy_start_stack = NULL; ]]) ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ m4_ifdef( [[M4_YY_NO_PUSH_STATE]],, [[ static void yy_push_state M4_YY_PARAMS( int new_state M4_YY_PROTO_LAST_ARG); ]]) m4_ifdef( [[M4_YY_NO_POP_STATE]],, [[ static void yy_pop_state M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) m4_ifdef( [[M4_YY_NO_TOP_STATE]],, [[ static int yy_top_state M4_YY_PARAMS( M4_YY_PROTO_ONLY_ARG ); ]]) ]]) ]], [[ m4_define( [[M4_YY_NO_PUSH_STATE]]) m4_define( [[M4_YY_NO_POP_STATE]]) m4_define( [[M4_YY_NO_TOP_STATE]]) ]]) %endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO %if-c-only Standard (non-C++) definition /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) %endif %if-c++-only C++ definition #define ECHO LexerOutput( yytext, yyleng ) %endif #endif ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ \ %if-c++-only C++ definition \ if ( (result = LexerInput( (char *) buf, max_size )) < 0 ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); %endif #endif ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif ]]) /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* Report a fatal error. */ #ifndef YY_FATAL_ERROR %if-c-only #define YY_FATAL_ERROR(msg) yy_fatal_error( msg M4_YY_CALL_LAST_ARG) %endif %if-c++-only #define YY_FATAL_ERROR(msg) LexerError( msg ) %endif #endif ]]) %if-tables-serialization structures and prototypes m4preproc_include(`tables_shared.h') /* Load the DFA tables from the given stream. */ int yytables_fload M4_YY_PARAMS(FILE * fp M4_YY_PROTO_LAST_ARG); /* Unload the tables from memory. */ int yytables_destroy M4_YY_PARAMS(M4_YY_PROTO_ONLY_ARG); %not-for-header /** Describes a mapping from a serialized table id to its deserialized state in * this scanner. This is the bridge between our "generic" deserialization code * and the specifics of this scanner. */ struct yytbl_dmap { enum yytbl_id dm_id;/**< table identifier */ void **dm_arr; /**< address of pointer to store the deserialized table. */ size_t dm_sz; /**< local sizeof() each element in table. */ }; /** A {0,0,0}-terminated list of structs, forming the map */ static struct yytbl_dmap yydmap[] = { %tables-yydmap generated elements {0,0,0} }; /** A tables-reader object to maintain some state in the read. */ struct yytbl_reader { FILE * fp; /**< input stream */ flex_uint32_t bread; /**< bytes read since beginning of current tableset */ }; %endif /* end tables serialization structures and prototypes */ %ok-for-header /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 %if-c-only Standard (non-C++) definition m4_define( [[M4_YY_LEX_PROTO]], [[M4_YY_PARAMS(M4_YY_PROTO_ONLY_ARG)]]) m4_define( [[M4_YY_LEX_DECLARATION]], [[YYFARGS0(void)]]) m4_ifdef( [[M4_YY_BISON_LVAL]], [[ m4_dnl The bison pure parser is used. Redefine yylex to m4_dnl accept the lval parameter. m4_define( [[M4_YY_LEX_PROTO]], [[\]] [[M4_YY_PARAMS(YYSTYPE * yylval_param M4_YY_PROTO_LAST_ARG)]]) m4_define( [[M4_YY_LEX_DECLARATION]], [[\]] [[YYFARGS1(YYSTYPE *,yylval_param)]]) ]]) m4_ifdef( [[]], [[ m4_dnl Locations are used. yylex should also accept the ylloc parameter. m4_define( [[M4_YY_LEX_PROTO]], [[\]] [[M4_YY_PARAMS(YYSTYPE * yylval_param, YYLTYPE * yylloc_param M4_YY_PROTO_LAST_ARG)]]) m4_define( [[M4_YY_LEX_DECLARATION]], [[\]] [[YYFARGS2(YYSTYPE *,yylval_param, YYLTYPE *,yylloc_param)]]) ]]) extern int yylex M4_YY_LEX_PROTO; #define YY_DECL int yylex M4_YY_LEX_DECLARATION %endif %if-c++-only C++ definition #define YY_DECL int yyFlexLexer::yylex() %endif #endif /* !YY_DECL */ m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ %% [6.0] YY_RULE_SETUP definition goes here ]]) %not-for-header /** The main scanner function which does all the work. */ YY_DECL { yy_state_type yy_current_state; char *yy_cp, *yy_bp; int yy_act; M4_YY_DECL_GUTS_VAR(); m4_ifdef( [[M4_YY_NOT_REENTRANT]], [[ m4_ifdef( [[M4_YY_BISON_LVAL]], [[ YYSTYPE * yylval; ]]) m4_ifdef( [[]], [[ YYLTYPE * yylloc; ]]) ]]) %% [7.0] user's declarations go here m4_ifdef( [[M4_YY_BISON_LVAL]], [[ yylval = yylval_param; ]]) m4_ifdef( [[]], [[ yylloc = yylloc_param; ]]) if ( !YY_G(yy_init) ) { YY_G(yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif m4_ifdef( [[M4_YY_USES_REJECT]], [[ /* Create the reject buffer large enough to save one state per allowed character. */ if ( ! YY_G(yy_state_buf) ) YY_G(yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE M4_YY_CALL_LAST_ARG); if ( ! YY_G(yy_state_buf) ) YY_FATAL_ERROR( "out of dynamic memory in yylex()" ); ]]) if ( ! YY_G(yy_start) ) YY_G(yy_start) = 1; /* first start state */ if ( ! yyin ) %if-c-only yyin = stdin; %endif %if-c++-only yyin = & std::cin; %endif if ( ! yyout ) %if-c-only yyout = stdout; %endif %if-c++-only yyout = & std::cout; %endif if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE M4_YY_CALL_LAST_ARG); } yy_load_buffer_state( M4_YY_CALL_ONLY_ARG ); } while ( 1 ) /* loops until end-of-file is reached */ { %% [8.0] yymore()-related code goes here yy_cp = YY_G(yy_c_buf_p); /* Support of yytext. */ *yy_cp = YY_G(yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; %% [9.0] code to set up and find next match goes here yy_find_action: %% [10.0] code to find the action number goes here YY_DO_BEFORE_ACTION; %% [11.0] code for yylineno update goes here do_action: /* This label is used only to access EOF actions. */ %% [12.0] debug code goes here switch ( yy_act ) { /* beginning of action switch */ %% [13.0] actions go here case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - YY_G(yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = YY_G(yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ YY_G(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( YY_G(yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; YY_G(yy_c_buf_p) = YY_G(yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( M4_YY_CALL_ONLY_ARG ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state M4_YY_CALL_LAST_ARG); yy_bp = YY_G(yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++YY_G(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here goto yy_find_action; } } else switch ( yy_get_next_buffer( M4_YY_CALL_ONLY_ARG ) ) { case EOB_ACT_END_OF_FILE: { YY_G(yy_did_buffer_switch_on_eof) = 0; if ( yywrap( M4_YY_CALL_ONLY_ARG ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ YY_G(yy_c_buf_p) = YY_G(yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! YY_G(yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: YY_G(yy_c_buf_p) = YY_G(yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( M4_YY_CALL_ONLY_ARG ); yy_cp = YY_G(yy_c_buf_p); yy_bp = YY_G(yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: YY_G(yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars)]; yy_current_state = yy_get_previous_state( M4_YY_CALL_ONLY_ARG ); yy_cp = YY_G(yy_c_buf_p); yy_bp = YY_G(yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ %ok-for-header %if-c++-only %not-for-header /* The contents of this function are C++ specific, so the YY_G macro is not used. */ yyFlexLexer::yyFlexLexer( std::istream* arg_yyin, std::ostream* arg_yyout ) { yyin = arg_yyin; yyout = arg_yyout; yy_c_buf_p = 0; yy_init = 0; yy_start = 0; yy_flex_debug = 0; yylineno = 1; // this will only get updated if %option yylineno yy_did_buffer_switch_on_eof = 0; yy_looking_for_trail_begin = 0; yy_more_flag = 0; yy_more_len = 0; yy_more_offset = yy_prev_more_offset = 0; yy_start_stack_ptr = yy_start_stack_depth = 0; yy_start_stack = NULL; yy_buffer_stack = 0; yy_buffer_stack_top = 0; yy_buffer_stack_max = 0; m4_ifdef( [[M4_YY_USES_REJECT]], [[ yy_state_buf = new yy_state_type[YY_STATE_BUF_SIZE]; ]], [[ yy_state_buf = 0; ]]) } /* The contents of this function are C++ specific, so the YY_G macro is not used. */ yyFlexLexer::~yyFlexLexer() { delete [] yy_state_buf; yyfree( yy_start_stack M4_YY_CALL_LAST_ARG ); yy_delete_buffer( YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG); yyfree( yy_buffer_stack M4_YY_CALL_LAST_ARG ); } /* The contents of this function are C++ specific, so the YY_G macro is not used. */ void yyFlexLexer::switch_streams( std::istream* new_in, std::ostream* new_out ) { if ( new_in ) { yy_delete_buffer( YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG); yy_switch_to_buffer( yy_create_buffer( new_in, YY_BUF_SIZE M4_YY_CALL_LAST_ARG) M4_YY_CALL_LAST_ARG); } if ( new_out ) yyout = new_out; } #ifdef YY_INTERACTIVE int yyFlexLexer::LexerInput( char* buf, int /* max_size */ ) #else int yyFlexLexer::LexerInput( char* buf, int max_size ) #endif { if ( yyin->eof() || yyin->fail() ) return 0; #ifdef YY_INTERACTIVE yyin->get( buf[0] ); if ( yyin->eof() ) return 0; if ( yyin->bad() ) return -1; return 1; #else (void) yyin->read( buf, max_size ); if ( yyin->bad() ) return -1; else return yyin->gcount(); #endif } void yyFlexLexer::LexerOutput( const char* buf, int size ) { (void) yyout->write( buf, size ); } %ok-for-header %endif m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ %if-c-only static int yy_get_next_buffer YYFARGS0(void) %endif %if-c++-only int yyFlexLexer::yy_get_next_buffer() %endif { M4_YY_DECL_GUTS_VAR(); char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = YY_G(yytext_ptr); int number_to_move, i; int ret_val; if ( YY_G(yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( YY_G(yy_c_buf_p) - YY_G(yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) (YY_G(yy_c_buf_p) - YY_G(yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = YY_G(yy_n_chars) = 0; else { yy_size_t num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ m4_ifdef( [[M4_YY_USES_REJECT]], [[ YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); ]], [[ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; int yy_c_buf_p_offset = (int) (YY_G(yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { yy_size_t new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc( (void *) b->yy_ch_buf, b->yy_buf_size + 2 M4_YY_CALL_LAST_ARG ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); YY_G(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; ]]) } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), YY_G(yy_n_chars), num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = YY_G(yy_n_chars); } if ( YY_G(yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin M4_YY_CALL_LAST_ARG); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) (YY_G(yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = YY_G(yy_n_chars) + number_to_move + (YY_G(yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, new_size M4_YY_CALL_LAST_ARG ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } YY_G(yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; YY_G(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } ]]) /* yy_get_previous_state - get the state just before the EOB char was reached */ %if-c-only %not-for-header static yy_state_type yy_get_previous_state YYFARGS0(void) %endif %if-c++-only yy_state_type yyFlexLexer::yy_get_previous_state() %endif { yy_state_type yy_current_state; char *yy_cp; M4_YY_DECL_GUTS_VAR(); %% [15.0] code to get the start state into yy_current_state goes here for ( yy_cp = YY_G(yytext_ptr) + YY_MORE_ADJ; yy_cp < YY_G(yy_c_buf_p); ++yy_cp ) { %% [16.0] code to find the next state goes here } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ %if-c-only static yy_state_type yy_try_NUL_trans YYFARGS1( yy_state_type, yy_current_state) %endif %if-c++-only yy_state_type yyFlexLexer::yy_try_NUL_trans( yy_state_type yy_current_state ) %endif { int yy_is_jam; M4_YY_DECL_GUTS_VAR(); /* This var may be unused depending upon options. */ %% [17.0] code to find the next state, and perhaps do backing up, goes here M4_YY_NOOP_GUTS_VAR(); return yy_is_jam ? 0 : yy_current_state; } %if-c-only m4_ifdef( [[M4_YY_NO_UNPUT]],, [[ #ifndef YY_NO_UNPUT static void yyunput YYFARGS2( int,c, char *,yy_bp) %endif %if-c++-only #ifndef YY_NO_UNPUT void yyFlexLexer::yyunput( int c, char* yy_bp) %endif { char *yy_cp; M4_YY_DECL_GUTS_VAR(); yy_cp = YY_G(yy_c_buf_p); /* undo effects of setting up yytext */ *yy_cp = YY_G(yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ yy_size_t number_to_move = YY_G(yy_n_chars) + 2; char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = YY_G(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; %% [18.0] update yylineno here m4_ifdef( [[M4_YY_USE_LINENO]], [[ if ( c == '\n' ){ --yylineno; } ]]) YY_G(yytext_ptr) = yy_bp; YY_G(yy_hold_char) = *yy_cp; YY_G(yy_c_buf_p) = yy_cp; } #endif /* ifndef YY_NO_UNPUT */ %if-c-only ]]) %endif %if-c-only #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput YYFARGS0(void) #else static int input YYFARGS0(void) #endif %endif %if-c++-only int yyFlexLexer::yyinput() %endif { int c; M4_YY_DECL_GUTS_VAR(); *YY_G(yy_c_buf_p) = YY_G(yy_hold_char); if ( *YY_G(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( YY_G(yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars)] ) /* This was really a NUL. */ *YY_G(yy_c_buf_p) = '\0'; else { /* need more input */ yy_size_t offset = YY_G(yy_c_buf_p) - YY_G(yytext_ptr); ++YY_G(yy_c_buf_p); switch ( yy_get_next_buffer( M4_YY_CALL_ONLY_ARG ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin M4_YY_CALL_LAST_ARG); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( M4_YY_CALL_ONLY_ARG ) ) return EOF; if ( ! YY_G(yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(M4_YY_CALL_ONLY_ARG); #else return input(M4_YY_CALL_ONLY_ARG); #endif } case EOB_ACT_CONTINUE_SCAN: YY_G(yy_c_buf_p) = YY_G(yytext_ptr) + offset; break; } } } c = *(unsigned char *) YY_G(yy_c_buf_p); /* cast for 8-bit char's */ *YY_G(yy_c_buf_p) = '\0'; /* preserve yytext */ YY_G(yy_hold_char) = *++YY_G(yy_c_buf_p); %% [19.0] update BOL and yylineno return c; } %if-c-only #endif /* ifndef YY_NO_INPUT */ %endif /** Immediately switch to a different input stream. * @param input_file A readable stream. * M4_YY_DOC_PARAM * @note This function does not reset the start condition to @c INITIAL . */ %if-c-only void yyrestart YYFARGS1( FILE *,input_file) %endif %if-c++-only void yyFlexLexer::yyrestart( std::istream* input_file ) %endif { M4_YY_DECL_GUTS_VAR(); if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE M4_YY_CALL_LAST_ARG); } yy_init_buffer( YY_CURRENT_BUFFER, input_file M4_YY_CALL_LAST_ARG); yy_load_buffer_state( M4_YY_CALL_ONLY_ARG ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * M4_YY_DOC_PARAM */ %if-c-only void yy_switch_to_buffer YYFARGS1( YY_BUFFER_STATE ,new_buffer) %endif %if-c++-only void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) %endif { M4_YY_DECL_GUTS_VAR(); /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *YY_G(yy_c_buf_p) = YY_G(yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = YY_G(yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = YY_G(yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( M4_YY_CALL_ONLY_ARG ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ YY_G(yy_did_buffer_switch_on_eof) = 1; } %if-c-only static void yy_load_buffer_state YYFARGS0(void) %endif %if-c++-only void yyFlexLexer::yy_load_buffer_state() %endif { M4_YY_DECL_GUTS_VAR(); YY_G(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_G(yytext_ptr) = YY_G(yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; YY_G(yy_hold_char) = *YY_G(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * M4_YY_DOC_PARAM * @return the allocated buffer state. */ %if-c-only YY_BUFFER_STATE yy_create_buffer YYFARGS2( FILE *,file, int ,size) %endif %if-c++-only YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( std::istream* file, int size ) %endif { YY_BUFFER_STATE b; m4_dnl M4_YY_DECL_GUTS_VAR(); b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) M4_YY_CALL_LAST_ARG ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc( b->yy_buf_size + 2 M4_YY_CALL_LAST_ARG ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file M4_YY_CALL_LAST_ARG); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * M4_YY_DOC_PARAM */ %if-c-only void yy_delete_buffer YYFARGS1( YY_BUFFER_STATE ,b) %endif %if-c++-only void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b ) %endif { M4_YY_DECL_GUTS_VAR(); if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree( (void *) b->yy_ch_buf M4_YY_CALL_LAST_ARG ); yyfree( (void *) b M4_YY_CALL_LAST_ARG ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ %if-c-only static void yy_init_buffer YYFARGS2( YY_BUFFER_STATE ,b, FILE *,file) %endif %if-c++-only void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, std::istream* file ) %endif { int oerrno = errno; M4_YY_DECL_GUTS_VAR(); yy_flush_buffer( b M4_YY_CALL_LAST_ARG); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } %if-c-only m4_ifdef( [[M4_YY_ALWAYS_INTERACTIVE]], [[ b->yy_is_interactive = 1; ]], [[ m4_ifdef( [[M4_YY_NEVER_INTERACTIVE]], [[ b->yy_is_interactive = 0; ]], [[ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; ]]) ]]) %endif %if-c++-only b->yy_is_interactive = 0; %endif errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * M4_YY_DOC_PARAM */ %if-c-only void yy_flush_buffer YYFARGS1( YY_BUFFER_STATE ,b) %endif %if-c++-only void yyFlexLexer::yy_flush_buffer( YY_BUFFER_STATE b ) %endif { M4_YY_DECL_GUTS_VAR(); if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( M4_YY_CALL_ONLY_ARG ); } %if-c-or-c++ /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * M4_YY_DOC_PARAM */ %if-c-only void yypush_buffer_state YYFARGS1(YY_BUFFER_STATE,new_buffer) %endif %if-c++-only void yyFlexLexer::yypush_buffer_state (YY_BUFFER_STATE new_buffer) %endif { M4_YY_DECL_GUTS_VAR(); if (new_buffer == NULL) return; yyensure_buffer_stack(M4_YY_CALL_ONLY_ARG); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *YY_G(yy_c_buf_p) = YY_G(yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = YY_G(yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = YY_G(yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) YY_G(yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( M4_YY_CALL_ONLY_ARG ); YY_G(yy_did_buffer_switch_on_eof) = 1; } %endif %if-c-or-c++ /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * M4_YY_DOC_PARAM */ %if-c-only void yypop_buffer_state YYFARGS0(void) %endif %if-c++-only void yyFlexLexer::yypop_buffer_state (void) %endif { M4_YY_DECL_GUTS_VAR(); if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG); YY_CURRENT_BUFFER_LVALUE = NULL; if (YY_G(yy_buffer_stack_top) > 0) --YY_G(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( M4_YY_CALL_ONLY_ARG ); YY_G(yy_did_buffer_switch_on_eof) = 1; } } %endif %if-c-or-c++ /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ %if-c-only static void yyensure_buffer_stack YYFARGS0(void) %endif %if-c++-only void yyFlexLexer::yyensure_buffer_stack(void) %endif { yy_size_t num_to_alloc; M4_YY_DECL_GUTS_VAR(); if (!YY_G(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; YY_G(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) M4_YY_CALL_LAST_ARG); if ( ! YY_G(yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset(YY_G(yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); YY_G(yy_buffer_stack_max) = num_to_alloc; YY_G(yy_buffer_stack_top) = 0; return; } if (YY_G(yy_buffer_stack_top) >= (YY_G(yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = YY_G(yy_buffer_stack_max) + grow_size; YY_G(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc (YY_G(yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) M4_YY_CALL_LAST_ARG); if ( ! YY_G(yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset(YY_G(yy_buffer_stack) + YY_G(yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); YY_G(yy_buffer_stack_max) = num_to_alloc; } } %endif m4_ifdef( [[M4_YY_NO_SCAN_BUFFER]],, [[ %if-c-only /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * M4_YY_DOC_PARAM * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer YYFARGS2( char *,base, yy_size_t ,size) { YY_BUFFER_STATE b; m4_dnl M4_YY_DECL_GUTS_VAR(); if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) M4_YY_CALL_LAST_ARG ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer( b M4_YY_CALL_LAST_ARG ); return b; } %endif ]]) m4_ifdef( [[M4_YY_NO_SCAN_STRING]],, [[ %if-c-only /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * M4_YY_DOC_PARAM * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string YYFARGS1( yyconst char *, yystr) { m4_dnl M4_YY_DECL_GUTS_VAR(); return yy_scan_bytes( yystr, strlen(yystr) M4_YY_CALL_LAST_ARG); } %endif ]]) m4_ifdef( [[M4_YY_NO_SCAN_BYTES]],, [[ %if-c-only /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * M4_YY_DOC_PARAM * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes YYFARGS2( yyconst char *,yybytes, yy_size_t ,_yybytes_len) { YY_BUFFER_STATE b; char *buf; yy_size_t n; yy_size_t i; m4_dnl M4_YY_DECL_GUTS_VAR(); /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) yyalloc( n M4_YY_CALL_LAST_ARG ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer( buf, n M4_YY_CALL_LAST_ARG); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } %endif ]]) m4_ifdef( [[M4_YY_NO_PUSH_STATE]],, [[ %if-c-only static void yy_push_state YYFARGS1( int ,new_state) %endif %if-c++-only void yyFlexLexer::yy_push_state( int new_state ) %endif { M4_YY_DECL_GUTS_VAR(); if ( YY_G(yy_start_stack_ptr) >= YY_G(yy_start_stack_depth) ) { yy_size_t new_size; YY_G(yy_start_stack_depth) += YY_START_STACK_INCR; new_size = YY_G(yy_start_stack_depth) * sizeof( int ); if ( ! YY_G(yy_start_stack) ) YY_G(yy_start_stack) = (int *) yyalloc( new_size M4_YY_CALL_LAST_ARG ); else YY_G(yy_start_stack) = (int *) yyrealloc( (void *) YY_G(yy_start_stack), new_size M4_YY_CALL_LAST_ARG ); if ( ! YY_G(yy_start_stack) ) YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); } YY_G(yy_start_stack)[YY_G(yy_start_stack_ptr)++] = YY_START; BEGIN(new_state); } ]]) m4_ifdef( [[M4_YY_NO_POP_STATE]],, [[ %if-c-only static void yy_pop_state YYFARGS0(void) %endif %if-c++-only void yyFlexLexer::yy_pop_state() %endif { M4_YY_DECL_GUTS_VAR(); if ( --YY_G(yy_start_stack_ptr) < 0 ) YY_FATAL_ERROR( "start-condition stack underflow" ); BEGIN(YY_G(yy_start_stack)[YY_G(yy_start_stack_ptr)]); } ]]) m4_ifdef( [[M4_YY_NO_TOP_STATE]],, [[ %if-c-only static int yy_top_state YYFARGS0(void) %endif %if-c++-only int yyFlexLexer::yy_top_state() %endif { M4_YY_DECL_GUTS_VAR(); return YY_G(yy_start_stack)[YY_G(yy_start_stack_ptr) - 1]; } ]]) #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif %if-c-only static void yy_fatal_error YYFARGS1(yyconst char*, msg) { m4_dnl M4_YY_DECL_GUTS_VAR(); (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } %endif %if-c++-only void yyFlexLexer::LexerError( yyconst char msg[] ) { M4_YY_DECL_GUTS_VAR(); std::cerr << msg << std::endl; exit( YY_EXIT_FAILURE ); } %endif /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = YY_G(yy_hold_char); \ YY_G(yy_c_buf_p) = yytext + yyless_macro_arg; \ YY_G(yy_hold_char) = *YY_G(yy_c_buf_p); \ *YY_G(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ %if-c-only %if-reentrant m4_ifdef( [[M4_YY_NO_GET_EXTRA]],, [[ /** Get the user-defined data for this scanner. * M4_YY_DOC_PARAM */ YY_EXTRA_TYPE yyget_extra YYFARGS0(void) { M4_YY_DECL_GUTS_VAR(); return yyextra; } ]]) %endif m4_ifdef( [[M4_YY_NO_GET_LINENO]],, [[ /** Get the current line number. * M4_YY_DOC_PARAM */ int yyget_lineno YYFARGS0(void) { M4_YY_DECL_GUTS_VAR(); m4_ifdef( [[M4_YY_REENTRANT]], [[ if (! YY_CURRENT_BUFFER) return 0; ]]) return yylineno; } ]]) m4_ifdef( [[M4_YY_REENTRANT]], [[ m4_ifdef( [[M4_YY_NO_GET_COLUMN]],, [[ /** Get the current column number. * M4_YY_DOC_PARAM */ int yyget_column YYFARGS0(void) { M4_YY_DECL_GUTS_VAR(); m4_ifdef( [[M4_YY_REENTRANT]], [[ if (! YY_CURRENT_BUFFER) return 0; ]]) return yycolumn; } ]]) ]]) m4_ifdef( [[M4_YY_NO_GET_IN]],, [[ /** Get the input stream. * M4_YY_DOC_PARAM */ FILE *yyget_in YYFARGS0(void) { M4_YY_DECL_GUTS_VAR(); return yyin; } ]]) m4_ifdef( [[M4_YY_NO_GET_OUT]],, [[ /** Get the output stream. * M4_YY_DOC_PARAM */ FILE *yyget_out YYFARGS0(void) { M4_YY_DECL_GUTS_VAR(); return yyout; } ]]) m4_ifdef( [[M4_YY_NO_GET_LENG]],, [[ /** Get the length of the current token. * M4_YY_DOC_PARAM */ yy_size_t yyget_leng YYFARGS0(void) { M4_YY_DECL_GUTS_VAR(); return yyleng; } ]]) /** Get the current token. * M4_YY_DOC_PARAM */ m4_ifdef( [[M4_YY_NO_GET_TEXT]],, [[ char *yyget_text YYFARGS0(void) { M4_YY_DECL_GUTS_VAR(); return yytext; } ]]) %if-reentrant m4_ifdef( [[M4_YY_NO_SET_EXTRA]],, [[ /** Set the user-defined data. This data is never touched by the scanner. * @param user_defined The data to be associated with this scanner. * M4_YY_DOC_PARAM */ void yyset_extra YYFARGS1( YY_EXTRA_TYPE ,user_defined) { M4_YY_DECL_GUTS_VAR(); yyextra = user_defined ; } ]]) %endif m4_ifdef( [[M4_YY_NO_SET_LINENO]],, [[ /** Set the current line number. * @param line_number * M4_YY_DOC_PARAM */ void yyset_lineno YYFARGS1( int ,line_number) { M4_YY_DECL_GUTS_VAR(); m4_ifdef( [[M4_YY_REENTRANT]], [[ /* lineno is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) YY_FATAL_ERROR( "yyset_lineno called with no buffer" ); ]]) yylineno = line_number; } ]]) m4_ifdef( [[M4_YY_REENTRANT]], [[ m4_ifdef( [[M4_YY_NO_SET_COLUMN]],, [[ /** Set the current column. * @param line_number * M4_YY_DOC_PARAM */ void yyset_column YYFARGS1( int , column_no) { M4_YY_DECL_GUTS_VAR(); m4_ifdef( [[M4_YY_REENTRANT]], [[ /* column is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) YY_FATAL_ERROR( "yyset_column called with no buffer" ); ]]) yycolumn = column_no; } ]]) ]]) m4_ifdef( [[M4_YY_NO_SET_IN]],, [[ /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * M4_YY_DOC_PARAM * @see yy_switch_to_buffer */ void yyset_in YYFARGS1( FILE * ,in_str) { M4_YY_DECL_GUTS_VAR(); yyin = in_str ; } ]]) m4_ifdef( [[M4_YY_NO_SET_OUT]],, [[ void yyset_out YYFARGS1( FILE * ,out_str) { M4_YY_DECL_GUTS_VAR(); yyout = out_str ; } ]]) m4_ifdef( [[M4_YY_NO_GET_DEBUG]],, [[ int yyget_debug YYFARGS0(void) { M4_YY_DECL_GUTS_VAR(); return yy_flex_debug; } ]]) m4_ifdef( [[M4_YY_NO_SET_DEBUG]],, [[ void yyset_debug YYFARGS1( int ,bdebug) { M4_YY_DECL_GUTS_VAR(); yy_flex_debug = bdebug ; } ]]) %endif %if-reentrant /* Accessor methods for yylval and yylloc */ %if-bison-bridge m4_ifdef( [[M4_YY_NO_GET_LVAL]],, [[ YYSTYPE * yyget_lval YYFARGS0(void) { M4_YY_DECL_GUTS_VAR(); return yylval; } ]]) m4_ifdef( [[M4_YY_NO_SET_LVAL]],, [[ void yyset_lval YYFARGS1( YYSTYPE * ,yylval_param) { M4_YY_DECL_GUTS_VAR(); yylval = yylval_param; } ]]) m4_ifdef( [[]], [[ m4_ifdef( [[M4_YY_NO_GET_LLOC]],, [[ YYLTYPE *yyget_lloc YYFARGS0(void) { M4_YY_DECL_GUTS_VAR(); return yylloc; } ]]) m4_ifdef( [[M4_YY_NO_SET_LLOC]],, [[ void yyset_lloc YYFARGS1( YYLTYPE * ,yylloc_param) { M4_YY_DECL_GUTS_VAR(); yylloc = yylloc_param; } ]]) ]]) %endif /* User-visible API */ /* yylex_init is special because it creates the scanner itself, so it is * the ONLY reentrant function that doesn't take the scanner as the last argument. * That's why we explicitly handle the declaration, instead of using our macros. */ m4_ifdef( [[M4_YY_NO_ANSI_FUNC_DEFS]], [[ int yylex_init( ptr_yy_globals ) yyscan_t* ptr_yy_globals; ]], [[ int yylex_init(yyscan_t* ptr_yy_globals) ]]) { if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; return 1; } /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); return yy_init_globals ( *ptr_yy_globals ); } /* yylex_init_extra has the same functionality as yylex_init, but follows the * convention of taking the scanner as the last argument. Note however, that * this is a *pointer* to a scanner, as it will be allocated by this call (and * is the reason, too, why this function also must handle its own declaration). * The user defined value in the first argument will be available to yyalloc in * the yyextra field. */ m4_ifdef( [[M4_YY_NO_ANSI_FUNC_DEFS]], [[ int yylex_init_extra( yy_user_defined, ptr_yy_globals ) YY_EXTRA_TYPE yy_user_defined; yyscan_t* ptr_yy_globals; ]], [[ int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals ) ]]) { struct yyguts_t dummy_yyguts; yyset_extra (yy_user_defined, &dummy_yyguts); if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; return 1; } /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); yyset_extra (yy_user_defined, *ptr_yy_globals); return yy_init_globals ( *ptr_yy_globals ); } %endif if-c-only %if-c-only static int yy_init_globals YYFARGS0(void) { M4_YY_DECL_GUTS_VAR(); /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ m4_ifdef( [[M4_YY_USE_LINENO]], [[ m4_ifdef( [[M4_YY_NOT_REENTRANT]], [[ /* We do not touch yylineno unless the option is enabled. */ yylineno = 1; ]]) ]]) YY_G(yy_buffer_stack) = 0; YY_G(yy_buffer_stack_top) = 0; YY_G(yy_buffer_stack_max) = 0; YY_G(yy_c_buf_p) = (char *) 0; YY_G(yy_init) = 0; YY_G(yy_start) = 0; m4_ifdef( [[M4_YY_HAS_START_STACK_VARS]], [[ YY_G(yy_start_stack_ptr) = 0; YY_G(yy_start_stack_depth) = 0; YY_G(yy_start_stack) = NULL; ]]) m4_ifdef( [[M4_YY_USES_REJECT]], [[ YY_G(yy_state_buf) = 0; YY_G(yy_state_ptr) = 0; YY_G(yy_full_match) = 0; YY_G(yy_lp) = 0; ]]) m4_ifdef( [[M4_YY_TEXT_IS_ARRAY]], [[ YY_G(yytext_ptr) = 0; YY_G(yy_more_offset) = 0; YY_G(yy_prev_more_offset) = 0; ]]) /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = (FILE *) 0; yyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } %endif %if-c-only SNIP! this currently causes conflicts with the c++ scanner /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy YYFARGS0(void) { M4_YY_DECL_GUTS_VAR(); /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer( YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(M4_YY_CALL_ONLY_ARG); } /* Destroy the stack itself. */ yyfree(YY_G(yy_buffer_stack) M4_YY_CALL_LAST_ARG); YY_G(yy_buffer_stack) = NULL; m4_ifdef( [[M4_YY_HAS_START_STACK_VARS]], [[ /* Destroy the start condition stack. */ yyfree( YY_G(yy_start_stack) M4_YY_CALL_LAST_ARG ); YY_G(yy_start_stack) = NULL; ]]) m4_ifdef( [[M4_YY_USES_REJECT]], [[ yyfree ( YY_G(yy_state_buf) M4_YY_CALL_LAST_ARG); YY_G(yy_state_buf) = NULL; ]]) /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( M4_YY_CALL_ONLY_ARG); %if-reentrant /* Destroy the main struct (reentrant only). */ yyfree ( yyscanner M4_YY_CALL_LAST_ARG ); yyscanner = NULL; %endif return 0; } %endif m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ /* * Internal utility routines. */ ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ #ifndef yytext_ptr static void yy_flex_strncpy YYFARGS3( char*,s1, yyconst char *,s2, int,n) { int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif ]]) m4_ifdef( [[M4_YY_NOT_IN_HEADER]], [[ #ifdef YY_NEED_STRLEN static int yy_flex_strlen YYFARGS1( yyconst char *,s) { int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif ]]) m4_ifdef( [[M4_YY_NO_FLEX_ALLOC]],, [[ void *yyalloc YYFARGS1( yy_size_t ,size) { return (void *) malloc( size ); } ]]) m4_ifdef( [[M4_YY_NO_FLEX_REALLOC]],, [[ void *yyrealloc YYFARGS2( void *,ptr, yy_size_t ,size) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } ]]) m4_ifdef( [[M4_YY_NO_FLEX_FREE]],, [[ void yyfree YYFARGS1( void *,ptr) { free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } ]]) %if-tables-serialization definitions m4preproc_include(`tables_shared.c') static int yytbl_read8 (void *v, struct yytbl_reader * rd) { errno = 0; if (fread (v, sizeof (flex_uint8_t), 1, rd->fp) != 1){ errno = EIO; return -1; } rd->bread += sizeof(flex_uint8_t); return 0; } static int yytbl_read16 (void *v, struct yytbl_reader * rd) { errno = 0; if (fread (v, sizeof (flex_uint16_t), 1, rd->fp) != 1){ errno = EIO; return -1; } *((flex_uint16_t *) v) = ntohs (*((flex_uint16_t *) v)); rd->bread += sizeof(flex_uint16_t); return 0; } static int yytbl_read32 (void *v, struct yytbl_reader * rd) { errno = 0; if (fread (v, sizeof (flex_uint32_t), 1, rd->fp) != 1){ errno = EIO; return -1; } *((flex_uint32_t *) v) = ntohl (*((flex_uint32_t *) v)); rd->bread += sizeof(flex_uint32_t); return 0; } /** Read the header */ static int yytbl_hdr_read YYFARGS2(struct yytbl_hdr *, th, struct yytbl_reader *, rd) { int bytes; memset (th, 0, sizeof (struct yytbl_hdr)); if (yytbl_read32 (&(th->th_magic), rd) != 0) return -1; if (th->th_magic != YYTBL_MAGIC){ YY_FATAL_ERROR( "bad magic number" ); /* TODO: not fatal. */ return -1; } if (yytbl_read32 (&(th->th_hsize), rd) != 0 || yytbl_read32 (&(th->th_ssize), rd) != 0 || yytbl_read16 (&(th->th_flags), rd) != 0) return -1; /* Sanity check on header size. Greater than 1k suggests some funny business. */ if (th->th_hsize < 16 || th->th_hsize > 1024){ YY_FATAL_ERROR( "insane header size detected" ); /* TODO: not fatal. */ return -1; } /* Allocate enough space for the version and name fields */ bytes = th->th_hsize - 14; th->th_version = (char *) yyalloc (bytes M4_YY_CALL_LAST_ARG); if ( ! th->th_version ) YY_FATAL_ERROR( "out of dynamic memory in yytbl_hdr_read()" ); /* we read it all into th_version, and point th_name into that data */ if (fread (th->th_version, 1, bytes, rd->fp) != bytes){ errno = EIO; yyfree(th->th_version M4_YY_CALL_LAST_ARG); th->th_version = NULL; return -1; } else rd->bread += bytes; th->th_name = th->th_version + strlen (th->th_version) + 1; return 0; } /** lookup id in the dmap list. * @param dmap pointer to first element in list * @return NULL if not found. */ static struct yytbl_dmap *yytbl_dmap_lookup YYFARGS2(struct yytbl_dmap *, dmap, int, id) { while (dmap->dm_id) if (dmap->dm_id == id) return dmap; else dmap++; return NULL; } /** Read a table while mapping its contents to the local array. * @param dmap used to performing mapping * @return 0 on success */ static int yytbl_data_load YYFARGS2(struct yytbl_dmap *, dmap, struct yytbl_reader*, rd) { struct yytbl_data td; struct yytbl_dmap *transdmap=0; int len, i, rv, inner_loop_count; void *p=0; memset (&td, 0, sizeof (struct yytbl_data)); if (yytbl_read16 (&td.td_id, rd) != 0 || yytbl_read16 (&td.td_flags, rd) != 0 || yytbl_read32 (&td.td_hilen, rd) != 0 || yytbl_read32 (&td.td_lolen, rd) != 0) return -1; /* Lookup the map for the transition table so we have it in case we need it * inside the loop below. This scanner might not even have a transition * table, which is ok. */ transdmap = yytbl_dmap_lookup (dmap, YYTD_ID_TRANSITION M4_YY_CALL_LAST_ARG); if ((dmap = yytbl_dmap_lookup (dmap, td.td_id M4_YY_CALL_LAST_ARG)) == NULL){ YY_FATAL_ERROR( "table id not found in map." ); /* TODO: not fatal. */ return -1; } /* Allocate space for table. * The --full yy_transition table is a special case, since we * need the dmap.dm_sz entry to tell us the sizeof the individual * struct members. */ { size_t bytes; if ((td.td_flags & YYTD_STRUCT)) bytes = sizeof(struct yy_trans_info) * td.td_lolen * (td.td_hilen ? td.td_hilen : 1); else bytes = td.td_lolen * (td.td_hilen ? td.td_hilen : 1) * dmap->dm_sz; if(M4_YY_TABLES_VERIFY) /* We point to the array itself */ p = dmap->dm_arr; else /* We point to the address of a pointer. */ *dmap->dm_arr = p = (void *) yyalloc (bytes M4_YY_CALL_LAST_ARG); if ( ! p ) YY_FATAL_ERROR( "out of dynamic memory in yytbl_data_load()" ); } /* If it's a struct, we read 2 integers to get one element */ if ((td.td_flags & YYTD_STRUCT) != 0) inner_loop_count = 2; else inner_loop_count = 1; /* read and map each element. * This loop iterates once for each element of the td_data array. * Notice that we increment 'i' in the inner loop. */ len = yytbl_calc_total_len (&td); for (i = 0; i < len; ){ int j; /* This loop really executes exactly 1 or 2 times. * The second time is to handle the second member of the * YYTD_STRUCT for the yy_transition array. */ for (j = 0; j < inner_loop_count; j++, i++) { flex_int32_t t32; /* read into t32 no matter what the real size is. */ { flex_int16_t t16; flex_int8_t t8; switch (YYTDFLAGS2BYTES (td.td_flags)) { case sizeof (flex_int32_t): rv = yytbl_read32 (&t32, rd); break; case sizeof (flex_int16_t): rv = yytbl_read16 (&t16, rd); t32 = t16; break; case sizeof (flex_int8_t): rv = yytbl_read8 (&t8, rd); t32 = t8; break; default: YY_FATAL_ERROR( "invalid td_flags" ); /* TODO: not fatal. */ return -1; } } if (rv != 0) return -1; /* copy into the deserialized array... */ if ((td.td_flags & YYTD_STRUCT)) { /* t32 is the j'th member of a two-element struct. */ void *v; v = j == 0 ? &(((struct yy_trans_info *) p)->yy_verify) : &(((struct yy_trans_info *) p)->yy_nxt); switch (dmap->dm_sz) { case sizeof (flex_int32_t): if (M4_YY_TABLES_VERIFY){ if( ((flex_int32_t *) v)[0] != (flex_int32_t) t32) YY_FATAL_ERROR( "tables verification failed at YYTD_STRUCT flex_int32_t" ); }else ((flex_int32_t *) v)[0] = (flex_int32_t) t32; break; case sizeof (flex_int16_t): if (M4_YY_TABLES_VERIFY ){ if(((flex_int16_t *) v)[0] != (flex_int16_t) t32) YY_FATAL_ERROR( "tables verification failed at YYTD_STRUCT flex_int16_t" ); }else ((flex_int16_t *) v)[0] = (flex_int16_t) t32; break; case sizeof(flex_int8_t): if (M4_YY_TABLES_VERIFY ){ if( ((flex_int8_t *) v)[0] != (flex_int8_t) t32) YY_FATAL_ERROR( "tables verification failed at YYTD_STRUCT flex_int8_t" ); }else ((flex_int8_t *) v)[0] = (flex_int8_t) t32; break; default: YY_FATAL_ERROR( "invalid dmap->dm_sz for struct" ); /* TODO: not fatal. */ return -1; } /* if we're done with j, increment p */ if (j == 1) p = (struct yy_trans_info *) p + 1; } else if ((td.td_flags & YYTD_PTRANS)) { /* t32 is an index into the transition array. */ struct yy_trans_info *v; if (!transdmap){ YY_FATAL_ERROR( "transition table not found" ); /* TODO: not fatal. */ return -1; } if( M4_YY_TABLES_VERIFY) v = &(((struct yy_trans_info *) (transdmap->dm_arr))[t32]); else v = &((*((struct yy_trans_info **) (transdmap->dm_arr)))[t32]); if(M4_YY_TABLES_VERIFY ){ if( ((struct yy_trans_info **) p)[0] != v) YY_FATAL_ERROR( "tables verification failed at YYTD_PTRANS" ); }else ((struct yy_trans_info **) p)[0] = v; /* increment p */ p = (struct yy_trans_info **) p + 1; } else { /* t32 is a plain int. copy data, then incrememnt p. */ switch (dmap->dm_sz) { case sizeof (flex_int32_t): if(M4_YY_TABLES_VERIFY ){ if( ((flex_int32_t *) p)[0] != (flex_int32_t) t32) YY_FATAL_ERROR( "tables verification failed at flex_int32_t" ); }else ((flex_int32_t *) p)[0] = (flex_int32_t) t32; p = ((flex_int32_t *) p) + 1; break; case sizeof (flex_int16_t): if(M4_YY_TABLES_VERIFY ){ if( ((flex_int16_t *) p)[0] != (flex_int16_t) t32) YY_FATAL_ERROR( "tables verification failed at flex_int16_t" ); }else ((flex_int16_t *) p)[0] = (flex_int16_t) t32; p = ((flex_int16_t *) p) + 1; break; case sizeof (flex_int8_t): if(M4_YY_TABLES_VERIFY ){ if( ((flex_int8_t *) p)[0] != (flex_int8_t) t32) YY_FATAL_ERROR( "tables verification failed at flex_int8_t" ); }else ((flex_int8_t *) p)[0] = (flex_int8_t) t32; p = ((flex_int8_t *) p) + 1; break; default: YY_FATAL_ERROR( "invalid dmap->dm_sz for plain int" ); /* TODO: not fatal. */ return -1; } } } } /* Now eat padding. */ { int pad; pad = yypad64(rd->bread); while(--pad >= 0){ flex_int8_t t8; if(yytbl_read8(&t8,rd) != 0) return -1; } } return 0; } %define-yytables The name for this specific scanner's tables. /* Find the key and load the DFA tables from the given stream. */ static int yytbl_fload YYFARGS2(FILE *, fp, const char *, key) { int rv=0; struct yytbl_hdr th; struct yytbl_reader rd; rd.fp = fp; th.th_version = NULL; /* Keep trying until we find the right set of tables or end of file. */ while (!feof(rd.fp)) { rd.bread = 0; if (yytbl_hdr_read (&th, &rd M4_YY_CALL_LAST_ARG) != 0){ rv = -1; goto return_rv; } /* A NULL key means choose the first set of tables. */ if (key == NULL) break; if (strcmp(th.th_name,key) != 0){ /* Skip ahead to next set */ fseek(rd.fp, th.th_ssize - th.th_hsize, SEEK_CUR); yyfree(th.th_version M4_YY_CALL_LAST_ARG); th.th_version = NULL; } else break; } while (rd.bread < th.th_ssize){ /* Load the data tables */ if(yytbl_data_load (yydmap,&rd M4_YY_CALL_LAST_ARG) != 0){ rv = -1; goto return_rv; } } return_rv: if(th.th_version){ yyfree(th.th_version M4_YY_CALL_LAST_ARG); th.th_version = NULL; } return rv; } /** Load the DFA tables for this scanner from the given stream. */ int yytables_fload YYFARGS1(FILE *, fp) { if( yytbl_fload(fp, YYTABLES_NAME M4_YY_CALL_LAST_ARG) != 0) return -1; return 0; } /** Destroy the loaded tables, freeing memory, etc.. */ int yytables_destroy YYFARGS0(void) { struct yytbl_dmap *dmap=0; if(!M4_YY_TABLES_VERIFY){ /* Walk the dmap, freeing the pointers */ for(dmap=yydmap; dmap->dm_id; dmap++) { void * v; v = dmap->dm_arr; if(v && *(char**)v){ yyfree(*(char**)v M4_YY_CALL_LAST_ARG); *(char**)v = NULL; } } } return 0; } /* end table serialization code definitions */ %endif m4_ifdef([[M4_YY_MAIN]], [[ int main M4_YY_PARAMS(void); int main () { %if-reentrant yyscan_t lexer; yylex_init(&lexer); yylex( lexer ); yylex_destroy( lexer); %endif %if-not-reentrant yylex(); %endif return 0; } ]]) %ok-for-header m4_ifdef( [[M4_YY_IN_HEADER]], [[ #undef YY_NEW_FILE #undef YY_FLUSH_BUFFER #undef yy_set_bol #undef yy_new_buffer #undef yy_set_interactive #undef YY_DO_BEFORE_ACTION #ifdef YY_DECL_IS_OURS #undef YY_DECL_IS_OURS #undef YY_DECL #endif ]]) freebsd-buildutils-10.0/src/contrib/flex/dfa.c0000644000000000000000000006515712146743317016221 0ustar /* dfa - DFA construction routines */ /* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */ /* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */ /* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #include "flexdef.h" #include "tables.h" /* declare functions that have forward references */ void dump_associated_rules PROTO ((FILE *, int)); void dump_transitions PROTO ((FILE *, int[])); void sympartition PROTO ((int[], int, int[], int[])); int symfollowset PROTO ((int[], int, int, int[])); /* check_for_backing_up - check a DFA state for backing up * * synopsis * void check_for_backing_up( int ds, int state[numecs] ); * * ds is the number of the state to check and state[] is its out-transitions, * indexed by equivalence class. */ void check_for_backing_up (ds, state) int ds; int state[]; { if ((reject && !dfaacc[ds].dfaacc_set) || (!reject && !dfaacc[ds].dfaacc_state)) { /* state is non-accepting */ ++num_backing_up; if (backing_up_report) { fprintf (backing_up_file, _("State #%d is non-accepting -\n"), ds); /* identify the state */ dump_associated_rules (backing_up_file, ds); /* Now identify it further using the out- and * jam-transitions. */ dump_transitions (backing_up_file, state); putc ('\n', backing_up_file); } } } /* check_trailing_context - check to see if NFA state set constitutes * "dangerous" trailing context * * synopsis * void check_trailing_context( int nfa_states[num_states+1], int num_states, * int accset[nacc+1], int nacc ); * * NOTES * Trailing context is "dangerous" if both the head and the trailing * part are of variable size \and/ there's a DFA state which contains * both an accepting state for the head part of the rule and NFA states * which occur after the beginning of the trailing context. * * When such a rule is matched, it's impossible to tell if having been * in the DFA state indicates the beginning of the trailing context or * further-along scanning of the pattern. In these cases, a warning * message is issued. * * nfa_states[1 .. num_states] is the list of NFA states in the DFA. * accset[1 .. nacc] is the list of accepting numbers for the DFA state. */ void check_trailing_context (nfa_states, num_states, accset, nacc) int *nfa_states, num_states; int *accset; int nacc; { int i, j; for (i = 1; i <= num_states; ++i) { int ns = nfa_states[i]; int type = state_type[ns]; int ar = assoc_rule[ns]; if (type == STATE_NORMAL || rule_type[ar] != RULE_VARIABLE) { /* do nothing */ } else if (type == STATE_TRAILING_CONTEXT) { /* Potential trouble. Scan set of accepting numbers * for the one marking the end of the "head". We * assume that this looping will be fairly cheap * since it's rare that an accepting number set * is large. */ for (j = 1; j <= nacc; ++j) if (accset[j] & YY_TRAILING_HEAD_MASK) { line_warning (_ ("dangerous trailing context"), rule_linenum[ar]); return; } } } } /* dump_associated_rules - list the rules associated with a DFA state * * Goes through the set of NFA states associated with the DFA and * extracts the first MAX_ASSOC_RULES unique rules, sorts them, * and writes a report to the given file. */ void dump_associated_rules (file, ds) FILE *file; int ds; { int i, j; int num_associated_rules = 0; int rule_set[MAX_ASSOC_RULES + 1]; int *dset = dss[ds]; int size = dfasiz[ds]; for (i = 1; i <= size; ++i) { int rule_num = rule_linenum[assoc_rule[dset[i]]]; for (j = 1; j <= num_associated_rules; ++j) if (rule_num == rule_set[j]) break; if (j > num_associated_rules) { /* new rule */ if (num_associated_rules < MAX_ASSOC_RULES) rule_set[++num_associated_rules] = rule_num; } } qsort (&rule_set [1], num_associated_rules, sizeof (rule_set [1]), intcmp); fprintf (file, _(" associated rule line numbers:")); for (i = 1; i <= num_associated_rules; ++i) { if (i % 8 == 1) putc ('\n', file); fprintf (file, "\t%d", rule_set[i]); } putc ('\n', file); } /* dump_transitions - list the transitions associated with a DFA state * * synopsis * dump_transitions( FILE *file, int state[numecs] ); * * Goes through the set of out-transitions and lists them in human-readable * form (i.e., not as equivalence classes); also lists jam transitions * (i.e., all those which are not out-transitions, plus EOF). The dump * is done to the given file. */ void dump_transitions (file, state) FILE *file; int state[]; { int i, ec; int out_char_set[CSIZE]; for (i = 0; i < csize; ++i) { ec = ABS (ecgroup[i]); out_char_set[i] = state[ec]; } fprintf (file, _(" out-transitions: ")); list_character_set (file, out_char_set); /* now invert the members of the set to get the jam transitions */ for (i = 0; i < csize; ++i) out_char_set[i] = !out_char_set[i]; fprintf (file, _("\n jam-transitions: EOF ")); list_character_set (file, out_char_set); putc ('\n', file); } /* epsclosure - construct the epsilon closure of a set of ndfa states * * synopsis * int *epsclosure( int t[num_states], int *numstates_addr, * int accset[num_rules+1], int *nacc_addr, * int *hashval_addr ); * * NOTES * The epsilon closure is the set of all states reachable by an arbitrary * number of epsilon transitions, which themselves do not have epsilon * transitions going out, unioned with the set of states which have non-null * accepting numbers. t is an array of size numstates of nfa state numbers. * Upon return, t holds the epsilon closure and *numstates_addr is updated. * accset holds a list of the accepting numbers, and the size of accset is * given by *nacc_addr. t may be subjected to reallocation if it is not * large enough to hold the epsilon closure. * * hashval is the hash value for the dfa corresponding to the state set. */ int *epsclosure (t, ns_addr, accset, nacc_addr, hv_addr) int *t, *ns_addr, accset[], *nacc_addr, *hv_addr; { int stkpos, ns, tsp; int numstates = *ns_addr, nacc, hashval, transsym, nfaccnum; int stkend, nstate; static int did_stk_init = false, *stk; #define MARK_STATE(state) \ do{ trans1[state] = trans1[state] - MARKER_DIFFERENCE;} while(0) #define IS_MARKED(state) (trans1[state] < 0) #define UNMARK_STATE(state) \ do{ trans1[state] = trans1[state] + MARKER_DIFFERENCE;} while(0) #define CHECK_ACCEPT(state) \ do{ \ nfaccnum = accptnum[state]; \ if ( nfaccnum != NIL ) \ accset[++nacc] = nfaccnum; \ }while(0) #define DO_REALLOCATION() \ do { \ current_max_dfa_size += MAX_DFA_SIZE_INCREMENT; \ ++num_reallocs; \ t = reallocate_integer_array( t, current_max_dfa_size ); \ stk = reallocate_integer_array( stk, current_max_dfa_size ); \ }while(0) \ #define PUT_ON_STACK(state) \ do { \ if ( ++stkend >= current_max_dfa_size ) \ DO_REALLOCATION(); \ stk[stkend] = state; \ MARK_STATE(state); \ }while(0) #define ADD_STATE(state) \ do { \ if ( ++numstates >= current_max_dfa_size ) \ DO_REALLOCATION(); \ t[numstates] = state; \ hashval += state; \ }while(0) #define STACK_STATE(state) \ do { \ PUT_ON_STACK(state); \ CHECK_ACCEPT(state); \ if ( nfaccnum != NIL || transchar[state] != SYM_EPSILON ) \ ADD_STATE(state); \ }while(0) if (!did_stk_init) { stk = allocate_integer_array (current_max_dfa_size); did_stk_init = true; } nacc = stkend = hashval = 0; for (nstate = 1; nstate <= numstates; ++nstate) { ns = t[nstate]; /* The state could be marked if we've already pushed it onto * the stack. */ if (!IS_MARKED (ns)) { PUT_ON_STACK (ns); CHECK_ACCEPT (ns); hashval += ns; } } for (stkpos = 1; stkpos <= stkend; ++stkpos) { ns = stk[stkpos]; transsym = transchar[ns]; if (transsym == SYM_EPSILON) { tsp = trans1[ns] + MARKER_DIFFERENCE; if (tsp != NO_TRANSITION) { if (!IS_MARKED (tsp)) STACK_STATE (tsp); tsp = trans2[ns]; if (tsp != NO_TRANSITION && !IS_MARKED (tsp)) STACK_STATE (tsp); } } } /* Clear out "visit" markers. */ for (stkpos = 1; stkpos <= stkend; ++stkpos) { if (IS_MARKED (stk[stkpos])) UNMARK_STATE (stk[stkpos]); else flexfatal (_ ("consistency check failed in epsclosure()")); } *ns_addr = numstates; *hv_addr = hashval; *nacc_addr = nacc; return t; } /* increase_max_dfas - increase the maximum number of DFAs */ void increase_max_dfas () { current_max_dfas += MAX_DFAS_INCREMENT; ++num_reallocs; base = reallocate_integer_array (base, current_max_dfas); def = reallocate_integer_array (def, current_max_dfas); dfasiz = reallocate_integer_array (dfasiz, current_max_dfas); accsiz = reallocate_integer_array (accsiz, current_max_dfas); dhash = reallocate_integer_array (dhash, current_max_dfas); dss = reallocate_int_ptr_array (dss, current_max_dfas); dfaacc = reallocate_dfaacc_union (dfaacc, current_max_dfas); if (nultrans) nultrans = reallocate_integer_array (nultrans, current_max_dfas); } /* ntod - convert an ndfa to a dfa * * Creates the dfa corresponding to the ndfa we've constructed. The * dfa starts out in state #1. */ void ntod () { int *accset, ds, nacc, newds; int sym, hashval, numstates, dsize; int num_full_table_rows=0; /* used only for -f */ int *nset, *dset; int targptr, totaltrans, i, comstate, comfreq, targ; int symlist[CSIZE + 1]; int num_start_states; int todo_head, todo_next; struct yytbl_data *yynxt_tbl = 0; flex_int32_t *yynxt_data = 0, yynxt_curr = 0; /* Note that the following are indexed by *equivalence classes* * and not by characters. Since equivalence classes are indexed * beginning with 1, even if the scanner accepts NUL's, this * means that (since every character is potentially in its own * equivalence class) these arrays must have room for indices * from 1 to CSIZE, so their size must be CSIZE + 1. */ int duplist[CSIZE + 1], state[CSIZE + 1]; int targfreq[CSIZE + 1], targstate[CSIZE + 1]; /* accset needs to be large enough to hold all of the rules present * in the input, *plus* their YY_TRAILING_HEAD_MASK variants. */ accset = allocate_integer_array ((num_rules + 1) * 2); nset = allocate_integer_array (current_max_dfa_size); /* The "todo" queue is represented by the head, which is the DFA * state currently being processed, and the "next", which is the * next DFA state number available (not in use). We depend on the * fact that snstods() returns DFA's \in increasing order/, and thus * need only know the bounds of the dfas to be processed. */ todo_head = todo_next = 0; for (i = 0; i <= csize; ++i) { duplist[i] = NIL; symlist[i] = false; } for (i = 0; i <= num_rules; ++i) accset[i] = NIL; if (trace) { dumpnfa (scset[1]); fputs (_("\n\nDFA Dump:\n\n"), stderr); } inittbl (); /* Check to see whether we should build a separate table for * transitions on NUL characters. We don't do this for full-speed * (-F) scanners, since for them we don't have a simple state * number lying around with which to index the table. We also * don't bother doing it for scanners unless (1) NUL is in its own * equivalence class (indicated by a positive value of * ecgroup[NUL]), (2) NUL's equivalence class is the last * equivalence class, and (3) the number of equivalence classes is * the same as the number of characters. This latter case comes * about when useecs is false or when it's true but every character * still manages to land in its own class (unlikely, but it's * cheap to check for). If all these things are true then the * character code needed to represent NUL's equivalence class for * indexing the tables is going to take one more bit than the * number of characters, and therefore we won't be assured of * being able to fit it into a YY_CHAR variable. This rules out * storing the transitions in a compressed table, since the code * for interpreting them uses a YY_CHAR variable (perhaps it * should just use an integer, though; this is worth pondering ... * ###). * * Finally, for full tables, we want the number of entries in the * table to be a power of two so the array references go fast (it * will just take a shift to compute the major index). If * encoding NUL's transitions in the table will spoil this, we * give it its own table (note that this will be the case if we're * not using equivalence classes). */ /* Note that the test for ecgroup[0] == numecs below accomplishes * both (1) and (2) above */ if (!fullspd && ecgroup[0] == numecs) { /* NUL is alone in its equivalence class, which is the * last one. */ int use_NUL_table = (numecs == csize); if (fulltbl && !use_NUL_table) { /* We still may want to use the table if numecs * is a power of 2. */ int power_of_two; for (power_of_two = 1; power_of_two <= csize; power_of_two *= 2) if (numecs == power_of_two) { use_NUL_table = true; break; } } if (use_NUL_table) nultrans = allocate_integer_array (current_max_dfas); /* From now on, nultrans != nil indicates that we're * saving null transitions for later, separate encoding. */ } if (fullspd) { for (i = 0; i <= numecs; ++i) state[i] = 0; place_state (state, 0, 0); dfaacc[0].dfaacc_state = 0; } else if (fulltbl) { if (nultrans) /* We won't be including NUL's transitions in the * table, so build it for entries from 0 .. numecs - 1. */ num_full_table_rows = numecs; else /* Take into account the fact that we'll be including * the NUL entries in the transition table. Build it * from 0 .. numecs. */ num_full_table_rows = numecs + 1; /* Begin generating yy_nxt[][] * This spans the entire LONG function. * This table is tricky because we don't know how big it will be. * So we'll have to realloc() on the way... * we'll wait until we can calculate yynxt_tbl->td_hilen. */ yynxt_tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); yytbl_data_init (yynxt_tbl, YYTD_ID_NXT); yynxt_tbl->td_hilen = 1; yynxt_tbl->td_lolen = num_full_table_rows; yynxt_tbl->td_data = yynxt_data = (flex_int32_t *) calloc (yynxt_tbl->td_lolen * yynxt_tbl->td_hilen, sizeof (flex_int32_t)); yynxt_curr = 0; buf_prints (&yydmap_buf, "\t{YYTD_ID_NXT, (void**)&yy_nxt, sizeof(%s)},\n", long_align ? "flex_int32_t" : "flex_int16_t"); /* Unless -Ca, declare it "short" because it's a real * long-shot that that won't be large enough. */ if (gentables) out_str_dec ("static yyconst %s yy_nxt[][%d] =\n {\n", long_align ? "flex_int32_t" : "flex_int16_t", num_full_table_rows); else { out_dec ("#undef YY_NXT_LOLEN\n#define YY_NXT_LOLEN (%d)\n", num_full_table_rows); out_str ("static yyconst %s *yy_nxt =0;\n", long_align ? "flex_int32_t" : "flex_int16_t"); } if (gentables) outn (" {"); /* Generate 0 entries for state #0. */ for (i = 0; i < num_full_table_rows; ++i) { mk2data (0); yynxt_data[yynxt_curr++] = 0; } dataflush (); if (gentables) outn (" },\n"); } /* Create the first states. */ num_start_states = lastsc * 2; for (i = 1; i <= num_start_states; ++i) { numstates = 1; /* For each start condition, make one state for the case when * we're at the beginning of the line (the '^' operator) and * one for the case when we're not. */ if (i % 2 == 1) nset[numstates] = scset[(i / 2) + 1]; else nset[numstates] = mkbranch (scbol[i / 2], scset[i / 2]); nset = epsclosure (nset, &numstates, accset, &nacc, &hashval); if (snstods (nset, numstates, accset, nacc, hashval, &ds)) { numas += nacc; totnst += numstates; ++todo_next; if (variable_trailing_context_rules && nacc > 0) check_trailing_context (nset, numstates, accset, nacc); } } if (!fullspd) { if (!snstods (nset, 0, accset, 0, 0, &end_of_buffer_state)) flexfatal (_ ("could not create unique end-of-buffer state")); ++numas; ++num_start_states; ++todo_next; } while (todo_head < todo_next) { targptr = 0; totaltrans = 0; for (i = 1; i <= numecs; ++i) state[i] = 0; ds = ++todo_head; dset = dss[ds]; dsize = dfasiz[ds]; if (trace) fprintf (stderr, _("state # %d:\n"), ds); sympartition (dset, dsize, symlist, duplist); for (sym = 1; sym <= numecs; ++sym) { if (symlist[sym]) { symlist[sym] = 0; if (duplist[sym] == NIL) { /* Symbol has unique out-transitions. */ numstates = symfollowset (dset, dsize, sym, nset); nset = epsclosure (nset, &numstates, accset, &nacc, &hashval); if (snstods (nset, numstates, accset, nacc, hashval, &newds)) { totnst = totnst + numstates; ++todo_next; numas += nacc; if (variable_trailing_context_rules && nacc > 0) check_trailing_context (nset, numstates, accset, nacc); } state[sym] = newds; if (trace) fprintf (stderr, "\t%d\t%d\n", sym, newds); targfreq[++targptr] = 1; targstate[targptr] = newds; ++numuniq; } else { /* sym's equivalence class has the same * transitions as duplist(sym)'s * equivalence class. */ targ = state[duplist[sym]]; state[sym] = targ; if (trace) fprintf (stderr, "\t%d\t%d\n", sym, targ); /* Update frequency count for * destination state. */ i = 0; while (targstate[++i] != targ) ; ++targfreq[i]; ++numdup; } ++totaltrans; duplist[sym] = NIL; } } numsnpairs += totaltrans; if (ds > num_start_states) check_for_backing_up (ds, state); if (nultrans) { nultrans[ds] = state[NUL_ec]; state[NUL_ec] = 0; /* remove transition */ } if (fulltbl) { /* Each time we hit here, it's another td_hilen, so we realloc. */ yynxt_tbl->td_hilen++; yynxt_tbl->td_data = yynxt_data = (flex_int32_t *) realloc (yynxt_data, yynxt_tbl->td_hilen * yynxt_tbl->td_lolen * sizeof (flex_int32_t)); if (gentables) outn (" {"); /* Supply array's 0-element. */ if (ds == end_of_buffer_state) { mk2data (-end_of_buffer_state); yynxt_data[yynxt_curr++] = -end_of_buffer_state; } else { mk2data (end_of_buffer_state); yynxt_data[yynxt_curr++] = end_of_buffer_state; } for (i = 1; i < num_full_table_rows; ++i) { /* Jams are marked by negative of state * number. */ mk2data (state[i] ? state[i] : -ds); yynxt_data[yynxt_curr++] = state[i] ? state[i] : -ds; } dataflush (); if (gentables) outn (" },\n"); } else if (fullspd) place_state (state, ds, totaltrans); else if (ds == end_of_buffer_state) /* Special case this state to make sure it does what * it's supposed to, i.e., jam on end-of-buffer. */ stack1 (ds, 0, 0, JAMSTATE); else { /* normal, compressed state */ /* Determine which destination state is the most * common, and how many transitions to it there are. */ comfreq = 0; comstate = 0; for (i = 1; i <= targptr; ++i) if (targfreq[i] > comfreq) { comfreq = targfreq[i]; comstate = targstate[i]; } bldtbl (state, ds, totaltrans, comstate, comfreq); } } if (fulltbl) { dataend (); if (tablesext) { yytbl_data_compress (yynxt_tbl); if (yytbl_data_fwrite (&tableswr, yynxt_tbl) < 0) flexerror (_ ("Could not write yynxt_tbl[][]")); } if (yynxt_tbl) { yytbl_data_destroy (yynxt_tbl); yynxt_tbl = 0; } } else if (!fullspd) { cmptmps (); /* create compressed template entries */ /* Create tables for all the states with only one * out-transition. */ while (onesp > 0) { mk1tbl (onestate[onesp], onesym[onesp], onenext[onesp], onedef[onesp]); --onesp; } mkdeftbl (); } flex_free ((void *) accset); flex_free ((void *) nset); } /* snstods - converts a set of ndfa states into a dfa state * * synopsis * is_new_state = snstods( int sns[numstates], int numstates, * int accset[num_rules+1], int nacc, * int hashval, int *newds_addr ); * * On return, the dfa state number is in newds. */ int snstods (sns, numstates, accset, nacc, hashval, newds_addr) int sns[], numstates, accset[], nacc, hashval, *newds_addr; { int didsort = 0; int i, j; int newds, *oldsns; for (i = 1; i <= lastdfa; ++i) if (hashval == dhash[i]) { if (numstates == dfasiz[i]) { oldsns = dss[i]; if (!didsort) { /* We sort the states in sns so we * can compare it to oldsns quickly. */ qsort (&sns [1], numstates, sizeof (sns [1]), intcmp); didsort = 1; } for (j = 1; j <= numstates; ++j) if (sns[j] != oldsns[j]) break; if (j > numstates) { ++dfaeql; *newds_addr = i; return 0; } ++hshcol; } else ++hshsave; } /* Make a new dfa. */ if (++lastdfa >= current_max_dfas) increase_max_dfas (); newds = lastdfa; dss[newds] = allocate_integer_array (numstates + 1); /* If we haven't already sorted the states in sns, we do so now, * so that future comparisons with it can be made quickly. */ if (!didsort) qsort (&sns [1], numstates, sizeof (sns [1]), intcmp); for (i = 1; i <= numstates; ++i) dss[newds][i] = sns[i]; dfasiz[newds] = numstates; dhash[newds] = hashval; if (nacc == 0) { if (reject) dfaacc[newds].dfaacc_set = (int *) 0; else dfaacc[newds].dfaacc_state = 0; accsiz[newds] = 0; } else if (reject) { /* We sort the accepting set in increasing order so the * disambiguating rule that the first rule listed is considered * match in the event of ties will work. */ qsort (&accset [1], nacc, sizeof (accset [1]), intcmp); dfaacc[newds].dfaacc_set = allocate_integer_array (nacc + 1); /* Save the accepting set for later */ for (i = 1; i <= nacc; ++i) { dfaacc[newds].dfaacc_set[i] = accset[i]; if (accset[i] <= num_rules) /* Who knows, perhaps a REJECT can yield * this rule. */ rule_useful[accset[i]] = true; } accsiz[newds] = nacc; } else { /* Find lowest numbered rule so the disambiguating rule * will work. */ j = num_rules + 1; for (i = 1; i <= nacc; ++i) if (accset[i] < j) j = accset[i]; dfaacc[newds].dfaacc_state = j; if (j <= num_rules) rule_useful[j] = true; } *newds_addr = newds; return 1; } /* symfollowset - follow the symbol transitions one step * * synopsis * numstates = symfollowset( int ds[current_max_dfa_size], int dsize, * int transsym, int nset[current_max_dfa_size] ); */ int symfollowset (ds, dsize, transsym, nset) int ds[], dsize, transsym, nset[]; { int ns, tsp, sym, i, j, lenccl, ch, numstates, ccllist; numstates = 0; for (i = 1; i <= dsize; ++i) { /* for each nfa state ns in the state set of ds */ ns = ds[i]; sym = transchar[ns]; tsp = trans1[ns]; if (sym < 0) { /* it's a character class */ sym = -sym; ccllist = cclmap[sym]; lenccl = ccllen[sym]; if (cclng[sym]) { for (j = 0; j < lenccl; ++j) { /* Loop through negated character * class. */ ch = ccltbl[ccllist + j]; if (ch == 0) ch = NUL_ec; if (ch > transsym) /* Transsym isn't in negated * ccl. */ break; else if (ch == transsym) /* next 2 */ goto bottom; } /* Didn't find transsym in ccl. */ nset[++numstates] = tsp; } else for (j = 0; j < lenccl; ++j) { ch = ccltbl[ccllist + j]; if (ch == 0) ch = NUL_ec; if (ch > transsym) break; else if (ch == transsym) { nset[++numstates] = tsp; break; } } } else if (sym == SYM_EPSILON) { /* do nothing */ } else if (ABS (ecgroup[sym]) == transsym) nset[++numstates] = tsp; bottom:; } return numstates; } /* sympartition - partition characters with same out-transitions * * synopsis * sympartition( int ds[current_max_dfa_size], int numstates, * int symlist[numecs], int duplist[numecs] ); */ void sympartition (ds, numstates, symlist, duplist) int ds[], numstates; int symlist[], duplist[]; { int tch, i, j, k, ns, dupfwd[CSIZE + 1], lenccl, cclp, ich; /* Partitioning is done by creating equivalence classes for those * characters which have out-transitions from the given state. Thus * we are really creating equivalence classes of equivalence classes. */ for (i = 1; i <= numecs; ++i) { /* initialize equivalence class list */ duplist[i] = i - 1; dupfwd[i] = i + 1; } duplist[1] = NIL; dupfwd[numecs] = NIL; for (i = 1; i <= numstates; ++i) { ns = ds[i]; tch = transchar[ns]; if (tch != SYM_EPSILON) { if (tch < -lastccl || tch >= csize) { flexfatal (_ ("bad transition character detected in sympartition()")); } if (tch >= 0) { /* character transition */ int ec = ecgroup[tch]; mkechar (ec, dupfwd, duplist); symlist[ec] = 1; } else { /* character class */ tch = -tch; lenccl = ccllen[tch]; cclp = cclmap[tch]; mkeccl (ccltbl + cclp, lenccl, dupfwd, duplist, numecs, NUL_ec); if (cclng[tch]) { j = 0; for (k = 0; k < lenccl; ++k) { ich = ccltbl[cclp + k]; if (ich == 0) ich = NUL_ec; for (++j; j < ich; ++j) symlist[j] = 1; } for (++j; j <= numecs; ++j) symlist[j] = 1; } else for (k = 0; k < lenccl; ++k) { ich = ccltbl[cclp + k]; if (ich == 0) ich = NUL_ec; symlist[ich] = 1; } } } } } freebsd-buildutils-10.0/src/contrib/flex/scanopt.c0000644000000000000000000004763212146741165017133 0ustar /* flex - tool to generate fast lexical analyzers */ /* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */ /* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */ /* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #include "flexdef.h" #include "scanopt.h" /* Internal structures */ #ifdef HAVE_STRCASECMP #define STRCASECMP(a,b) strcasecmp(a,b) #else static int STRCASECMP PROTO ((const char *, const char *)); static int STRCASECMP (a, b) const char *a; const char *b; { while (tolower (*a++) == tolower (*b++)) ; return b - a; } #endif #define ARG_NONE 0x01 #define ARG_REQ 0x02 #define ARG_OPT 0x04 #define IS_LONG 0x08 struct _aux { int flags; /* The above hex flags. */ int namelen; /* Length of the actual option word, e.g., "--file[=foo]" is 4 */ int printlen; /* Length of entire string, e.g., "--file[=foo]" is 12 */ }; struct _scanopt_t { const optspec_t *options; /* List of options. */ struct _aux *aux; /* Auxiliary data about options. */ int optc; /* Number of options. */ int argc; /* Number of args. */ char **argv; /* Array of strings. */ int index; /* Used as: argv[index][subscript]. */ int subscript; char no_err_msg; /* If true, do not print errors. */ char has_long; char has_short; }; /* Accessor functions. These WOULD be one-liners, but portability calls. */ static const char *NAME PROTO ((struct _scanopt_t *, int)); static int PRINTLEN PROTO ((struct _scanopt_t *, int)); static int RVAL PROTO ((struct _scanopt_t *, int)); static int FLAGS PROTO ((struct _scanopt_t *, int)); static const char *DESC PROTO ((struct _scanopt_t *, int)); static int scanopt_err PROTO ((struct _scanopt_t *, int, int, int)); static int matchlongopt PROTO ((char *, char **, int *, char **, int *)); static int find_opt PROTO ((struct _scanopt_t *, int, char *, int, int *, int *opt_offset)); static const char *NAME (s, i) struct _scanopt_t *s; int i; { return s->options[i].opt_fmt + ((s->aux[i].flags & IS_LONG) ? 2 : 1); } static int PRINTLEN (s, i) struct _scanopt_t *s; int i; { return s->aux[i].printlen; } static int RVAL (s, i) struct _scanopt_t *s; int i; { return s->options[i].r_val; } static int FLAGS (s, i) struct _scanopt_t *s; int i; { return s->aux[i].flags; } static const char *DESC (s, i) struct _scanopt_t *s; int i; { return s->options[i].desc ? s->options[i].desc : ""; } #ifndef NO_SCANOPT_USAGE static int get_cols PROTO ((void)); static int get_cols () { char *env; int cols = 80; /* default */ #ifdef HAVE_NCURSES_H initscr (); endwin (); if (COLS > 0) return COLS; #endif if ((env = getenv ("COLUMNS")) != NULL) cols = atoi (env); return cols; } #endif /* Macro to check for NULL before assigning a value. */ #define SAFE_ASSIGN(ptr,val) \ do{ \ if((ptr)!=NULL) \ *(ptr) = val; \ }while(0) /* Macro to assure we reset subscript whenever we adjust s->index.*/ #define INC_INDEX(s,n) \ do{ \ (s)->index += (n); \ (s)->subscript= 0; \ }while(0) scanopt_t *scanopt_init (options, argc, argv, flags) const optspec_t *options; int argc; char **argv; int flags; { int i; struct _scanopt_t *s; s = (struct _scanopt_t *) malloc (sizeof (struct _scanopt_t)); s->options = options; s->optc = 0; s->argc = argc; s->argv = (char **) argv; s->index = 1; s->subscript = 0; s->no_err_msg = (flags & SCANOPT_NO_ERR_MSG); s->has_long = 0; s->has_short = 0; /* Determine option count. (Find entry with all zeros). */ s->optc = 0; while (options[s->optc].opt_fmt || options[s->optc].r_val || options[s->optc].desc) s->optc++; /* Build auxiliary data */ s->aux = (struct _aux *) malloc (s->optc * sizeof (struct _aux)); for (i = 0; i < s->optc; i++) { const Char *p, *pname; const struct optspec_t *opt; struct _aux *aux; opt = s->options + i; aux = s->aux + i; aux->flags = ARG_NONE; if (opt->opt_fmt[0] == '-' && opt->opt_fmt[1] == '-') { aux->flags |= IS_LONG; pname = (const Char *)(opt->opt_fmt + 2); s->has_long = 1; } else { pname = (const Char *)(opt->opt_fmt + 1); s->has_short = 1; } aux->printlen = strlen (opt->opt_fmt); aux->namelen = 0; for (p = pname + 1; *p; p++) { /* detect required arg */ if (*p == '=' || isspace (*p) || !(aux->flags & IS_LONG)) { if (aux->namelen == 0) aux->namelen = p - pname; aux->flags |= ARG_REQ; aux->flags &= ~ARG_NONE; } /* detect optional arg. This overrides required arg. */ if (*p == '[') { if (aux->namelen == 0) aux->namelen = p - pname; aux->flags &= ~(ARG_REQ | ARG_NONE); aux->flags |= ARG_OPT; break; } } if (aux->namelen == 0) aux->namelen = p - pname; } return (scanopt_t *) s; } #ifndef NO_SCANOPT_USAGE /* these structs are for scanopt_usage(). */ struct usg_elem { int idx; struct usg_elem *next; struct usg_elem *alias; }; typedef struct usg_elem usg_elem; /* Prints a usage message based on contents of optlist. * Parameters: * scanner - The scanner, already initialized with scanopt_init(). * fp - The file stream to write to. * usage - Text to be prepended to option list. * Return: Always returns 0 (zero). * The output looks something like this: [indent][option, alias1, alias2...][indent][description line1 description line2...] */ int scanopt_usage (scanner, fp, usage) scanopt_t *scanner; FILE *fp; const char *usage; { struct _scanopt_t *s; int i, columns, indent = 2; usg_elem *byr_val = NULL; /* option indices sorted by r_val */ usg_elem *store; /* array of preallocated elements. */ int store_idx = 0; usg_elem *ue; int maxlen[2]; int desccol = 0; int print_run = 0; maxlen[0] = 0; maxlen[1] = 0; s = (struct _scanopt_t *) scanner; if (usage) { fprintf (fp, "%s\n", usage); } else { /* Find the basename of argv[0] */ const char *p; p = s->argv[0] + strlen (s->argv[0]); while (p != s->argv[0] && *p != '/') --p; if (*p == '/') p++; fprintf (fp, _("Usage: %s [OPTIONS]...\n"), p); } fprintf (fp, "\n"); /* Sort by r_val and string. Yes, this is O(n*n), but n is small. */ store = (usg_elem *) malloc (s->optc * sizeof (usg_elem)); for (i = 0; i < s->optc; i++) { /* grab the next preallocate node. */ ue = store + store_idx++; ue->idx = i; ue->next = ue->alias = NULL; /* insert into list. */ if (!byr_val) byr_val = ue; else { int found_alias = 0; usg_elem **ue_curr, **ptr_if_no_alias = NULL; ue_curr = &byr_val; while (*ue_curr) { if (RVAL (s, (*ue_curr)->idx) == RVAL (s, ue->idx)) { /* push onto the alias list. */ ue_curr = &((*ue_curr)->alias); found_alias = 1; break; } if (!ptr_if_no_alias && STRCASECMP (NAME (s, (*ue_curr)->idx), NAME (s, ue->idx)) > 0) { ptr_if_no_alias = ue_curr; } ue_curr = &((*ue_curr)->next); } if (!found_alias && ptr_if_no_alias) ue_curr = ptr_if_no_alias; ue->next = *ue_curr; *ue_curr = ue; } } #if 0 if (1) { printf ("ORIGINAL:\n"); for (i = 0; i < s->optc; i++) printf ("%2d: %s\n", i, NAME (s, i)); printf ("SORTED:\n"); ue = byr_val; while (ue) { usg_elem *ue2; printf ("%2d: %s\n", ue->idx, NAME (s, ue->idx)); for (ue2 = ue->alias; ue2; ue2 = ue2->next) printf (" +---> %2d: %s\n", ue2->idx, NAME (s, ue2->idx)); ue = ue->next; } } #endif /* Now build each row of output. */ /* first pass calculate how much room we need. */ for (ue = byr_val; ue; ue = ue->next) { usg_elem *ap; int len = 0; int nshort = 0, nlong = 0; #define CALC_LEN(i) do {\ if(FLAGS(s,i) & IS_LONG) \ len += (nlong++||nshort) ? 2+PRINTLEN(s,i) : PRINTLEN(s,i);\ else\ len += (nshort++||nlong)? 2+PRINTLEN(s,i) : PRINTLEN(s,i);\ }while(0) if (!(FLAGS (s, ue->idx) & IS_LONG)) CALC_LEN (ue->idx); /* do short aliases first. */ for (ap = ue->alias; ap; ap = ap->next) { if (FLAGS (s, ap->idx) & IS_LONG) continue; CALC_LEN (ap->idx); } if (FLAGS (s, ue->idx) & IS_LONG) CALC_LEN (ue->idx); /* repeat the above loop, this time for long aliases. */ for (ap = ue->alias; ap; ap = ap->next) { if (!(FLAGS (s, ap->idx) & IS_LONG)) continue; CALC_LEN (ap->idx); } if (len > maxlen[0]) maxlen[0] = len; /* It's much easier to calculate length for description column! */ len = strlen (DESC (s, ue->idx)); if (len > maxlen[1]) maxlen[1] = len; } /* Determine how much room we have, and how much we will allocate to each col. * Do not address pathological cases. Output will just be ugly. */ columns = get_cols () - 1; if (maxlen[0] + maxlen[1] + indent * 2 > columns) { /* col 0 gets whatever it wants. we'll wrap the desc col. */ maxlen[1] = columns - (maxlen[0] + indent * 2); if (maxlen[1] < 14) /* 14 is arbitrary lower limit on desc width. */ maxlen[1] = INT_MAX; } desccol = maxlen[0] + indent * 2; #define PRINT_SPACES(fp,n)\ do{\ int _n;\ _n=(n);\ while(_n-- > 0)\ fputc(' ',(fp));\ }while(0) /* Second pass (same as above loop), this time we print. */ /* Sloppy hack: We iterate twice. The first time we print short and long options. The second time we print those lines that have ONLY long options. */ while (print_run++ < 2) { for (ue = byr_val; ue; ue = ue->next) { usg_elem *ap; int nwords = 0, nchars = 0, has_short = 0; /* TODO: get has_short schtick to work */ has_short = !(FLAGS (s, ue->idx) & IS_LONG); for (ap = ue->alias; ap; ap = ap->next) { if (!(FLAGS (s, ap->idx) & IS_LONG)) { has_short = 1; break; } } if ((print_run == 1 && !has_short) || (print_run == 2 && has_short)) continue; PRINT_SPACES (fp, indent); nchars += indent; /* Print, adding a ", " between aliases. */ #define PRINT_IT(i) do{\ if(nwords++)\ nchars+=fprintf(fp,", ");\ nchars+=fprintf(fp,"%s",s->options[i].opt_fmt);\ }while(0) if (!(FLAGS (s, ue->idx) & IS_LONG)) PRINT_IT (ue->idx); /* print short aliases first. */ for (ap = ue->alias; ap; ap = ap->next) { if (!(FLAGS (s, ap->idx) & IS_LONG)) PRINT_IT (ap->idx); } if (FLAGS (s, ue->idx) & IS_LONG) PRINT_IT (ue->idx); /* repeat the above loop, this time for long aliases. */ for (ap = ue->alias; ap; ap = ap->next) { if (FLAGS (s, ap->idx) & IS_LONG) PRINT_IT (ap->idx); } /* pad to desccol */ PRINT_SPACES (fp, desccol - nchars); /* Print description, wrapped to maxlen[1] columns. */ if (1) { const char *pstart; pstart = DESC (s, ue->idx); while (1) { int n = 0; const char *lastws = NULL, *p; p = pstart; while (*p && n < maxlen[1] && *p != '\n') { if (isspace ((Char)(*p)) || *p == '-') lastws = p; n++; p++; } if (!*p) { /* hit end of desc. done. */ fprintf (fp, "%s\n", pstart); break; } else if (*p == '\n') { /* print everything up to here then wrap. */ fprintf (fp, "%.*s\n", n, pstart); PRINT_SPACES (fp, desccol); pstart = p + 1; continue; } else { /* we hit the edge of the screen. wrap at space if possible. */ if (lastws) { fprintf (fp, "%.*s\n", (int)(lastws - pstart), pstart); pstart = lastws + 1; } else { fprintf (fp, "%.*s\n", n, pstart); pstart = p + 1; } PRINT_SPACES (fp, desccol); continue; } } } } } /* end while */ free (store); return 0; } #endif /* no scanopt_usage */ static int scanopt_err (s, opt_offset, is_short, err) struct _scanopt_t *s; int opt_offset; int is_short; int err; { const char *optname = ""; char optchar[2]; const optspec_t *opt = NULL; if (opt_offset >= 0) opt = s->options + opt_offset; if (!s->no_err_msg) { if (s->index > 0 && s->index < s->argc) { if (is_short) { optchar[0] = s->argv[s->index][s->subscript]; optchar[1] = '\0'; optname = optchar; } else { optname = s->argv[s->index]; } } fprintf (stderr, "%s: ", s->argv[0]); switch (err) { case SCANOPT_ERR_ARG_NOT_ALLOWED: fprintf (stderr, _ ("option `%s' doesn't allow an argument\n"), optname); break; case SCANOPT_ERR_ARG_NOT_FOUND: fprintf (stderr, _("option `%s' requires an argument\n"), optname); break; case SCANOPT_ERR_OPT_AMBIGUOUS: fprintf (stderr, _("option `%s' is ambiguous\n"), optname); break; case SCANOPT_ERR_OPT_UNRECOGNIZED: fprintf (stderr, _("Unrecognized option `%s'\n"), optname); break; default: fprintf (stderr, _("Unknown error=(%d)\n"), err); break; } } return err; } /* Internal. Match str against the regex ^--([^=]+)(=(.*))? * return 1 if *looks* like a long option. * 'str' is the only input argument, the rest of the arguments are output only. * optname will point to str + 2 * */ static int matchlongopt (str, optname, optlen, arg, arglen) char *str; char **optname; int *optlen; char **arg; int *arglen; { char *p; *optname = *arg = (char *) 0; *optlen = *arglen = 0; /* Match regex /--./ */ p = str; if (p[0] != '-' || p[1] != '-' || !p[2]) return 0; p += 2; *optname = (char *) p; /* find the end of optname */ while (*p && *p != '=') ++p; *optlen = p - *optname; if (!*p) /* an option with no '=...' part. */ return 1; /* We saw an '=' char. The rest of p is the arg. */ p++; *arg = p; while (*p) ++p; *arglen = p - *arg; return 1; } /* Internal. Look up long or short option by name. * Long options must match a non-ambiguous prefix, or exact match. * Short options must be exact. * Return boolean true if found and no error. * Error stored in err_code or zero if no error. */ static int find_opt (s, lookup_long, optstart, len, err_code, opt_offset) struct _scanopt_t *s; int lookup_long; char *optstart; int len; int *err_code; int *opt_offset; { int nmatch = 0, lastr_val = 0, i; *err_code = 0; *opt_offset = -1; if (!optstart) return 0; for (i = 0; i < s->optc; i++) { char *optname; optname = (char *) (s->options[i].opt_fmt + (lookup_long ? 2 : 1)); if (lookup_long && (s->aux[i].flags & IS_LONG)) { if (len > s->aux[i].namelen) continue; if (strncmp (optname, optstart, len) == 0) { nmatch++; *opt_offset = i; /* exact match overrides all. */ if (len == s->aux[i].namelen) { nmatch = 1; break; } /* ambiguity is ok between aliases. */ if (lastr_val && lastr_val == s->options[i].r_val) nmatch--; lastr_val = s->options[i].r_val; } } else if (!lookup_long && !(s->aux[i].flags & IS_LONG)) { if (optname[0] == optstart[0]) { nmatch++; *opt_offset = i; } } } if (nmatch == 0) { *err_code = SCANOPT_ERR_OPT_UNRECOGNIZED; *opt_offset = -1; } else if (nmatch > 1) { *err_code = SCANOPT_ERR_OPT_AMBIGUOUS; *opt_offset = -1; } return *err_code ? 0 : 1; } int scanopt (svoid, arg, optindex) scanopt_t *svoid; char **arg; int *optindex; { char *optname = NULL, *optarg = NULL, *pstart; int namelen = 0, arglen = 0; int errcode = 0, has_next; const optspec_t *optp; struct _scanopt_t *s; struct _aux *auxp; int is_short; int opt_offset = -1; s = (struct _scanopt_t *) svoid; /* Normalize return-parameters. */ SAFE_ASSIGN (arg, NULL); SAFE_ASSIGN (optindex, s->index); if (s->index >= s->argc) return 0; /* pstart always points to the start of our current scan. */ pstart = s->argv[s->index] + s->subscript; if (!pstart) return 0; if (s->subscript == 0) { /* test for exact match of "--" */ if (pstart[0] == '-' && pstart[1] == '-' && !pstart[2]) { SAFE_ASSIGN (optindex, s->index + 1); INC_INDEX (s, 1); return 0; } /* Match an opt. */ if (matchlongopt (pstart, &optname, &namelen, &optarg, &arglen)) { /* it LOOKS like an opt, but is it one?! */ if (!find_opt (s, 1, optname, namelen, &errcode, &opt_offset)) { scanopt_err (s, opt_offset, 0, errcode); return errcode; } /* We handle this below. */ is_short = 0; /* Check for short opt. */ } else if (pstart[0] == '-' && pstart[1]) { /* Pass through to below. */ is_short = 1; s->subscript++; pstart++; } else { /* It's not an option. We're done. */ return 0; } } /* We have to re-check the subscript status because it * may have changed above. */ if (s->subscript != 0) { /* we are somewhere in a run of short opts, * e.g., at the 'z' in `tar -xzf` */ optname = pstart; namelen = 1; is_short = 1; if (!find_opt (s, 0, pstart, namelen, &errcode, &opt_offset)) { return scanopt_err (s, opt_offset, 1, errcode); } optarg = pstart + 1; if (!*optarg) { optarg = NULL; arglen = 0; } else arglen = strlen (optarg); } /* At this point, we have a long or short option matched at opt_offset into * the s->options array (and corresponding aux array). * A trailing argument is in {optarg,arglen}, if any. */ /* Look ahead in argv[] to see if there is something * that we can use as an argument (if needed). */ has_next = s->index + 1 < s->argc && strcmp ("--", s->argv[s->index + 1]) != 0; optp = s->options + opt_offset; auxp = s->aux + opt_offset; /* case: no args allowed */ if (auxp->flags & ARG_NONE) { if (optarg && !is_short) { scanopt_err (s, opt_offset, is_short, errcode = SCANOPT_ERR_ARG_NOT_ALLOWED); INC_INDEX (s, 1); return errcode; } else if (!optarg) INC_INDEX (s, 1); else s->subscript++; return optp->r_val; } /* case: required */ if (auxp->flags & ARG_REQ) { if (!optarg && !has_next) return scanopt_err (s, opt_offset, is_short, SCANOPT_ERR_ARG_NOT_FOUND); if (!optarg) { /* Let the next argv element become the argument. */ SAFE_ASSIGN (arg, s->argv[s->index + 1]); INC_INDEX (s, 2); } else { SAFE_ASSIGN (arg, (char *) optarg); INC_INDEX (s, 1); } return optp->r_val; } /* case: optional */ if (auxp->flags & ARG_OPT) { SAFE_ASSIGN (arg, optarg); INC_INDEX (s, 1); return optp->r_val; } /* Should not reach here. */ return 0; } int scanopt_destroy (svoid) scanopt_t *svoid; { struct _scanopt_t *s; s = (struct _scanopt_t *) svoid; if (s) { if (s->aux) free (s->aux); free (s); } return 0; } /* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */ freebsd-buildutils-10.0/src/contrib/flex/tables_shared.h0000644000000000000000000001200012146741165020246 0ustar #ifdef FLEX_SCANNER /* dnl tables_shared.h - tables serialization header dnl dnl Copyright (c) 1990 The Regents of the University of California. dnl All rights reserved. dnl dnl This code is derived from software contributed to Berkeley by dnl Vern Paxson. dnl dnl The United States Government has rights in this work pursuant dnl to contract no. DE-AC03-76SF00098 between the United States dnl Department of Energy and the University of California. dnl dnl This file is part of flex. dnl dnl Redistribution and use in source and binary forms, with or without dnl modification, are permitted provided that the following conditions dnl are met: dnl dnl 1. Redistributions of source code must retain the above copyright dnl notice, this list of conditions and the following disclaimer. dnl 2. Redistributions in binary form must reproduce the above copyright dnl notice, this list of conditions and the following disclaimer in the dnl documentation and/or other materials provided with the distribution. dnl dnl Neither the name of the University nor the names of its contributors dnl may be used to endorse or promote products derived from this software dnl without specific prior written permission. dnl dnl THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR dnl IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR dnl PURPOSE. dnl dnl This file is meant to be included in both the skeleton and the actual dnl flex code (hence the name "_shared"). */ #ifndef yyskel_static #define yyskel_static static #endif #else #ifndef yyskel_static #define yyskel_static #endif #endif /* Structures and prototypes for serializing flex tables. The * binary format is documented in the manual. * * Design considerations: * * - The format allows many tables per file. * - The tables can be streamed. * - All data is stored in network byte order. * - We do not hinder future unicode support. * - We can lookup tables by name. */ /** Magic number for serialized format. */ #ifndef YYTBL_MAGIC #define YYTBL_MAGIC 0xF13C57B1 #endif /** Calculate (0-7) = number bytes needed to pad n to next 64-bit boundary. */ #ifndef yypad64 #define yypad64(n) ((8-((n)%8))%8) #endif #ifndef YYTABLES_TYPES #define YYTABLES_TYPES /** Possible values for td_id field. Each one corresponds to a * scanner table of the same name. */ enum yytbl_id { YYTD_ID_ACCEPT = 0x01, /**< 1-dim ints */ YYTD_ID_BASE = 0x02, /**< 1-dim ints */ YYTD_ID_CHK = 0x03, /**< 1-dim ints */ YYTD_ID_DEF = 0x04, /**< 1-dim ints */ YYTD_ID_EC = 0x05, /**< 1-dim ints */ YYTD_ID_META = 0x06, /**< 1-dim ints */ YYTD_ID_NUL_TRANS = 0x07, /**< 1-dim ints, maybe indices */ YYTD_ID_NXT = 0x08, /**< may be 2 dimensional ints */ YYTD_ID_RULE_CAN_MATCH_EOL = 0x09, /**< 1-dim ints */ YYTD_ID_START_STATE_LIST = 0x0A, /**< 1-dim indices into trans tbl */ YYTD_ID_TRANSITION = 0x0B, /**< structs */ YYTD_ID_ACCLIST = 0x0C /**< 1-dim ints */ }; /** bit flags for t_flags field of struct yytbl_data */ enum yytbl_flags { /* These first three are mutually exclusive */ YYTD_DATA8 = 0x01, /**< data is an array of type flex_int8_t */ YYTD_DATA16 = 0x02, /**< data is an array of type flex_int16_t */ YYTD_DATA32 = 0x04, /**< data is an array of type flex_int32_t */ /* These two are mutually exclusive. */ YYTD_PTRANS = 0x08, /**< data is a list of indexes of entries into the expanded `yy_transition' array. See notes in manual. */ YYTD_STRUCT = 0x10 /**< data consists of yy_trans_info structs */ }; /* The serialized tables header. */ struct yytbl_hdr { flex_uint32_t th_magic; /**< Must be 0xF13C57B1 (comes from "Flex Table") */ flex_uint32_t th_hsize; /**< Size of this header in bytes. */ flex_uint32_t th_ssize; /**< Size of this dataset, in bytes, including header. */ flex_uint16_t th_flags; /**< Currently unused, must be 0 */ char *th_version; /**< Flex version string. NUL terminated. */ char *th_name; /**< The name of this table set. NUL terminated. */ }; /** A single serialized table */ struct yytbl_data { flex_uint16_t td_id; /**< enum yytbl_id table identifier */ flex_uint16_t td_flags; /**< how to interpret this data */ flex_uint32_t td_hilen; /**< num elements in highest dimension array */ flex_uint32_t td_lolen; /**< num elements in lowest dimension array */ void *td_data; /**< table data */ }; #endif /** Extract corresponding data size_t from td_flags */ #ifndef YYTDFLAGS2BYTES #define YYTDFLAGS2BYTES(td_flags)\ (((td_flags) & YYTD_DATA8)\ ? sizeof(flex_int8_t)\ :(((td_flags) & YYTD_DATA16)\ ? sizeof(flex_int16_t)\ :sizeof(flex_int32_t))) #endif #ifdef FLEX_SCANNER %not-for-header #endif yyskel_static flex_int32_t yytbl_calc_total_len (const struct yytbl_data *tbl); #ifdef FLEX_SCANNER %ok-for-header #endif /* vim:set noexpandtab cindent tabstop=8 softtabstop=0 shiftwidth=8 textwidth=0: */ freebsd-buildutils-10.0/src/contrib/flex/options.h0000644000000000000000000000624312146741165017155 0ustar /* flex - tool to generate fast lexical analyzers */ /* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */ /* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */ /* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #ifndef OPTIONS_H #define OPTIONS_H #include "scanopt.h" extern optspec_t flexopts[]; enum flexopt_flag_t { /* Use positive integers only, since they are return codes for scanopt. * Order is not important. */ OPT_7BIT = 1, OPT_8BIT, OPT_ALIGN, OPT_ALWAYS_INTERACTIVE, OPT_ARRAY, OPT_BACKUP, OPT_BATCH, OPT_BISON_BRIDGE, OPT_BISON_BRIDGE_LOCATIONS, OPT_CASE_INSENSITIVE, OPT_COMPRESSION, OPT_CPLUSPLUS, OPT_DEBUG, OPT_DEFAULT, OPT_DONOTHING, OPT_ECS, OPT_FAST, OPT_FULL, OPT_HEADER_FILE, OPT_HELP, OPT_INTERACTIVE, OPT_LEX_COMPAT, OPT_POSIX_COMPAT, OPT_MAIN, OPT_META_ECS, OPT_NEVER_INTERACTIVE, OPT_NO_ALIGN, OPT_NO_ANSI_FUNC_DEFS, OPT_NO_ANSI_FUNC_PROTOS, OPT_NO_DEBUG, OPT_NO_DEFAULT, OPT_NO_ECS, OPT_NO_LINE, OPT_NO_MAIN, OPT_NO_META_ECS, OPT_NO_REENTRANT, OPT_NO_REJECT, OPT_NO_STDINIT, OPT_NO_UNPUT, OPT_NO_WARN, OPT_NO_YYGET_EXTRA, OPT_NO_YYGET_IN, OPT_NO_YYGET_LENG, OPT_NO_YYGET_LINENO, OPT_NO_YYGET_LLOC, OPT_NO_YYGET_LVAL, OPT_NO_YYGET_OUT, OPT_NO_YYGET_TEXT, OPT_NO_YYLINENO, OPT_NO_YYMORE, OPT_NO_YYSET_EXTRA, OPT_NO_YYSET_IN, OPT_NO_YYSET_LINENO, OPT_NO_YYSET_LLOC, OPT_NO_YYSET_LVAL, OPT_NO_YYSET_OUT, OPT_NO_YYWRAP, OPT_NO_YY_POP_STATE, OPT_NO_YY_PUSH_STATE, OPT_NO_YY_SCAN_BUFFER, OPT_NO_YY_SCAN_BYTES, OPT_NO_YY_SCAN_STRING, OPT_NO_YY_TOP_STATE, OPT_OUTFILE, OPT_PERF_REPORT, OPT_POINTER, OPT_PREFIX, OPT_PREPROCDEFINE, OPT_PREPROC_LEVEL, OPT_READ, OPT_REENTRANT, OPT_REJECT, OPT_SKEL, OPT_STACK, OPT_STDINIT, OPT_STDOUT, OPT_TABLES_FILE, OPT_TABLES_VERIFY, OPT_TRACE, OPT_NO_UNISTD_H, OPT_VERBOSE, OPT_VERSION, OPT_WARN, OPT_YYCLASS, OPT_YYLINENO, OPT_YYMORE, OPT_YYWRAP }; #endif /* vim:set tabstop=8 softtabstop=4 shiftwidth=4 textwidth=0: */ freebsd-buildutils-10.0/src/contrib/flex/COPYING0000644000000000000000000000347712146741165016352 0ustar Flex carries the copyright used for BSD software, slightly modified because it originated at the Lawrence Berkeley (not Livermore!) Laboratory, which operates under a contract with the Department of Energy: Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The Flex Project. Copyright (c) 1990, 1997 The Regents of the University of California. All rights reserved. This code is derived from software contributed to Berkeley by Vern Paxson. The United States Government has rights in this work pursuant to contract no. DE-AC03-76SF00098 between the United States Department of Energy and the University of California. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. This basically says "do whatever you please with this software except remove this notice or take advantage of the University's (or the flex authors') name". Note that the "flex.skl" scanner skeleton carries no copyright notice. You are free to do whatever you please with scanners generated using flex; for them, you are not even bound by the above copyright. freebsd-buildutils-10.0/src/contrib/flex/ChangeLog0000644000000000000000000070266212146741165017073 0ustar 2012-08-03 Will Estes * NEWS: update NEWS to reflect changes in 2.5.37 2012-08-03 Will Estes * configure.in: update flex version to 2.5.37 2012-08-03 Will Estes * po/de.po: new de translation from the translation project 2012-08-02 Will Estes * po/vi.po: new vi translation from the translation project 2012-08-02 Will Estes * po/pl.po: new pl translation from the translation project 2012-08-02 Will Estes * po/fi.po: new fi translation from the translation project 2012-08-02 Will Estes * Makefile.am: Add -f option to LN_S to create flex++ The autoconf macro LN_S needs -f to successfully install flex++ if flex++ already exists. Fortunately, ln, ln -s and cp -p, which are the various forms that LN_S can take all will do the right thing with a -f argument passed. 2012-08-02 Will Estes * Makefile.am, tools/Makefile.am, tools/cvs2cl.pl, tools/cvsauthors, tools/git2cl: replace cvs2cl with git2cl Add the git2cl script in tools/ and remove the (now unnecessary) cvs2cl script. Remove tools/cvsauthors since git2cl does not need that file. Account for all the above in Makefile.am and tools/Makefile.am 2012-07-29 Will Estes * tests/.cvsignore, tests/.gitignore, tests/TEMPLATE/.cvsignore, tests/TEMPLATE/.gitignore, tests/test-alloc-extra/.cvsignore, tests/test-alloc-extra/.gitignore, tests/test-array-nr/.cvsignore, tests/test-array-nr/.gitignore, tests/test-array-r/.cvsignore, tests/test-array-r/.gitignore, tests/test-basic-nr/.cvsignore, tests/test-basic-nr/.gitignore, tests/test-basic-r/.cvsignore, tests/test-basic-r/.gitignore, tests/test-bison-nr/.cvsignore, tests/test-bison-nr/.gitignore, tests/test-bison-yylloc/.cvsignore, tests/test-bison-yylloc/.gitignore, tests/test-bison-yylval/.cvsignore, tests/test-bison-yylval/.gitignore, tests/test-c++-basic/.cvsignore, tests/test-c++-basic/.gitignore, tests/test-c++-multiple-scanners/.cvsignore, tests/test-c++-multiple-scanners/.gitignore, tests/test-c++-yywrap/.cvsignore, tests/test-c++-yywrap/.gitignore, tests/test-c-cpp-nr/.cvsignore, tests/test-c-cpp-nr/.gitignore, tests/test-c-cpp-r/.cvsignore, tests/test-c-cpp-r/.gitignore, tests/test-ccl/.cvsignore, tests/test-ccl/.gitignore, tests/test-concatenated-options/.cvsignore, tests/test-concatenated-options/.gitignore, tests/test-debug-nr/.cvsignore, tests/test-debug-nr/.gitignore, tests/test-debug-r/.cvsignore, tests/test-debug-r/.gitignore, tests/test-extended/.cvsignore, tests/test-extended/.gitignore, tests/test-header-nr/.cvsignore, tests/test-header-nr/.gitignore, tests/test-header-r/.cvsignore, tests/test-header-r/.gitignore, tests/test-include-by-buffer/.cvsignore, tests/test-include-by-buffer/.gitignore, tests/test-include-by-push/.cvsignore, tests/test-include-by-push/.gitignore, tests/test-include-by-reentrant/.cvsignore, tests/test-include-by-reentrant/.gitignore, tests/test-linedir-r/.cvsignore, tests/test-linedir-r/.gitignore, tests/test-lineno-nr/.cvsignore, tests/test-lineno-nr/.gitignore, tests/test-lineno-r/.cvsignore, tests/test-lineno-r/.gitignore, tests/test-mem-nr/.cvsignore, tests/test-mem-nr/.gitignore, tests/test-mem-r/.cvsignore, tests/test-mem-r/.gitignore, tests/test-multiple-scanners-nr/.cvsignore, tests/test-multiple-scanners-nr/.gitignore, tests/test-multiple-scanners-r/.cvsignore, tests/test-multiple-scanners-r/.gitignore, tests/test-noansi-nr/.cvsignore, tests/test-noansi-nr/.gitignore, tests/test-noansi-r/.cvsignore, tests/test-noansi-r/.gitignore, tests/test-posix/.cvsignore, tests/test-posix/.gitignore, tests/test-posixly-correct/.cvsignore, tests/test-posixly-correct/.gitignore, tests/test-prefix-nr/.cvsignore, tests/test-prefix-nr/.gitignore, tests/test-prefix-r/.cvsignore, tests/test-prefix-r/.gitignore, tests/test-pthread/.cvsignore, tests/test-pthread/.gitignore, tests/test-quotes/.cvsignore, tests/test-quotes/.gitignore, tests/test-reject/.cvsignore, tests/test-reject/.gitignore, tests/test-rescan-nr/.cvsignore, tests/test-rescan-nr/.gitignore, tests/test-rescan-r/.cvsignore, tests/test-rescan-r/.gitignore, tests/test-string-nr/.cvsignore, tests/test-string-nr/.gitignore, tests/test-string-r/.cvsignore, tests/test-string-r/.gitignore, tests/test-table-opts/.cvsignore, tests/test-table-opts/.gitignore, tests/test-top/.cvsignore, tests/test-top/.gitignore, tests/test-yyextra/.cvsignore, tests/test-yyextra/.gitignore: rename .cvsignore files in tests/ subdirectories to gitignore 2012-07-23 Will Estes * examples/.cvsignore, examples/fastwc/.cvsignore, examples/manual/.cvsignore, lib/.cvsignore, tools/.cvsignore: remove unneeded .cvsignore files 2012-07-22 Will Estes * .gitignore: add *.o and *.a to top level .gitignore The cvs tree did not need these additions because cvs assumed a lot of C-style defaults for .cvsignore files. flex builds *.o object files in the course of compilation and *.a files are built as a part of the libraries that flex compiles in the build process. 2012-07-22 Will Estes * .cvsignore, .gitignore, doc/.cvsignore, doc/.gitignore, m4/.cvsignore, m4/.gitignore, po/.cvsignore, po/.gitignore: rename .cvsignore files to .gitignore The .cvsignore files from the legacy cvs repository tracked what files got autogenerated during various stages of the flex build. Renaming the .cvsignore files to .gitignore lets git do the same thing. git is better about letting higher level .gitignore files not-track files in lower level directories. As I work my way through the test directories, we may add additional .gitignore files from the old .cvsignore files. The po/ directory has a lot of special files used by gettext, so the patterns in po/.gitignore look very different. The doc/.gitignore file accounts for what texinfo/makeinfo do, and so it also has special patterns. The m4 directory is mainly present for autoconf's benefit, but we have to account for it so make can do the right thing. Hence, m4/.gitignore says to ignore *.m4, as counterintuitive as that may seem. 2012-07-22 Will Estes * NEWS: update NEWS file to note release date of 2.5.36 2012-06-23 Will Estes * doc/flex.texi: fix call to version in manual 2012-06-22 Will Estes * doc/flex.texi: add missing argument to call to yylex in manual 2012-04-27 Will Estes * flex.skl: lintish cleanup in flex.skl; resolves #2040664 2012-04-27 Will Estes * doc/flex.texi: add a 7 to the c99 octal pattern; resolves #3518269 2012-03-31 Will Estes * doc/flex.texi: copyedit; resolves #3513670 2012-03-23 Will Estes * buf.c: escape backslashes in #line filenames in %top section; resolves #3212400; patch submitted by scfc_de 2012-03-21 Will Estes * Makefile.am, configure.in, lib/Makefile.am, lib/lib.c, lib/malloc.c, lib/realloc.c: provide malloc() and realloc() for systems that do not have satisfactory versions; resolves #1899047 2012-03-21 Will Estes * Makefile.am: install flex++ as a link; resolves bug #2939681 2012-03-21 Will Estes * tests/test-bison-nr/Makefile.am, tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylval/Makefile.am: fix dependencies for make -j in test suite 2012-03-19 Will Estes * flex.skl: add missing prototypes for yyset_column() and yyget_column(); resolves #3029024; patch submitted by scfc_de 2012-03-02 Will Estes * flex.skl, tests/test-reject/scanner.l, tests/test-table-opts/scanner.l: wrap yy_fatal_error calls appropriately 2012-03-02 Will Estes * regex.c: fix overlapping data buffer issue; patch from Tim Landsheet scfc_de 2012-03-02 Will Estes * scan.l: better bracket handling in the scanner 2012-03-02 Will Estes * flexdef.h, main.c, misc.c: Remove unneeded tracking of line/column output; patch from Tim Landsheet scfc_de 2012-03-02 Will Estes * configure.in: fix test for m4 to accept an m4 with -P and not jus tGNU m4; patch from Tim Landsheet scfc_de on sourceforge 2012-03-02 Will Estes * doc/flex.texi: fix order of td_lolen and td_hilen in documentation; resolves #2913693; patch submitted by Andreas Gruenbacher 2012-03-02 Will Estes * doc/flex.texi: correct document of YY_FLUSH_BUFFER; resolves #1723028 2012-02-17 Will Estes * dfa.c, flexdef.h, misc.c, parse.y: speed up things for complex inputs; resolves #2891390 2012-02-17 Will Estes * doc/flex.texi: fix ipv6 pattern in manual; update manual copyright to 2012 2012-02-17 Will Estes * flex.skl: fremove isatty() declaration; resolves #1984987 2012-02-17 Will Estes * doc/flex.texi: Add link for RFC 2396 2012-02-17 Will Estes * flex.skl: resolve #1990170 2012-02-17 Will Estes * flex.skl: fix documentation to reflect arguments actually used; bug #2783023 2012-02-05 Will Estes * main.c: fix yywrap behavior for reentrant scanners 2012-02-04 Will Estes * NEWS: Mmention tr translation 2012-02-04 Will Estes * tables.c: prevent unused stuff from being compiled so as to reduce warnings 2012-02-03 Will Estes * buf.c, filter.c, main.c, misc.c, regex.c, scanflags.c: more better error messages; more better memory handling 2012-02-03 Will Estes * misc.c: more careful/paranoia 2012-02-03 Will Estes * scanopt.c: more careful memory allocation in option processing 2012-02-03 Will Estes * Makefile.am, configure.in: remove m4/ directory and generally clean up automake/autoconf inputs 2012-02-03 Will Estes * lib/.cvsignore: cvsignore files that need that 2012-02-03 Will Estes * NEWS, po/da.po, po/es.po, po/ko.po, po/pt_BR.po, po/ro.po, po/ru.po, po/sv.po, po/tr.po, po/zh_CN.po: check in translations 2012-02-03 Will Estes * main.c: correct macro definition of yywrap 2012-02-03 Will Estes * scan.l: Greater specificity in error messages 2012-02-03 Will Estes * parse.y: improve rule handling at EOF 2012-02-03 Will Estes * flex.skl: include cstdio for definition of EOF in all cases 2012-02-03 Will Estes * flex.skl: suppress warning on unused yyguts_t 2010-08-13 Will Estes * NEWS, po/LINGUAS, po/fi.po: new fi translation from the translation project 2009-03-31 Will Estes * doc/flex.texi: Include version.texi after @setfilename, so that @set values are correctly evaluated. (Start Conditions, Performance, Lex and Posix): Fix some markup errors. (Cxx): Likewise. Also, fix C++ example to actually be compilable. Patch from Ralf Wildenhues 2008-12-28 Will Estes * configure.in: remove line break that broke configure 2008-12-28 Will Estes * doc/flex.texi: specify the title on the title page since @settitle doesn't do that for us; resolves bug #2043491 2008-12-28 Will Estes * configure.in, flexdef.h: check for regex.h; resolves bug #2337486 2008-07-23 Will Estes * NEWS, po/ga.po: new ga translation from the translation project 2008-06-10 Will Estes * NEWS, po/ca.po: new ca translation 2008-05-31 Will Estes * Makefile.am: move ABOUT-NLS back to EXTRA_DIST 2008-05-31 Will Estes * Makefile.am: create new dist_doc_DATA; move some EXTRA_DIST files to new dist_doc_DATA target 2008-05-31 Will Estes * .cvsignore: ignore more automake generated config.status* files 2008-05-31 Will Estes * NEWS: flex distribution now built with automake and autoconf versions ... 2008-05-31 Will Estes * README.cvs: document GNU auto* version changes for building flex from cvs 2008-05-31 Will Estes * .cvsignore, doc/Makefile.am: ignore automake-supplied ylwrap 2008-05-15 Will Estes * NEWS, flex.skl: clean up types; resolves 1961902 2008-05-15 Will Estes * NEWS: update NEWS re manual 2008-05-15 Will Estes * doc/flex.texi: correct eroneous references to 'nowrap' to refer to 'noyywrap'; resolves bug #1739912 2008-05-14 Will Estes * filter.c: call clearerr on stdin before dup2'ing it; resolves bug #1902612 2008-05-14 Will Estes * NEWS: generic updates to NEWS 2008-05-14 Will Estes * tests/test-pthread/Makefile.am: move library flags in linker command; resolves patch #1943403; patch submitted by nullnix@users.sourceforge.net 2008-05-14 Will Estes * doc/flex.texi: use ansi syntax in simple examples; resolves patch #1909844; patch submitted by Tom Browder, tbrowder2@users.sourceforge.net 2008-04-10 Will Estes * doc/flex.texi: fix typo in example (from Paolo J. Matos 2008-04-10 Will Estes * flexint.h: move endif to better account for what C99 defines for integer types (fix from debian project) 2008-04-10 Will Estes * gen.c: fix another int type to be size_t 2008-03-30 Will Estes * NEWS, po/fr.po: new fr translation 2008-03-30 Will Estes * NEWS, configure.in: start version 2.5.36 2008-02-26 Will Estes * NEWS: add date of release 2008-02-15 Will Estes * NEWS, parse.y: fix bug that prevented comments from working properly 2008-02-12 Will Estes * po/de.po: new de translation 2008-02-10 Will Estes * NEWS, po/vi.po: new vi translation 2008-02-10 Will Estes * NEWS, po/nl.po: new nl translation 2008-02-09 Will Estes * NEWS, po/pl.po: new pl translation 2008-02-09 Will Estes * NEWS, po/de.po, po/pt_BR.po: new de, pt_br translations 2008-02-09 Will Estes * NEWS, flex.skl: generate headers for all functions (resolves bug #1628314) 2008-02-09 Will Estes * NEWS, flex.skl: change yy_size_t to be size_t (resolves bug #1849812) 2008-02-09 Will Estes * configure.in: start work on version 2.5.35 2007-12-12 Will Estes * NEWS, configure.in: revert NEWS and configure.in to version 2.5.34 2007-09-12 Will Estes * NEWS, configure.in: update version number to 2.5.35 2007-09-10 Aaron Stone * tests/test-alloc-extra/scanner.l: Use %option extra-type. 2007-09-10 Aaron Stone * NEWS, doc/flex.texi, flex.skl, flexdef.h, main.c, parse.y, scan.l: Introduce %option extra-type="your_type *" (resolves bug #1744505). 2007-08-15 Will Estes * po/nl.po: new nl translations from the translation project 2007-06-28 Will Estes * NEWS: change release date 2007-06-28 Will Estes * flex.skl: adjustment for prefix classes; patch submitted by Petr Machata 2007-06-28 Will Estes * NEWS: NEWS item for yy_init_extra 2007-06-12 Aaron Stone * doc/flex.texi: Docs and example for yylex_init_extra. 2007-06-01 Will Estes * tests/test-alloc-extra/.cvsignore: ignore OUTPUT file in test-alloc-extra 2007-06-01 Will Estes * tests/descriptions: add description of concatenated options test 2007-05-31 Will Estes * tests/test-alloc-extra/.cvsignore: add missing .cvsignore to test-alloc-extra 2007-05-31 Aaron Stone * configure.in, flex.skl, gen.c, main.c: Changes to resolve SF bugs 1568325 and 1563589. 2007-05-31 Aaron Stone * tests/Makefile.am, tests/descriptions, tests/test-alloc-extra/Makefile.am, tests/test-alloc-extra/scanner.l, tests/test-alloc-extra/test.input: Adding test cases for yylex_init_extra. 2007-05-12 Will Estes * configure.in, tests/test-pthread/scanner.l: fixes to test-pthread 2007-05-12 Will Estes * NEWS: NEWS item for concatenated options 2007-05-12 Will Estes * configure.in, tests/Makefile.am, tests/test-concatenated-options/.cvsignore, tests/test-concatenated-options/Makefile.am: unit test to verify concatenated options parsing 2007-05-12 Will Estes * scanopt.c: parse multiple short concatenated options; patch submitted by Petr Machata * autogen.sh: remove --force option from autogen.sh; much faster without it 2007-05-11 Will Estes * NEWS, configure.in: version 2.5.34 2007-05-08 Aaron Stone * NEWS, flex.skl: Better checking after yyalloc/yyrealloc (resolves bug #1595967) 2007-05-01 Will Estes * doc/flex.texi: change title of manual to 'Lexical Analysis with Flex' 2007-04-25 Will Estes * flex.skl: c++ memory leak plug 2007-04-23 Will Estes * flex.skl: roll back c++ memory patch as it causes the test suite no end of grief 2007-04-23 Will Estes * flex.skl: fix function definitions for non-ANSI environments (from Manoj Srivastava from Debian patchset) 2007-04-23 Will Estes * flex.skl: fix c++ memory leak (from Manoj Srivastava from Debian patchset) 2007-04-23 Will Estes * flex.skl: fix parameter name in comment (patch from Manoj Srivastava from the debian patchset 2007-04-23 Will Estes * flex.skl: add a size_t cast (patch from Manoj Srivastava from the debian patchset 2007-04-16 Will Estes * tests/test-extended/Makefile.am, tests/test-quotes/Makefile.am: cleanups to handle VPATH builds better; passifies make distcheck 2007-04-16 Will Estes * doc/flex.texi: drop using the \ in \ escaping as it throws pdf generation for a loop 2007-04-14 Will Estes * .cvsignore: add compile and *.tar.bz2 to .cvsignore 2007-04-14 Will Estes * main.c: add call to setlocale for ctype as per debian patchset 2007-04-14 Will Estes * Makefile.am, NEWS: provide for a PIC version of libfl.a for shared libraries using flex scanners 2007-04-13 Will Estes * FlexLexer.h: annotate endifs since they're a bit far from their opening #if statements 2007-04-13 Will Estes * flexdef.h, parse.y: refactor and slightly redo alloca testing, resolves bug #1675899 2007-04-13 Will Estes * : overhaul configure.in: use octathorps for comments so they're passed through m4 processing; better bracketing of m4 arguments; retool checks as per suggestions from autoscan(1) 2007-04-13 Will Estes * flex.skl: fix skeleton for reentrant scanners 2007-04-13 Will Estes * Makefile.am: remove homegrown tags target; automake does that for us 2007-04-12 Will Estes * flex.skl: fix skeleton for reentrant scanners, resolves bug #1694318 2007-04-12 Will Estes * FlexLexer.h: declare some const where missing in c++ header file 2007-04-10 Will Estes * doc/flex.texi: corrections to the manual as per suggestions from flex-help@ 2007-04-03 Will Estes * doc/flex.texi: include author names in online versions of the manual 2007-04-03 Will Estes * COPYING: update copyright notice 2007-04-03 Will Estes * AUTHORS: rearrange and update AUTHORS 2007-03-29 Will Estes * NEWS: note sf feature request 1658379 in NEWS 2007-03-29 Will Estes * tools/cvsauthors: add sodabrew to cvsauthors file 2007-03-29 Aaron Stone * flex.skl: SourceForge feature request #1658379: Expose YY_BUF_SIZE in the header file. 2007-03-07 Will Estes * NEWS, filter.c, flex.skl: apply patches submitted by sodabrew 2007-03-07 Will Estes * README.cvs: more changes describing building flex from cvs 2007-03-07 Will Estes * Makefile.am, README.cvs, README.cvs-snapshot: rename README.cvs-snapshot to README.cvs 2007-03-07 Will Estes * README.cvs-snapshot: update to explain where flex cvs lives 2007-03-07 Will Estes * README, doc/flex.texi: correct how to submit bugs 2007-02-16 Will Estes * NEWS: clarify NEWS item re man page and pdf manual 2007-02-14 Will Estes * po/Makevars: update bug address to point to flex-devel instead of lex-help 2007-02-13 Will Estes * configure.in, doc/Makefile.am: make better use of AC_INIT; clean up, simplify and make more robust the generation of the man page 2007-02-13 Will Estes * configure.in: remove option check-news from call to AM_INIT_AUTOMAKE as gnits implies check-news 2007-02-13 Will Estes * Makefile.am, configure.in: move automake options from Makefile.am to configure.in 2007-02-13 Will Estes * autogen.sh: restore --install option to autogen.sh since --force does not imply --install 2007-02-13 Will Estes * tools/cvsauthors: add john43 to cvsauthors file 2007-02-13 Will Estes * autogen.sh: call autoreconf with --force instead of --install 2007-02-13 Will Estes * doc/.cvsignore: remove texinfo.tex from cvs tree 2007-02-13 Will Estes * NEWS: updates to NEWS file to reflect recent changes 2007-02-13 Will Estes * doc/Makefile.am: add flex.pdf to EXTRA_DIST 2007-02-13 Will Estes * configure.in: remove flex.spec 2007-02-13 Will Estes * Makefile.am: remove maintainercleanfiles 2007-02-01 Will Estes * doc/Makefile.am: more changes to build system to distribute man page 2007-02-01 Will Estes * doc/Makefile.am: add flex man page to distribution 2007-02-01 Will Estes * .cvsignore, flex.spec.in: remove flex spec file 2006-11-17 Will Estes * tests/test-table-opts/Makefile.am: make test target depend on test groupings, which in turn depend on building executables; cygwin portability fix 2006-11-10 Will Estes * tests/create-test: change create-test script to edit files in place 2006-11-09 Will Estes * tests/test-array-nr/Makefile.am, tests/test-array-r/Makefile.am, tests/test-basic-nr/Makefile.am, tests/test-basic-r/Makefile.am, tests/test-bison-nr/Makefile.am, tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylval/Makefile.am, tests/test-c++-basic/Makefile.am, tests/test-c++-multiple-scanners/Makefile.am, tests/test-c++-yywrap/Makefile.am, tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-r/Makefile.am, tests/test-ccl/Makefile.am, tests/test-debug-nr/Makefile.am, tests/test-debug-r/Makefile.am, tests/test-extended/Makefile.am, tests/test-header-nr/Makefile.am, tests/test-header-r/Makefile.am, tests/test-include-by-buffer/Makefile.am, tests/test-include-by-push/Makefile.am, tests/test-include-by-reentrant/Makefile.am, tests/test-linedir-r/Makefile.am, tests/test-lineno-nr/Makefile.am, tests/test-lineno-r/Makefile.am, tests/test-mem-nr/Makefile.am, tests/test-mem-r/Makefile.am, tests/test-multiple-scanners-nr/Makefile.am, tests/test-multiple-scanners-r/Makefile.am, tests/test-noansi-nr/Makefile.am, tests/test-noansi-r/Makefile.am, tests/test-posix/Makefile.am, tests/test-posixly-correct/Makefile.am, tests/test-prefix-nr/Makefile.am, tests/test-prefix-r/Makefile.am, tests/test-pthread/Makefile.am, tests/test-quotes/Makefile.am, tests/test-reject/Makefile.am, tests/test-rescan-nr/Makefile.am, tests/test-rescan-r/Makefile.am, tests/test-string-nr/Makefile.am, tests/test-string-r/Makefile.am, tests/test-top/Makefile.am, tests/test-yyextra/Makefile.am: change CLEANFILES to include instead of just the testname for the executable 2006-11-09 Will Estes * doc/flex.texi: fix typos in manual; resolves bug #1592857 2006-11-09 Will Estes * tests/TEMPLATE/Makefile.am: change test template to remove test executable when that executable has an extension, e.g. under Cygwin 2006-11-08 Will Estes * tests/Makefile.am: test names weren't displaying in test success/failure messages (from #1591672 2006-10-30 Will Estes * doc/.cvsignore: add flex.html to .cvsignore in doc directory 2006-10-22 Will Estes * NEWS: update NEWS file for the work that millaway did 2006-10-22 Will Estes * FlexLexer.h, NEWS, main.c, tests/test-c++-multiple-scanners/scanner-2.l: make yywrap work with c++ scanners as per sf bug report 2006-10-20 Will Estes * NEWS, flex.skl, tests/test-c++-multiple-scanners/main.cpp, tests/test-c-cpp-nr/scanner.l: memory leak issues in c++ scanner 2006-10-20 Will Estes * NEWS, configure.in, tests/Makefile.am, tests/descriptions, tests/test-c++-yywrap/.cvsignore, tests/test-c++-yywrap/Makefile.am, tests/test-c++-yywrap/scanner.l, tests/test-c++-yywrap/test.input: add unit test for c++ with yywrap 2006-10-20 Will Estes * NEWS, tests/test-c++-basic/Makefile.am, tests/test-linedir-r/Makefile.am: use configure-provided awk variable for portability; add loadlibes variable to c++ test 2006-10-17 Will Estes * doc/flex.texi: add noyywrap option to example; use whitespace to clarify example 2006-08-02 Will Estes * NEWS, po/ca.po, po/vi.po: new translations 2006-04-11 John Millaway * tables.c: Casted away signedness to appease -Werror freaks. 2006-03-28 John Millaway * ccl.c, doc/flex.texi, flexdef.h, parse.y, scan.l, sym.c, tests/test-ccl/scanner.l, tests/test-ccl/test.input: Added ccl union operator. Added test in test suite for ccl union operator. Documented ccl union operator. Removed crufty ccl cache to prevent parser problems. 2006-03-28 John Millaway * doc/flex.texi, scan.l, tests/test-extended/scanner.l, tests/test-extended/test.input: Extended syntax excluded for lex/posix compat mode. Comments discarded inside (?x:) patterns. Added test in test suite for comments in extended patterns. Documented syntax additions. 2006-03-27 John Millaway * scan.l, tests/test-ccl/scanner.l, tests/test-ccl/test.input: Implemented (?x:) syntax to allow whitespace in patterns. Added test for (?x:) syntax in test suite. 2006-03-27 John Millaway * parse.y, tests/test-ccl/scanner.l, tests/test-ccl/test.input: Implemented dot-all syntax. Added test for dot-all syntax in test suite. 2006-03-27 John Millaway * dfa.c, doc/flex.texi, flexdef.h, gen.c, main.c, parse.y, scan.l, scanflags.c, tests/test-ccl/scanner.l, tests/test-ccl/test.input: Removed global variable caseins. Added scanner stack flags for case-insensitivity. Moved case-folding code from DFA-generation to parse time read-macros. Added localized case-sensitivity syntax from Perl. Added test for new syntax in test suite. Documented new syntax. 2006-03-27 John Millaway * Makefile.am, configure.in, flexdef.h, scanflags.c: Added configure check for assert.h. Added scanner flags stack. 2006-03-25 John Millaway * configure.in, doc/flex.texi, scan.l, tests/Makefile.am, tests/descriptions, tests/test-extended/.cvsignore, tests/test-extended/Makefile.am, tests/test-extended/scanner.l, tests/test-extended/test.input: Added extended, perl-compatible comment syntax. Added test for extended comment syntax. Documented extended comment syntax. 2006-03-25 John Millaway * doc/flex.texi, parse.y: Changed explicit 'A'-'Z' to isupper(), where correct to do so. Documentation. 2006-03-24 John Millaway * doc/flex.texi: Documentation. 2006-03-24 John Millaway * doc/flex.texi: Added appendix of patterns to manual. 2006-03-23 John Millaway * doc/flex.texi: . 2006-03-22 John Millaway * doc/flex.texi: Documentation. 2006-03-22 John Millaway * doc/flex.texi: Documented set difference operator {-}. 2006-03-22 John Millaway * ccl.c, flexdef.h, parse.y, scan.l, tests/test-ccl/scanner.l, tests/test-ccl/test.input: Added set difference operator {-} for character classes. 2006-03-22 John Millaway * configure.in, doc/flex.texi, parse.y, scan.l, tests/Makefile.am, tests/descriptions, tests/test-ccl/.cvsignore, tests/test-ccl/Makefile.am, tests/test-ccl/scanner.l, tests/test-ccl/test.input: Added negated character class expressions. Documented negated character class expressions. Added regression test for negated character class expressions. 2006-03-22 John Millaway * buf.c, filter.c, gen.c, main.c, misc.c, nfa.c, parse.y, regex.c: Replaced sprintf with snprintf everywhere. 2006-03-22 John Millaway * Makefile.am: Removed includedir from AM_CPPFLAGS #1439351. 2006-03-21 John Millaway * configure.in, tests/Makefile.am, tests/descriptions, tests/test-quotes/.cvsignore, tests/test-quotes/Makefile.am, tests/test-quotes/scanner.l, tests/test-quotes/test.input: Added test to verify user code is unmangled. 2006-03-21 John Millaway * flexdef.h, misc.c, scan.l: Fixed escape in actions. 2006-03-21 John Millaway * filter.c, flexdef.h, main.c, scan.l: Reverted previous input filter changes. Added noop macro to scanner output. Modified scan.l to escape m4 quotes found in user code. 2006-03-21 John Millaway * tests/test-table-opts/Makefile.am, tests/test-table-opts/scanner.l: Removed m4 from test-table-opts 2006-03-21 John Millaway * tests/test-reject/Makefile.am, tests/test-reject/scanner.l: Removed m4 from test-reject 2006-03-21 John Millaway * filter.c, flexdef.h, main.c, scan.l: Moved set_input_file to different file. 2006-03-21 John Millaway * flex.skl, flexdef.h, flexint.h, misc.c: Relaxed tests for __STDC__ and __STDC_VERSION__ to cope with bugs in GCC and Sun cc. 2006-03-20 John Millaway * filter.c: Documented filter chain. Removed fdopen. Added no-op fseek. 2006-03-13 John Millaway * gen.c: Fixed another -Wall report. 2006-03-10 Will Estes * NEWS, po/vi.po: new vi translation 2006-03-09 Will Estes * NEWS, po/ga.po, po/nl.po: new nl, ga translations 2006-02-21 Will Estes * m4/Makefile.am: add po.m4 to extra_dist in m4/ so it gets picked up by distributions 2006-02-21 Will Estes * m4/Makefile.am: add nls.m4 to extra_dist in m4/ so it will get picked up in distribution tarballs 2006-02-21 Will Estes * configure.in: remove website directory from configure.in 2006-02-20 Will Estes * NEWS, configure.in: version 2.5.33 marks in NEWS and configure.in 2006-02-20 Will Estes * configure.in: change email address in configure.in to point to flex-help@sourceforge.net 2006-02-20 John Millaway * doc/flex.texi: Documentation. 2006-02-20 John Millaway * BUGS: Appended to BUGS file. 2006-02-18 Will Estes * Makefile.am: remove website directory (since it now has its own module in the flex project 2006-02-16 John Millaway * doc/flex.texi, flex.skl: Fixed buffer overflow in reject state buffer. Corrected documentation on the state buffer. 2006-02-16 John Millaway * flex.skl: Reverted num_read from size_t back to int. 2006-02-15 John Millaway * Makefile.am, configure.in: Removed reference to RoadMap in Makefile.am. Added website directory. 2006-02-15 Will Estes * README, RoadMap: remove RoadMap and reference to it in README 2006-02-15 John Millaway * BUGS, README, doc/flex.texi, doc/flex.xml: Eliminated references to lex.sf.net. 2006-02-15 John Millaway * BUGS, flex.skl: Transfered bugs list from lex.sf.net to BUGS file. 2006-02-15 John Millaway * tests/test-rescan-nr/.cvsignore, tests/test-rescan-nr/Makefile.am, tests/test-rescan-nr/scanner.l, tests/test-rescan-nr/test.input, tests/test-rescan-r/.cvsignore, tests/test-rescan-r/Makefile.am, tests/test-rescan-r/scanner.l, tests/test-rescan-r/test.input: Recommit of last commit -- broken pipe. 2006-02-15 John Millaway * configure.in, flex.skl, tests/Makefile.am, tests/descriptions: yy_lex_destroy calls yy_init_globals to reset everything for next call to yylex. Added two new tests for reusing scanners. 2006-02-14 John Millaway * flex.spec.in: Patched rpm spec file. 2006-02-14 John Millaway * configure.in, flexint.h: Added C99 macro for inttypes, just to be conformant. 2006-02-14 John Millaway * flexdef.h, nfa.c, parse.y: Changed symbol INFINITE to fix conflict with C math symbol. 2006-02-14 John Millaway * scan.l: Omitting parens for named rules in trailing context. 2006-02-14 John Millaway * configure.in, main.c, po/ca.po, po/da.po, po/de.po, po/es.po, po/fr.po, po/ga.po, po/ko.po, po/nl.po, po/pl.po, po/pt_BR.po, po/ro.po, po/ru.po, po/sv.po, po/tr.po, po/vi.po, po/zh_CN.po, tests/test-mem-nr/scanner.l, tests/test-mem-r/scanner.l: Added check for locale.h and libintl.h in configure script. 2006-02-14 John Millaway * flex.skl: Removed unused local vars. 2006-02-14 John Millaway * flex.skl: Removed certain offending #undefs. 2006-02-14 John Millaway * flexint.h: Removed logical and from preprocessor statement. 2006-02-14 Will Estes * po/nl.po, po/nl.po.1: remove eroneously named nl.po.1; update nl.po 2006-02-14 John Millaway * dfa.c: . 2006-02-14 John Millaway * flex.skl: Included for serialized tables. 2006-02-14 John Millaway * configure.in: Minor patch to call to head in configure script. 2006-02-14 John Millaway * doc/flex.texi: Documentation patch. 2006-02-14 John Millaway * filter.c, gen.c, libyywrap.c, main.c: Patch for full file system failure. 2006-02-13 John Millaway * doc/flex.texi: Documentation. 2006-02-13 John Millaway * main.c: Fixed double-fclose when input file is empty. 2006-02-10 Will Estes * po/ca.po, po/da.po, po/de.po, po/es.po, po/fr.po, po/ga.po, po/ko.po, po/nl.po.1, po/pl.po, po/pt_BR.po, po/ro.po, po/ru.po, po/sv.po, po/tr.po, po/vi.po, po/zh_CN.po: newtranslations 2005-12-22 John Millaway * buf.c, main.c: Improvement request 1069716 log vs. log10 2005-12-22 John Millaway * flex.skl: Fixed bug 1257093 yy_init_globals in header file 2005-04-14 Will Estes * po/nl.po: new nl translation 2005-04-07 Will Estes * NEWS, po/LINGUAS, po/nl.po, po/vi.po: new nl and vi translations 2004-07-20 Will Estes * filter.c: correct improper stdin assignment 2004-05-22 Will Estes * NEWS, po/tr.po: new tr translation 2004-05-12 Will Estes * .cvsignore, .indent.pro: .cvsignore and .indent.pro got missed in the import to sourceforge; replace them 2004-05-11 Will Estes * po/fr.po: new fr translation 2004-05-03 Will Estes * po/LINGUAS: polish is pl, not po 2004-03-22 Will Estes * po/sv.po: yet another sweedish update 2004-03-19 Will Estes * NEWS, po/sv.po: new sv translation 2003-12-11 John Millaway * configure.in, filter.c, main.c: Configure checks for GNU m4. Environment variable M4 overrides built-in m4 path. Generated m4 does a late check for GNU m4. 2003-12-09 John Millaway * doc/flex.texi: added 3 faqs 2003-11-24 Will Estes * po/ro.po: new ro translation 2003-11-07 Will Estes * NEWS, po/fr.po: new french translation 2003-11-07 Will Estes * NEWS, po/ca.po: new catalan translation from the translation project 2003-11-07 Will Estes * NEWS, po/LINGUAS, po/ga.po, po/pl.po: new polish translation; updated irish translation from translation project 2003-10-10 Will Estes * NEWS, po/LINGUAS, po/ga.po: new Irish translation 2003-08-25 Will Estes * NEWS, po/LINGUAS, po/ro.po: add romanian translation 2003-07-16 Will Estes * flex.skl: flex_*int* type fixes 2003-07-16 Will Estes * tools/cvsauthors: change wlestes email address 2003-07-16 Will Estes * flex.skl: undef yytext_ptr has some bad side effects 2003-07-07 John Millaway * doc/flex.texi: Documented m4 incompatibility with lex. 2003-05-21 Will Estes * NEWS: upgrade to gettext 0.12 2003-05-20 Will Estes * flex.skl, gen.c: patches from manoj via sourceforge 2003-05-20 Will Estes * configure.in, po/.cvsignore, po/Makevars: upgrade gettext to 0.12; this allows running make pdf and make ps to be successful 2003-05-20 Will Estes * doc/.cvsignore: cvs should ignore flex.pdf and flex.ps 2003-04-25 John Millaway * TODO: Added yylineno bugs to TODO list. 2003-04-03 John Millaway * doc/flex.xml: Docbook. 2003-04-03 John Millaway * doc/flex.xml: xml now validates. 2003-04-02 John Millaway * doc/flex.xml: Began conversion to DocBook. 2003-04-01 Will Estes * NEWS, configure.in: version 2.5.31 2003-04-01 Will Estes * NEWS: remove --enable-maintainer-mode configure option 2003-04-01 Will Estes * configure.in: remove AM_MAINTAINER_MODE 2003-04-01 John Millaway * flex.skl, flexdef.h, main.c, misc.c, scan.l: Renamed some internal variables. 2003-03-31 Will Estes * NEWS: yylineno is now per-buffer in reentrant scanners 2003-03-31 John Millaway * TODO: Added TODO item. 2003-03-30 John Millaway * flex.skl, gen.c: yylineno is per-buffer in the reentrant scanner. support for yycolumn exists, but is not yet developed. 2003-03-28 John Millaway * flex.skl: Minor documentation. 2003-03-28 Will Estes * NEWS: added %top directive 2003-03-27 John Millaway * buf.c, configure.in, doc/flex.texi, flexdef.h, main.c, scan.l, tests/Makefile.am, tests/descriptions, tests/test-top/.cvsignore, tests/test-top/Makefile.am, tests/test-top/main.c, tests/test-top/scanner.l, tests/test-top/test.input: Added %top block syntax. Added test for %top block. Documented %top block. 2003-03-27 John Millaway * TODO, doc/flex.texi: Documented the m4 dependency. 2003-03-26 Will Estes * configure.in, flexdef.h: check for sys/wait.h since we use wait(2) 2003-03-26 Will Estes * flexdef.h: reorder include directives so as to catch system integer types before flex defined values for same 2003-03-26 Will Estes * TODO: assign tasks due before major release can happen; remove --enable-maintainer-mode entry 2003-03-26 Will Estes * Makefile.am: only rebuild the ChangeLog if we're inside a cvs working directory 2003-03-26 Will Estes * configure.in, tools/.cvsignore, tools/Makefile.am: add tools/ subdirectory to distribution 2003-03-26 Will Estes * Makefile.am: remove maintainer_mode conditional; add filter.c and regex.c to indentfiles; reformat and sort indentfiles so it's easier to add files in the future 2003-03-26 Will Estes * doc/Makefile.am: clean up flex.texi processing leftovers with cleanfiles 2003-03-26 Will Estes * tests/test-linedir-r/Makefile.am: an awk script wasn't included in the distribution 2003-03-26 John Millaway * TODO, configure.in, tests/Makefile.am, tests/descriptions, tests/test-include-by-push/.cvsignore, tests/test-include-by-push/Makefile.am, tests/test-include-by-push/scanner.l, tests/test-include-by-push/test-1.input, tests/test-include-by-push/test-2.input, tests/test-include-by-push/test-3.input: Added test for yypush_buffer_state and yypop_buffer_state. 2003-03-26 John Millaway * TODO: Removed items from TODO list. 2003-03-26 John Millaway * configure.in, tests/Makefile.am, tests/descriptions, tests/test-linedir-r/.cvsignore, tests/test-linedir-r/Makefile.am, tests/test-linedir-r/check-lines.awk, tests/test-linedir-r/main.c, tests/test-linedir-r/scanner.l, tests/test-linedir-r/test.input: Added test for #line directives. 2003-03-26 John Millaway * configure.in, tests/Makefile.am, tests/test-noansi-nr/.cvsignore, tests/test-noansi-nr/Makefile.am, tests/test-noansi-nr/scanner.l, tests/test-noansi-nr/test.input, tests/test-noansi-r/.cvsignore, tests/test-noansi-r/Makefile.am, tests/test-noansi-r/scanner.l, tests/test-noansi-r/test.input: Added test for noansi (traditional) options. Reordered the tests so the basic ones are first. 2003-03-25 Will Estes * TODO, doc/Makefile.am: remove maintainer-mode conditional around rebuilding of manpage 2003-03-25 Will Estes * README: mention doc/ for user documentation 2003-03-25 Will Estes * TODO: rework distribution items 2003-03-25 Will Estes * NEWS: mention m4 processing 2003-03-25 Will Estes * tests/README: update instructions for running test suite 2003-03-25 Will Estes * FlexLexer.h, Makefile.am, TODO, buf.c, configure.in, doc/flex.texi, filter.c, flex.skl, flexdef.h, gen.c, main.c, misc.c, options.c, options.h, regex.c, scan.l, sym.c, tests/test-bison-nr/scanner.l, tests/test-bison-yylloc/scanner.l, tests/test-reject/scanner.l, tests/test-table-opts/scanner.l: merge millaway's m4 branch work 2003-03-24 John Millaway * doc/flex.texi, flex.skl, flexdef.h, gen.c, main.c, options.c, options.h, scan.l: Option ansi-definitions. Option ansi-prototypes. Cleaned up some of header. Documented bison-locations. 2003-03-24 John Millaway * scan.l: Escaped m4 macros in scan.l which would cause bootstrapping issues. 2003-03-21 John Millaway * doc/flex.texi, flex.skl, main.c: Cleaning up the skel. 2003-03-20 Will Estes * TODO: we want to move the contents of to.do/Wishlist to top level TODO 2003-03-20 John Millaway * to.do/Wish-List: Assessment of every item in Wish-List. 2003-03-19 John Millaway * main.c: Fixed allocation of slightly more memory than needed. 2003-03-19 John Millaway * TODO, buf.c, configure.in, flex.skl, flexdef.h, main.c, sym.c: Start conditions now generated in a single place. 2003-03-19 Will Estes * TODO: cosmetic changes to TODO list 2003-03-19 John Millaway * flex.skl: Cleaned up warnings so multiple headers could coincide. 2003-03-19 John Millaway * TODO, flex.skl, main.c: Moved prefixes to m4. 2003-03-19 John Millaway * FlexLexer.h, filter.c, flex.skl, flexdef.h, main.c, misc.c, regex.c: Removed Paxson/Berkeley copyright restriction from filter.c and regex.c. Inline documentation of much of the generated API. Line directives now fixed for header and stdin/stdout. Blank lines squeezed from generated scanner. 2003-03-18 John Millaway * filter.c, flexdef.h, main.c, regex.c: Fixed #line directives. 2003-03-17 John Millaway * Makefile.am, filter.c, flexdef.h, regex.c: Added regex.c for regex-related code. Worked on fixing line directives;incomplete. 2003-03-14 John Millaway * TODO: Added some TODOs. 2003-03-14 John Millaway * flexdef.h, main.c, options.c, options.h, scan.l, tests/test-bison-nr/scanner.l, tests/test-bison-yylloc/scanner.l: Bison bridge was simplified to rely less on bison output. New option bison-locations. 2003-03-14 John Millaway * filter.c, flex.skl, flexdef.h, gen.c, main.c, scan.l, tests/test-reject/scanner.l: Filters are now direct children of main process. Header file now generated through m4. 2003-03-14 John Millaway * buf.c, filter.c, flexdef.h, main.c, misc.c: Added internal filter ability. Deleted various unused variables. 2003-03-14 John Millaway * main.c, tests/test-table-opts/scanner.l: Keeping tests up to date with m4 changes. Proper wait for all children. 2003-03-14 John Millaway * flex.skl, tests/test-table-opts/scanner.l: Moved test-tables to m4. 2003-03-14 John Millaway * flex.skl, main.c, options.c: Moved bison bridge code to m4. 2003-03-13 John Millaway * flex.skl, gen.c, main.c, scan.l: Moved YY_USE_LINENO to m4. 2003-03-13 John Millaway * buf.c, flexdef.h, scan.l: Added function buf_m4_undefine. 2003-03-13 John Millaway * flex.skl, main.c, scan.l: Replaced YY_ALWAYS_INTERACTIVE with m4. Replaced YY_NEVER_INTERACTIVE with m4. 2003-03-13 John Millaway * flex.skl, main.c: Moved YY_TEXT_IS_ARRAY to m4. 2003-03-12 John Millaway * flex.skl, gen.c, main.c, tests/test-reject/scanner.l: Renaming macros from YY_* to M4_YY_* where appropriate. 2003-03-12 John Millaway * flex.skl, tests/test-reject/scanner.l, tests/test-table-opts/scanner.l: Now using local variable "yyg" instead of lengthly YY_G expansion. 2003-03-12 John Millaway * buf.c, filter.c, flex.skl, flexdef.h, main.c, misc.c, options.c, options.h, scan.l, tests/test-reject/scanner.l: More m4 macro conversions. Added debugging option --preproc-level=NUM. 2003-03-11 John Millaway * Makefile.am, buf.c, flex.skl, flexdef.h, gen.c, main.c, misc.c, scan.l: Replaced many CPP macros with m4 equivalents. 2003-03-10 John Millaway * Makefile.am, filter.c, flex.skl, flexdef.h, main.c, misc.c: Added filter.c Added filter.c rules to Makefile.am Added filter prototypes to flexdef.h Flex now filters output through m4. 2003-03-05 Will Estes * doc/.cvsignore, texinfo.tex: move texinfo.tex to doc/ 2003-03-05 Will Estes * TODO: update TODO 2003-03-05 Will Estes * NEWS, configure.in: version 2.5.29 2003-03-04 John Millaway * FlexLexer.h, flex.skl: Added growable buffer stack to C++ scanner as well. yyensure_buffer_stack is now static. 2003-03-02 John Millaway * flex.skl, misc.c: Removed awkward %push %pop syntax from skeleton. 2003-03-02 John Millaway * flex.skl: Renamed YY_CURRENT_BUFFER_FAST to YY_CURRENT_BUFFER_LVALUE to better reflect its purpose. 2003-02-28 John Millaway * NEWS: made entry on input buffer stacks. 2003-02-28 Will Estes * Makefile.am, doc/Makefile.am: build on . in top level first; this will simplify calling help2man 2003-02-28 John Millaway * TODO, doc/flex.texi, flex.skl, gen.c, main.c: Removed yy_current_buffer from the planet. Input buffer states are now in an internal unbounded stack. Added new internal function, yyensure_buffer_stack. Added new API function, yypush_buffer_state. Added new API function, yypop_buffer_state. Documented the new API calls in the manual. Macro YY_BUFFER_STATE now refers to top of stack. This revision breaks the C++ scanner (again.) 2003-02-28 John Millaway * main.c: Removed some symbols from the undef list. They are needed for multiple headers to coexist. 2003-02-27 Will Estes * Makefile.am, NEWS, configure.in, doc/.cvsignore, doc/Makefile.am, doc/flex.texi, flex.texi: move flex.texi and flex.1 to new doc/ subdirectory 2003-02-27 Will Estes * NEWS: namespace cleanups 2003-02-26 John Millaway * main.c: Added a few macros to the undef list. 2003-02-26 John Millaway * main.c: Put the undef macros in an array. 2003-02-12 Will Estes * NEWS, configure.in: version 2.5.28 2003-02-10 Will Estes * README, TODO, configure.in, flex.texi: update documentation to reflect the sourceforge move 2003-02-06 Will Estes * TODO: update according to current thinking 2003-02-06 Will Estes * TODO: mcvs reviewed 2003-02-06 Will Estes * TODO: sourceforge migration tasks 2003-02-04 Will Estes * NEWS: Flex now warns if always-interactive is specified with fast or full; Fixed trailing slash bug in YY_INPUT macro def 2003-01-31 John Millaway * scan.l: Flex now warns if always-interactive is specified with fast or full. 2003-01-31 Will Estes * Makefile.am: switch to using cvs2cl.pl to generate the ChangeLog 2003-01-31 Will Estes * tools/cvs2cl.pl, tools/cvsauthors: we're going to be switching how we handle our ChangeLog 2003-01-29 John Millaway * gen.c, misc.c: Fixed trailing slash bug in YY_INPUT macro def. 2003-01-29 Will Estes * README.cvs-snapshot: upgrade texinfo to 4.3d 2003-01-29 Will Estes * flex.texi: the @copying construct works now; thanks to the texinfo maintainers for finding the problem 2003-01-21 Will Estes * NEWS, configure.in: version 2.5.27 2003-01-21 Will Estes * NEWS: flex now works with recent bison versions 2003-01-18 John Millaway * flex.skl: Check for YYLTYPE_IS_DECLARED. This fixes bison-bridge with latest bison. 2003-01-15 Will Estes * NEWS, po/pt_BR.po: new pt_br translation 2003-01-14 Will Estes * NEWS, configure.in: version 2.5.26 2003-01-14 Will Estes * NEWS: Fixed table deserialization bug on big-endian archs. Patch sent from Bryce Nichols 2003-01-12 John Millaway * tables_shared.h: Fixed table deserialization bug on big-endian archs. Patch sent from Bryce Nichols . 2003-01-10 Will Estes * README.cvs-snapshot: add version numbers for some tools and explain about version.texi and --enable-maintainer-mode 2003-01-10 Will Estes * NEWS: catch news up 2003-01-09 John Millaway * tests/test-mem-nr/scanner.l, tests/test-mem-r/scanner.l: Changed size_t to yy_size_t in yyalloc() and yyrealloc(). Is this really what we want? 2003-01-09 John Millaway * flex.skl: Changed type of yyleng from size_t to int. This fixes bug in PostgreSQL compilation. 2003-01-09 Will Estes * NEWS: catch news up 2003-01-09 Will Estes * flex.skl: more c++ fixes 2003-01-09 Will Estes * Makefile.am, configure.in, flex.spec.in: add a spec file 2003-01-09 Will Estes * flex.skl: type cast to pacify c++ compilers; patch from Bruce Lilly 2003-01-08 Will Estes * NEWS: new es translation 2003-01-08 Will Estes * po/es.po: new spanish translation 2002-12-19 John Millaway * gen.c: Fixed bug where YY_G(0) sometimes occurs (created by my previous commit.) 2002-12-17 John Millaway * gen.c: Fixed bug submitted by Bojan Smojver where the use of yylineno, reentrant, and yymore together caused a compile-time error. 2002-12-17 Will Estes * NEWS: update NEWS 2002-12-17 John Millaway * flex.texi: Documented new behavior with character ranges. 2002-12-16 John Millaway * parse.y: Fixed bug submitted by Bruce Lilly where character ranges would yield unexpected behavior in a caseless scanner. Also, flex now emits a warning if the range looks like trouble. 2002-12-16 John Millaway * ccl.c, flexdef.h: Added utility functions to deal with character case. 2002-12-09 Will Estes * flexint.h: we don't really need int64 anyway 2002-12-09 Will Estes * flex.skl: apparently some lints are happier with fllthrough without a space 2002-12-02 Will Estes * NEWS, configure.in: version 2.5.25 2002-12-02 Will Estes * Makefile.am: enclose flex.1 target in MAINTERNER_MODE 2002-12-02 Will Estes * po/pt_BR.po: new pt_br translation 2002-12-01 John Millaway * flex.texi: Indexed some more faqs. 2002-11-29 John Millaway * flex.skl: Fixed bug in SECOND yyless definition where argument was not enclosed in parentheses. 2002-11-29 John Millaway * flex.skl: Fixed bug in yyless definition where argument was not enclosed in parentheses. 2002-11-27 Will Estes * NEWS: flex uses flex_int*_t types 2002-11-27 Will Estes * flexint.h: integer types for non-C99 systems flexint.h 2002-11-27 John Millaway * dfa.c, flexint.h, gen.c, tables.c, tables.h, tables_shared.c, tables_shared.h: Changed int types to flex_intX_t. The build is now broken until typedef's are established. 2002-11-27 Will Estes * Makefile.am: MAINTAINERCLEANFILES: new variable: try to make it so that make maintainer-clean erases everything not under version control 2002-11-27 Will Estes * config.rpath: remove config.rpath 2002-11-27 Will Estes * README-alpha: just list location of betas 2002-11-26 Will Estes * flexint.h: __STDC_VERSION__ needs an L suffix 2002-11-26 Will Estes * NEWS, po/LINGUAS, po/pt_BR.po: new pt_br translation from the translation project 2002-11-25 Will Estes * flexint.h: include inttypes.h for folks who really are C99 2002-11-25 Will Estes * TODO: fix a typo 2002-11-25 Will Estes * NEWS, configure.in: version 2.5.24 2002-11-23 Will Estes * configure.in: try to make sure we have GNU m4 2002-11-23 Will Estes * tests/test-c++-multiple-scanners/Makefile.am: include tests/test-c++-multipl-scanners/test.input 2002-11-23 Will Estes * NEWS: more portability fixes 2002-11-23 Will Estes * configure.in, flexdef.h: apparently on some BSD systems, we need sys/params.h; reported by millaway 2002-11-22 Will Estes * NEWS: update NEWS 2002-11-22 John Millaway * flex.skl, main.c, tests/test-c++-multiple-scanners/Makefile.am: Fixed prefix of yyalloc,yyfree,yyrealloc in C++ scanner. Removed yylex_destroy from C++ scanner. 2002-11-22 John Millaway * flex.texi: renamed some faqs. 2002-11-22 Will Estes * AUTHORS: update wording about authorship 2002-11-17 John Millaway * parse.y: Removed space before line num in error messages to look more like gcc's errors. 2002-11-06 Will Estes * NEWS, po/tr.po: new turkish translation from the translation project 2002-10-28 Will Estes * gen.c: applied c++ from lilypond folks for std:: reasons 2002-10-25 Will Estes * flex.texi: proofreading 2002-10-24 Will Estes * flex.texi: proofreading 2002-10-22 Will Estes * flex.skl: use c-style header names in c++ for now; at some point we'll have a separate c++ skeleton and we can go whole-hog pure c++ 2002-10-22 Will Estes * TODO: c++ rants 2002-10-22 Will Estes * flex.texi: more proofreading 2002-10-22 Will Estes * Makefile.am: include intent.pro; indent target is MAINTAINER_MODE conditional 2002-10-22 Will Estes * configure.in: When we use AC_PATH_PROG, value-if-not-found is the name of the program we wanted to find; this will generate more helpful error messages 2002-10-21 John Millaway * tables.c: Added a missing function prototype. 2002-10-21 Will Estes * NEWS, configure.in: version 2.5.23 2002-10-21 Will Estes * NEWS: update NEWS on recent changes 2002-10-21 Will Estes * flexint.h: use sys/types.h and not inttypes.h 2002-10-21 Will Estes * configure.in: check for limits.h 2002-10-21 Will Estes * TODO: update TODO on recent suggestions 2002-10-21 Will Estes * flex.texi: titlepage and contents 2002-10-21 Will Estes * Makefile.am: typo 2002-10-21 Will Estes * Makefile.am, README.cvs-snapshot: include README.cvs-snapshot in the distribution; in README-cvs-snapshot, mention the need for enable-maintainer-mode 2002-10-21 John Millaway * flex.texi: typo. 2002-10-18 Will Estes * flex.texi: report the current version info that flex provides; reformat a list of non-posix features 2002-10-18 Will Estes * NEWS: report the current version info that flex provides 2002-10-18 Will Estes * flex.skl: FLEX_BETA defined if flex is beta 2002-10-16 Will Estes * flexint.h: if we're doing c++, then we can't use long long 2002-10-14 Will Estes * TODO: update TODO on several things 2002-10-11 Will Estes * flex.texi: more proofreading 2002-10-11 Will Estes * tests/TEMPLATE/Makefile.am, tests/test-array-nr/Makefile.am, tests/test-array-r/Makefile.am, tests/test-basic-nr/Makefile.am, tests/test-basic-r/Makefile.am, tests/test-bison-nr/Makefile.am, tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylval/Makefile.am, tests/test-c++-basic/Makefile.am, tests/test-c++-multiple-scanners/Makefile.am, tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-r/Makefile.am, tests/test-debug-nr/Makefile.am, tests/test-debug-r/Makefile.am, tests/test-header-nr/Makefile.am, tests/test-header-r/Makefile.am, tests/test-include-by-buffer/Makefile.am, tests/test-include-by-reentrant/Makefile.am, tests/test-lineno-nr/Makefile.am, tests/test-lineno-r/Makefile.am, tests/test-mem-nr/Makefile.am, tests/test-mem-r/Makefile.am, tests/test-multiple-scanners-nr/Makefile.am, tests/test-multiple-scanners-r/Makefile.am, tests/test-posix/Makefile.am, tests/test-posixly-correct/Makefile.am, tests/test-prefix-nr/Makefile.am, tests/test-prefix-r/Makefile.am, tests/test-pthread/Makefile.am, tests/test-reject/Makefile.am, tests/test-string-nr/Makefile.am, tests/test-string-r/Makefile.am, tests/test-table-opts/Makefile.am, tests/test-yyextra/Makefile.am: remove BISON assignment as per suggestion from Akim Demaille 2002-10-11 Will Estes * Makefile.am, configure.in: remove intl from dist 2002-10-11 Will Estes * configure.in: we use maintainer mode now 2002-10-11 Will Estes * NEWS: include create-test 2002-10-11 Will Estes * tests/Makefile.am: rename test to check-local as per Akim Demaille; test for failed tests so that make check fails if any tests do 2002-10-11 Will Estes * tests/Makefile.am: use dist_noinst_scripts as per email from Akim Demaille 2002-10-10 John Millaway * flex.texi: Documentation. 2002-10-10 Will Estes * NEWS, configure.in: version 2.5.22; portability fixes and attn to the test suite 2002-10-10 Will Estes * flexint.h: ok, this seems to work 2002-10-10 Will Estes * tests/TEMPLATE/Makefile.am, tests/test-bison-nr/Makefile.am, tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylval/Makefile.am, tests/test-header-nr/Makefile.am, tests/test-header-r/Makefile.am, tests/test-multiple-scanners-nr/Makefile.am, tests/test-multiple-scanners-r/Makefile.am: use builddir in tests that need it in their include path 2002-10-10 Will Estes * tests/TEMPLATE/Makefile.am: sometimes we put header files in the builddir and so we should account for that 2002-10-10 Will Estes * tests/TEMPLATE/Makefile.am: replace the last instance 2002-10-10 Will Estes * flex.skl: include unistd.h and not cunistd as cunistd only seems to be present on very recent systems 2002-10-10 Will Estes * Makefile.am, configure.in, flex.skl, flexdef.h, flexint.h: redo integral types again; add flexint.h; change dependencies caused by adding flexint.h; remove autoconf wrapper around cunistd; restore netinet/in.h includes; remove unneded feature checks in configure.in 2002-10-08 Will Estes * configure.in, flex.skl, flexdef.h: current swipe at header magic; int types be damned 2002-10-08 Will Estes * NEWS: change version constant info to reflect change to flex.skl 2002-10-08 Will Estes * Makefile.am: remove README-alpha option; add definitions for FLEX_{MAJOR,MINOR,SUBMINOR}_VERSION 2002-10-07 Will Estes * flex.skl, flexdef.h: ok, here goes; try to handle integral typedefs in one swell foop 2002-10-07 Will Estes * configure.in: we check for {u,}int*_t types; maybe this will simplify things 2002-10-07 Will Estes * configure.in: we create the tests/TEMPLATE/Makefile so that we can build the dist archives 2002-10-07 Will Estes * NEWS: more test suite cleanups 2002-10-07 Will Estes * tests/test-c++-multiple-scanners/Makefile.am: we don't use header files... 2002-10-07 Will Estes * flexdef.h: remove include of malloc.h 2002-10-04 Will Estes * flex.texi: more editing; remove examples index; merge examples into concept index 2002-10-04 Will Estes * flex.texi: edited one more faq; used C-u C-c C-u C-a to update menus and nodes since the other updating commands are somewhat broken; unfortunately this means that all nodes have all pointers filled in 2002-10-04 Will Estes * flex.texi: yesterday's proofreading 2002-10-02 Will Estes * flex.texi: proofread some more 2002-10-02 Will Estes * flex.texi: proofread edit begins 2002-10-01 Will Estes * configure.in, tests/Makefile.am, tests/test-c++-multiple-scanners/.cvsignore, tests/test-c++-multiple-scanners/Makefile.am, tests/test-c++-multiple-scanners/main.cpp, tests/test-c++-multiple-scanners/scanner-1.l, tests/test-c++-multiple-scanners/scanner-2.l, tests/test-c++-multiple-scanners/test.input: test c++ with multiple scanners 2002-09-27 Will Estes * tests/test-array-nr/Makefile.am, tests/test-array-r/Makefile.am, tests/test-basic-nr/Makefile.am, tests/test-basic-r/Makefile.am, tests/test-bison-nr/Makefile.am, tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylval/Makefile.am, tests/test-c++-basic/Makefile.am, tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-r/Makefile.am, tests/test-debug-nr/Makefile.am, tests/test-debug-r/Makefile.am, tests/test-header-nr/Makefile.am, tests/test-header-r/Makefile.am, tests/test-include-by-buffer/Makefile.am, tests/test-include-by-reentrant/Makefile.am, tests/test-lineno-nr/Makefile.am, tests/test-lineno-r/Makefile.am, tests/test-mem-nr/Makefile.am, tests/test-mem-r/Makefile.am, tests/test-multiple-scanners-nr/Makefile.am, tests/test-multiple-scanners-r/Makefile.am, tests/test-posix/Makefile.am, tests/test-posixly-correct/Makefile.am, tests/test-prefix-nr/Makefile.am, tests/test-prefix-r/Makefile.am, tests/test-pthread/Makefile.am, tests/test-reject/Makefile.am, tests/test-string-nr/Makefile.am, tests/test-string-r/Makefile.am, tests/test-table-opts/Makefile.am, tests/test-yyextra/Makefile.am: we used INCLUDES in another place in the Makefile.am files in the test suite 2002-09-27 Will Estes * tests/test-array-nr/Makefile.am, tests/test-array-r/Makefile.am, tests/test-basic-nr/Makefile.am, tests/test-basic-r/Makefile.am, tests/test-bison-nr/Makefile.am, tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylval/Makefile.am, tests/test-c++-basic/Makefile.am, tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-r/Makefile.am, tests/test-debug-nr/Makefile.am, tests/test-debug-r/Makefile.am, tests/test-header-nr/Makefile.am, tests/test-header-r/Makefile.am, tests/test-include-by-buffer/Makefile.am, tests/test-include-by-reentrant/Makefile.am, tests/test-lineno-nr/Makefile.am, tests/test-lineno-r/Makefile.am, tests/test-mem-nr/Makefile.am, tests/test-mem-r/Makefile.am, tests/test-multiple-scanners-nr/Makefile.am, tests/test-multiple-scanners-r/Makefile.am, tests/test-posix/Makefile.am, tests/test-posixly-correct/Makefile.am, tests/test-prefix-nr/Makefile.am, tests/test-prefix-r/Makefile.am, tests/test-pthread/Makefile.am, tests/test-reject/Makefile.am, tests/test-string-nr/Makefile.am, tests/test-string-r/Makefile.am, tests/test-table-opts/Makefile.am, tests/test-yyextra/Makefile.am: oops, I typed that last s/// command to perl way wrong 2002-09-27 Will Estes * tests/TEMPLATE/Makefile.am, tests/test-array-nr/Makefile.am, tests/test-array-r/Makefile.am, tests/test-basic-nr/Makefile.am, tests/test-basic-r/Makefile.am, tests/test-bison-nr/Makefile.am, tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylval/Makefile.am, tests/test-c++-basic/Makefile.am, tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-r/Makefile.am, tests/test-debug-nr/Makefile.am, tests/test-debug-r/Makefile.am, tests/test-header-nr/Makefile.am, tests/test-header-r/Makefile.am, tests/test-include-by-buffer/Makefile.am, tests/test-include-by-reentrant/Makefile.am, tests/test-lineno-nr/Makefile.am, tests/test-lineno-r/Makefile.am, tests/test-mem-nr/Makefile.am, tests/test-mem-r/Makefile.am, tests/test-multiple-scanners-nr/Makefile.am, tests/test-multiple-scanners-r/Makefile.am, tests/test-posix/Makefile.am, tests/test-posixly-correct/Makefile.am, tests/test-prefix-nr/Makefile.am, tests/test-prefix-r/Makefile.am, tests/test-pthread/Makefile.am, tests/test-reject/Makefile.am, tests/test-string-nr/Makefile.am, tests/test-string-r/Makefile.am, tests/test-table-opts/Makefile.am, tests/test-yyextra/Makefile.am: use AM_CPPFLAGS instead of INCLUDES; write -I with no space after it for broken compilers 2002-09-27 Will Estes * Makefile.am: INCLUDES is obsolete; use AM_CPPFLAGS instead 2002-09-27 Will Estes * configure.in: apparently, AM_CONFIG_HEADER is obsolete 2002-09-27 Will Estes * TODO: integrate test suite into automake 2002-09-27 Will Estes * configure.in: since we dont run the template test, we dont need to generate its Makefile either 2002-09-27 Will Estes * autogen.sh: use autoreconf instead of calling individual utilities separately 2002-09-27 Will Estes * configure.in: check for c++ compiler 2002-09-27 Will Estes * configure.in: re-organize according to suggested layout in autoconf manual 2002-09-26 Will Estes * Makefile.am, NEWS, configure.in: update automake to 1.7 and autoconf to 2.54 2002-09-26 Will Estes * Makefile.am: use AM_YFLAGS since YFLAGS is a user variable 2002-09-25 Will Estes * NEWS: catch NEWS up on things, some of which happened a long time ago; correct punctuation; try to remove some editorializing 2002-09-25 Will Estes * Makefile.am, flex.skl, flex.texi: include a single, automatically generated version number in flex scanners 2002-09-23 Will Estes * tests/create-test: complain audibly when argument not supplied; echo on stderr when writing error messages 2002-09-23 Will Estes * tests/Makefile.am, tests/create-test: DIST_SUBDIRS so we don't have to run the TEMPLATE test; so we add new tests to SUBDIRS and DIST_SUBDIRS 2002-09-23 Will Estes * tests/TEMPLATE/Makefile.am: not all compilers support '-I dir' so we write '-Idir' instead 2002-09-23 Will Estes * TODO: reorganize faq entries; proofread the manual 2002-09-23 Will Estes * flex.texi: move c++ experimental warning to top of cxx node 2002-09-20 Will Estes * flex.skl: move stdint.h include to table-serialization section; we'll still need to think about stdint.h more though 2002-09-20 Will Estes * NEWS: new smarter skeleton/scanner generation 2002-09-20 John Millaway * flex.skl, misc.c: bison-bridge skel handled via %if/%endif pairs. 2002-09-19 John Millaway * flex.skl, misc.c: reentrant skel handled via %if/%endif pairs. 2002-09-19 John Millaway * flex.skl, misc.c: skeleton uses %push/%pop to keep skelout() scope sane. skel commands are omitted unless --debug enabled. 2002-09-19 John Millaway * flex.skl, main.c, misc.c, tables.h: Added %push and %pop operations to skel processing. 2002-09-17 Will Estes * NEWS, configure.in: flex 2.5.21 2002-09-17 John Millaway * tests/test-reject/Makefile.am: minor fixup for dist. 2002-09-16 Will Estes * NEWS, configure.in: version 2.5.20 2002-09-16 Will Estes * flex.texi: correct typo 2002-09-16 Will Estes * NEWS: note the new tables functionality 2002-09-16 John Millaway * tests/test-multiple-scanners-r/.cvsignore, tests/test-multiple-scanners-r/Makefile.am: Fixed `clean' target and .cvsignore. 2002-09-16 John Millaway * TODO, flex.skl, flex.texi, main.c, tables_shared.h, tests/test-multiple-scanners-r/main.c, tests/test-multiple-scanners-r/scanner-1.l, tests/test-multiple-scanners-r/scanner-2.l: Serialization works in headers (%option headers). Serialization code (Tables API) is complete. 2002-09-16 Will Estes * tests/test-reject/scanner.l: replace yytables_load with yytables_fload as per millaway's other changes 2002-09-15 John Millaway * TODO, flex.texi: Created user API for tables deserialization. Documented API and --tables-* options in manual. 2002-09-15 John Millaway * flex.skl, tests/test-table-opts/scanner.l: Tables deserialization uses yyalloc/yyfree. Changed yytables_load to yytables_fload. 2002-09-15 John Millaway * tests/test-bison-nr/.cvsignore: minor upkeep. 2002-09-15 John Millaway * flex.texi: Categorized and indexed scanner options in manual. 2002-09-15 John Millaway * flex.skl: Initialization of reject vars and %array vars in reentrant scanner. 2002-09-13 John Millaway * TODO, configure.in, devel/tables.pl, dfa.c, flex.skl, flex.texi, gen.c, tables.c, tables_shared.c, tables_shared.h, tests/Makefile.am, tests/test-reject/.cvsignore, tests/test-reject/Makefile.am, tests/test-reject/scanner.l, tests/test-reject/test.input, tests/test-table-opts/Makefile.am: Created test for reject. Handled reject-triggered tables in serialization. 2002-09-13 Will Estes * NEWS: millaway has been very busy 2002-09-13 John Millaway * flex.skl, tests/test-table-opts/Makefile.am, tests/test-table-opts/scanner.l: Added test for multiple tables in one file. 2002-09-13 John Millaway * tests/test-bison-nr/.cvsignore: forgot to add .cvsignore on last commit. 2002-09-13 John Millaway * tests/test-bison-nr/Makefile.am, tests/test-bison-nr/main.c, tests/test-bison-nr/parser.y, tests/test-bison-nr/scanner.l, tests/test-bison-nr/test.input: Added test-bison-bridge. 2002-09-13 John Millaway * configure.in, flex.skl, flex.texi, flexdef.h, gen.c, main.c, misc.c, options.c, options.h, scan.l, tables.h, tests/Makefile.am, tests/descriptions, tests/test-bison-yylloc/scanner.l, tests/test-bison-yylval/scanner.l, tests/test-table-opts/scanner.l: Bison bridge code now works for all C scanners and pure/non-pure bison parsers. Added %option bison-bridge (--bison-bridge). Removed %option reentrant-bison/--reentrant-bison/-Rb. Scanner knows the name of its tables. Tables serialization is OK on EOF. yylineno is present in all scanners. Modified nasty performance penalty warning w/ yylineno. test-table-opts is now run last because it's so fat. Updated manual. 2002-09-12 John Millaway * flex.texi: documentation of tabels api in manual 2002-09-12 John Millaway * TODO, tables.c: Renamed *_fwrite to *_write to reflect writer abstraction. 2002-09-11 John Millaway * devel/tables.pl: Added perl script to read/dump serialized tables in devel/ 2002-09-11 Will Estes * scan.l: the debian patch used strlen(yytext) and similar constructs--as millaway points out, this is better known as yyleng 2002-09-11 Will Estes * NEWS, po/de.po: new de translation from the translation project 2002-09-11 John Millaway * flex.skl: yytbl_load now checks tables set by name. Localized var scaope in yytbl_load. 2002-09-10 Will Estes * tests/Makefile.am: make clean before make test 2002-09-09 John Millaway * TODO, flex.skl: Fixed deserialization of --fast tables. 2002-09-09 Will Estes * TODO: fix typo; remove the yylineo entry 2002-09-09 John Millaway * TODO, buf.c, devel/dump-tables.pl, dfa.c, flex.skl, flexdef.h, gen.c, main.c, misc.c, options.c, options.h, scan.l, tables.c, tables.h, tables_shared.h, tests/test-table-opts/.cvsignore, tests/test-table-opts/Makefile.am, tests/test-table-opts/scanner.l: Table deserialization works for everything except --fast scanners. Scanners can auto-verify serialized table integrity via --tables-verify. Added tables API items to TODO list. test-table-opts is becoming exhaustive (a good thing). 2002-09-09 Will Estes * NEWS: flex has better internal diagnostics 2002-09-09 Will Estes * configure.in, flexdef.h: test for presence of __func__ and compensate if absent 2002-09-09 Will Estes * Makefile.am: include the intl/ subdirectory when searching for include files 2002-09-09 Will Estes * NEWS, po/ru.po, po/sv.po: new sv, ru translations from the translation project 2002-09-07 John Millaway * flex.skl, misc.c: Changed cryptic skeleton markers to readable form. 2002-09-07 John Millaway * Makefile.am, dfa.c, flex.skl, flex.texi, flexdef.h, gen.c, main.c, misc.c, parse.y, tables.c, tables.h, tables_shared.c, tables_shared.h: Members of struct yy_trans_info are now forced to be the same size. Added shared file tables_shared.c. Separated tables.h from flexdef.h Bulk of table deserialization code is done. 2002-09-06 Will Estes * NEWS, po/ca.po: new ca translation 2002-09-06 Will Estes * NEWS: new fr translation 2002-09-06 Will Estes * po/fr.po: new french translation from the translation project 2002-09-05 Will Estes * NEWS: c99 function defs by default 2002-09-05 John Millaway * flexdef.h, tables.c: Added flex_die macro. May need some autoconf massaging. Added thorough error checking in tables code. 2002-09-05 John Millaway * flex.skl, flex.texi: Flex generates C99 defs now. Documented the above change in manual. 2002-09-05 John Millaway * tests/test-table-opts/.cvsignore, tests/test-table-opts/Makefile.am: Added serialization test to table-opts test. 2002-09-05 Will Estes * configure.in: oops, i made a typo 2002-09-05 Will Estes * NEWS, configure.in: version 2.5.19 2002-09-05 Will Estes * scan.l: use FLEX_EXIT(), not exit() 2002-09-05 John Millaway * devel/00EXTRACT-ALL-SYMS.sh, devel/README, devel/dump-tables.pl: Added devel/ directory for junk that we don't want in the distribution, but that we want in CVS. 2002-09-05 Will Estes * scan.l: s/exit(1)/exit(EXIT_FAILURE) 2002-09-05 John Millaway * dfa.c, gen.c: Tables are now generated with %option tables-file=FILE. 2002-09-05 Will Estes * NEWS: catch up on a few things 2002-09-05 Will Estes * scan.l: prevent segfault on input lines which are longer than the allocated space (problem report from Manoj Srivastava ) 2002-09-05 John Millaway * flex.texi, main.c, options.c, options.h: Changed option 'header' to 'header-file'. 'header' still works, though. 2002-09-05 John Millaway * flex.texi, flexdef.h, gen.c, main.c, options.c, options.h, scan.l, tables.c: Tons more work on tables. 2002-09-05 John Millaway * flexdef.h, gen.c, tables.c, tables_shared.h: Lots of work on tables serialization code. 2002-09-04 Will Estes * README.cvs-snapshot: mention GNU indent 2002-09-04 Will Estes * NEWS: remove the word after from the version line 2002-09-03 Will Estes * NEWS, configure.in: version 2.5.18 2002-09-03 Will Estes * NEWS: catch up on the NEWS 2002-09-03 Will Estes * tests/Makefile.am: target test: quote the results echoing so that the ECHO_C will work on systems where it is used 2002-09-03 Will Estes * configure.in: when we don't have GNU indent, the test will generate output on stderr, so we send that to /dev/null 2002-09-03 Will Estes * configure.in: fixed bug whereby bison was reported missing even when it was found 2002-09-02 John Millaway * tables.c: In-code documentation. 2002-09-02 John Millaway * flexdef.h: Forgot to indent before previous commit. 2002-09-02 John Millaway * flexdef.h: Added known integer limits if undefined. 2002-08-29 Will Estes * configure.in: version 2.5.17 2002-08-29 Will Estes * NEWS: more portability fixes; new version number 2002-08-29 Will Estes * flexdef.h, main.c, misc.c, scanopt.c: #include fixes; we've factored out all the system include files and put them in flexdef.h 2002-08-29 Will Estes * dfa.c: eat a blank line 2002-08-29 Will Estes * NEWS: new config.{sub,guess} files; mention that we use indent on flex 2002-08-28 Will Estes * configure.in: warn if no indent found; version 2.5.16 2002-08-28 Will Estes * NEWS: catch up on recent changes; version 2.5.16 2002-08-27 Will Estes * buf.c, ccl.c, dfa.c, ecs.c, flexdef.h, gen.c, libmain.c, libyywrap.c, main.c, misc.c, nfa.c, options.c, options.h, scanopt.c, scanopt.h, sym.c, tables.c, tables_shared.h, tblcmp.c, yylex.c: ran the indent target; commit the results 2002-08-27 Will Estes * Makefile.am: touch up the indent targeet; it's ready for production use now 2002-08-27 Will Estes * configure.in: test for GNU indent; reorder the tests somewhat 2002-08-23 Will Estes * configure.in: automake is smarter about autoconf's versioning scheme 2002-08-23 Will Estes * NEWS: catch NEWS up on what we've been doing 2002-08-22 Will Estes * flexdef.h: do some more conditional including for folks without standard systems 2002-08-22 Will Estes * tests/test-c++-basic/Makefile.am: use CXX to link the test scanner here 2002-08-22 John Millaway * flex.texi: Documentation. 2002-08-22 John Millaway * Makefile.am: Created 'indent' target and added .indent.pro. 2002-08-22 John Millaway * tests/test-array-nr/Makefile.am, tests/test-array-r/Makefile.am, tests/test-basic-nr/Makefile.am, tests/test-basic-r/Makefile.am, tests/test-c-cpp-nr/Makefile.am: Fixed missing 'make clean' files. 2002-08-22 John Millaway * tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylval/Makefile.am: fixed missing 'clean' file. 2002-08-22 John Millaway * flex.skl, tests/test-c++-basic/Makefile.am, tests/test-c++-basic/scanner.l: Removed core of yylex_destroy from c++ scanner -- hack! Added -lstdc++ to LDFLAGS (should we have to do this??) 2002-08-21 Will Estes * README: official releases are being hosted by Vern 2002-08-21 Will Estes * NEWS, configure.in: new beta version; more entries in NEWS from millaway; the top level entry for test-c++-basic 2002-08-21 Will Estes * tests/Makefile.am, tests/test-c++-basic/.cvsignore, tests/test-c++-basic/Makefile.am, tests/test-c++-basic/scanner.l, tests/test-c++-basic/test.input: add test-c++-basic 2002-08-21 John Millaway * gen.c, nfa.c: More tabels work. 2002-08-21 John Millaway * flexdef.h, gen.c, tables.c, tables_shared.h: More work on tables. 2002-08-20 John Millaway * dfa.c: Cleaned up macros that took no ';'. 2002-08-20 John Millaway * scanopt.c: Fixed oddball '=-'. 2002-08-20 John Millaway * flex.skl, flex.texi, gen.c: Dynamically allocate REJECT state buffer. Mentioned memory usage in docs. Made REJECT buffer variables reentrant-safe. 2002-08-20 John Millaway * tables.c: More work on tables code. 2002-08-20 Will Estes * Makefile.am, NEWS, configure.in: we're using m4 so have configure test for it 2002-08-20 John Millaway * Makefile.am, tables.c: Added tables.c and rebuilt dependencies. 2002-08-20 John Millaway * TODO, flex.texi: Dicussed prototypes and header in manual. 2002-08-19 John Millaway * Makefile.am, configure.in, flex.skl, flexdef.h, tables_shared.h: More work on tables serialization. 2002-08-19 John Millaway * Makefile.am, mkskel.sh: Skeleton is now passed through m4 (before dist is built). 2002-08-19 Will Estes * po/LINGUAS, po/zh_CN.po: add zh_cn translation from the translation project 2002-08-19 Will Estes * NEWS: millaway's done a lot of things which need to be mentioned in NEWS 2002-08-18 John Millaway * main.c: Removed #undef of start conditions. 2002-08-17 John Millaway * TODO: todo list 2002-08-17 John Millaway * flexdef.h, main.c, misc.c: Start conditions now optional in header. undef's now optional in header. Start conditions are NOT prefixed. 2002-08-17 John Millaway * flex.skl, flex.texi: Working on tables API. 2002-08-16 John Millaway * flexdef.h, main.c, misc.c, options.c, options.h, parse.y, scan.l: Added --tables option. Omitted tables code from generated scanner when unused. 2002-08-16 John Millaway * flex.skl, flex.texi, misc.c: Prelimary work on tables API. 2002-08-16 John Millaway * tests/TEMPLATE/Makefile.am, tests/test-array-nr/Makefile.am, tests/test-array-r/Makefile.am, tests/test-basic-nr/Makefile.am, tests/test-basic-r/Makefile.am, tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylval/Makefile.am, tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-r/Makefile.am, tests/test-debug-nr/Makefile.am, tests/test-debug-r/Makefile.am, tests/test-header-nr/Makefile.am, tests/test-header-r/Makefile.am, tests/test-include-by-buffer/Makefile.am, tests/test-include-by-reentrant/Makefile.am, tests/test-lineno-nr/Makefile.am, tests/test-lineno-r/Makefile.am, tests/test-mem-nr/Makefile.am, tests/test-mem-r/Makefile.am, tests/test-multiple-scanners-nr/Makefile.am, tests/test-multiple-scanners-r/Makefile.am, tests/test-posix/Makefile.am, tests/test-posixly-correct/Makefile.am, tests/test-prefix-nr/Makefile.am, tests/test-prefix-r/Makefile.am, tests/test-pthread/Makefile.am, tests/test-string-nr/Makefile.am, tests/test-string-r/Makefile.am, tests/test-table-opts/Makefile.am, tests/test-yyextra/Makefile.am: Tests now respect CFLAGS, CPPFLAGS, etc.. 2002-08-16 John Millaway * tests/test-basic-nr/scanner.l, tests/test-basic-r/scanner.l, tests/test-lineno-nr/scanner.l, tests/test-lineno-r/scanner.l: Got rid of flex -s warnings in tests. 2002-08-16 John Millaway * Makefile.am: Updated dependencies list. 2002-08-15 John Millaway * main.c: Fixed seg fault bug in ecs. 2002-08-15 Will Estes * tests/test-c-cpp-nr/.cvsignore, tests/test-c-cpp-r/.cvsignore: ignore .cpp files since we generate them instead of .c 2002-08-15 Will Estes * configure.in: version 2.5.14 2002-08-15 Will Estes * NEWS: c-as-c++ tests reworked 2002-08-15 John Millaway * tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-nr/scanner.l, tests/test-c-cpp-r/Makefile.am, tests/test-c-cpp-r/scanner.l: The c++ tests use .cpp instead of .c extensions just to be on the safe side. 2002-08-15 Will Estes * main.c: conditionally include ; include config.h as well 2002-08-15 Will Estes * configure.in, flex.skl: only include if we have it 2002-08-15 Will Estes * NEWS: portability fixes; added missing punctuation; de translation now included 2002-08-15 Will Estes * po/LINGUAS: we also translate to german 2002-08-15 Will Estes * Makefile.am: require automake at least 1.6 2002-08-15 Will Estes * NEWS, configure.in: version 2.5.13 2002-08-14 Will Estes * flex.texi: reverted away from the @copying as it breaks the info reader 2002-08-14 John Millaway * flex.texi, flexdef.h, main.c, misc.c: Start condition prefixes attempts to adjust to user preferences. 2002-08-13 John Millaway * main.c: Include start condition symbols in header. 2002-08-13 John Millaway * flexdef.h, main.c: Omit user code and tables from generated header file. 2002-08-13 Will Estes * flex.texi: use @copying construct to display the flex license; move copying and bug reporting to the front of the manual 2002-08-13 Will Estes * NEWS: printf fix and yylex_init reports errors 2002-08-12 John Millaway * flex.texi: Updated manual for %option header. 2002-08-12 John Millaway * flex.skl, flex.texi, gen.c: Fixed type mismatch in printf. yylex_init now reports errors. 2002-08-10 John Millaway * dfa.c, main.c: Added alignment flag for future use. 2002-08-10 John Millaway * tests/test-table-opts/.cvsignore, tests/test-table-opts/Makefile.am: Added options to test-table-opts 2002-08-10 John Millaway * configure.in, tests/Makefile.am, tests/descriptions, tests/test-c-cpp-nr/Makefile.am, tests/test-table-opts/.cvsignore, tests/test-table-opts/Makefile.am, tests/test-table-opts/scanner.l, tests/test-table-opts/test.input: Added a test for various DFA table options. 2002-08-09 Will Estes * flex.texi: more faq editing; corrected mistyped nodenames 2002-08-09 Will Estes * flex.skl: fix typo which propogates out to generated scanners 2002-08-09 Will Estes * flex.texi: edited a few more faqs 2002-08-09 Will Estes * Makefile.am, faq.texi: remove faq.texi as it's included in flex.texi 2002-08-08 Will Estes * flex.texi: a few more faq edits; remove faq-89 2002-08-08 Will Estes * flex.texi: cite, not site 2002-08-08 Will Estes * flex.texi: and get the faq included 2002-08-08 Will Estes * flex.texi: fix some grammer/typography in the top node and add a detailed menu 2002-08-08 Will Estes * TODO: we've updated gettext 2002-08-08 Will Estes * po/.cvsignore: we need to ignore a few more gettext files 2002-08-08 Will Estes * NEWS, configure.in: version 2.5.12 2002-08-08 Will Estes * NEWS: mention gettext; document the non-need for bison/flex in the build process 2002-08-08 Will Estes * Makefile.am, configure.in: include intl in the distribution and in the build process 2002-08-08 Will Estes * Makefile.am: builddir in help2man call needed @-signs around it 2002-08-08 Will Estes * po/.cvsignore: we can ignore Makefile.in.in 2002-08-08 Will Estes * m4/.cvsignore, m4/Makefile.am: oops, too hasty on deleting this directory, sigh 2002-08-08 Will Estes * autogen.sh: if autopoint is going to run automatically, it's going to need to be able to update existing files 2002-08-08 Will Estes * ABOUT-NLS, autogen.sh, configure.in, m4/.cvsignore, m4/Makefile.am, m4/codeset.m4, m4/gettext.m4, m4/glibc21.m4, m4/iconv.m4, m4/isc-posix.m4, m4/lcmessage.m4, m4/lib-ld.m4, m4/lib-link.m4, m4/lib-prefix.m4, m4/progtest.m4: autopoint now works so let's let it run the gettext show 2002-08-07 Will Estes * TODO: we need to index the faq entries 2002-08-07 Will Estes * faq.texi: proofed "Why do flex scanners call fileno if it is not ANSI compatible?" 2002-08-07 Will Estes * faq.texi: proofed "How do I expand \ escape sequences in C-style quoted strings?" 2002-08-07 Will Estes * README: changes to README to align with GNU coding standards 2002-08-06 Will Estes * Makefile.am: help2man should look in builddir for the flex binary 2002-08-02 John Millaway * flex.skl: Fixed yyunput prototype. 2002-08-01 Will Estes * NEWS: new fr translation from the translation project 2002-08-01 Will Estes * po/fr.po: new fr.po translation from the translation project 2002-08-01 Will Estes * NEWS: yylineno performance hit is fixed 2002-07-31 John Millaway * TODO, flex.texi: Updated docs on yylineno. 2002-07-31 Will Estes * TODO: discuss yylineno performance 2002-07-31 Will Estes * NEWS: forgot to say what the date was that we made the release 2002-07-31 Will Estes * NEWS, configure.in: version 2.5.11 2002-07-31 Will Estes * faq.texi: fixed a menu entry and related problems 2002-07-31 Will Estes * configure.in: someday, maybe we can use autopoint 2002-07-31 Will Estes * Makefile.am: we need to include texinfo.tex now 2002-07-31 Will Estes * texinfo.tex: add texinfo.tex 2002-07-30 Will Estes * faq.texi: fix up some fatal bugs in the texinfo of the faq; begin the clean up; remove trailing and leading white space 2002-07-30 Will Estes * TODO: faqs need work 2002-07-30 Will Estes * NEWS, TODO: prototypes get airtime these days 2002-07-28 John Millaway * flex.skl: Added some comments. 2002-07-28 John Millaway * flex.skl: Fixed bug where yyless did not consider yylineno. 2002-07-28 John Millaway * scan.l: Fixed bug I created in previous commit. 2002-07-28 John Millaway * scan.l: Don't wrap ()s around {NAMEDEFS} at the end of a rule. 2002-07-27 John Millaway * flex.skl, tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-r/Makefile.am: Fixed test-c-cpp to actually use the C++ compiler for the test. Fixed the bug that this exposed. 2002-07-27 John Millaway * ccl.c, flex.skl, flexdef.h, gen.c, main.c, nfa.c, parse.y, scan.l: yylineno check is only performed on rules whose regexs can match a newline. 2002-07-25 John Millaway * flex.skl, tests/TEMPLATE/scanner.l, tests/test-array-nr/scanner.l, tests/test-array-r/scanner.l, tests/test-basic-nr/scanner.l, tests/test-basic-r/scanner.l, tests/test-bison-yylloc/parser.y, tests/test-c-cpp-nr/scanner.l, tests/test-c-cpp-r/scanner.l, tests/test-debug-nr/scanner.l, tests/test-debug-r/scanner.l, tests/test-include-by-buffer/scanner.l, tests/test-include-by-reentrant/scanner.l, tests/test-lineno-nr/scanner.l, tests/test-lineno-r/scanner.l, tests/test-mem-nr/scanner.l, tests/test-mem-r/scanner.l, tests/test-posix/scanner.l, tests/test-posixly-correct/scanner.l, tests/test-prefix-nr/scanner.l, tests/test-prefix-r/scanner.l, tests/test-pthread/scanner.l, tests/test-string-nr/scanner.l, tests/test-string-r/scanner.l, tests/test-yyextra/scanner.l: All prototypes were rewritten to depend upon the macro YY_TRADITIONAL_FUNC_DEFS, which is defined by default. The generated scanners build cleanly under gcc's traditional strictness and under C++ compilers. 2002-07-24 Will Estes * NEWS: dist-bzip2 and rename yy_globals and yy_globals_t 2002-07-24 Will Estes * configure.in: version 2.5.10 2002-07-24 Will Estes * Makefile.am: add dist-bzip2 to automake_options so we'll start getting tar.bz2 archives 2002-07-23 John Millaway * flex.skl, flex.texi, tests/test-bison-yylval/scanner.l, tests/test-mem-r/scanner.l, tests/test-multiple-scanners-r/scanner-1.l, tests/test-multiple-scanners-r/scanner-2.l, tests/test-prefix-r/scanner.l, tests/test-pthread/scanner.l, tests/test-yyextra/scanner.l: s/yy_globals_t/yyguts_t/g s/yy_globals/yyscanner/g 2002-07-23 John Millaway * Makefile.am: typo in tags target 2002-07-22 John Millaway * Makefile.am: Removed erroneous $(srcdir) from help2man target. 2002-07-22 Will Estes * NEWS, configure.in: it's version 2.5.9 now 2002-07-22 Will Estes * po/.cvsignore: updated gettext to 0.11.3 2002-07-22 Will Estes * ABOUT-NLS, config.rpath, m4/gettext.m4, m4/iconv.m4, m4/isc-posix.m4, m4/lcmessage.m4, m4/lib-link.m4: updated gettext to version 0.11.3 2002-07-22 Will Estes * autogen.sh, configure.in: rollback on configure.in and autogen.sh because autpoint is broken 2002-07-22 Will Estes * po/ru.po: new russian translation from translation project 2002-07-19 Will Estes * autogen.sh: ok, we're going to start using autopoint, but the tree is going to undergo some changes after this 2002-07-19 Will Estes * configure.in: we're preparing for autopoint 2002-07-17 John Millaway * flex.texi: Updated manual. 2002-07-17 Will Estes * NEWS: update the NEWS file for lots of things millaway has done 2002-07-17 John Millaway * flex.skl, main.c, misc.c, scan.l, scanopt.c, sym.c, tests/test-mem-nr/scanner.l, tests/test-mem-r/scanner.l: Fixed prototype/definition conflicts with "traditional" C in skeleton at request of gcc developer. Removed duplicate prototypes in gen.c, sym.c, main.c. Added missing prototypes where needed. All functions in skeleton follow ISO C style protos and defs, instead of BOTH ISO and new-style. Skeleton now compiles cleanly under super-strict gcc flags. Flex itself almost compiles cleanly under strict flags. 2002-07-15 John Millaway * faq.texi, flex.texi: Worked on mem mgmt sect of manual. 2002-07-15 Will Estes * scan.l: allow blank lines and continuations in more places 2002-07-12 Will Estes * TODO: millaway finished the faqs directory 2002-07-12 Will Estes * TODO: removed items as per email from millaway 2002-07-12 John Millaway * configure.in, tests/Makefile.am, tests/descriptions, tests/test-posix/.cvsignore, tests/test-posix/Makefile.am, tests/test-posix/scanner.l, tests/test-posixly-correct/.cvsignore, tests/test-posixly-correct/Makefile.am, tests/test-posixly-correct/scanner.l: Added test for %option posix-compat and repeat operator. Added test for POSIXLY_CORRECT environment variable and repeat operator. 2002-07-12 John Millaway * main.c, scan.l: Fixed POSIXLY_CORRECT detection in scanner. 2002-07-11 John Millaway * faq.texi: More work on faq. 2002-07-11 John Millaway * faq.texi: Moved all faqs into manual -- but did not evaluate them yet. Removed the old faq files. 2002-07-10 John Millaway * main.c: Removed duplicate definition of FLEX_DEBUG. gcc doesn't care, but other compilers might. 2002-07-10 John Millaway * flex.texi: Wrote some more about memory mgmt in the manual. 2002-07-10 John Millaway * flex.texi: flex.texi now works with install-info. 2002-07-10 Will Estes * TODO: added items as per email from millaway 2002-07-10 Will Estes * NEWS: after we release a version, we have to keep the version number in NEWS current 2002-07-10 John Millaway * flex.skl, flex.texi, main.c, scan.l, tests/test-mem-nr/scanner.l, tests/test-mem-r/scanner.l: Fixed prefix issue with get/set debug functions. Fixed prefix issues with memory functions. 2002-07-09 John Millaway * flex.skl: Memory functions are no longer static. 2002-07-09 John Millaway * tests/test-mem-nr/test.input: Added a missing input file for test-mem-nr/ 2002-07-09 John Millaway * tests/test-mem-nr/.cvsignore, tests/test-mem-nr/Makefile.am, tests/test-mem-nr/scanner.l, tests/test-mem-r/.cvsignore, tests/test-mem-r/Makefile.am, tests/test-mem-r/scanner.l, tests/test-mem-r/test.input: Added tests for overriding memory. 2002-07-09 John Millaway * flex.texi: Added sections in manual for memory management. 2002-07-09 Will Estes * NEWS: noted more user visible changes 2002-07-09 John Millaway * configure.in, flex.skl, scan.l, tests/Makefile.am: Added yylex_destroy() to non-reentrant scanner. Added ability to override memory functions. Added tests for overriding memory functions. 2002-07-09 Will Estes * NEWS: new POSIXLY_CORRECT and new ru translation 2002-07-09 Will Estes * po/ru.po: new ru translation from the translation project 2002-07-09 John Millaway * flex.texi: Made note of set/get debug in docs. 2002-07-09 John Millaway * configure.in, flexdef.h, tests/create-test: Replaced obsolete macros in configure.in. Modified create-test to handle the above changes in configure.in. Added support for . 2002-07-09 John Millaway * main.c: Check POSIXLY_CORRECT env variable. 2002-07-09 John Millaway * flex.skl: Added prototypes for the get/set debug functions. 2002-07-09 John Millaway * configure.in, flex.skl, gen.c, main.c, scan.l, tests/Makefile.am, tests/test-debug-nr/.cvsignore, tests/test-debug-nr/Makefile.am, tests/test-debug-nr/scanner.l, tests/test-debug-nr/test.input, tests/test-debug-r/.cvsignore, tests/test-debug-r/Makefile.am, tests/test-debug-r/scanner.l, tests/test-debug-r/test.input: Made yy_flex_debug non-global in reentrant scanner. Created get/set functions for yy_flex_debug. Defined prefixes for new yy_flex_debug symbols. Added tests/ for yy_flex_debug. 2002-07-09 John Millaway * tests/create-test: create-test script now modifies .cvsignore 2002-07-09 John Millaway * tests/create-test: Improved the error checking. 2002-07-03 Will Estes * main.c: fix bug whereby prefix didn't get passed to everybody; patch by rse@engelschall.com 2002-07-03 Will Estes * faq.texi: ~ is an active character, so we'll just use the word 'about' 2002-07-02 John Millaway * Makefile.am: Fixed typo. 2002-07-02 John Millaway * faq.texi: Added a faq. 2002-06-28 John Millaway * Makefile.am: Added 'tags' target -- something I should have done long ago. 2002-06-28 Will Estes * TODO: add two new items regarding coding; remove tests/ copyright notice item as it's done 2002-06-26 Will Estes * NEWS: note the copyright messages in tests/ 2002-06-25 John Millaway * tests/TEMPLATE/Makefile.am, tests/TEMPLATE/parser.y, tests/TEMPLATE/scanner.l, tests/test-array-nr/Makefile.am, tests/test-array-nr/scanner.l, tests/test-array-r/Makefile.am, tests/test-array-r/scanner.l, tests/test-basic-nr/Makefile.am, tests/test-basic-nr/scanner.l, tests/test-basic-r/Makefile.am, tests/test-basic-r/scanner.l, tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylloc/main.c, tests/test-bison-yylloc/parser.y, tests/test-bison-yylloc/scanner.l, tests/test-bison-yylval/Makefile.am, tests/test-bison-yylval/main.c, tests/test-bison-yylval/parser.y, tests/test-bison-yylval/scanner.l, tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-nr/scanner.l, tests/test-c-cpp-r/Makefile.am, tests/test-c-cpp-r/scanner.l, tests/test-header-nr/Makefile.am, tests/test-header-nr/main.c, tests/test-header-nr/scanner.l, tests/test-header-r/Makefile.am, tests/test-header-r/main.c, tests/test-header-r/scanner.l, tests/test-include-by-buffer/Makefile.am, tests/test-include-by-buffer/scanner.l, tests/test-include-by-reentrant/Makefile.am, tests/test-include-by-reentrant/scanner.l, tests/test-lineno-nr/Makefile.am, tests/test-lineno-nr/scanner.l, tests/test-lineno-r/Makefile.am, tests/test-lineno-r/scanner.l, tests/test-multiple-scanners-nr/Makefile.am, tests/test-multiple-scanners-nr/main.c, tests/test-multiple-scanners-nr/scanner-1.l, tests/test-multiple-scanners-nr/scanner-2.l, tests/test-multiple-scanners-r/Makefile.am, tests/test-multiple-scanners-r/main.c, tests/test-multiple-scanners-r/scanner-1.l, tests/test-multiple-scanners-r/scanner-2.l, tests/test-prefix-nr/Makefile.am, tests/test-prefix-nr/scanner.l, tests/test-prefix-r/Makefile.am, tests/test-prefix-r/scanner.l, tests/test-pthread/Makefile.am, tests/test-pthread/scanner.l, tests/test-string-nr/Makefile.am, tests/test-string-nr/scanner.l, tests/test-string-r/Makefile.am, tests/test-string-r/scanner.l, tests/test-yyextra/Makefile.am, tests/test-yyextra/scanner.l: Prepended explicit license to all test-*/ sources. 2002-06-25 Will Estes * NEWS, po/ca.po, po/de.po, po/fr.po, po/sv.po, po/tr.po: new ca, de, fr, sv, tr translations 2002-06-19 Will Estes * TODO: add bootstrapper to the todo list 2002-06-19 Will Estes * configure.in: new version number 2002-06-19 Will Estes * TODO: update TODO list 2002-06-19 Will Estes * NEWS, TODO, flex.texi, flexdef.h, main.c, options.c, options.h, parse.y, scan.l: address typos in NEWS; add --posix option for ERE parsing the way posix wants it; update the TODO file 2002-05-31 Will Estes * README-alpha: made code quality warning more explicit; gave url for cvs and beta flex 2002-05-23 John Millaway * gen.c: Fixed bug where omission of user section 3 caused unmatched #ifdef's in generated code. 2002-05-20 Will Estes * configure.in: configure.in requires at least autoconf 2.50 2002-05-13 John Millaway * Makefile.am: Updated my email address. 2002-05-10 John Millaway * flexdef.h, misc.c: chomp'd lines when reading external skel file. 2002-05-07 Will Estes * po/sv.po: new sweedish translation from the translation project 2002-04-29 Will Estes * po/ca.po: new catalan translation from the translation project 2002-04-29 Will Estes * po/es.po: new spanish translation from the translation project 2002-04-25 Will Estes * TODO: note that the lex matching of abc{1,3} is the posix behavior and so we have a problem 2002-04-25 Will Estes * flex.texi: note that the lex matching of abc{1,3} is the posix behavior 2002-04-23 Will Estes * configure.in: new version 2.5.7; use autoconf versioning info 2002-04-23 Will Estes * NEWS: note changes in 2.5.7 2002-04-23 Will Estes * main.c: conditional compile gettext initialization 2002-04-22 Will Estes * po/de.po: new german translation from the translation project 2002-04-19 John Millaway * tests/test-include-by-reentrant/Makefile.am: Fixed command line for test-include-by-reentrant/Makefile.am 2002-04-19 John Millaway * tests/Makefile.am, tests/TEMPLATE/Makefile.am, tests/test-array-nr/Makefile.am, tests/test-array-r/Makefile.am, tests/test-basic-nr/Makefile.am, tests/test-basic-r/Makefile.am, tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylval/Makefile.am, tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-r/Makefile.am, tests/test-header-nr/Makefile.am, tests/test-header-r/Makefile.am, tests/test-include-by-buffer/Makefile.am, tests/test-include-by-reentrant/Makefile.am, tests/test-lineno-nr/Makefile.am, tests/test-lineno-r/Makefile.am, tests/test-multiple-scanners-nr/Makefile.am, tests/test-multiple-scanners-r/Makefile.am, tests/test-prefix-nr/Makefile.am, tests/test-prefix-r/Makefile.am, tests/test-pthread/Makefile.am, tests/test-string-nr/Makefile.am, tests/test-string-r/Makefile.am, tests/test-yyextra/Makefile.am: Added -I . to compiler search path in tests (so it finds the generated parser.h). 2002-04-19 John Millaway * flexdef.h, misc.c, parse.y, sym.c: Applied 'const' to a few more char*, where appropriate. 2002-04-19 John Millaway * tests/TEMPLATE/Makefile.am, tests/test-array-nr/Makefile.am, tests/test-array-r/Makefile.am, tests/test-basic-nr/Makefile.am, tests/test-basic-r/Makefile.am, tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylval/Makefile.am, tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-r/Makefile.am, tests/test-header-nr/Makefile.am, tests/test-header-r/Makefile.am, tests/test-include-by-buffer/Makefile.am, tests/test-include-by-reentrant/Makefile.am, tests/test-lineno-nr/Makefile.am, tests/test-lineno-r/Makefile.am, tests/test-multiple-scanners-nr/Makefile.am, tests/test-multiple-scanners-r/Makefile.am, tests/test-prefix-nr/Makefile.am, tests/test-prefix-r/Makefile.am, tests/test-pthread/Makefile.am, tests/test-string-nr/Makefile.am, tests/test-string-r/Makefile.am, tests/test-yyextra/Makefile.am: Added top_builddir to -I path. Changed $(srcdir)/$(testname) to ./$(testname) in 'make test' rule. 2002-04-19 John Millaway * flexdef.h, gen.c, misc.c: Changed 'char[]' to 'const char*' wherever in conflicted with gettext. 2002-04-19 Will Estes * po/fr.po, po/sv.po: new files from translation after 2.5.6 beta release 2002-04-18 John Millaway * tests/test-lineno-r/Makefile.am: Fixed minor typo/cut and paste error. 2002-04-18 John Millaway * configure.in: Added yylineno test. 2002-04-18 John Millaway * tests/Makefile.am: Added yylineno tests. 2002-04-18 John Millaway * tests/test-lineno-nr/.cvsignore, tests/test-lineno-nr/Makefile.am, tests/test-lineno-nr/scanner.l, tests/test-lineno-nr/test.input, tests/test-lineno-r/.cvsignore, tests/test-lineno-r/Makefile.am, tests/test-lineno-r/scanner.l, tests/test-lineno-r/test.input: Created yylineno tests. 2002-04-15 John Millaway * scanopt.c: Applied gettext macros to error messages from scanopt. 2002-04-15 John Millaway * buf.c, faq.texi, options.c, options.h, scanopt.c, scanopt.h: Changed copyright from Millaway to flex? U.S. Gov't? Regents of U. Cali.? Paxson? 2002-04-15 Will Estes * tests/test-bison-yylloc/Makefile.am, tests/test-header-nr/Makefile.am, tests/test-header-r/Makefile.am: we missed a few main.c files in the distribution 2002-04-15 Will Estes * TODO: a lot more work has happened to flex; note this by removing a number of TODO entries 2002-04-15 Will Estes * TODO: make sure all gettext modules use gettext translation facilities 2002-04-14 John Millaway * faq.texi: Converted faqs 34-41 to texinfo. 2002-04-14 John Millaway * Makefile.am, faq.texi, flex.texi: Added faq.texi to archive. Added faq.texi to flex_TEXINFOS macro in Makefile.am. flex.texi now includes faq.texi. 2002-04-13 John Millaway * flexdef.h: defined FLEX_EXIT macro to call longjmp on errors. 2002-04-13 John Millaway * main.c, misc.c: Replaced exit(2) calls with longjmps (in the form of FLEX_EXIT macro). Moved main() to flex_main() to allow flex to be called from a library. 2002-04-13 John Millaway * scanopt.c: Fixed minor typo in error message 2002-04-12 Will Estes * tests/test-header-nr/Makefile.am, tests/test-header-r/Makefile.am, tests/test-multiple-scanners-nr/Makefile.am, tests/test-multiple-scanners-r/Makefile.am, tests/test-pthread/Makefile.am, tests/test-string-nr/Makefile.am, tests/test-string-r/Makefile.am, tests/test-yyextra/Makefile.am: removed eroneous files listed in EXTRA_DIST 2002-04-12 Will Estes * tests/test-yyextra/.cvsignore: ignore Makefile.in 2002-04-12 Will Estes * tests/test-string-r/.cvsignore: it's Makefile.in, not makefile.in 2002-04-12 Will Estes * tests/test-yyextra/Makefile.am, tests/test-yyextra/Makefile.in: put test-yyextra under automake 2002-04-12 Will Estes * tests/test-string-r/Makefile.am, tests/test-string-r/Makefile.in: put test-string-r under automake 2002-04-12 Will Estes * tests/test-string-nr/.cvsignore, tests/test-string-r/.cvsignore: we can ignore Makefile.in 2002-04-12 Will Estes * tests/test-string-nr/Makefile.am, tests/test-string-nr/Makefile.in: put test-string-nr under automake 2002-04-12 Will Estes * tests/test-pthread/.cvsignore: ignore Makefile.in 2002-04-12 Will Estes * tests/test-pthread/Makefile.am, tests/test-pthread/Makefile.in: put test-pthread under automake 2002-04-12 Will Estes * tests/test-prefix-r/Makefile.am, tests/test-prefix-r/Makefile.in: put test-prefix-r under automake 2002-04-12 Will Estes * tests/test-prefix-nr/.cvsignore, tests/test-prefix-r/.cvsignore: we can ignore Makefile.in 2002-04-12 Will Estes * tests/test-prefix-nr/Makefile.am, tests/test-prefix-nr/Makefile.in: put test-prefix-nr under automake 2002-04-12 Will Estes * tests/test-multiple-scanners-r/Makefile.am, tests/test-multiple-scanners-r/Makefile.in: put test-multiple-scanners-r under automake 2002-04-12 Will Estes * tests/test-multiple-scanners-nr/.cvsignore, tests/test-multiple-scanners-r/.cvsignore: we can ignore Makefile.in now 2002-04-12 Will Estes * tests/test-multiple-scanners-nr/Makefile.am, tests/test-multiple-scanners-nr/Makefile.in: put test-multiple-scanners-nr under automake 2002-04-11 Will Estes * tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-r/Makefile.am: we didn't need parser.y 2002-04-11 Will Estes * TODO: work done on the test suite; remove relevant entries from TODO 2002-04-10 Will Estes * tests/test-include-by-reentrant/.cvsignore, tests/test-include-by-reentrant/Makefile.am, tests/test-include-by-reentrant/Makefile.in: put test-include-by-reentrant under automake 2002-04-09 Will Estes * tests/test-include-by-buffer/.cvsignore: we have a Makefile.in which we need to ignore 2002-04-09 Will Estes * tests/test-include-by-buffer/Makefile.am, tests/test-include-by-buffer/Makefile.in: test-include-by-buffer now under automake control 2002-04-09 Will Estes * tests/TEMPLATE/Makefile.am: and we want LFLAGS in the rule to make scanner.c as well 2002-04-09 Will Estes * tests/test-header-r/.cvsignore, tests/test-header-r/Makefile.am, tests/test-header-r/Makefile.in: put test-header-r under automake 2002-04-09 Will Estes * tests/test-header-nr/.cvsignore: we now generate a Makefile.in from automake; cvs should ignore it 2002-04-09 Will Estes * tests/test-header-nr/Makefile.am: add dependencies for main.o and scaner.h 2002-04-09 Will Estes * tests/TEMPLATE/Makefile.am: We may want to have LFLAGS readily available 2002-04-09 Will Estes * tests/test-header-nr/Makefile.am, tests/test-header-nr/Makefile.in: put test-header-nr under automake 2002-04-09 Will Estes * tests/TEMPLATE/Makefile.am: oops, we need to clean objects too 2002-04-09 Will Estes * tests/TEMPLATE/Makefile.am, tests/test-array-nr/Makefile.am, tests/test-array-r/Makefile.am, tests/test-basic-nr/Makefile.am, tests/test-basic-r/Makefile.am, tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylval/Makefile.am, tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-r/Makefile.am: now that config.h lives in the top-level directory, we need to tell the testsuite 2002-04-08 Will Estes * tests/test-array-nr/.cvsignore, tests/test-array-r/.cvsignore, tests/test-basic-nr/.cvsignore, tests/test-basic-r/.cvsignore, tests/test-bison-yylval/.cvsignore, tests/test-c-cpp-nr/.cvsignore, tests/test-c-cpp-r/.cvsignore: we can ignore some Makefile.in 2002-04-08 Will Estes * configure.in, tests/TEMPLATE/Makefile.am: only one config file header apparently; this will have consequences in the test suite 2002-04-08 Will Estes * tests/test-bison-yylval/Makefile.am, tests/test-bison-yylval/Makefile.in: adding automake support 2002-04-08 Will Estes * tests/test-bison-yylloc/.cvsignore, tests/test-bison-yylloc/Makefile.am: tuned Makefile.am to build correctly; ignore Makefile.in now 2002-04-08 Will Estes * tests/configure.in: test suite changes 2002-04-08 Will Estes * autogen.sh, configure.in, tests/.cvsignore, tests/Makefile.am, tests/Makefile.in, tests/README, tests/TEMPLATE/.cvsignore, tests/TEMPLATE/Makefile.am, tests/TEMPLATE/Makefile.in, tests/configure.in, tests/create-test, tests/create-test.pl, tests/test-array-nr/Makefile.am, tests/test-array-nr/Makefile.in, tests/test-array-r/Makefile.am, tests/test-array-r/Makefile.in, tests/test-basic-nr/Makefile.am, tests/test-basic-nr/Makefile.in, tests/test-basic-r/Makefile.am, tests/test-basic-r/Makefile.in, tests/test-bison-yylloc/Makefile.am, tests/test-bison-yylloc/Makefile.in, tests/test-c-cpp-nr/Makefile.am, tests/test-c-cpp-nr/Makefile.in, tests/test-c-cpp-r/Makefile.am, tests/test-c-cpp-r/Makefile.in: test suite changes 2002-04-05 John Millaway * flex.texi: Corrected error in manual regarding return type for yy_scan_{string,buffer,bytes}. 2002-04-05 Will Estes * po/de.po: new german translations from the translation project 2002-04-03 Will Estes * po/es.po: new spanish translations 2002-04-01 Will Estes * Makefile.am: DIST_SUBDIRS: new variable. we can build flex with SUBDIRS and then build the distribution using DIST_SUBDIRS 2002-04-01 Will Estes * main.c: fix typo in comment 2002-03-31 John Millaway * main.c: Documented the header file kludge, (in anticipation of buffering Section 1.) 2002-03-31 John Millaway * flex.texi: Created appendix "Makefiles and Flex" in the manual. 2002-03-30 John Millaway * flex.texi: updating manual. 2002-03-29 Will Estes * po/POTFILES.in: we want parse.y, not parse.c 2002-03-29 John Millaway * flex.texi: Indexing the manual (75% done). 2002-03-29 Will Estes * Makefile.am: unlisted intermediate flex/yacc-created files 2002-03-29 Will Estes * TODO: millaway has done more work 2002-03-29 Will Estes * Makefile.am, configure.in: ok, one last touch up; users most likely wont have help2man so we need to insure that's ok 2002-03-29 Will Estes * Makefile.am: fine tune flex.1 some more 2002-03-29 Will Estes * Makefile.am, configure.in: generalize the manpage a bit and tell autofoo about help2man 2002-03-29 Will Estes * po/da.po: new danish from translation project robot 2002-03-28 John Millaway * flex.texi: Indexing the manual -- it's only half done. 2002-03-28 John Millaway * flex.texi: flex manual now uses automake's versioning info. 2002-03-28 John Millaway * README.cvs-snapshot: Mentioned requirements for gettext and help2man. 2002-03-28 John Millaway * Makefile.am, main.c: Output of `flex --version` now matches GNU coding standards. Makefile.am now uses `help2man` to generate flex.1 2002-03-27 Will Estes * TODO: millaway has done a lot on the TODO list; remove those items that he has take care of 2002-03-27 Will Estes * README.cvs-snapshot: edited millaway's initial draft 2002-03-27 John Millaway * README.cvs-snapshot: Created file. 2002-03-27 John Millaway * flex.texi: Fixed case of node names in flex.texi. 2002-03-24 Will Estes * TODO: lex- and yacc- generated files 2002-03-24 Will Estes * po/fr.po: new french 2002-03-18 Will Estes * NEWS: ending periods in news items removed; mention nounistd options 2002-03-18 Will Estes * po/sv.po: updated sweedish translations 2002-03-18 Will Estes * po/de.po: german translation 2002-03-18 John Millaway * flex.skl, flex.texi, main.c, options.c, options.h, scan.l: Removed CFront 1.2 -specific code from skeleton, because CFront now defines __cplusplus properly. Removed TurboC-specific code from skeleton. Skeleton now includes proper C++ standard headers. Relocated "unistd.h" code after user section 1 to allow user to overrid it. New option "nounistd" to suppress unistd.h from being included. 2002-03-15 Will Estes * po/tr.po: new turkish translation 2002-03-15 Will Estes * NEWS: mention included translations 2002-03-15 Will Estes * TODO: we've done the gettext thing, but sometime we should get 0.11.1 2002-03-15 Will Estes * po/ca.po: new catalan translation 2002-03-14 John Millaway * flex.texi: Added section on format of comments. 2002-03-14 John Millaway * flex.texi: Split format chapter into sections. 2002-03-14 John Millaway * flex.texi: Removed explicit pointers in node definitions. 2002-03-14 Will Estes * configure.in: unistd.h can be problematic 2002-03-14 Will Estes * tests/README: editing changes to README 2002-03-13 Will Estes * po/POTFILES.in: scan.l, not scan.c because gettext gets confused 2002-03-13 Will Estes * scan.l: gettext cruft 2002-03-13 Will Estes * tests/descriptions: separate out test descriptions 2002-03-13 Will Estes * po/LINGUAS: french and korean dont crash now 2002-03-12 Will Estes * po/fr.po, po/ko.po: remove duplicate messages as per advice from Jordi Mallach 2002-03-12 Will Estes * gettext.h: yes, more gettext cruft 2002-03-12 Will Estes * ABOUT-NLS, config.rpath, m4/codeset.m4, m4/gettext.m4, m4/glibc21.m4, m4/iconv.m4, m4/isc-posix.m4, m4/lcmessage.m4, m4/lib-ld.m4, m4/lib-link.m4, m4/lib-prefix.m4, m4/progtest.m4: this is gettext cruft 2002-03-12 Will Estes * NEWS: gettext and autofoo are now involved 2002-03-12 Will Estes * Makefile.am, autogen.sh, configure.in, flexdef.h, main.c: mostly, changes for gettext 2002-03-12 Will Estes * po/ca.po, po/da.po, po/es.po, po/ru.po, po/sv.po, po/tr.po: these sure change a lot 2002-03-12 Will Estes * TODO: note about cvs documentation 2002-03-12 Will Estes * po/LINGUAS: we now have turkish 2002-03-12 Will Estes * po/tr.po: updated translations, i think 2002-03-12 Will Estes * po/ca.po, po/da.po, po/es.po, po/fr.po, po/ko.po, po/ru.po, po/sv.po, po/tr.po: ok, maybe we do keep these things? 2002-03-12 Will Estes * README-alpha: README-alpha for those bad-hair days 2002-03-12 Will Estes * m4/.cvsignore, m4/Makefile.am: ok,now we kinda have a m4/ subdir for gettext 2002-03-12 Will Estes * po/.cvsignore, po/LINGUAS, po/Makevars, po/POTFILES.in, po/da.po, po/es.po, po/fr.po, po/ko.po, po/ru.po, po/sv.po: now, we have a po/ subdirectory for gettext. i hope you're happy 2002-03-12 Will Estes * po/ca.po: removing po files, maybe 2002-03-12 Will Estes * tests/.cvsignore: ignore autom4te.cache 2002-03-11 Will Estes * po/ca.po, po/da.po, po/es.po, po/fr.po, po/ko.po, po/ru.po, po/sv.po: po files from debian 2002-03-08 Will Estes * TODO: add several notes about tasks which need doing; create a new top-level entry for generic coding concerns (this is distinct from specific API or other such issues) 2002-03-06 Will Estes * README: eliminate to.do and faqs from the README file 2002-03-06 Will Estes * TODO: more notes on tests/ 2002-03-06 Will Estes * Makefile.am: remove subdirectories from EXTRA_DIST; add a SUBDIRS macro to handle examples/; clean up the dist-hook target 2002-03-06 Will Estes * configure.in: we want to generate Makefiles in some more subdirectories; automake will like this 2002-03-06 Will Estes * TODO: notes on subdirectories 2002-03-05 Will Estes * examples/.cvsignore, examples/Makefile.am: now examples/ fits into automake 2002-03-05 Will Estes * examples/fastwc/.cvsignore, examples/fastwc/Makefile.am: examples/fastwc now fits into automake 2002-03-05 Will Estes * examples/manual/.cvsignore, examples/manual/Makefile.am, examples/manual/Makefile.examples, examples/manual/README: examples/manual directory now fits into automake 2002-03-05 Will Estes * examples/manual/Makefile: renamed Makefile to Makefile.examples for automake's sake 2002-03-04 Will Estes * Makefile.am: add parse.c and scan.c to built_sources 2002-02-24 John Millaway * Makefile.am: Removed CVS-specific code from 'dist-hook' target so anybody with a copy of the tree can build a dist. 2002-02-22 John Millaway * tests/Makefile.in: Converted test script to portable /bin/sh. 2002-02-22 John Millaway * tests/test-bison-yylloc/Makefile.in: Added some spaces in shell scripts for portability. 2002-02-22 John Millaway * tests/create-test.pl: Fixed #! line for portability. 2002-02-22 John Millaway * tests/test-bison-yylloc/Makefile.in: Fixed return status code on bison-lloc test. 2002-02-21 John Millaway * tests/create-test.pl: Added script to auto-create tests. Probably overkill. 2002-02-21 John Millaway * flex.skl: Fixed C++ #ifdef problem. Removed mistyped __CPLUSPLUS macro. Removed THROW_NIL. Not sure where it came from in the first place. 2002-02-21 John Millaway * tests/README, tests/TEMPLATE/Makefile.in, tests/configure.in, tests/test-c-cpp-nr/.cvsignore, tests/test-c-cpp-nr/Makefile.in, tests/test-c-cpp-nr/scanner.l, tests/test-c-cpp-nr/test.input, tests/test-c-cpp-r/.cvsignore, tests/test-c-cpp-r/Makefile.in, tests/test-c-cpp-r/scanner.l, tests/test-c-cpp-r/test.input: Added test-c-cpp-nr and test-c-cpp-r. 2002-02-16 John Millaway * flex.skl: Added missing #endif. 2002-02-07 Will Estes * tests/TEMPLATE/.cvsignore, tests/test-array-nr/.cvsignore, tests/test-array-r/.cvsignore, tests/test-basic-nr/.cvsignore, tests/test-basic-r/.cvsignore, tests/test-bison-yylloc/.cvsignore, tests/test-bison-yylval/.cvsignore, tests/test-header-nr/.cvsignore, tests/test-header-r/.cvsignore, tests/test-include-by-buffer/.cvsignore, tests/test-include-by-reentrant/.cvsignore, tests/test-multiple-scanners-nr/.cvsignore, tests/test-multiple-scanners-r/.cvsignore, tests/test-prefix-nr/.cvsignore, tests/test-prefix-r/.cvsignore, tests/test-pthread/.cvsignore, tests/test-string-nr/.cvsignore, tests/test-string-r/.cvsignore, tests/test-yyextra/.cvsignore: add OUTPUT to .cvsignore files in test directories; it's also in the template directory 2002-02-06 Will Estes * gen.c: fix interrupted reads and freads; from the debian package maintainer 2002-02-06 Will Estes * flex.texi, flexdef.h, main.c, nfa.c: support large flex tables; from debian package maintainer 2002-01-29 Will Estes * tests/configure.in: add more output files to account for new tests 2002-01-03 Will Estes * tests/test-array-nr/.cvsignore, tests/test-array-nr/Makefile.in, tests/test-array-nr/scanner.l, tests/test-array-nr/test.input: add this test 2002-01-03 Will Estes * tests/test-array-r/.cvsignore, tests/test-array-r/Makefile.in, tests/test-array-r/scanner.l, tests/test-array-r/test.input: add this test suite 2001-11-20 Will Estes * flex.skl, main.c: millaway: Fixed yytext_ptr when using %array in reentrant scanner 2001-11-20 Will Estes * buf.c: oops, forgot this one line 2001-11-14 Will Estes * tests/test-header-r/.cvsignore, tests/test-header-r/Makefile.in, tests/test-header-r/main.c, tests/test-header-r/scanner.l, tests/test-header-r/test.input: and more fallout 2001-11-14 Will Estes * TODO, flex.skl, flex.texi, flexdef.h, main.c, misc.c, tests/README, tests/TEMPLATE/Makefile.in, tests/configure.in, tests/test-basic-r/scanner.l, tests/test-bison-yylloc/.cvsignore, tests/test-bison-yylloc/Makefile.in, tests/test-bison-yylloc/parser.y, tests/test-bison-yylloc/scanner.l, tests/test-bison-yylval/.cvsignore, tests/test-bison-yylval/Makefile.in, tests/test-bison-yylval/parser.y, tests/test-bison-yylval/scanner.l, tests/test-include-by-reentrant/scanner.l, tests/test-prefix-r/scanner.l, tests/test-pthread/scanner.l, tests/test-string-r/scanner.l, tests/test-yyextra/scanner.l: more from the same batch 2001-11-14 Will Estes * tests/test-bison-yylloc/main.c, tests/test-bison-yylval/main.c, tests/test-header-nr/.cvsignore, tests/test-header-nr/Makefile.in, tests/test-header-nr/main.c, tests/test-header-nr/scanner.l, tests/test-header-nr/test.input, tests/test-multiple-scanners-nr/.cvsignore, tests/test-multiple-scanners-nr/Makefile.in, tests/test-multiple-scanners-nr/main.c, tests/test-multiple-scanners-nr/scanner-1.l, tests/test-multiple-scanners-nr/scanner-2.l, tests/test-multiple-scanners-r/.cvsignore, tests/test-multiple-scanners-r/Makefile.in, tests/test-multiple-scanners-r/main.c, tests/test-multiple-scanners-r/scanner-1.l, tests/test-multiple-scanners-r/scanner-2.l: a big batch from millaway 2001-10-26 Will Estes * NEWS: now NEWS has forgotten about the _r variables 2001-10-26 Will Estes * flex.skl, flex.texi, gen.c, main.c, tests/test-bison-yylloc/scanner.l, tests/test-bison-yylval/scanner.l, tests/test-include-by-reentrant/scanner.l, tests/test-prefix-nr/scanner.l, tests/test-pthread/scanner.l, tests/test-string-r/scanner.l, tests/test-yyextra/scanner.l: millaway simplified the reentrant api; here's the result 2001-10-23 Will Estes * main.c, options.c, options.h: more from millaway 2001-10-22 Will Estes * main.c, options.c, options.h: the last checkin was broken; millaway fixed it 2001-10-22 Will Estes * flex.skl, flex.texi, gen.c, main.c, misc.c, options.h, scan.l, scanopt.c, tests/README, tests/configure.in: phew, millaway's latest batch 2001-10-21 Will Estes * flex.skl: flex.skl should come up in C mode 2001-10-21 Will Estes * flex.skl: apparently, isatty and c++ need help getting along (from octave) 2001-10-19 Will Estes * NEWS: document new options and new option handling 2001-10-19 Will Estes * TODO: tell emacs that TODO is a text/outline mode file 2001-10-19 Will Estes * TODO: we have new long options; we need to document that 2001-10-19 Will Estes * NEWS: tell emacs that NEWS is text/outline mode 2001-10-19 Will Estes * flex.skl: oops, lost a line somewhere in the merge process on millaway's work 2001-10-17 Will Estes * Makefile.am, buf.c, flex.skl, flex.texi, flexdef.h, main.c, misc.c, options.c, options.h, parse.y, scan.l, scanopt.c, scanopt.h: merge latest batch of millaway's changes 2001-09-22 Will Estes * main.c: Fixed typo in options display 2001-09-20 Will Estes * main.c: reentrant and non-reentrant scanners share the same yywrap MACRO. millaway 2001-09-20 Will Estes * TODO: clarify item on comments in lexical files 2001-09-20 Will Estes * NEWS, scan.l: now flex recognizes \r as an eol character 2001-09-20 Will Estes * Makefile.am: specify cvsroot so automake distcheck works 2001-09-19 Will Estes * flex.texi: tex has lost its mind; we remove parentheses to compensate 2001-09-19 Will Estes * NEWS: now that c++ is better supported, let's mention it as a news item 2001-09-19 Will Estes * examples/fastwc/wc1.l, examples/fastwc/wc2.l, examples/fastwc/wc3.l, examples/fastwc/wc4.l, examples/fastwc/wc5.l, flex.skl, main.c: commit the backwash from the branch merges 2001-09-19 Will Estes * FlexLexer.h, examples/testxxLexer.l, flex.skl: made preliminary c++ fixes; the intent is to make it work with recent c++ compilers 2001-08-26 Will Estes * main.c: remove argv_fixup; fix typo in error message; changes from millaway's branch 2001-08-24 Will Estes * NEWS: mention no more c++ comments in c scanners 2001-08-21 John Millaway * flex.skl: Changed // comments to /* */ comments in skeleton. 2001-08-19 John Millaway * flex.texi: Changed @var to @code everywhere. 2001-08-16 Will Estes * to.do/flex.rmail: more mail 2001-08-16 Will Estes * TODO: the manual now has its own section; we're not adding comments either 2001-08-04 John Millaway * tests/Makefile.in, tests/README, tests/TEMPLATE/Makefile.in, tests/test-basic-nr/Makefile.in, tests/test-basic-r/Makefile.in, tests/test-bison-yylloc/Makefile.in, tests/test-bison-yylval/Makefile.in, tests/test-include-by-buffer/Makefile.in, tests/test-include-by-reentrant/Makefile.in, tests/test-prefix-nr/Makefile.in, tests/test-prefix-r/Makefile.in, tests/test-pthread/Makefile.in, tests/test-string-nr/Makefile.in, tests/test-string-r/Makefile.in, tests/test-yyextra/Makefile.in: Cleaned up the output of the tests. 2001-08-03 Will Estes * TODO: note jason's thoughts on having a manpage 2001-08-03 Will Estes * TODO: note millaway's assignment and tests to be under flex license 2001-08-01 John Millaway * tests/test-bison-yylval/scanner.l: Fixed semantics of test (the success or failure of this test should be unaffected by this change.) 2001-08-01 Will Estes * autogen.sh: fake automake into believing that ChangeLog already exists 2001-08-01 Will Estes * Makefile.am: millaway needs to be covered in the ChangeLog 2001-08-01 Will Estes * version.h: automake is supplying version info now so we just pick it up 2001-08-01 Will Estes * flex.texi: forgot braces on @copyright 2001-08-01 John Millaway * flex.skl: Added missing argument to yy_flex_free. 2001-08-01 Will Estes * AUTHORS: john millaway wrote the reentrant C support 2001-08-01 Will Estes * flex.texi: add license node to the manual 2001-08-01 Will Estes * TODO: c++ ideas 2001-07-31 Will Estes * parse.y: error messages will now show up the way that emacs likes them 2001-07-31 Will Estes * Makefile.am: oops, left in an extra backslash 2001-07-31 Will Estes * TODO: flex.texi is here; clarify tests/ rewrite issue 2001-07-31 Will Estes * NEWS: hey, we have texinfo, not man 2001-07-31 Will Estes * flex.1: no more manpage 2001-07-31 Will Estes * Makefile.am: remove flex.1 and rewrite the dist-hook so that we pick up a couple more directories 2001-07-31 Will Estes * flex.texi: the namual now compiles; hurray 2001-07-31 Will Estes * Makefile.am: first attempt at including the tests/ directory via automake, dist-hook target added 2001-07-31 Will Estes * tests/.cvsignore: ignore config.cache in tests/ directory 2001-07-31 Will Estes * Makefile.am: automake groks the ChangeLog now so we don't have to remind the maintainer to remake it 2001-07-30 Will Estes * flex.texi: more corrections to the manual; the end is in site 2001-07-30 Will Estes * TODO: auto-generated backup? 2001-07-27 Will Estes * flex.texi: today's tinkering on the manual 2001-07-27 Will Estes * Makefile.am: if we want flex.1 we have to say so in EXTRA_DIST 2001-07-27 Will Estes * TODO: note future issues with flex.texi 2001-07-27 Will Estes * Makefile.am: include flex.1 as it's the only working documentation for now 2001-07-27 Will Estes * Makefile.am: rearrange to work with automake on building the ChangeLog 2001-07-27 Will Estes * scan.l: automake is unhappy if we specify the outfile 2001-07-26 Will Estes * flex.texi: more conversions/corrections 2001-07-26 Will Estes * README: we removed misc/ so we don't mention it any more 2001-07-25 Will Estes * flex.texi: begin the manual conversion to texinfo; yes, it's broken right now 2001-07-25 Will Estes * AUTHORS, THANKS: copy in manual author and thanks info 2001-07-25 Will Estes * Makefile.am: how to fake the ChangeLog into showing up in the distribution 2001-07-25 Will Estes * Makefile.am: add YFLAGS so parse.h gets made 2001-07-24 Will Estes * examples/fastwc/README, examples/fastwc/mywc.c, examples/fastwc/wc1.l, examples/fastwc/wc2.l, examples/fastwc/wc3.l, examples/fastwc/wc4.l, examples/fastwc/wc5.l: re-add these files 2001-07-24 Will Estes * TODO: reflect recent doings 2001-07-24 Will Estes * Makefile.in: what with automake, we don't need Makefile.in any more 2001-07-24 Will Estes * configure.in: more rearranging for automake 2001-07-24 Will Estes * to.do/flex.rmail: more mail came in 2001-07-24 Will Estes * autogen.sh: adjust to automake's idea of the world 2001-07-24 Will Estes * Makefile.am: add Vern's misc dependencies; noinst_SCRIPTS was broken?; list a few last files to be included in the distribution 2001-07-24 Will Estes * NEWS: rearrange for better order; add automake support as a news item 2001-07-24 Will Estes * Makefile.am: copyright notice on Makefile.am; document some -D switches (are they still usable?) 2001-07-24 Will Estes * TODO: add lex-replacement issue 2001-07-24 Will Estes * Makefile.am: add EXTRA_DIST 2001-07-23 Will Estes * autogen.sh: we need to do the same thing in each directory 2001-07-23 Will Estes * configure.in: introduce automake into the macro calls 2001-07-23 Will Estes * Makefile.am: add AUTOMAKE_OPTIONS, info_TEXINFOS, include_HEADERS, noinst_HEADERS; it's libfl.a, not libflex.a 2001-07-23 Will Estes * Makefile.am: bin_PROGRAMS and lib_LIBRARIES 2001-07-23 Will Estes * to.do/streams.mail: streams.mail has moved here 2001-07-23 Will Estes * TODO: add xref for teximanual 2001-07-19 Will Estes * flex.1: include typo/punctuation fixes from a patch submitted by noon@cote-dazur.com (Fabrice Bauzac) 2001-07-17 Will Estes * TODO: we want gettext 2001-06-24 Will Estes * flex.skl: include c++ STD fixes from quanstro@quanstro.net 2001-06-24 Will Estes * flex.skl, gen.c: change some int types to size_t as per FreeBSD 28364 from avn@any.ru 2001-06-24 Will Estes * TODO: remove parse.[ch] from make clean target; repackage distribution (not rework) 2001-06-19 Will Estes * TODO: add memory api and reworking of flex.skl reworking 2001-06-18 Will Estes * flex.skl: remove extraneous notice from flex.skl 2001-06-18 Will Estes * flex.skl: patch memory leak as per millaway 2001-06-17 Will Estes * to.do/flex.rmail: add vern's ok for copyright/license changes and john's answer on line offsets 2001-06-17 Will Estes * TODO: remove creation of .cvsignore files (it's done); add other notes about the test suite 2001-06-17 Will Estes * tests/TEMPLATE/.cvsignore, tests/test-basic-nr/.cvsignore, tests/test-basic-r/.cvsignore, tests/test-bison-yylloc/.cvsignore, tests/test-bison-yylval/.cvsignore, tests/test-include-by-buffer/.cvsignore, tests/test-include-by-reentrant/.cvsignore, tests/test-prefix-nr/.cvsignore, tests/test-prefix-r/.cvsignore, tests/test-pthread/.cvsignore, tests/test-string-nr/.cvsignore, tests/test-string-r/.cvsignore, tests/test-yyextra/.cvsignore: adding .cvsignore files for existing tests/ subdirectories 2001-06-17 Will Estes * tests/README: reformat, say to add a description to this file and mention what to do re .cvsignore 2001-06-17 Will Estes * tests/TEMPLATE/cvsignore: create template for .cvsignore 2001-06-17 Will Estes * TODO: reorganize for logical reasons; test suite now seems to run out of the box 2001-06-17 Will Estes * tests/.cvsignore: we dont want the Makefile either 2001-06-17 Will Estes * tests/test-prefix-nr/test.input, tests/test-prefix-r/test.input: test.input was supposed to be here 2001-06-17 Will Estes * tests/.cvsignore: add autoconf legacy files to be ignored 2001-06-17 Will Estes * autogen.sh: clarify usage instructions; prepare tests/ as well 2001-06-17 Will Estes * tests/.cvsignore: . cvsignore for tests/ subdirectory 2001-06-17 Will Estes * FlexLexer.h: tell emacs that FlexLexer.h is c++ 2001-06-17 Will Estes * scan.l: tell emacs scan.l is in C mode 2001-06-17 Will Estes * flex.skl: added punctuation 2001-06-17 Will Estes * FlexLexer.h, Makefile.in, README, RoadMap, autogen.sh, ccl.c, configure.in, dfa.c, ecs.c, flex.1, flex.skl, flexdef.h, gen.c, libmain.c, libyywrap.c, main.c, misc.c, mkskel.sh, nfa.c, parse.y, scan.l, sym.c, tblcmp.c, yylex.c: change copyright/license notices as per Vern's response to Theo 2001-06-15 Will Estes * to.do/flex.rmail: add bill fenlason's emails 2001-06-15 Will Estes * COPYING: make changes as per Theo De Raadt; remove tabs 2001-06-08 Will Estes * flex.skl: save errno as per Theo de Raadt 2001-06-07 Will Estes * flex.1: correct hyphenation as per openbsd tree 2001-06-05 Will Estes * Makefile.in, configure.in: change references to TESTS/ to tests/ to account for the directory name changes 2001-05-27 Will Estes * flex.skl, gen.c: commit john millaway's YY_G wrapper corrections 2001-05-21 Will Estes * tests/Makefile.in: remove || exit calls 2001-05-21 Will Estes * gen.c: complete john millaway's reentrant patch 2001-05-21 Will Estes * to.do/flex.rmail: more flex messages in the queue 2001-05-18 Will Estes * flex.skl, flexdef.h, gen.c, main.c, nfa.c, scan.l: john millaway's reentrancy patch 2001-05-18 Will Estes * tests/Makefile.in: remove || exit from testing loop 2001-05-18 Will Estes * Makefile.in: tell make about the tests directory and its associated targets 2001-05-18 Will Estes * TODO: rethink the todo list 2001-05-18 Will Estes * flex.1: describe reentrant api changes 2001-05-18 Will Estes * TODO: mention work needed for tests/ 2001-05-18 Will Estes * configure.in: tell auto* about the test directory 2001-05-18 Will Estes * README: make punctuation uniform, mention the new tests/ directory 2001-05-18 Will Estes * NEWS: reformat items; cut out old items and move them to ONEWS 2001-05-18 Will Estes * ONEWS: move old NEWS items to ONEWS 2001-05-18 Will Estes * tests/Makefile.in, tests/README, tests/TEMPLATE/Makefile.in, tests/TEMPLATE/parser.y, tests/TEMPLATE/scanner.l, tests/TEMPLATE/test.input, tests/configure.in, tests/test-basic-nr/Makefile.in, tests/test-basic-nr/scanner.l, tests/test-basic-nr/test.input, tests/test-basic-r/Makefile.in, tests/test-basic-r/scanner.l, tests/test-basic-r/test.input, tests/test-bison-yylloc/Makefile.in, tests/test-bison-yylloc/parser.y, tests/test-bison-yylloc/scanner.l, tests/test-bison-yylloc/test.input, tests/test-bison-yylval/Makefile.in, tests/test-bison-yylval/parser.y, tests/test-bison-yylval/scanner.l, tests/test-bison-yylval/test.input, tests/test-include-by-buffer/Makefile.in, tests/test-include-by-buffer/scanner.l, tests/test-include-by-buffer/test-1.input, tests/test-include-by-buffer/test-2.input, tests/test-include-by-buffer/test-3.input, tests/test-include-by-reentrant/Makefile.in, tests/test-include-by-reentrant/scanner.l, tests/test-include-by-reentrant/test-1.input, tests/test-include-by-reentrant/test-2.input, tests/test-include-by-reentrant/test-3.input, tests/test-prefix-nr/Makefile.in, tests/test-prefix-nr/README, tests/test-prefix-nr/scanner.l, tests/test-prefix-r/Makefile.in, tests/test-prefix-r/README, tests/test-prefix-r/scanner.l, tests/test-pthread/Makefile.in, tests/test-pthread/scanner.l, tests/test-pthread/test-1.input, tests/test-pthread/test-2.input, tests/test-pthread/test-3.input, tests/test-pthread/test-4.input, tests/test-pthread/test-5.input, tests/test-string-nr/Makefile.in, tests/test-string-nr/scanner.l, tests/test-string-r/Makefile.in, tests/test-string-r/scanner.l, tests/test-yyextra/Makefile.in, tests/test-yyextra/scanner.l, tests/test-yyextra/test.input: add john millaway's test directory 2001-05-04 Will Estes * to.do/flex.rmail: more mail in flex.rmail 2001-05-03 Will Estes * FlexLexer.h, ccl.c, dfa.c, ecs.c, flex.skl, flexdef.h, gen.c, libmain.c, libyywrap.c, main.c, misc.c, nfa.c, parse.y, scan.l, sym.c, tblcmp.c, yylex.c: remove extraneous rcs keywords 2001-05-03 Will Estes * README: mention RoadMap 2001-05-01 Will Estes * examples/README, examples/debflex.awk, examples/manual/ChangeLog, examples/manual/Makefile, examples/manual/README, examples/manual/cat.lex, examples/manual/dates.lex, examples/manual/datetest.dat, examples/manual/eof_rules.lex, examples/manual/eof_test01.txt, examples/manual/eof_test02.txt, examples/manual/eof_test03.txt, examples/manual/expr.lex, examples/manual/expr.y, examples/manual/front.lex, examples/manual/front.y, examples/manual/j2t.lex, examples/manual/myname.lex, examples/manual/myname.txt, examples/manual/myname2.lex, examples/manual/numbers.lex, examples/manual/pas_include.lex, examples/manual/pascal.lex, examples/manual/reject.lex, examples/manual/replace.lex, examples/manual/string1.lex, examples/manual/string2.lex, examples/manual/strtest.dat, examples/manual/unput.lex, examples/manual/user_act.lex, examples/manual/userinit.lex, examples/manual/wc.lex, examples/manual/yymore.lex, examples/manual/yymore2.lex, examples/manual/yymoretest.dat, examples/testxxLexer.l, to.do/README, to.do/Wilhelms.todo, to.do/Wish-List, to.do/flex.rmail, to.do/unicode/FlexLexer.h, to.do/unicode/ccl.c, to.do/unicode/changes.txt, to.do/unicode/ecs.c, to.do/unicode/flex.1, to.do/unicode/flex.skl, to.do/unicode/flexdef.h, to.do/unicode/gen.c, to.do/unicode/main.c, to.do/unicode/misc.c, to.do/unicode/scan.l, to.do/unicode/tblcmp.c: adding the rest of vern's files 2001-05-01 Will Estes * README: mention misc/ directory 2001-05-01 Will Estes * version.h: version is 2.5.5b 2001-05-01 Will Estes * Makefile.in: remove header from top; add rule to generate initscan.c just in case 2001-05-01 Will Estes * configure.in: dont check for initscan.c; check for scan.l instead 2001-05-01 Will Estes * RoadMap: list of source files 2001-05-01 Will Estes * README: rewrite README to reflect changes in layout of directories 2001-05-01 Will Estes * AUTHORS, THANKS, TODO: initial attempt at the files 2001-05-01 Will Estes * COPYING: add 2001 copyright notice 2001-05-01 Will Estes * autogen.sh: initial attempt at a bootstrap script for developers 2001-05-01 Will Estes * flex.texi: texinfo manual, old contributed version 2000-08-21 Vern Paxson * flex.1: fixed some bugs in examples of [[:...:]] ccls 2000-08-21 Vern Paxson * version.h: version shipped to Dick King 2000-08-21 Vern Paxson * flex.skl: explicit include of iostream.h 2000-08-21 Vern Paxson * scan.l: if a newline is seen in , assume it terminates the string. 2000-08-21 Vern Paxson * flexdef.h, sym.c: moved symbol table definitions from flexdef.h into sym.c 2000-08-21 Vern Paxson * dfa.c: fixed underallocation for accset 1997-06-27 Vern Paxson * COPYING: revised for rms 1997-06-23 Vern Paxson * flex.skl: fixed memory leak 1997-06-23 Vern Paxson * flex.1: input() doesn't destroy yytext 1997-06-23 Vern Paxson * FlexLexer.h: wrapped with extern "C++" 1996-12-13 Vern Paxson * flex.skl: use delete [] for yy_state_buf 1996-10-29 Vern Paxson * flex.skl: fixed %option noinput 1996-10-29 Vern Paxson * flex.skl: free(char*) fix ... Sigh ... 1996-10-11 Vern Paxson * gen.c: bug fix for yymore()/yylineno interaction 1996-10-11 Vern Paxson * gen.c: fixed memory leak 1996-09-10 Vern Paxson * NEWS: release 2.5.4 1996-09-10 Vern Paxson * Makefile.in: more stuff for distclean 1996-09-10 Vern Paxson * flex.skl: "str" -> "yy_str" 1996-09-10 Vern Paxson * version.h: 2.5.4 1996-07-02 Vern Paxson * flex.skl: (attempted) fix for input() crossing a file boundary 1996-05-29 Vern Paxson * NEWS: don't do Acorn diffs 1996-05-29 Vern Paxson * NEWS: some minor additions for 2.5.3 1996-05-29 Vern Paxson * NEWS, version.h: 2.5.3 1996-05-25 Vern Paxson * flex.skl: initialize yy_more_offset etc. for yyFlexLexer class 1996-05-25 Vern Paxson * flex.skl: niggling cosmetic tweak 1996-05-25 Vern Paxson * flex.skl: bug fixes for yymore (especially with %array) 1996-05-25 Vern Paxson * gen.c: yymore + %array tweaks 1996-05-25 Vern Paxson * FlexLexer.h: added yy_{,prev_}more_offset 1996-05-25 Vern Paxson * main.c: removed decl of unused library function 1996-05-25 Vern Paxson * flex.skl: snapshot of cscope yymore fixes, prior to switching yymore-on-%array approach 1995-12-18 Vern Paxson * gen.c: don't stack states on NUL-transitions that are jams 1995-09-27 Vern Paxson * libmain.c: fixed re Esmond Pitt's ancient suggestion 1995-04-28 Vern Paxson * misc.c: ANSI C / Solaris tweak 1995-04-24 Vern Paxson * flex.1: credits 1995-04-24 Vern Paxson * NEWS: multiple FlexLexer.h includes 1995-04-24 Vern Paxson * FlexLexer.h: fix multiple inclusions 1995-04-24 Vern Paxson * scan.l: lint tweak 1995-04-24 Vern Paxson * flex.1: typo fixed 1995-04-24 Vern Paxson * flex.1: credits update 1995-04-24 Vern Paxson * flex.skl: (char*) cast for realloc 1995-04-24 Vern Paxson * NEWS: (char*) tweak 1995-04-21 Vern Paxson * NEWS: VMS update for 2.5.2 1995-04-21 Vern Paxson * Makefile.in: clarify when 8-bit scanners are created by default, vs. 7-bit 1995-04-21 Vern Paxson * parse.y: reworked alloca() chud, from Francois 1995-04-20 Vern Paxson * NEWS, version.h: 2.5.2 1995-04-20 Vern Paxson * flex.1: 2.5.2 update 1995-04-20 Vern Paxson * dfa.c, main.c: const -> yyconst 1995-04-20 Vern Paxson * Makefile.in: fixed some old libfl.a references 1995-04-20 Vern Paxson * Makefile.in: some (but not all) of Francois' tweaks 1995-04-20 Vern Paxson * configure.in: tweaks from Francois 1995-04-20 Vern Paxson * flex.skl: yy_delete_buffer allows nil buffer pointer 1995-04-20 Vern Paxson * main.c: do_stdinit now defaults to false 1995-04-20 Vern Paxson * FlexLexer.h: remove first default for yylex(new_in, new_out) 1995-04-20 Vern Paxson * flex.skl: rearrange some definitions; fix YY_NO_UNPUT 1995-04-20 Vern Paxson * parse.y: more alloca() bullshit 1995-04-20 Vern Paxson * misc.c: octal escape sequence must have just digits 0-7 1995-04-20 Vern Paxson * scan.l: '-' means stdin octal escape sequence must just be digits 0-7 1995-04-20 Vern Paxson * main.c: -- terminates options 1995-04-20 Vern Paxson * flexdef.h: added dataflush() prototype 1995-04-20 Vern Paxson * misc.c: move dataflush, otoi prototypes into flexdef.h 1995-04-20 Vern Paxson * flex.skl, gen.c: const -> yyconst 1995-04-20 Vern Paxson * gen.c: fixed bug in needing yy_cp for -Cf w/ backing up 1995-03-28 Vern Paxson * README, flex.1: Stan Adermann credit 1995-03-27 Vern Paxson * README: beta-tester update 1995-03-27 Vern Paxson * NEWS, version.h: 2.5.1 1995-03-27 Vern Paxson * flex.1: update date for 2.5.1 release, some feedbacker credits 1995-03-27 Vern Paxson * gen.c: fixed lint problem with declaring yy_cp unnecessarily 1995-03-27 Vern Paxson * dfa.c: {}'s around full-table initializations 1995-03-21 Vern Paxson * README: for version 2.5 1995-03-21 Vern Paxson * flex.1: added note regarding yylineno should be maintained on a per-buffer basis 1995-03-21 Vern Paxson * NEWS: new C++ member functions 1995-03-21 Vern Paxson * NEWS, flex.1: 2.5.0.8 update 1995-03-21 Vern Paxson * main.c: rename yylineno if -P 1995-03-20 Vern Paxson * flexdef.h: do_yylineno MARKER_DIFFERENCE depends on MAXIMUM_MNS 1995-03-20 Vern Paxson * Makefile.in: removed redundant skel.c from DISTFILES 1995-03-20 Vern Paxson * FlexLexer.h: debug(), setdebug(), lineno() 1995-03-20 Vern Paxson * flex.skl: %option yylineno support 1995-03-20 Vern Paxson * gen.c: read up to newline for interactive reads, rather than one char 1995-03-20 Vern Paxson * main.c, scan.l: added %option yylineno 1995-03-18 Vern Paxson * gen.c: added do_yylineno 1995-03-06 Vern Paxson * NEWS, flex.1: 2.5.0.7 1995-03-05 Vern Paxson * Makefile.in: realclean -> maintainer-clean 1995-03-05 Vern Paxson * flex.skl: Added yy_flush_buffer 1995-03-05 Vern Paxson * FlexLexer.h: added yy_flush_buffer 1995-03-05 Vern Paxson * main.c: prefix support for yy_flush_buffer 1995-03-05 Vern Paxson * parse.y: added %option yyclass 1995-03-05 Vern Paxson * flexdef.h, main.c, scan.l: added yyclass 1995-03-05 Vern Paxson * FlexLexer.h: Added switch_streams 1995-03-05 Vern Paxson * flex.skl: added switch_streams 1995-03-05 Vern Paxson * main.c: don't rename yy_flex_debug for C++ 1995-03-05 Vern Paxson * gen.c: yy_flex_debug extern only if not C++ 1995-03-05 Vern Paxson * FlexLexer.h: added yy_flex_debug member variable 1995-03-05 Vern Paxson * flex.skl: yyFlexLexer initialization of yy_flex_debug 1995-03-04 Vern Paxson * flexdef.h, main.c: VMS POSIX stuff 1995-03-04 Vern Paxson * flex.skl: moved position of yy_init = 0 1995-03-04 Vern Paxson * flex.skl: added YY_EXIT_FAILURE 1995-03-04 Vern Paxson * main.c: removed VMS-specific exit 1995-03-04 Vern Paxson * dfa.c, flexdef.h, gen.c, main.c, misc.c, nfa.c, scan.l, sym.c, yylex.c: internationalization aids 1995-03-04 Vern Paxson * main.c: do yy_flex_debug prefix for both C++ and C 1995-02-06 Vern Paxson * main.c: fixed program_name tweak again 1995-01-11 Vern Paxson * main.c: oops, fixed program_name tweak 1995-01-11 Vern Paxson * main.c: program_name is "flex" if argv[0] nil 1995-01-10 Vern Paxson * NEWS: 2.5.0.5 1995-01-10 Vern Paxson * flex.1: Documented YY_NUM_RULES 1995-01-10 Vern Paxson * Makefile.in: added formatted man page to MISC 1995-01-10 Vern Paxson * main.c: help messages to stdout 1995-01-09 Vern Paxson * gen.c: Added YY_NUM_RULES 1995-01-09 Vern Paxson * flex.skl: better fix for #pragma problem 1995-01-09 Vern Paxson * flexdef.h: better fix for #pragma portability problem 1995-01-09 Vern Paxson * misc.c: "# line" -> #line 1995-01-09 Vern Paxson * flex.skl, flexdef.h: comment out Turbo C #pragma's 1995-01-09 Vern Paxson * scan.l: reset linenum on new file 1995-01-09 Vern Paxson * flex.skl: isatty() extern 1995-01-09 Vern Paxson * NEWS, flex.1: 2.5.0.4 1995-01-09 Vern Paxson * main.c: long options, VMS tweaks 1995-01-09 Vern Paxson * Makefile.in: Added parse.c, parse.h for dist MISC directory 1995-01-09 Vern Paxson * flexdef.h: some "const" cleansing 1995-01-09 Vern Paxson * mkskel.sh: skel[] is now const 1995-01-09 Vern Paxson * misc.c: some const cleansing 1995-01-09 Vern Paxson * scan.l: #line in section 1 1995-01-05 Vern Paxson * sym.c: preen 1994-12-29 Vern Paxson * configure.in: config.h from conf.in 1994-12-29 Vern Paxson * flexdef.h: for VMS, delete -> remove 1994-12-29 Vern Paxson * Makefile.in: config.h.in -> conf.in rm config.h on distclean 1994-12-29 Vern Paxson * main.c: stdinit tweaks 1994-12-29 Vern Paxson * scan.l: added nostdinit 1994-12-28 Vern Paxson * NEWS: added MS-DOS note for 2.5.0.2 1994-12-28 Vern Paxson * flex.1: typos, tweaks 1994-12-28 Vern Paxson * Makefile.in: removed flexdoc 1994-12-28 Vern Paxson * flex.1: flexdoc/flex merge 1994-12-28 Vern Paxson * flex.1: typos 1994-12-28 Vern Paxson * NEWS: typo 1994-12-28 Vern Paxson * flex.1: 2.5 update 1994-12-28 Vern Paxson * NEWS: 2.5.0.2 1994-12-28 Vern Paxson * scan.l: fixed sense of %option main implying %option noyywrap 1994-12-28 Vern Paxson * flex.skl: YY_FLEX_{MAJOR,MINOR}_VERSION fixed bug in unput trashing yytext even with %array 1994-12-17 Vern Paxson * flex.1: prior to 2.5 update 1994-12-17 Vern Paxson * main.c: C++/-P fixes 1994-12-17 Vern Paxson * FlexLexer.h: -P fixes constructor, destructor moved to flex.skl 1994-12-17 Vern Paxson * flex.skl: YY_SKIP_YYWRAP yyFlexLexer constructor, destructor 1994-12-15 Vern Paxson * gen.c: formatting 1994-12-15 Vern Paxson * gen.c: fixed bug in adjusting yytext before backing up 1994-12-10 Vern Paxson * scan.l: switched scanner itself over to [:xxx:] 1994-12-10 Vern Paxson * flex.skl: added YY_FLEX_VERSION 1994-12-10 Vern Paxson * scan.l: Fixed CCL-match pattern for [:whatever:] 1994-12-10 Vern Paxson * parse.y: treat [:upper:] as [:lower:] if -i 1994-12-06 Vern Paxson * NEWS: 2.5.0.1 1994-12-06 Vern Paxson * flex.skl, gen.c: input() maintains BOL 1994-12-06 Vern Paxson * flex.skl: check size of buffer in yy_scan_buffer 1994-12-06 Vern Paxson * flex.skl: added %option main, fixed missing %* 1994-12-06 Vern Paxson * parse.y: added ccl exprs 1994-12-06 Vern Paxson * scan.l: added ccl exprs, %option main 1994-12-06 Vern Paxson * yylex.c: added %options, ccl exprs 1994-12-05 Vern Paxson * misc.c: undid previous change 1994-12-04 Vern Paxson * Makefile.in: Makefile.in from srcdir 1994-12-04 Vern Paxson * Makefile.in: added skel.c to DISTFILES 1994-12-04 Vern Paxson * flex.skl: added YYSTATE alias 1994-12-04 Vern Paxson * scan.l: NL is now \r?\n 1994-12-04 Vern Paxson * gen.c: use cerr for C++ diagnostics 1994-12-03 Vern Paxson * flex.skl: undid YY_UNIX_NEWLINE 1994-12-03 Vern Paxson * flexdef.h: STDC_HEADERS to check for stdlib 1994-12-03 Vern Paxson * configure.in: AC_STDC_HEADERS -> AC_HEADER_STDC 1994-12-03 Vern Paxson * misc.c: \n -> '\012' 1994-12-03 Vern Paxson * flex.skl: Added YY_UNIX_NEWLINE 1994-12-03 Vern Paxson * flex.skl: BOL changes 1994-12-03 Vern Paxson * dfa.c: fixed bug with caseins but not ecs 1994-12-03 Vern Paxson * gen.c: BOL changes some casts for Turbo C 1994-12-03 Vern Paxson * main.c: messages identify filenames 1994-12-03 Vern Paxson * misc.c: Increase slowly if realloc double overflows 1994-12-03 Vern Paxson * nfa.c: YY_RULE_SETUP 1994-12-03 Vern Paxson * scan.l: Added yy_XX_state %option's Added yy_set_bol 1994-11-29 Vern Paxson * Makefile.in: don't remove ~ files 1994-11-24 Vern Paxson * Makefile.in: get CFLAGS from autoconf 1994-11-24 Vern Paxson * dfa.c, flex.skl, flexdef.h, gen.c, misc.c, parse.y, scan.l, sym.c: Brian Madsen's tweaks for Borland 1994-11-24 Vern Paxson * version.h: 2.5.0 1994-11-24 Vern Paxson * flexdef.h: Added do_stdinit 1994-11-24 Vern Paxson * FlexLexer.h: Added yy_delete_buffer() in destructor 1994-11-24 Vern Paxson * flex.skl: Added yy_set_interactive, YY_ALWAYS_INTERACTIVE, YY_NEVER_INTERACTIVE, YY_NO_INPUT, YY_NO_UNPUT, YY_NO_*_STATE 1994-11-24 Vern Paxson * main.c: Added do_stdinit, Think C hacks 1994-11-24 Vern Paxson * scan.l: Added %options for input, always-interactive, never-interactive, yy_scan_{buffer,bytes,string} 1994-11-05 Vern Paxson * flex.skl: size_t #ifdef's for not compiling some statics 1994-11-05 Vern Paxson * Makefile.in: $(FLEX) config.h 1994-11-05 Vern Paxson * configure.in: config.h, size_t, malloc.h, sys/types.h 1994-11-05 Vern Paxson * flexdef.h: config.h, size_t 1994-11-05 Vern Paxson * main.c: yywrap option, no stdin/out init for VMS, mundane tweaks 1994-11-05 Vern Paxson * parse.y: alloca, lint tweaks 1994-11-05 Vern Paxson * scan.l: %option yywrap size_t tweaks 1994-11-05 Vern Paxson * tblcmp.c: size_t tweaks 1994-11-05 Vern Paxson * misc.c: size_t, STDC tweaks 1994-11-05 Vern Paxson * flex.skl: Added yy_scan_{buffer,bytes,string}, plus tweaks 1994-10-12 Vern Paxson * flex.skl: made stack code conditional on "stack" option 1994-10-12 Vern Paxson * scan.l: added use of "stack" %option 1994-08-03 Vern Paxson * gen.c: Fixed fencepost in call to yy_flex_strncpy 1994-07-25 Vern Paxson * flex.skl: yy_eof_status -> yy_buffer_status 1994-07-25 Vern Paxson * flex.skl: yy_flex_strcpy -> yy_flex_strncpy minor prototype tweak 1994-07-25 Vern Paxson * gen.c: Bug fix for matching NUL's at end of token when interactive. yy_flex_strcpy -> yy_flex_strncpy 1994-07-25 Vern Paxson * nfa.c: No YY_USER_ACTION if continued action 1994-03-16 Vern Paxson * flex.skl: Added fix for 8-bit chars returned by input() 1994-03-16 Vern Paxson * flex.skl: Move definition of yy_flex_strcpy to come after #define of yytext_ptr 1994-01-08 Vern Paxson * mkskel.sh: flex.skel -> flex.skl 1994-01-08 Vern Paxson * mkskel.sh: Initial revision 1993-12-29 Vern Paxson * Makefile.in: Fixed scan.c target so "make" detects flex failure 1993-12-27 Vern Paxson * scan.l: Added %option's 1993-12-27 Vern Paxson * Makefile.in: Nuked FLEX_FLAGS that are now done using %option 1993-12-27 Vern Paxson * parse.y, scan.l: %option 1993-12-27 Vern Paxson * main.c: Reworked for %option 1993-12-27 Vern Paxson * flexdef.h: Added "unspecified", globals for %option 1993-12-27 Vern Paxson * sym.c: start condition #define's go to action file 1993-12-27 Vern Paxson * misc.c: Added action_define() 1993-12-27 Vern Paxson * scan.l: Minor consolidation using scon scopes etc 1993-12-27 Vern Paxson * scan.l: Modified to use scon scopes 1993-12-27 Vern Paxson * scan.l: indented rules 1993-12-26 Vern Paxson * parse.y: Added scon_stk stuff, format_warn 1993-12-26 Vern Paxson * flexdef.h: Added format_warn 1993-12-26 Vern Paxson * parse.y: Working checkpoint prior to adding { stuff 1993-12-26 Vern Paxson * flexdef.h, main.c: Added in_rule, deleted actvsc 1993-12-26 Vern Paxson * misc.c: Added doubling of '\'s in filenames 1993-12-26 Vern Paxson * scan.l: Added in_rule, doing_rule_action 1993-12-26 Vern Paxson * sym.c: Removed actvsc 1993-12-23 Vern Paxson * flex.1: -ooutput #line directives credits 1993-12-23 Vern Paxson * flex.skl: Fixsed sense of test for %array 1993-12-23 Vern Paxson * NEWS: 2.5.0 snapshot for Craig 1993-12-23 Vern Paxson * parse.y: Added beginnings of { ... } 1993-12-23 Vern Paxson * scan.l: Simplified scanning {}'s 1993-12-20 Vern Paxson * flexdef.h: Added 1993-12-17 Vern Paxson * flex.skl: prototypes for alloc/string routines 1993-12-17 Vern Paxson * flex.skl: alloc, string routines internal 1993-12-17 Vern Paxson * Makefile.in: Nuked lib{string,alloc}.c, added dependency of yylex.o on parse.h 1993-12-17 Vern Paxson * configure.in: Check for string.h 1993-12-17 Vern Paxson * flexdef.h: Use autoconf for string/strings.h yy_flex_XXX -> flex_XXX 1993-12-17 Vern Paxson * scan.l: Added flex_XXX -> yy_flex_XXX wrappers 1993-12-17 Vern Paxson * dfa.c, misc.c, sym.c: yy_flex_XXX -> flex_XXX 1993-12-17 Vern Paxson * yylex.c: No more WHITESPACE token 1993-12-16 Vern Paxson * FlexLexer.h, flex.skl: Added yy_top_state() 1993-12-16 Vern Paxson * scan.l: simplified comment-scanning using push/pop states 1993-12-16 Vern Paxson * parse.y: removed crufty WHITESPACE token, some uses of '\n' token 1993-12-15 Vern Paxson * FlexLexer.h: start stack, extern "C++" moved 1993-12-15 Vern Paxson * dfa.c: Bug fix for -CF 1993-12-15 Vern Paxson * flexdef.h, misc.c: alloc routines take unsigned 1993-12-15 Vern Paxson * flex.skl: start-state stacks, alloc routines take unsigned 1993-12-15 Vern Paxson * flexdef.h, misc.c: bracket -CF table elements 1993-12-13 Vern Paxson * misc.c: Do #bytes computation in {re,}allocate_array() only once 1993-12-11 Vern Paxson * flex.skl, flexdef.h, gen.c, main.c, misc.c, scan.l, sym.c: yy_str*() -> str*() 1993-12-11 Vern Paxson * Makefile.in, dfa.c, flexdef.h, gen.c, main.c, misc.c, nfa.c, parse.y, scan.l, sym.c: -o option 1993-12-11 Vern Paxson * gen.c: lint tweak 1993-12-11 Vern Paxson * NEWS: Expanded on extern "C++" news item 1993-12-11 Vern Paxson * NEWS: 2.4.5 1993-12-11 Vern Paxson * flex.skl: Added yy_fill_buffer 1993-12-11 Vern Paxson * gen.c: is_interactive -> yy_is_interactive 1993-12-11 Vern Paxson * flex.1: Updated credits 1993-12-11 Vern Paxson * Makefile.in: Fixed typo in "uninstall" target 1993-12-11 Vern Paxson * gen.c: Updated comment regarding 0-based vs. 1-based arrays for -CF. 1993-12-11 Vern Paxson * dfa.c: Initialize dfaacc[0] for -CF representation Fixed minor memory leak 1993-12-11 Vern Paxson * main.c: #include "FlexLexer.h" -> 1993-12-11 Vern Paxson * FlexLexer.h: Added extern "C++" wrapper 1993-12-09 Vern Paxson * main.c: Detect REJECT etc. before generating YY_USES_REJECT! 1993-12-09 Vern Paxson * gen.c: Fixed bug in interactive reads where char is unsigned 1993-12-09 Vern Paxson * parse.y: Fixed bug in treating '$' as variable trailing context 1993-12-09 Vern Paxson * version.h: 2.4.5 1993-12-07 Vern Paxson * README: pretester update 1993-12-07 Vern Paxson * NEWS: 2.4.4 1993-12-07 Vern Paxson * flex.1: LexError(), C++ experiment warning, credits 1993-12-07 Vern Paxson * scan.l: Fixed 8-bit bug 1993-12-07 Vern Paxson * flex.skl, gen.c: Fixed nasty 8-bit bugs 1993-12-07 Vern Paxson * dfa.c, ecs.c, flexdef.h, gen.c, main.c, nfa.c, tblcmp.c: {min,max,abs} -> {MIN,MAX,ABS} 1993-12-07 Vern Paxson * FlexLexer.h, flex.skl: Support for yyFlexLexer::LexerError 1993-12-06 Vern Paxson * version.h: 2.4.4 1993-12-05 Vern Paxson * flex.1: credits update 1993-12-05 Vern Paxson * Makefile.in: very minor "install" tweaks 1993-12-05 Vern Paxson * flex.skl, nfa.c: YY_USER_ACTION generated now for each case in action switch 1993-12-04 Vern Paxson * flex.skl: Fixed bug in pointing yyin at a new file and resuming scanning 1993-12-03 Vern Paxson * NEWS: Added note regarding g++ 2.5.X 1993-12-03 Vern Paxson * flex.1: updated credits 1993-12-03 Vern Paxson * NEWS: ranlib addition for 2.4.3 1993-12-03 Vern Paxson * Makefile.in: Minor tweak to last change 1993-12-03 Vern Paxson * Makefile.in: run ranlib on libfl.a 1993-12-03 Vern Paxson * NEWS: Hopefully last update prior to 2.4.3 1993-12-03 Vern Paxson * flexdef.h, gen.c, misc.c, sym.c: lint tweaks 1993-12-03 Vern Paxson * Makefile.in: Added exec_prefix 1993-12-03 Vern Paxson * flex.1: credit update 1993-12-03 Vern Paxson * flex.skl: lint tweak 1993-12-03 Vern Paxson * NEWS: FlexLexer.h fixed for separate inclusion 1993-12-03 Vern Paxson * FlexLexer.h, flex.skl, main.c: mods so FlexLexer.h can be included separately 1993-12-03 Vern Paxson * flex.1: -F incompatible with -+ 1993-12-02 Vern Paxson * NEWS: Elaborated comments for 2.4.3 1993-12-02 Vern Paxson * NEWS: 2.4.3 1993-12-02 Vern Paxson * flex.1: Updated message regarding missing libfl.a routines Added thanks to Noah Friedman 1993-12-02 Vern Paxson * Makefile.in: Added libstring.c Modified "lint" target to use -Dconst= Added a.out, lex.yy.cc to sundry clean targets 1993-12-02 Vern Paxson * flex.skl, flexdef.h, gen.c, main.c, misc.c, scan.l, sym.c: Use yy_strXXX() routines instead of 1993-12-01 Vern Paxson * version.h: 2.4.3 1993-12-01 Vern Paxson * flexdef.h, misc.c: yy_flex_xmalloc() moved to misc.c 1993-12-01 Vern Paxson * flex.skl: Fixed bug in yy_fatal_error() 1993-12-01 Vern Paxson * Makefile.in: ... and remove plain tar file after compression 1993-12-01 Vern Paxson * NEWS: 2.4.2 1993-12-01 Vern Paxson * Makefile.in: Produce both compress'd and gzip'd distribution tar files 1993-12-01 Vern Paxson * version.h: Release 2.4.2 1993-11-30 Vern Paxson * NEWS: -a -> -Ca 1993-11-30 Vern Paxson * README: described configuration files in manifest 1993-11-30 Vern Paxson * Makefile.in: Added intermediate step of copying MISC/alloca.c -> alloca.c Included CPPFLAGS when compiling alloca.c 1993-11-30 Vern Paxson * README: Credit to 2.4 pre-testers. 1993-11-30 Vern Paxson * gen.c: Fixed nasty bug in short/long decl decision 1993-11-30 Vern Paxson * flexdef.h: Lowered MAX_SHORT out of increased general paranoia. Added yy_flex_xmalloc() proto 1993-11-30 Vern Paxson * main.c: Fixed very minor typo in -v output 1993-11-30 Vern Paxson * misc.c: Removed vestigal cast to (char) in isupper() call 1993-11-30 Vern Paxson * misc.c: Added casts to unsigned Char for isascii() calls 1993-11-30 Vern Paxson * parse.y: Added #ifdef chud for alloca() 1993-11-30 Vern Paxson * Makefile.in: Added alloca 1993-11-30 Vern Paxson * configure.in: Add AC_ALLOCA if using bison 1993-11-29 Vern Paxson * Makefile.in: Added intermediate file going scan.l -> scan.c 1993-11-29 Vern Paxson * Makefile.in: Removed parse.{c,h} from distribution files, since they may not be all that portable. 1993-11-29 Vern Paxson * flex.skl: Fixed %array YYLMAX headaches, added error message if buffer needs growing but REJECT used 1993-11-29 Vern Paxson * gen.c, main.c: Fixed YYLMAX headaches 1993-11-29 Vern Paxson * flex.1: Documented that buffer can't grow if REJECT used 1993-11-29 Vern Paxson * Makefile.in: Added parse.{c,h} to dist files 1993-11-29 Vern Paxson * flex.skl, flexdef.h, gen.c, main.c, misc.c, scan.l: Fixed to buffer section 1 definitions 1993-11-29 Vern Paxson * sym.c: Fixed ANSI-C glitch with '%' operator 1993-11-29 Vern Paxson * scan.l: Fixed mis-definition of ndlookup() 1993-11-29 Vern Paxson * NEWS: 2.4 -> 2.4.1 1993-11-29 Vern Paxson * Makefile.in: Added install.sh, mkinstalldirs to distribution files 1993-11-29 Vern Paxson * flex.1: Added Nathan Zelle, "promoted" Francois 1993-11-29 Vern Paxson * Makefile.in: only "realclean" removes flex dist depends on flex 1993-11-29 Vern Paxson * flexdef.h, misc.c: myctoi takes char[] instead of Char[] 1993-11-28 Vern Paxson * flexdef.h: -a -> -Ca all_lower, all_upper -> work on char* 1993-11-28 Vern Paxson * Makefile.in: Added -Ca to bigcheck 1993-11-28 Vern Paxson * main.c: -a -> -Ca; fixed help output 1993-11-28 Vern Paxson * dfa.c, flex.1: -a -> -Ca 1993-11-28 Vern Paxson * misc.c: all_lower, all_upper work on char* 1993-11-28 Vern Paxson * scan.l: Fixed some casts now that yytext is always char* and never unsigned char* 1993-11-28 Vern Paxson * Makefile.in: Francois' tweaks 1993-11-28 Vern Paxson * configure.in: AC_LN_S, AC_STDC_HEADERS (but not AC_ALLOCA) 1993-11-27 Vern Paxson * NEWS: fixed typo 1993-11-27 Vern Paxson * Makefile.in: Don't remove dist directory 1993-11-27 Vern Paxson * Makefile.in: Include liballoc.c in lint targets 1993-11-27 Vern Paxson * misc.c: lint tweak 1993-11-27 Vern Paxson * Makefile.in: Added -l compression to bigcheck 1993-11-27 Vern Paxson * Makefile.in: permission tweaking for "dist" 1993-11-27 Vern Paxson * Makefile.in: more "dist" tweaks 1993-11-27 Vern Paxson * Makefile.in: Changed "make dist" to use version.h, include scan.c in initial dir copy 1993-11-27 Vern Paxson * version.h: 2.4.1 1993-11-27 Vern Paxson * README: Revised as per Francois Pinard 1993-11-27 Vern Paxson * COPYING: flex.skel -> flex.skl 1993-11-27 Vern Paxson * NEWS: Updated date of 2.4 release 1993-11-27 Vern Paxson * Makefile.in: Removed manual & nroff output from distribution 1993-11-27 Vern Paxson * NEWS: 2.4.1 release 1993-11-27 Vern Paxson * configure.in: Initial revision 1993-11-27 Vern Paxson * Makefile.in: Merge w/ 2.4.1 changes added "dist2" target 1993-11-26 Vern Paxson * Makefile.in: Initial revision 1993-11-26 Vern Paxson * flexdef.h: Removed #ifndef FILE protection from include of stdio 1993-11-26 Vern Paxson * flex.1: Added Francois Pinard to distribution headache helpers 1993-11-26 Vern Paxson * flex.skl: Modified C++ scanners to get input a character at a time for interactive scanners. 1993-11-26 Vern Paxson * main.c: Added YY_INTERACTIVE. 1993-11-26 Vern Paxson * scan.l: Put definitions inside ()'s so we can test -l option for "make bigcheck" 1993-11-26 Vern Paxson * flex.1: Documented YY_INTERACTIVE. 1993-11-26 Vern Paxson * flex.1, flex.skl, flexdef.h, gen.c, main.c, parse.y, scan.l: -l lex compatibility flag 1993-11-20 Vern Paxson * flex.skl: Support for read()/fread() section 1 definitions precede default macro definitions 1993-11-20 Vern Paxson * flexdef.h: Added use_read global 1993-11-20 Vern Paxson * gen.c: Cleaner definition for yymore() Fixed string broken across multiple lines 1993-11-20 Vern Paxson * main.c: Added -Cr 1993-11-20 Vern Paxson * misc.c: K&R declaration for check_char() 1993-11-20 Vern Paxson * flex.1: Documented -Cr 1993-11-20 Vern Paxson * flex.1: No need to #undef before redefining prior to -Cr documentation 1993-11-10 Vern Paxson * README: Heavily massaged for 2.4 1993-11-10 Vern Paxson * flex.1: Added Landon Noll to thanks. 1993-11-10 Vern Paxson * NEWS: 2.4 release 1993-11-10 Vern Paxson * flex.1: 2.4 documentation 1993-11-10 Vern Paxson * main.c: Added global to remember -P prefix so it can be written in -v summary. Alphabetized prefix generation, added yywrap 1993-11-09 Vern Paxson * version.h: updated date for 2.4.0 :-( 1993-10-10 Vern Paxson * FlexLexer.h: Whitespace tweaking 1993-10-10 Vern Paxson * main.c: Use DEFAULT_CSIZE only if not using equivalence classes. 1993-10-10 Vern Paxson * flex.1: Checkpoint prior to final 2.4 update 1993-10-04 Vern Paxson * NEWS: Raw 2.4 changes 1993-10-04 Vern Paxson * flex.skl: osfcn.h -> unistd.h 1993-10-04 Vern Paxson * flex.skl: Added "static" to definition of yy_fatal_error as well as fwd decl. 1993-10-04 Vern Paxson * flex.skl: Added yy_fatal_error function. 1993-10-03 Vern Paxson * flex.skl, gen.c: Got rid of (char *) casts of yytext, no longer needed. 1993-10-03 Vern Paxson * FlexLexer.h: YY_CHAR -> char added YYText(), YYLeng() 1993-10-03 Vern Paxson * flex.skl, gen.c: Minimized use of YY_CHAR 1993-10-03 Vern Paxson * main.c: Added "flex++" feature Minimized use of YY_CHAR 1993-10-02 Vern Paxson * main.c: Clarified help message for -S 1993-10-02 Vern Paxson * libyywrap.c, version.h: Initial revision 1993-10-02 Vern Paxson * main.c: If -+ used, output to lex.yy.cc 1993-10-02 Vern Paxson * FlexLexer.h, flex.skl: Switched from FILE*'s to stream's 1993-10-02 Vern Paxson * flexdef.h: Added expand_nxt_chk() extern. 1993-10-02 Vern Paxson * flex.skl: Added dynamic buffer growing. Added yyless() for section 3. 1993-10-02 Vern Paxson * dfa.c, flexdef.h, gen.c, main.c: Added -a option for long-align. 1993-10-02 Vern Paxson * scan.l: formfeed no longer considered whitespace 1993-09-21 Vern Paxson * flexdef.h: Nuked FILENAMESIZE 1993-09-21 Vern Paxson * main.c: yyflexlexer.h -> FlexLexer.h minor portability tweak 1993-09-21 Vern Paxson * gen.c: Added start condition to EOF trace output 1993-09-21 Vern Paxson * flex.skl: Added YY_START changed yyFlexLexer to define yylex() 1993-09-21 Vern Paxson * misc.c: Minor portability tweaks 1993-09-21 Vern Paxson * FlexLexer.h: Split into two classes, one fully abstract. yylex() no longer abstract in yyFlexLexer 1993-09-21 Vern Paxson * scan.l: PC lint tweak 1993-09-21 Vern Paxson * parse.y: YYSTYPE #define'd to int 1993-09-21 Vern Paxson * nfa.c: minor lint tweak 1993-09-16 Vern Paxson * FlexLexer.h: Initial revision 1993-09-16 Vern Paxson * flexdef.h: Delete prototypes for Unix system calls. 1993-09-16 Vern Paxson * ccl.c, dfa.c, ecs.c, gen.c, main.c, misc.c, nfa.c, parse.y, scan.l, sym.c, tblcmp.c, yylex.c: nuked static RCS string 1993-09-16 Vern Paxson * main.c: %array not allowed with C++ scanners 1993-09-16 Vern Paxson * scan.l: Fixed bugs regarding %{%} code in section 2 prolog %array not allowed with C++ scanners 1993-08-25 Vern Paxson * flexdef.h: Added C_plus_plus flag. 1993-08-25 Vern Paxson * flex.skl: First version of C/C++ skeleton 1993-08-25 Vern Paxson * gen.c: yy_state_type declared earlier. Made a bunch of statics only output if not -+ 1993-08-25 Vern Paxson * main.c: Added -+ option, updated usage() output, rearranged some generated code to come at the right point in the output for yyflexlexer.h. 1993-08-25 Vern Paxson * misc.c: Added %+/%-/%* to skelout() 1993-08-25 Vern Paxson * scan.l: EOF in section 2 prolog leads to section 0, not section 3 1993-08-25 Vern Paxson * yylex.c: Dump promotion of EOF in section 2 to turn on section 3; instead just treat it like a final EOF 1993-08-25 Vern Paxson * dfa.c: yy_nxt table should be "const" 1993-08-24 Vern Paxson * flexdef.h: Removed a lot of #ifdef chud "backtracking" -> "backing up" 1993-08-24 Vern Paxson * main.c: "backtracking" -> "backing up" got rid of time reports 1993-08-24 Vern Paxson * gen.c: "backtracking" -> "backing up" some portability tweaks fixed to only call flexscan() when done if known to be in section 3 1993-08-24 Vern Paxson * misc.c: isascii() moved to flexdef.h nuked flex_gettime() 1993-08-24 Vern Paxson * scan.l: Fixed bug with empty section 2 1993-08-24 Vern Paxson * yylex.c: Chucked definition of isascii() 1993-08-24 Vern Paxson * flex.skl: preserve yytext on input() bug fix when combining yyless() with yymore() checkpoint prior to C++ option 1993-08-24 Vern Paxson * dfa.c: "backtracking" -> "backing up" 1993-07-09 Vern Paxson * flex.skl: Fixed to not generate extra EOF's after reading one. 1993-07-05 Vern Paxson * main.c: Spit out definition of YY_CHAR early 1993-07-05 Vern Paxson * flex.skl: Some rearranging to make sure things get declared in the right order 1993-07-05 Vern Paxson * tblcmp.c: Some comment fixes as per Wilhelms 1993-07-05 Vern Paxson * scan.l: Nuked #undef of yywrap, now that it's a function 1993-07-05 Vern Paxson * parse.y: Fixed bug with Z-a character classes as per Wilhelms 1993-07-05 Vern Paxson * nfa.c: added check_char call in mkstate() to prevent bad xtion chars 1993-07-05 Vern Paxson * gen.c: Fixed some reallocation bugs, etc. as per Wilhelms 1993-07-05 Vern Paxson * flexdef.h: Added check_char(), readable_form() 1993-07-05 Vern Paxson * flex.skl: Added #ifndef's around #define's to let user override Moved a bunch of definitions prior to section 1 1993-07-05 Vern Paxson * dfa.c: Wilhems bug fixes. 1993-07-05 Vern Paxson * ccl.c, misc.c: Added check_char() 1993-06-12 Vern Paxson * flexdef.h: Changed to use yy_flex_alloc() and friends 1993-06-12 Vern Paxson * main.c: Added -P flag 1993-06-12 Vern Paxson * scan.l: Fixed bug in lex % directives 1993-06-12 Vern Paxson * misc.c: Modified to use yy_flex_alloc() and friends 1993-06-12 Vern Paxson * sym.c: Modified to use yy_flex_alloc() 1993-06-12 Vern Paxson * flex.skl: Modified to use yy_flex_alloc() and friends Moved some globals earlier in the file to permit access in section 1 1993-06-12 Vern Paxson * dfa.c: Got rid of code needed for %t 1993-04-14 Vern Paxson * ccl.c, dfa.c, ecs.c, flex.skl, flexdef.h, gen.c, libmain.c, main.c, misc.c, nfa.c, parse.y, scan.l, sym.c, tblcmp.c, yylex.c: Reformatting. 1993-04-05 Vern Paxson * flex.1: Fixed bug in description of backtracking 1993-04-05 Vern Paxson * NEWS: 2.3.8 1993-04-05 Vern Paxson * flex.skl, main.c: %array support 1993-04-05 Vern Paxson * misc.c: Added non-STDC clause for '\a' 1993-04-05 Vern Paxson * scan.l: Fixed subtle problems regarding '*'s in comments %pointer/%array match entire lines 1993-04-05 Vern Paxson * gen.c: Added %array support 1993-02-06 Vern Paxson * README: Finally updated email addr 1993-02-06 Vern Paxson * flex.1: Mostly .LP -> .PP 1993-02-06 Vern Paxson * flexdef.h: [no log message] 1993-02-06 Vern Paxson * main.c, scan.l: A lot of tweaks ... 1993-02-06 Vern Paxson * ccl.c: reallocate_character_array -> reallocate_Character_array 1993-02-06 Vern Paxson * gen.c: Bug/lint fixes Modified to work with "action" array instead of temp file 1993-02-06 Vern Paxson * sym.c: Fixed bug in 8-bit hashing 1993-02-06 Vern Paxson * parse.y: numerous bug fixes extra formatting of error/warning messages added support of <*>, partial support for nested start conditions 1993-02-06 Vern Paxson * ecs.c: Remove %t cruft 1993-02-06 Vern Paxson * flex.skl: Beginning of %pointer/%array support 1993-02-06 Vern Paxson * dfa.c: Added keeping track of which rules are useful fixed a fencepost error in checking for scanners that require -8 1993-02-06 Vern Paxson * nfa.c: Added checking for whether rules are useful modified to work with internal "action" array 1993-02-06 Vern Paxson * misc.c: Added internal "action" array, internal skeleton, zero_out() in lieu of bzero 1993-02-06 Vern Paxson * tblcmp.c: Fixed a bunch of fencepost errors in increasing tables. 1993-02-06 Vern Paxson * yylex.c: -Wall fix 1991-03-28 Vern Paxson * gen.c: Fixed out-of-bounds access bug; patch #7 for release 2.3 1991-03-28 Vern Paxson * NEWS: Patch #7 for 2.3 1990-10-23 Vern Paxson * gen.c: fixed missing "rule_type" entry for end-of-buffer action 1990-08-29 Vern Paxson * gen.c: Fixed yymore() but in not resetting yy_more_len 1990-08-29 Vern Paxson * NEWS: Patch #6 for 2.3 1990-08-16 Vern Paxson * NEWS: Patch #5 1990-08-14 Vern Paxson * misc.c: fixed comment in myesc() 1990-08-14 Vern Paxson * NEWS: fixed date in patch #4 1990-08-14 Vern Paxson * NEWS: patch #4 1990-08-14 Vern Paxson * misc.c: fixed hexadecimal escapes; added is_hex_digit() 1990-08-03 Vern Paxson * NEWS: Patch #3 1990-08-03 Vern Paxson * flex.skl, flexdef.h: changed to include for __GNUC__ 1990-08-02 Vern Paxson * NEWS: 2.3 patch #2 1990-08-02 Vern Paxson * flex.skl: Another try at getting the malloc() definitions correct; this time for g++, too 1990-08-02 Vern Paxson * flex.skl, flexdef.h: fixed to declare malloc() and free() by hand if __GNUC__ 1990-07-28 Vern Paxson * flexdef.h: Changed to get malloc definition in identical fashion to that used by flex.skel 1990-06-28 Vern Paxson * NEWS: [no log message] 1990-06-28 Vern Paxson * flex.1: Fixed bug in mini-scanner examle Fixed bug in YY_INPUT redefinition yylineno defense reentrancy documentation Something else which I forget. 1990-06-27 Vern Paxson * COPYING, ccl.c, dfa.c, ecs.c, flexdef.h, gen.c, main.c, misc.c, nfa.c, parse.y, scan.l, sym.c, tblcmp.c, yylex.c: 4.4 BSD copyright 1990-05-26 Vern Paxson * README: Changed prolog to reflect 2.3 release. 1990-05-26 Vern Paxson * NEWS: pointed reader at Makefile instead of README for porting considerations added Makefile comments: support for SCO Unix; parameterization 1990-05-26 Vern Paxson * flex.skl: Added DONT_HAVE_STDLIB_H and declarations of malloc() 1990-05-26 Vern Paxson * NEWS: 2.3 changes 1990-05-26 Vern Paxson * flex.1: documentation on new features Comment regarding Ove's work ^foo|bar difference between flex / lex yyin initialization difference documented that yy_switch_to_buffer can be used in yywrap() documented that # comments are deprecated 1990-05-26 Vern Paxson * main.c: declared void functions as such added prototypes for forward references changed to check for error status when closing files 1990-05-26 Vern Paxson * yylex.c: Added macro definition for isascii() if not already present 1990-05-26 Vern Paxson * sym.c: declared void functions as such added prototypes for forward references changed to use format_pinpoint_message where appropriate 1990-05-26 Vern Paxson * scan.l: declared void functions as such changed to strip # comments, as documented moved #undef of yywrap() to before include of flexdef, so prototype doesn't get screwed up 1990-05-26 Vern Paxson * parse.y: introduced format_pinpoint_message() declared void functions as such changed lone <> to apply to all outstanding start conditions 1990-05-26 Vern Paxson * nfa.c, tblcmp.c: declared void functions as such added prototypes for forward references 1990-05-26 Vern Paxson * misc.c: declared void functions as such prototypes for forward references shuffled around some routines to make the order perhaps a little more logical changed memory references to use void* instead of char* 1990-05-26 Vern Paxson * libmain.c: Added declaration of arguments made yylex() a function 1990-05-26 Vern Paxson * gen.c: prototypes for forward references declared void functions as such yy_flex_debug testing of error on file closes casts to void for sprintf() and strcpy() 1990-05-26 Vern Paxson * flexdef.h: Added prototypes changed memory allocation routines to deal with void*'s instead of char*'s some rearranging for VMS 1990-05-26 Vern Paxson * flex.skl: Added YY_USER_INIT Added yy_new_buffer() alias for yy_create_buffer() fixed (hopefully) malloc declaration headaches 1990-05-26 Vern Paxson * ecs.c: declared void functions as such declared void functions as such 1990-05-26 Vern Paxson * dfa.c: prototypes for forward references declared void functions as such 1990-05-26 Vern Paxson * ccl.c: Declared void functions as such 1990-04-12 Vern Paxson * flex.skl: added fix for allowing yy_switch_to_buffer() in yywrap() 1990-04-03 Vern Paxson * NEWS: patch #3 - -I fix 1990-03-30 Vern Paxson * gen.c: Changed generation of archaic "continue" to "goto yy_find_action" 1990-03-27 Vern Paxson * NEWS: Patch #2 changes 1990-03-27 Vern Paxson * flex.skl: fixed fencepost errors with yy_buf_size and detecting NUL's 1990-03-26 Vern Paxson * NEWS: [no log message] 1990-03-26 Vern Paxson * flex.skl: g++ tweaks 1990-03-23 Vern Paxson * NEWS: Changes for Patch #1. 1990-03-23 Vern Paxson * flex.skl: fix for g++ 1990-03-23 Vern Paxson * flex.1: minor typos and formatting changes. Removed BITNET address. 1990-03-23 Vern Paxson * README: nuked BITNET address. 1990-03-20 Vern Paxson * README: 2.2 README 1990-03-20 Vern Paxson * NEWS: USG alias. 1990-03-20 Vern Paxson * flexdef.h: Added USG alias for SYS_V 1990-03-20 Vern Paxson * : [no log message] 1990-03-20 Vern Paxson * flex.skl: Tweaks for lint and C++ 1990-03-20 Vern Paxson * flex.1: -ll => -lfl 1990-03-20 Vern Paxson * NEWS: 2.2 changes 1990-03-20 Vern Paxson * flex.skl: Changed to use YY_BUFFER_STATE everywhere. 1990-03-20 Vern Paxson * flex.1: [no log message] 1990-03-20 Vern Paxson * dfa.c: "associated rules" changed to "associated rule line numbers". 1990-03-20 Vern Paxson * scan.l: cast added to malloc() call to keep lint happy. 1990-03-20 Vern Paxson * yylex.c: Fixed handling of premature EOF's. 1990-03-20 Vern Paxson * sym.c: Removed declaration of malloc() 1990-03-20 Vern Paxson * scan.l: Removed malloc() declaration. Added detection of EOF in actions. 1990-03-20 Vern Paxson * parse.y: Rules rewritten so '/' and '$' parsed correctly. 1990-03-20 Vern Paxson * nfa.c: Corrected line numbers for continued actions. 1990-03-20 Vern Paxson * misc.c: Removed declarations of malloc() and realloc(). 1990-03-20 Vern Paxson * main.c: Summary of generation flags. Minor -8 tweaks. 1990-03-20 Vern Paxson * gen.c: full support for -d 1990-03-20 Vern Paxson * flexdef.h: defines for malloc() and realloc() conditional defines for abs(), min(), and max() 1990-03-20 Vern Paxson * flex.skl: Many multiple-buffer additions. 1990-03-20 Vern Paxson * dfa.c: -8 tweaks. 1990-03-19 Vern Paxson * flex.skl: Proto hacks. NUL hacks. Debugging hacks. C++ hacks. 1990-03-16 Vern Paxson * : RCS won't let me unedit! gets "Missing access list" 1990-03-16 Vern Paxson * tblcmp.c: Minor tweaks for NUL's. 1990-03-16 Vern Paxson * : no changes -- had checked out for testing smaller read buffer sizes 1990-03-16 Vern Paxson * nfa.c: hack for NUL's. 1990-03-16 Vern Paxson * misc.c: Hack to cshell for NUL's. 1990-03-16 Vern Paxson * main.c: NUL's. -8 1990-03-16 Vern Paxson * gen.c: NUL's. 1990-03-16 Vern Paxson * flexdef.h: NUL's. 8-bit chars. 1990-03-16 Vern Paxson * flex.skl: NUL's; indenting 1990-03-16 Vern Paxson * dfa.c: more thrashing around with NUL's 1990-03-16 Vern Paxson * ccl.c: removed NUL hack 1990-03-14 Vern Paxson * yylex.c: Added <> token 1990-03-14 Vern Paxson * ecs.c, flexdef.h: Tweaks for NUL chars. 1990-03-14 Vern Paxson * dfa.c, gen.c, main.c, misc.c, parse.y, scan.l, tblcmp.c: Tweaks for NUL chars. 1990-03-14 Vern Paxson * ccl.c: Tweaks for handling NUL's. 1990-02-28 Vern Paxson * flex.1: [no log message] 1990-02-28 Vern Paxson * flex.1: Changed .so options.man to inlined version since flex.1 will have a different (shorter) options description. 1990-02-28 Vern Paxson * flex.1: [no log message] 1990-02-28 Vern Paxson * flex.1: [no log message] 1990-02-26 Vern Paxson * flex.1: [no log message] 1990-02-25 Vern Paxson * flex.1: [no log message] 1990-02-25 Vern Paxson * flex.1: Initial revision 1990-01-16 Vern Paxson * gen.c: Restored EOB accepting list for REJECT. Second try at 2.2 Release. 1990-01-16 Vern Paxson * misc.c: Added missing ',' in error message. 2.2 Release, second try. 1990-01-16 Vern Paxson * yylex.c: 8-bit char support. 2.2 Release. 1990-01-15 Vern Paxson * scan.l: 8-bit char support. Arbitrary indented/%{} code allowed in section 2. \x escapes. %t support. Minor POSIX-compliance changes. BEGIN(0) -> BEGIN(INITIAL). yywrap() and set_input_file() for multiple input files. C_COMMENT_2 removed. 2.2 Release. 1990-01-15 Vern Paxson * flexdef.h: 8-bit char support. SYS_V / Atari portability fixes. Removed generated array names. CSIZE now only defined if not already defined. Added "csize" global. Added "input_files", "num_input_files", and "program_name" globals. %t support globals. 2.2 Release. 1990-01-15 Vern Paxson * gen.c: Removed unused EOB_accepting_list array. 2.2 Release. 1990-01-15 Vern Paxson * gen.c: Bug in -F table generation fixed. 8-bit char support. Hardwired generated array names. "const"'s added to generated code. Fixed yymore() / trailing context bug. 1990-01-15 Vern Paxson * parse.y: 8-bit char support. Error-message pinpointing. 2.2 Release. 1990-01-15 Vern Paxson * main.c: Unsigned char support. %t support. Removed hard-wiring of program name "flex". -c changed to -C; -c now deprecated. -n added. :-( Multiple input files. SYSV tmpnam() use. Removed old #define's from output. Identified error messages w/ filename and line. 2.2 Release. 1990-01-15 Vern Paxson * sym.c: Unsigned char support. 2.2 Release. 1990-01-15 Vern Paxson * nfa.c: Removed redundant test. 2.2 Release. 1990-01-15 Vern Paxson * misc.c: Unsigned char support. \x support. 2.2 Release. 1990-01-15 Vern Paxson * tblcmp.c: 8-bit char support. 2.2 Release. 1990-01-15 Vern Paxson * flex.skl: C++ support. Turbo-C support. 8-bit char support. yyleng is an int. unput() callable in section 3. yymore hacks. yyrestart() no longer closes stdin. 2.2 Release. 1990-01-15 Vern Paxson * ecs.c: %t support. 8-bit/unsigned char support. 2.2 Release. 1990-01-15 Vern Paxson * dfa.c: %t hacks. minor cosmetics. 2.2 Relase. 1990-01-15 Vern Paxson * ccl.c: Changes for unsigned/8-bit chars. 2.2 Release. 1990-01-10 Vern Paxson * libmain.c: Initial revision 1989-12-30 Vern Paxson * nfa.c: removed gratuitous trailing context code 1989-12-30 Vern Paxson * main.c: made -c case-sensitive 1989-12-30 Vern Paxson * flex.skl: unput() bug fix 1989-12-30 Vern Paxson * README: [no log message] 1989-06-20 Vern Paxson * scan.l: changed to not use '|' and trailing context combo so users can test using -F ... 1989-06-20 Vern Paxson * parse.y: made trailing context combined with '|' warning always come out 1989-06-20 Vern Paxson * README: [no log message] 1989-06-20 Vern Paxson * COPYING: Initial revision 1989-06-20 Vern Paxson * NEWS, README, main.c: [no log message] 1989-06-20 Vern Paxson * README: [no log message] 1989-06-20 Vern Paxson * NEWS, README, main.c: [no log message] 1989-06-20 Vern Paxson * : Beta release 1989-06-20 Vern Paxson * NEWS, main.c: [no log message] 1989-06-20 Vern Paxson * flex.skl, flexdef.h, gen.c, misc.c, nfa.c, parse.y, scan.l, sym.c: 2.0.1 beta 1989-06-20 Vern Paxson * README: [no log message] 1989-05-25 Vern Paxson * gen.c: fixsed bug with -I and backtracking 1989-05-25 Vern Paxson * flex.skl: Cleaned up forward declarations of yyunput() and input() 1989-05-25 Vern Paxson * parse.y: Split copyright string. 1989-05-25 Vern Paxson * nfa.c: Split copyright string. Added check for empty machine in dupmachine(). 1989-05-25 Vern Paxson * ccl.c, dfa.c, ecs.c, gen.c, main.c, misc.c, scan.l, sym.c, tblcmp.c, yylex.c: Split copyright string into two to avoid tempting fate with \ sequences ... 1989-05-24 Vern Paxson * README: updated for 2nd release Beta test added RCS header 1989-05-24 Vern Paxson * flexdef.h: removed static char copyright 1989-05-24 Vern Paxson * flexdef.h: Added BSD copyright notice. Removed FAST_SKELETON_FILE. 1989-05-24 Vern Paxson * main.c: added BSD copyright notice. Removed references to FAST_SKELETON_FILE. 1989-05-24 Vern Paxson * ecs.c, gen.c, nfa.c: Added BSD copyright notice 1989-05-24 Vern Paxson * ccl.c, dfa.c, misc.c, parse.y, scan.l, sym.c, tblcmp.c, yylex.c: added BSD copyright notice 1989-05-24 Vern Paxson * flex.skl: Initial revision 1989-05-19 Vern Paxson * yylex.c: renamed accnum to num_rules 1989-05-19 Vern Paxson * tblcmp.c: moved table generation code to gen.c moved ntod() to dfa.c 1989-05-19 Vern Paxson * sym.c: the most piddling format change imaginable 1989-05-19 Vern Paxson * scan.l: changed to look for yymore, REJECT, %used and %unused removed gross magic for dealing with section 3 1989-05-19 Vern Paxson * nfa.c, parse.y: changes for variable trailing context 1989-05-19 Vern Paxson * misc.c: added all_lower() and all_upper() 1989-05-19 Vern Paxson * main.c: added checking for features being Really used backtracking, performance reports misc. cleanup 1989-05-19 Vern Paxson * gen.c: major overhaul for merged skeleton 1989-05-19 Vern Paxson * flexdef.h: a zillion changes/additions/cleanups 1989-05-19 Vern Paxson * dfa.c: added backtrack report added checking for dangerous trailing context considerable minor cleanup 1989-05-19 Vern Paxson * ccl.c: list_character_set() modified to take a FILE to write to ... 1989-05-19 Vern Paxson * README: updated for beta release 1988-11-25 Vern Paxson * main.c: added -p flag generation of #define's for scanner 1988-11-25 Vern Paxson * flexdef.h: Added END_OF_BUFFER_ACTION and bol_needed 1988-11-25 Vern Paxson * dfa.c: added ntod() 1988-05-09 Vern Paxson * gen.c: Initial revision 1988-05-08 Vern Paxson * yylex.c: RCS header changed display style of non-printings from ^x to \0xx 1988-05-08 Vern Paxson * tblcmp.c: RCS header MAX_XTIONS_FOR_FULL_INTERIOR_FIT -> MAX_XTIONS_FULL_INTERIOR_FIT made back-tracking accepting number be one greater than the last legit accepting number, instead of 0. This way, end-of-buffer can take 0 and no negative accepting numbers are needed. added genftbl() changed last ftl references to C added check for UNSIGNED_CHAR's added back-track logic to make_tables() added checking and report for backtracking fixed fence-post error with onesp stack pointer 1988-05-08 Vern Paxson * sym.c: RCS header changed "entry" to "sym_entry" to avoid conflict with old keyword 1988-05-08 Vern Paxson * scan.l: RCS header removed \^ from ESCSEQ 1988-05-08 Vern Paxson * parse.y: RCS header bug fix due to missing default rule, could have to backtrack when backtrack variables haven't been set up 1988-05-08 Vern Paxson * nfa.c: RCS ident yy_cp, yy_bp support name shortenings assoc_rule support 1988-05-08 Vern Paxson * misc.c: RCS header check before malloc()'ing for 16 bit overflow MS_DOS, VMS ifdef's removed commented-out \^ code removed FTLSOURCE code added readable_form() 1988-05-08 Vern Paxson * main.c: Added RCS header removed revision history misc additions and fixes to globals VMS ifdef's backtracking statistics -p flag name shortenings 1988-05-08 Vern Paxson * flexdef.h: removed revision history added RCS header added VMS, MS_DOS ifdef's removed DEFAULT_ACTION, changed END_OF_BUFFER_ACTION shortened MAX_XTIONS_FOR_FULL_INTERIOR_FIT to MAX_XTIONS_FULL_INTERIOR_FIT added MAX_ASSOC_RULES added performance_report, assoc_rule gloabls added num_backtracking gloabl shortened allocate_integer_pointer_array, reallocate_integer_pointer_array 1988-05-08 Vern Paxson * ecs.c: added RCS id added PROCFLG to avoid assumption of signed char's 1988-05-08 Vern Paxson * dfa.c: added RCS id added check_for_backtracking() added dump_associated_rules() added dump_transitions() shortened reallocate_integer_pointer_array to reallocate_int_ptr_array removed some dfaacc_{state,set} abuses 1988-05-08 Vern Paxson * ccl.c: Added list_character_set() 1988-05-07 Vern Paxson * ccl.c: added RCS id 1988-04-10 Vern Paxson * README: minor tweaks 1988-04-10 Vern Paxson * README: forgot sh flex.shar 1988-04-10 Vern Paxson * README: final tweaking 1988-04-10 Vern Paxson * tblcmp.c: removed minor lint fluff 1988-04-10 Vern Paxson * NEWS: [no log message] 1988-04-10 Vern Paxson * NEWS, README: Initial revision 1988-04-10 Vern Paxson * yylex.c: added identifying comment. changed to include "parse.h" instead of "y.tab.h" 1988-04-10 Vern Paxson * tblcmp.c: Changed name from flexcmp.c -> tblcmp.c fixed misc. typos made generating ec tables be a routine 1988-04-10 Vern Paxson * sym.c: changed name from flexsym.c -> sym.c revamped calling sequences, etc., for extended table struct definition which now has both char * and int fields. 1988-04-10 Vern Paxson * scan.l: Changed name from flexscan.l -> scan.l fixed bug in added block comments between rules. 1988-04-10 Vern Paxson * parse.y: changed name from flexparse.y -> parse.y added start condition "INITIAL" made a{3} have "variable length" 1988-04-10 Vern Paxson * nfa.c: changed name from flexnfa.c -> nfa.c corrected some typos. 1988-04-10 Vern Paxson * misc.c: changed name from flexmisc.c -> misc.c 1988-04-10 Vern Paxson * main.c: fixed bug causing core dumps if skeleton files could not be opened. Added -cF. Added fullspd to be equivalent to fulltbl for which options is cannot be mixed with. 1988-04-10 Vern Paxson * flexdef.h: fixed typos, enhanced symbol table definition. 1988-04-10 Vern Paxson * ecs.c: changed name from flexecs.c to ecs.c 1988-04-10 Vern Paxson * dfa.c: changed name from flexdfa.c to dfa.c 1988-04-10 Vern Paxson * ccl.c: changed name from flexccl.c -> ccl.c 1988-02-13 Vern Paxson * ccl.c, dfa.c, ecs.c, flexdef.h, main.c, misc.c, nfa.c, parse.y, scan.l, sym.c, tblcmp.c, yylex.c: Beta Release. 1987-11-08 Vern Paxson * Initial revision freebsd-buildutils-10.0/src/contrib/flex/version.h0000644000000000000000000000003512146741165017140 0ustar #define FLEX_VERSION VERSION freebsd-buildutils-10.0/src/contrib/flex/main.c0000644000000000000000000014207012146744705016403 0ustar /* flex - tool to generate fast lexical analyzers */ /* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */ /* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */ /* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #include "flexdef.h" #include "version.h" #include "options.h" #include "tables.h" static char flex_version[] = FLEX_VERSION; /* declare functions that have forward references */ void flexinit PROTO ((int, char **)); void readin PROTO ((void)); void set_up_initial_allocations PROTO ((void)); static char *basename2 PROTO ((char *path, int should_strip_ext)); /* these globals are all defined and commented in flexdef.h */ int printstats, syntaxerror, eofseen, ddebug, trace, nowarn, spprdflt; int interactive, lex_compat, posix_compat, do_yylineno, useecs, fulltbl, usemecs; int fullspd, gen_line_dirs, performance_report, backing_up_report; int C_plus_plus, long_align, use_read, yytext_is_array, do_yywrap, csize; int reentrant, bison_bridge_lval, bison_bridge_lloc; int yymore_used, reject, real_reject, continued_action, in_rule; int yymore_really_used, reject_really_used; int datapos, dataline, linenum; FILE *skelfile = NULL; int skel_ind = 0; char *action_array; int action_size, defs1_offset, prolog_offset, action_offset, action_index; char *infilename = NULL, *outfilename = NULL, *headerfilename = NULL; int did_outfilename; char *prefix, *yyclass, *extra_type = NULL; int do_stdinit, use_stdout; int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE]; int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp; int maximum_mns, current_mns, current_max_rules; int num_rules, num_eof_rules, default_rule, lastnfa; int *firstst, *lastst, *finalst, *transchar, *trans1, *trans2; int *accptnum, *assoc_rule, *state_type; int *rule_type, *rule_linenum, *rule_useful; int current_state_type; int variable_trailing_context_rules; int numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP]; int protcomst[MSP], firstprot, lastprot, protsave[PROT_SAVE_SIZE]; int numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs, tecfwd[CSIZE + 1]; int tecbck[CSIZE + 1]; int lastsc, *scset, *scbol, *scxclu, *sceof; int current_max_scs; char **scname; int current_max_dfa_size, current_max_xpairs; int current_max_template_xpairs, current_max_dfas; int lastdfa, *nxt, *chk, *tnxt; int *base, *def, *nultrans, NUL_ec, tblend, firstfree, **dss, *dfasiz; union dfaacc_union *dfaacc; int *accsiz, *dhash, numas; int numsnpairs, jambase, jamstate; int lastccl, *cclmap, *ccllen, *cclng, cclreuse; int current_maxccls, current_max_ccl_tbl_size; Char *ccltbl; char nmstr[MAXLINE]; int sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs; int tmpuses, totnst, peakpairs, numuniq, numdup, hshsave; int num_backing_up, bol_needed; FILE *backing_up_file; int end_of_buffer_state; char **input_files; int num_input_files; jmp_buf flex_main_jmp_buf; bool *rule_has_nl, *ccl_has_nl; int nlch = '\n'; bool ansi_func_defs, ansi_func_protos; bool tablesext, tablesverify, gentables; char *tablesfilename=0,*tablesname=0; struct yytbl_writer tableswr; /* Make sure program_name is initialized so we don't crash if writing * out an error message before getting the program name from argv[0]. */ char *program_name = "flex"; #ifndef SHORT_FILE_NAMES static char *outfile_template = "lex.%s.%s"; static char *backing_name = "lex.backup"; static char *tablesfile_template = "lex.%s.tables"; #else static char *outfile_template = "lex%s.%s"; static char *backing_name = "lex.bck"; static char *tablesfile_template = "lex%s.tbl"; #endif #ifdef MS_DOS extern unsigned _stklen = 16384; #endif /* From scan.l */ extern FILE* yyout; static char outfile_path[MAXLINE]; static int outfile_created = 0; static char *skelname = NULL; static int _stdout_closed = 0; /* flag to prevent double-fclose() on stdout. */ const char *escaped_qstart = "[[]]M4_YY_NOOP[M4_YY_NOOP[M4_YY_NOOP[[]]"; const char *escaped_qend = "[[]]M4_YY_NOOP]M4_YY_NOOP]M4_YY_NOOP[[]]"; /* For debugging. The max number of filters to apply to skeleton. */ static int preproc_level = 1000; int flex_main PROTO ((int argc, char *argv[])); int main PROTO ((int argc, char *argv[])); int flex_main (argc, argv) int argc; char *argv[]; { int i, exit_status, child_status; /* Set a longjmp target. Yes, I know it's a hack, but it gets worse: The * return value of setjmp, if non-zero, is the desired exit code PLUS ONE. * For example, if you want 'main' to return with code '2', then call * longjmp() with an argument of 3. This is because it is invalid to * specify a value of 0 to longjmp. FLEX_EXIT(n) should be used instead of * exit(n); */ exit_status = setjmp (flex_main_jmp_buf); if (exit_status){ if (stdout && !_stdout_closed && !ferror(stdout)){ fflush(stdout); fclose(stdout); } while (wait(&child_status) > 0){ if (!WIFEXITED (child_status) || WEXITSTATUS (child_status) != 0){ /* report an error of a child */ if( exit_status <= 1 ) exit_status = 2; } } return exit_status - 1; } flexinit (argc, argv); readin (); skelout (); /* %% [1.5] DFA */ ntod (); for (i = 1; i <= num_rules; ++i) if (!rule_useful[i] && i != default_rule) line_warning (_("rule cannot be matched"), rule_linenum[i]); if (spprdflt && !reject && rule_useful[default_rule]) line_warning (_ ("-s option given but default rule can be matched"), rule_linenum[default_rule]); /* Generate the C state transition tables from the DFA. */ make_tables (); /* Note, flexend does not return. It exits with its argument * as status. */ flexend (0); return 0; /* keep compilers/lint happy */ } /* Wrapper around flex_main, so flex_main can be built as a library. */ int main (argc, argv) int argc; char *argv[]; { #if ENABLE_NLS #if HAVE_LOCALE_H setlocale (LC_MESSAGES, ""); setlocale (LC_CTYPE, ""); textdomain (PACKAGE); bindtextdomain (PACKAGE, LOCALEDIR); #endif #endif return flex_main (argc, argv); } /* check_options - check user-specified options */ void check_options () { int i; const char * m4 = NULL; if (lex_compat) { if (C_plus_plus) flexerror (_("Can't use -+ with -l option")); if (fulltbl || fullspd) flexerror (_("Can't use -f or -F with -l option")); if (reentrant || bison_bridge_lval) flexerror (_ ("Can't use --reentrant or --bison-bridge with -l option")); yytext_is_array = true; do_yylineno = true; use_read = false; } #if 0 /* This makes no sense whatsoever. I'm removing it. */ if (do_yylineno) /* This should really be "maintain_backup_tables = true" */ reject_really_used = true; #endif if (csize == unspecified) { if ((fulltbl || fullspd) && !useecs) csize = DEFAULT_CSIZE; else csize = CSIZE; } if (interactive == unspecified) { if (fulltbl || fullspd) interactive = false; else interactive = true; } if (fulltbl || fullspd) { if (usemecs) flexerror (_ ("-Cf/-CF and -Cm don't make sense together")); if (interactive) flexerror (_("-Cf/-CF and -I are incompatible")); if (lex_compat) flexerror (_ ("-Cf/-CF are incompatible with lex-compatibility mode")); if (fulltbl && fullspd) flexerror (_ ("-Cf and -CF are mutually exclusive")); } if (C_plus_plus && fullspd) flexerror (_("Can't use -+ with -CF option")); if (C_plus_plus && yytext_is_array) { warn (_("%array incompatible with -+ option")); yytext_is_array = false; } if (C_plus_plus && (reentrant)) flexerror (_("Options -+ and --reentrant are mutually exclusive.")); if (C_plus_plus && bison_bridge_lval) flexerror (_("bison bridge not supported for the C++ scanner.")); if (useecs) { /* Set up doubly-linked equivalence classes. */ /* We loop all the way up to csize, since ecgroup[csize] is * the position used for NUL characters. */ ecgroup[1] = NIL; for (i = 2; i <= csize; ++i) { ecgroup[i] = i - 1; nextecm[i - 1] = i; } nextecm[csize] = NIL; } else { /* Put everything in its own equivalence class. */ for (i = 1; i <= csize; ++i) { ecgroup[i] = i; nextecm[i] = BAD_SUBSCRIPT; /* to catch errors */ } } if (!ansi_func_defs) buf_m4_define( &m4defs_buf, "M4_YY_NO_ANSI_FUNC_DEFS", NULL); if (!ansi_func_protos) buf_m4_define( &m4defs_buf, "M4_YY_NO_ANSI_FUNC_PROTOS", NULL); if (extra_type) buf_m4_define( &m4defs_buf, "M4_EXTRA_TYPE_DEFS", extra_type); if (!use_stdout) { FILE *prev_stdout; if (!did_outfilename) { char *suffix; if (C_plus_plus) suffix = "cc"; else suffix = "c"; snprintf (outfile_path, sizeof(outfile_path), outfile_template, prefix, suffix); outfilename = outfile_path; } prev_stdout = freopen (outfilename, "w+", stdout); if (prev_stdout == NULL) lerrsf (_("could not create %s"), outfilename); outfile_created = 1; } /* Setup the filter chain. */ output_chain = filter_create_int(NULL, filter_tee_header, headerfilename); if ( !(m4 = getenv("M4"))) m4 = M4; filter_create_ext(output_chain, m4, "-gP", 0); filter_create_int(output_chain, filter_fix_linedirs, NULL); /* For debugging, only run the requested number of filters. */ if (preproc_level > 0) { filter_truncate(output_chain, preproc_level); filter_apply_chain(output_chain); } yyout = stdout; /* always generate the tablesverify flag. */ buf_m4_define (&m4defs_buf, "M4_YY_TABLES_VERIFY", tablesverify ? "1" : "0"); if (tablesext) gentables = false; if (tablesverify) /* force generation of C tables. */ gentables = true; if (tablesext) { FILE *tablesout; struct yytbl_hdr hdr; char *pname = 0; int nbytes = 0; buf_m4_define (&m4defs_buf, "M4_YY_TABLES_EXTERNAL", NULL); if (!tablesfilename) { nbytes = strlen (prefix) + strlen (tablesfile_template) + 2; tablesfilename = pname = (char *) calloc (nbytes, 1); snprintf (pname, nbytes, tablesfile_template, prefix); } if ((tablesout = fopen (tablesfilename, "w")) == NULL) lerrsf (_("could not create %s"), tablesfilename); if (pname) free (pname); tablesfilename = 0; yytbl_writer_init (&tableswr, tablesout); nbytes = strlen (prefix) + strlen ("tables") + 2; tablesname = (char *) calloc (nbytes, 1); snprintf (tablesname, nbytes, "%stables", prefix); yytbl_hdr_init (&hdr, flex_version, tablesname); if (yytbl_hdr_fwrite (&tableswr, &hdr) <= 0) flexerror (_("could not write tables header")); } if (skelname && (skelfile = fopen (skelname, "r")) == NULL) lerrsf (_("can't open skeleton file %s"), skelname); if (reentrant) { buf_m4_define (&m4defs_buf, "M4_YY_REENTRANT", NULL); if (yytext_is_array) buf_m4_define (&m4defs_buf, "M4_YY_TEXT_IS_ARRAY", NULL); } if ( bison_bridge_lval) buf_m4_define (&m4defs_buf, "M4_YY_BISON_LVAL", NULL); if ( bison_bridge_lloc) buf_m4_define (&m4defs_buf, "", NULL); buf_m4_define(&m4defs_buf, "M4_YY_PREFIX", prefix); if (did_outfilename) line_directive_out (stdout, 0); if (do_yylineno) buf_m4_define (&m4defs_buf, "M4_YY_USE_LINENO", NULL); /* Create the alignment type. */ buf_strdefine (&userdef_buf, "YY_INT_ALIGNED", long_align ? "long int" : "short int"); /* Define the start condition macros. */ { struct Buf tmpbuf; buf_init(&tmpbuf, sizeof(char)); for (i = 1; i <= lastsc; i++) { char *str, *fmt = "#define %s %d\n"; size_t strsz; str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(scname[i]) + NUMCHARLINES + 2); if (!str) flexfatal(_("allocation of macro definition failed")); snprintf(str, strsz, fmt, scname[i], i - 1); buf_strappend(&tmpbuf, str); free(str); } buf_m4_define(&m4defs_buf, "M4_YY_SC_DEFS", tmpbuf.elts); buf_destroy(&tmpbuf); } /* This is where we begin writing to the file. */ /* Dump the %top code. */ if( top_buf.elts) outn((char*) top_buf.elts); /* Dump the m4 definitions. */ buf_print_strings(&m4defs_buf, stdout); m4defs_buf.nelts = 0; /* memory leak here. */ /* Place a bogus line directive, it will be fixed in the filter. */ outn("#line 0 \"M4_YY_OUTFILE_NAME\"\n"); /* Dump the user defined preproc directives. */ if (userdef_buf.elts) outn ((char *) (userdef_buf.elts)); skelout (); /* %% [1.0] */ } /* flexend - terminate flex * * note * This routine does not return. */ void flexend (exit_status) int exit_status; { static int called_before = -1; /* prevent infinite recursion. */ int tblsiz; if (++called_before) FLEX_EXIT (exit_status); if (skelfile != NULL) { if (ferror (skelfile)) lerrsf (_("input error reading skeleton file %s"), skelname); else if (fclose (skelfile)) lerrsf (_("error closing skeleton file %s"), skelname); } #if 0 fprintf (header_out, "#ifdef YY_HEADER_EXPORT_START_CONDITIONS\n"); fprintf (header_out, "/* Beware! Start conditions are not prefixed. */\n"); /* Special case for "INITIAL" */ fprintf (header_out, "#undef INITIAL\n#define INITIAL 0\n"); for (i = 2; i <= lastsc; i++) fprintf (header_out, "#define %s %d\n", scname[i], i - 1); fprintf (header_out, "#endif /* YY_HEADER_EXPORT_START_CONDITIONS */\n\n"); /* Kill ALL flex-related macros. This is so the user * can #include more than one generated header file. */ fprintf (header_out, "#ifndef YY_HEADER_NO_UNDEFS\n"); fprintf (header_out, "/* Undefine all internal macros, etc., that do no belong in the header. */\n\n"); { const char * undef_list[] = { "BEGIN", "ECHO", "EOB_ACT_CONTINUE_SCAN", "EOB_ACT_END_OF_FILE", "EOB_ACT_LAST_MATCH", "FLEX_SCANNER", "FLEX_STD", "REJECT", "YYFARGS0", "YYFARGS1", "YYFARGS2", "YYFARGS3", "YYLMAX", "YYSTATE", "YY_AT_BOL", "YY_BREAK", "YY_BUFFER_EOF_PENDING", "YY_BUFFER_NEW", "YY_BUFFER_NORMAL", "YY_BUF_SIZE", "M4_YY_CALL_LAST_ARG", "M4_YY_CALL_ONLY_ARG", "YY_CURRENT_BUFFER", "YY_DECL", "M4_YY_DECL_LAST_ARG", "M4_YY_DEF_LAST_ARG", "M4_YY_DEF_ONLY_ARG", "YY_DO_BEFORE_ACTION", "YY_END_OF_BUFFER", "YY_END_OF_BUFFER_CHAR", "YY_EXIT_FAILURE", "YY_EXTRA_TYPE", "YY_FATAL_ERROR", "YY_FLEX_DEFINED_ECHO", "YY_FLEX_LEX_COMPAT", "YY_FLEX_MAJOR_VERSION", "YY_FLEX_MINOR_VERSION", "YY_FLEX_SUBMINOR_VERSION", "YY_FLUSH_BUFFER", "YY_G", "YY_INPUT", "YY_INTERACTIVE", "YY_INT_ALIGNED", "YY_LAST_ARG", "YY_LESS_LINENO", "YY_LEX_ARGS", "YY_LEX_DECLARATION", "YY_LEX_PROTO", "YY_MAIN", "YY_MORE_ADJ", "YY_NEED_STRLEN", "YY_NEW_FILE", "YY_NULL", "YY_NUM_RULES", "YY_ONLY_ARG", "YY_PARAMS", "YY_PROTO", "M4_YY_PROTO_LAST_ARG", "M4_YY_PROTO_ONLY_ARG void", "YY_READ_BUF_SIZE", "YY_REENTRANT", "YY_RESTORE_YY_MORE_OFFSET", "YY_RULE_SETUP", "YY_SC_TO_UI", "YY_SKIP_YYWRAP", "YY_START", "YY_START_STACK_INCR", "YY_STATE_EOF", "YY_STDINIT", "YY_TRAILING_HEAD_MASK", "YY_TRAILING_MASK", "YY_USER_ACTION", "YY_USE_CONST", "YY_USE_PROTOS", "unput", "yyTABLES_NAME", "yy_create_buffer", "yy_delete_buffer", "yy_flex_debug", "yy_flush_buffer", "yy_init_buffer", "yy_load_buffer_state", "yy_new_buffer", "yy_scan_buffer", "yy_scan_bytes", "yy_scan_string", "yy_set_bol", "yy_set_interactive", "yy_switch_to_buffer", "yypush_buffer_state", "yypop_buffer_state", "yyensure_buffer_stack", "yyalloc", "yyconst", "yyextra", "yyfree", "yyget_debug", "yyget_extra", "yyget_in", "yyget_leng", "yyget_lineno", "yyget_lloc", "yyget_lval", "yyget_out", "yyget_text", "yyin", "yyleng", "yyless", "yylex", "yylex_destroy", "yylex_init", "yylex_init_extra", "yylineno", "yylloc", "yylval", "yymore", "yyout", "yyrealloc", "yyrestart", "yyset_debug", "yyset_extra", "yyset_in", "yyset_lineno", "yyset_lloc", "yyset_lval", "yyset_out", "yytables_destroy", "yytables_fload", "yyterminate", "yytext", "yytext_ptr", "yywrap", /* must be null-terminated */ NULL}; for (i=0; undef_list[i] != NULL; i++) fprintf (header_out, "#undef %s\n", undef_list[i]); } /* undef any of the auto-generated symbols. */ for (i = 0; i < defs_buf.nelts; i++) { /* don't undef start conditions */ if (sclookup (((char **) defs_buf.elts)[i]) > 0) continue; fprintf (header_out, "#undef %s\n", ((char **) defs_buf.elts)[i]); } fprintf (header_out, "#endif /* !YY_HEADER_NO_UNDEFS */\n"); fprintf (header_out, "\n"); fprintf (header_out, "#undef %sIN_HEADER\n", prefix); fprintf (header_out, "#endif /* %sHEADER_H */\n", prefix); if (ferror (header_out)) lerrsf (_("error creating header file %s"), headerfilename); fflush (header_out); fclose (header_out); #endif if (exit_status != 0 && outfile_created) { if (ferror (stdout)) lerrsf (_("error writing output file %s"), outfilename); else if ((_stdout_closed = 1) && fclose (stdout)) lerrsf (_("error closing output file %s"), outfilename); else if (unlink (outfilename)) lerrsf (_("error deleting output file %s"), outfilename); } if (backing_up_report && backing_up_file) { if (num_backing_up == 0) fprintf (backing_up_file, _("No backing up.\n")); else if (fullspd || fulltbl) fprintf (backing_up_file, _ ("%d backing up (non-accepting) states.\n"), num_backing_up); else fprintf (backing_up_file, _("Compressed tables always back up.\n")); if (ferror (backing_up_file)) lerrsf (_("error writing backup file %s"), backing_name); else if (fclose (backing_up_file)) lerrsf (_("error closing backup file %s"), backing_name); } if (printstats) { fprintf (stderr, _("%s version %s usage statistics:\n"), program_name, flex_version); fprintf (stderr, _(" scanner options: -")); if (C_plus_plus) putc ('+', stderr); if (backing_up_report) putc ('b', stderr); if (ddebug) putc ('d', stderr); if (sf_case_ins()) putc ('i', stderr); if (lex_compat) putc ('l', stderr); if (posix_compat) putc ('X', stderr); if (performance_report > 0) putc ('p', stderr); if (performance_report > 1) putc ('p', stderr); if (spprdflt) putc ('s', stderr); if (reentrant) fputs ("--reentrant", stderr); if (bison_bridge_lval) fputs ("--bison-bridge", stderr); if (bison_bridge_lloc) fputs ("--bison-locations", stderr); if (use_stdout) putc ('t', stderr); if (printstats) putc ('v', stderr); /* always true! */ if (nowarn) putc ('w', stderr); if (interactive == false) putc ('B', stderr); if (interactive == true) putc ('I', stderr); if (!gen_line_dirs) putc ('L', stderr); if (trace) putc ('T', stderr); if (csize == unspecified) /* We encountered an error fairly early on, so csize * never got specified. Define it now, to prevent * bogus table sizes being written out below. */ csize = 256; if (csize == 128) putc ('7', stderr); else putc ('8', stderr); fprintf (stderr, " -C"); if (long_align) putc ('a', stderr); if (fulltbl) putc ('f', stderr); if (fullspd) putc ('F', stderr); if (useecs) putc ('e', stderr); if (usemecs) putc ('m', stderr); if (use_read) putc ('r', stderr); if (did_outfilename) fprintf (stderr, " -o%s", outfilename); if (skelname) fprintf (stderr, " -S%s", skelname); if (strcmp (prefix, "yy")) fprintf (stderr, " -P%s", prefix); putc ('\n', stderr); fprintf (stderr, _(" %d/%d NFA states\n"), lastnfa, current_mns); fprintf (stderr, _(" %d/%d DFA states (%d words)\n"), lastdfa, current_max_dfas, totnst); fprintf (stderr, _(" %d rules\n"), num_rules + num_eof_rules - 1 /* - 1 for def. rule */ ); if (num_backing_up == 0) fprintf (stderr, _(" No backing up\n")); else if (fullspd || fulltbl) fprintf (stderr, _ (" %d backing-up (non-accepting) states\n"), num_backing_up); else fprintf (stderr, _ (" Compressed tables always back-up\n")); if (bol_needed) fprintf (stderr, _(" Beginning-of-line patterns used\n")); fprintf (stderr, _(" %d/%d start conditions\n"), lastsc, current_max_scs); fprintf (stderr, _ (" %d epsilon states, %d double epsilon states\n"), numeps, eps2); if (lastccl == 0) fprintf (stderr, _(" no character classes\n")); else fprintf (stderr, _ (" %d/%d character classes needed %d/%d words of storage, %d reused\n"), lastccl, current_maxccls, cclmap[lastccl] + ccllen[lastccl], current_max_ccl_tbl_size, cclreuse); fprintf (stderr, _(" %d state/nextstate pairs created\n"), numsnpairs); fprintf (stderr, _(" %d/%d unique/duplicate transitions\n"), numuniq, numdup); if (fulltbl) { tblsiz = lastdfa * numecs; fprintf (stderr, _(" %d table entries\n"), tblsiz); } else { tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend; fprintf (stderr, _(" %d/%d base-def entries created\n"), lastdfa + numtemps, current_max_dfas); fprintf (stderr, _ (" %d/%d (peak %d) nxt-chk entries created\n"), tblend, current_max_xpairs, peakpairs); fprintf (stderr, _ (" %d/%d (peak %d) template nxt-chk entries created\n"), numtemps * nummecs, current_max_template_xpairs, numtemps * numecs); fprintf (stderr, _(" %d empty table entries\n"), nummt); fprintf (stderr, _(" %d protos created\n"), numprots); fprintf (stderr, _(" %d templates created, %d uses\n"), numtemps, tmpuses); } if (useecs) { tblsiz = tblsiz + csize; fprintf (stderr, _ (" %d/%d equivalence classes created\n"), numecs, csize); } if (usemecs) { tblsiz = tblsiz + numecs; fprintf (stderr, _ (" %d/%d meta-equivalence classes created\n"), nummecs, csize); } fprintf (stderr, _ (" %d (%d saved) hash collisions, %d DFAs equal\n"), hshcol, hshsave, dfaeql); fprintf (stderr, _(" %d sets of reallocations needed\n"), num_reallocs); fprintf (stderr, _(" %d total table entries needed\n"), tblsiz); } FLEX_EXIT (exit_status); } /* flexinit - initialize flex */ void flexinit (argc, argv) int argc; char **argv; { int i, sawcmpflag, rv, optind; char *arg; scanopt_t sopt; printstats = syntaxerror = trace = spprdflt = false; lex_compat = posix_compat = C_plus_plus = backing_up_report = ddebug = fulltbl = false; fullspd = long_align = nowarn = yymore_used = continued_action = false; do_yylineno = yytext_is_array = in_rule = reject = do_stdinit = false; yymore_really_used = reject_really_used = unspecified; interactive = csize = unspecified; do_yywrap = gen_line_dirs = usemecs = useecs = true; reentrant = bison_bridge_lval = bison_bridge_lloc = false; performance_report = 0; did_outfilename = 0; prefix = "yy"; yyclass = 0; use_read = use_stdout = false; tablesext = tablesverify = false; gentables = true; tablesfilename = tablesname = NULL; ansi_func_defs = ansi_func_protos = true; sawcmpflag = false; /* Initialize dynamic array for holding the rule actions. */ action_size = 2048; /* default size of action array in bytes */ action_array = allocate_character_array (action_size); defs1_offset = prolog_offset = action_offset = action_index = 0; action_array[0] = '\0'; /* Initialize any buffers. */ buf_init (&userdef_buf, sizeof (char)); /* one long string */ buf_init (&defs_buf, sizeof (char *)); /* list of strings */ buf_init (&yydmap_buf, sizeof (char)); /* one long string */ buf_init (&top_buf, sizeof (char)); /* one long string */ { const char * m4defs_init_str[] = {"m4_changequote\n", "m4_changequote([[, ]])\n"}; buf_init (&m4defs_buf, sizeof (char *)); buf_append (&m4defs_buf, &m4defs_init_str, 2); } sf_init (); /* initialize regex lib */ flex_init_regex(); /* Enable C++ if program name ends with '+'. */ program_name = basename2 (argv[0], 0); if (program_name[0] != '\0' && program_name[strlen (program_name) - 1] == '+') C_plus_plus = true; /* read flags */ sopt = scanopt_init (flexopts, argc, argv, 0); if (!sopt) { /* This will only happen when flexopts array is altered. */ fprintf (stderr, _("Internal error. flexopts are malformed.\n")); FLEX_EXIT (1); } while ((rv = scanopt (sopt, &arg, &optind)) != 0) { if (rv < 0) { /* Scanopt has already printed an option-specific error message. */ fprintf (stderr, _ ("Try `%s --help' for more information.\n"), program_name); FLEX_EXIT (1); } switch ((enum flexopt_flag_t) rv) { case OPT_CPLUSPLUS: C_plus_plus = true; break; case OPT_BATCH: interactive = false; break; case OPT_BACKUP: backing_up_report = true; break; case OPT_DONOTHING: break; case OPT_COMPRESSION: if (!sawcmpflag) { useecs = false; usemecs = false; fulltbl = false; sawcmpflag = true; } for (i = 0; arg && arg[i] != '\0'; i++) switch (arg[i]) { case 'a': long_align = true; break; case 'e': useecs = true; break; case 'F': fullspd = true; break; case 'f': fulltbl = true; break; case 'm': usemecs = true; break; case 'r': use_read = true; break; default: lerrif (_ ("unknown -C option '%c'"), (int) arg[i]); break; } break; case OPT_DEBUG: ddebug = true; break; case OPT_NO_DEBUG: ddebug = false; break; case OPT_FULL: useecs = usemecs = false; use_read = fulltbl = true; break; case OPT_FAST: useecs = usemecs = false; use_read = fullspd = true; break; case OPT_HELP: usage (); FLEX_EXIT (0); case OPT_INTERACTIVE: interactive = true; break; case OPT_CASE_INSENSITIVE: sf_set_case_ins(true); break; case OPT_LEX_COMPAT: lex_compat = true; break; case OPT_POSIX_COMPAT: posix_compat = true; break; case OPT_PREPROC_LEVEL: preproc_level = strtol(arg,NULL,0); break; case OPT_MAIN: buf_strdefine (&userdef_buf, "YY_MAIN", "1"); do_yywrap = false; break; case OPT_NO_MAIN: buf_strdefine (&userdef_buf, "YY_MAIN", "0"); break; case OPT_NO_LINE: gen_line_dirs = false; break; case OPT_OUTFILE: outfilename = arg; did_outfilename = 1; break; case OPT_PREFIX: prefix = arg; break; case OPT_PERF_REPORT: ++performance_report; break; case OPT_BISON_BRIDGE: bison_bridge_lval = true; break; case OPT_BISON_BRIDGE_LOCATIONS: bison_bridge_lval = bison_bridge_lloc = true; break; case OPT_REENTRANT: reentrant = true; break; case OPT_NO_REENTRANT: reentrant = false; break; case OPT_SKEL: skelname = arg; break; case OPT_DEFAULT: spprdflt = false; break; case OPT_NO_DEFAULT: spprdflt = true; break; case OPT_STDOUT: use_stdout = true; break; case OPT_NO_UNISTD_H: //buf_strdefine (&userdef_buf, "YY_NO_UNISTD_H", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_UNISTD_H",0); break; case OPT_TABLES_FILE: tablesext = true; tablesfilename = arg; break; case OPT_TABLES_VERIFY: tablesverify = true; break; case OPT_TRACE: trace = true; break; case OPT_VERBOSE: printstats = true; break; case OPT_VERSION: printf (_("%s %s\n"), program_name, flex_version); FLEX_EXIT (0); case OPT_WARN: nowarn = false; break; case OPT_NO_WARN: nowarn = true; break; case OPT_7BIT: csize = 128; break; case OPT_8BIT: csize = CSIZE; break; case OPT_ALIGN: long_align = true; break; case OPT_NO_ALIGN: long_align = false; break; case OPT_ALWAYS_INTERACTIVE: buf_m4_define (&m4defs_buf, "M4_YY_ALWAYS_INTERACTIVE", 0); break; case OPT_NEVER_INTERACTIVE: buf_m4_define( &m4defs_buf, "M4_YY_NEVER_INTERACTIVE", 0); break; case OPT_ARRAY: yytext_is_array = true; break; case OPT_POINTER: yytext_is_array = false; break; case OPT_ECS: useecs = true; break; case OPT_NO_ECS: useecs = false; break; case OPT_HEADER_FILE: headerfilename = arg; break; case OPT_META_ECS: usemecs = true; break; case OPT_NO_META_ECS: usemecs = false; break; case OPT_PREPROCDEFINE: { /* arg is "symbol" or "symbol=definition". */ char *def; for (def = arg; *def != '\0' && *def != '='; ++def) ; buf_strappend (&userdef_buf, "#define "); if (*def == '\0') { buf_strappend (&userdef_buf, arg); buf_strappend (&userdef_buf, " 1\n"); } else { buf_strnappend (&userdef_buf, arg, def - arg); buf_strappend (&userdef_buf, " "); buf_strappend (&userdef_buf, def + 1); buf_strappend (&userdef_buf, "\n"); } } break; case OPT_READ: use_read = true; break; case OPT_STACK: //buf_strdefine (&userdef_buf, "YY_STACK_USED", "1"); buf_m4_define( &m4defs_buf, "M4_YY_STACK_USED",0); break; case OPT_STDINIT: do_stdinit = true; break; case OPT_NO_STDINIT: do_stdinit = false; break; case OPT_YYCLASS: yyclass = arg; break; case OPT_YYLINENO: do_yylineno = true; break; case OPT_NO_YYLINENO: do_yylineno = false; break; case OPT_YYWRAP: do_yywrap = true; break; case OPT_NO_YYWRAP: do_yywrap = false; break; case OPT_YYMORE: yymore_really_used = true; break; case OPT_NO_YYMORE: yymore_really_used = false; break; case OPT_REJECT: reject_really_used = true; break; case OPT_NO_REJECT: reject_really_used = false; break; case OPT_NO_ANSI_FUNC_DEFS: ansi_func_defs = false; break; case OPT_NO_ANSI_FUNC_PROTOS: ansi_func_protos = false; break; case OPT_NO_YY_PUSH_STATE: //buf_strdefine (&userdef_buf, "YY_NO_PUSH_STATE", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_PUSH_STATE",0); break; case OPT_NO_YY_POP_STATE: //buf_strdefine (&userdef_buf, "YY_NO_POP_STATE", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_POP_STATE",0); break; case OPT_NO_YY_TOP_STATE: //buf_strdefine (&userdef_buf, "YY_NO_TOP_STATE", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_TOP_STATE",0); break; case OPT_NO_UNPUT: //buf_strdefine (&userdef_buf, "YY_NO_UNPUT", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_UNPUT",0); break; case OPT_NO_YY_SCAN_BUFFER: //buf_strdefine (&userdef_buf, "YY_NO_SCAN_BUFFER", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_SCAN_BUFFER",0); break; case OPT_NO_YY_SCAN_BYTES: //buf_strdefine (&userdef_buf, "YY_NO_SCAN_BYTES", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_SCAN_BYTES",0); break; case OPT_NO_YY_SCAN_STRING: //buf_strdefine (&userdef_buf, "YY_NO_SCAN_STRING", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_SCAN_STRING",0); break; case OPT_NO_YYGET_EXTRA: //buf_strdefine (&userdef_buf, "YY_NO_GET_EXTRA", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_GET_EXTRA",0); break; case OPT_NO_YYSET_EXTRA: //buf_strdefine (&userdef_buf, "YY_NO_SET_EXTRA", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_SET_EXTRA",0); break; case OPT_NO_YYGET_LENG: //buf_strdefine (&userdef_buf, "YY_NO_GET_LENG", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_GET_LENG",0); break; case OPT_NO_YYGET_TEXT: //buf_strdefine (&userdef_buf, "YY_NO_GET_TEXT", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_GET_TEXT",0); break; case OPT_NO_YYGET_LINENO: //buf_strdefine (&userdef_buf, "YY_NO_GET_LINENO", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_GET_LINENO",0); break; case OPT_NO_YYSET_LINENO: //buf_strdefine (&userdef_buf, "YY_NO_SET_LINENO", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_SET_LINENO",0); break; case OPT_NO_YYGET_IN: //buf_strdefine (&userdef_buf, "YY_NO_GET_IN", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_GET_IN",0); break; case OPT_NO_YYSET_IN: //buf_strdefine (&userdef_buf, "YY_NO_SET_IN", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_SET_IN",0); break; case OPT_NO_YYGET_OUT: //buf_strdefine (&userdef_buf, "YY_NO_GET_OUT", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_GET_OUT",0); break; case OPT_NO_YYSET_OUT: //buf_strdefine (&userdef_buf, "YY_NO_SET_OUT", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_SET_OUT",0); break; case OPT_NO_YYGET_LVAL: //buf_strdefine (&userdef_buf, "YY_NO_GET_LVAL", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_GET_LVAL",0); break; case OPT_NO_YYSET_LVAL: //buf_strdefine (&userdef_buf, "YY_NO_SET_LVAL", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_SET_LVAL",0); break; case OPT_NO_YYGET_LLOC: //buf_strdefine (&userdef_buf, "YY_NO_GET_LLOC", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_GET_LLOC",0); break; case OPT_NO_YYSET_LLOC: //buf_strdefine (&userdef_buf, "YY_NO_SET_LLOC", "1"); buf_m4_define( &m4defs_buf, "M4_YY_NO_SET_LLOC",0); break; } /* switch */ } /* while scanopt() */ scanopt_destroy (sopt); num_input_files = argc - optind; input_files = argv + optind; set_input_file (num_input_files > 0 ? input_files[0] : NULL); lastccl = lastsc = lastdfa = lastnfa = 0; num_rules = num_eof_rules = default_rule = 0; numas = numsnpairs = tmpuses = 0; numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0; numuniq = numdup = hshsave = eofseen = datapos = dataline = 0; num_backing_up = onesp = numprots = 0; variable_trailing_context_rules = bol_needed = false; linenum = sectnum = 1; firstprot = NIL; /* Used in mkprot() so that the first proto goes in slot 1 * of the proto queue. */ lastprot = 1; set_up_initial_allocations (); } /* readin - read in the rules section of the input file(s) */ void readin () { static char yy_stdinit[] = "FILE *yyin = stdin, *yyout = stdout;"; static char yy_nostdinit[] = "FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;"; line_directive_out ((FILE *) 0, 1); if (yyparse ()) { pinpoint_message (_("fatal parse error")); flexend (1); } if (syntaxerror) flexend (1); /* If the user explicitly requested posix compatibility by specifing the * posix-compat option, then we check for conflicting options. However, if * the POSIXLY_CORRECT variable is set, then we quietly make flex as * posix-compatible as possible. This is the recommended behavior * according to the GNU Coding Standards. * * Note: The posix option was added to flex to provide the posix behavior * of the repeat operator in regular expressions, e.g., `ab{3}' */ if (posix_compat) { /* TODO: This is where we try to make flex behave according to * posiz, AND check for conflicting options. How far should we go * with this? Should we disable all the neat-o flex features? */ /* Update: Estes says no, since other flex features don't violate posix. */ } if (getenv ("POSIXLY_CORRECT")) { posix_compat = true; } if (backing_up_report) { backing_up_file = fopen (backing_name, "w"); if (backing_up_file == NULL) lerrsf (_ ("could not create backing-up info file %s"), backing_name); } else backing_up_file = NULL; if (yymore_really_used == true) yymore_used = true; else if (yymore_really_used == false) yymore_used = false; if (reject_really_used == true) reject = true; else if (reject_really_used == false) reject = false; if (performance_report > 0) { if (lex_compat) { fprintf (stderr, _ ("-l AT&T lex compatibility option entails a large performance penalty\n")); fprintf (stderr, _ (" and may be the actual source of other reported performance penalties\n")); } else if (do_yylineno) { fprintf (stderr, _ ("%%option yylineno entails a performance penalty ONLY on rules that can match newline characters\n")); } if (performance_report > 1) { if (interactive) fprintf (stderr, _ ("-I (interactive) entails a minor performance penalty\n")); if (yymore_used) fprintf (stderr, _ ("yymore() entails a minor performance penalty\n")); } if (reject) fprintf (stderr, _ ("REJECT entails a large performance penalty\n")); if (variable_trailing_context_rules) fprintf (stderr, _ ("Variable trailing context rules entail a large performance penalty\n")); } if (reject) real_reject = true; if (variable_trailing_context_rules) reject = true; if ((fulltbl || fullspd) && reject) { if (real_reject) flexerror (_ ("REJECT cannot be used with -f or -F")); else if (do_yylineno) flexerror (_ ("%option yylineno cannot be used with REJECT")); else flexerror (_ ("variable trailing context rules cannot be used with -f or -F")); } if (reject){ out_m4_define( "M4_YY_USES_REJECT", NULL); //outn ("\n#define YY_USES_REJECT"); } if (!do_yywrap) { if (!C_plus_plus) { if (reentrant) outn ("\n#define yywrap(yyscanner) 1"); else outn ("\n#define yywrap() 1"); } outn ("#define YY_SKIP_YYWRAP"); } if (ddebug) outn ("\n#define FLEX_DEBUG"); OUT_BEGIN_CODE (); if (csize == 256) outn ("typedef unsigned char YY_CHAR;"); else outn ("typedef char YY_CHAR;"); OUT_END_CODE (); if (C_plus_plus) { outn ("#define yytext_ptr yytext"); if (interactive) outn ("#define YY_INTERACTIVE"); } else { OUT_BEGIN_CODE (); /* In reentrant scanner, stdinit is handled in flex.skl. */ if (do_stdinit) { if (reentrant){ outn ("#ifdef VMS"); outn ("#ifdef __VMS_POSIX"); outn ("#define YY_STDINIT"); outn ("#endif"); outn ("#else"); outn ("#define YY_STDINIT"); outn ("#endif"); } outn ("#ifdef VMS"); outn ("#ifndef __VMS_POSIX"); outn (yy_nostdinit); outn ("#else"); outn (yy_stdinit); outn ("#endif"); outn ("#else"); outn (yy_stdinit); outn ("#endif"); } else { if(!reentrant) outn (yy_nostdinit); } OUT_END_CODE (); } OUT_BEGIN_CODE (); if (fullspd) outn ("typedef yyconst struct yy_trans_info *yy_state_type;"); else if (!C_plus_plus) outn ("typedef int yy_state_type;"); OUT_END_CODE (); if (lex_compat) outn ("#define YY_FLEX_LEX_COMPAT"); if (!C_plus_plus && !reentrant) { outn ("extern int yylineno;"); OUT_BEGIN_CODE (); outn ("int yylineno = 1;"); OUT_END_CODE (); } if (C_plus_plus) { outn ("\n#include "); if (!do_yywrap) { outn("\nint yyFlexLexer::yywrap() { return 1; }"); } if (yyclass) { outn ("int yyFlexLexer::yylex()"); outn ("\t{"); outn ("\tLexerError( \"yyFlexLexer::yylex invoked but %option yyclass used\" );"); outn ("\treturn 0;"); outn ("\t}"); out_str ("\n#define YY_DECL int %s::yylex()\n", yyclass); } } else { /* Watch out: yytext_ptr is a variable when yytext is an array, * but it's a macro when yytext is a pointer. */ if (yytext_is_array) { if (!reentrant) outn ("extern char yytext[];\n"); } else { if (reentrant) { outn ("#define yytext_ptr yytext_r"); } else { outn ("extern char *yytext;"); outn ("#define yytext_ptr yytext"); } } if (yyclass) flexerror (_ ("%option yyclass only meaningful for C++ scanners")); } if (useecs) numecs = cre8ecs (nextecm, ecgroup, csize); else numecs = csize; /* Now map the equivalence class for NUL to its expected place. */ ecgroup[0] = ecgroup[csize]; NUL_ec = ABS (ecgroup[0]); if (useecs) ccl2ecl (); } /* set_up_initial_allocations - allocate memory for internal tables */ void set_up_initial_allocations () { maximum_mns = (long_align ? MAXIMUM_MNS_LONG : MAXIMUM_MNS); current_mns = INITIAL_MNS; firstst = allocate_integer_array (current_mns); lastst = allocate_integer_array (current_mns); finalst = allocate_integer_array (current_mns); transchar = allocate_integer_array (current_mns); trans1 = allocate_integer_array (current_mns); trans2 = allocate_integer_array (current_mns); accptnum = allocate_integer_array (current_mns); assoc_rule = allocate_integer_array (current_mns); state_type = allocate_integer_array (current_mns); current_max_rules = INITIAL_MAX_RULES; rule_type = allocate_integer_array (current_max_rules); rule_linenum = allocate_integer_array (current_max_rules); rule_useful = allocate_integer_array (current_max_rules); rule_has_nl = allocate_bool_array (current_max_rules); current_max_scs = INITIAL_MAX_SCS; scset = allocate_integer_array (current_max_scs); scbol = allocate_integer_array (current_max_scs); scxclu = allocate_integer_array (current_max_scs); sceof = allocate_integer_array (current_max_scs); scname = allocate_char_ptr_array (current_max_scs); current_maxccls = INITIAL_MAX_CCLS; cclmap = allocate_integer_array (current_maxccls); ccllen = allocate_integer_array (current_maxccls); cclng = allocate_integer_array (current_maxccls); ccl_has_nl = allocate_bool_array (current_maxccls); current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE; ccltbl = allocate_Character_array (current_max_ccl_tbl_size); current_max_dfa_size = INITIAL_MAX_DFA_SIZE; current_max_xpairs = INITIAL_MAX_XPAIRS; nxt = allocate_integer_array (current_max_xpairs); chk = allocate_integer_array (current_max_xpairs); current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS; tnxt = allocate_integer_array (current_max_template_xpairs); current_max_dfas = INITIAL_MAX_DFAS; base = allocate_integer_array (current_max_dfas); def = allocate_integer_array (current_max_dfas); dfasiz = allocate_integer_array (current_max_dfas); accsiz = allocate_integer_array (current_max_dfas); dhash = allocate_integer_array (current_max_dfas); dss = allocate_int_ptr_array (current_max_dfas); dfaacc = allocate_dfaacc_union (current_max_dfas); nultrans = (int *) 0; } /* extracts basename from path, optionally stripping the extension "\.*" * (same concept as /bin/sh `basename`, but different handling of extension). */ static char *basename2 (path, strip_ext) char *path; int strip_ext; /* boolean */ { char *b, *e = 0; b = path; for (b = path; *path; path++) if (*path == '/') b = path + 1; else if (*path == '.') e = path; if (strip_ext && e && e > b) *e = '\0'; return b; } void usage () { FILE *f = stdout; if (!did_outfilename) { snprintf (outfile_path, sizeof(outfile_path), outfile_template, prefix, C_plus_plus ? "cc" : "c"); outfilename = outfile_path; } fprintf (f, _("Usage: %s [OPTIONS] [FILE]...\n"), program_name); fprintf (f, _ ("Generates programs that perform pattern-matching on text.\n" "\n" "Table Compression:\n" " -Ca, --align trade off larger tables for better memory alignment\n" " -Ce, --ecs construct equivalence classes\n" " -Cf do not compress tables; use -f representation\n" " -CF do not compress tables; use -F representation\n" " -Cm, --meta-ecs construct meta-equivalence classes\n" " -Cr, --read use read() instead of stdio for scanner input\n" " -f, --full generate fast, large scanner. Same as -Cfr\n" " -F, --fast use alternate table representation. Same as -CFr\n" " -Cem default compression (same as --ecs --meta-ecs)\n" "\n" "Debugging:\n" " -d, --debug enable debug mode in scanner\n" " -b, --backup write backing-up information to %s\n" " -p, --perf-report write performance report to stderr\n" " -s, --nodefault suppress default rule to ECHO unmatched text\n" " -T, --trace %s should run in trace mode\n" " -w, --nowarn do not generate warnings\n" " -v, --verbose write summary of scanner statistics to stdout\n" "\n" "Files:\n" " -o, --outfile=FILE specify output filename\n" " -S, --skel=FILE specify skeleton file\n" " -t, --stdout write scanner on stdout instead of %s\n" " --yyclass=NAME name of C++ class\n" " --header-file=FILE create a C header file in addition to the scanner\n" " --tables-file[=FILE] write tables to FILE\n" "\n" "Scanner behavior:\n" " -7, --7bit generate 7-bit scanner\n" " -8, --8bit generate 8-bit scanner\n" " -B, --batch generate batch scanner (opposite of -I)\n" " -i, --case-insensitive ignore case in patterns\n" " -l, --lex-compat maximal compatibility with original lex\n" " -X, --posix-compat maximal compatibility with POSIX lex\n" " -I, --interactive generate interactive scanner (opposite of -B)\n" " --yylineno track line count in yylineno\n" "\n" "Generated code:\n" " -+, --c++ generate C++ scanner class\n" " -Dmacro[=defn] #define macro defn (default defn is '1')\n" " -L, --noline suppress #line directives in scanner\n" " -P, --prefix=STRING use STRING as prefix instead of \"yy\"\n" " -R, --reentrant generate a reentrant C scanner\n" " --bison-bridge scanner for bison pure parser.\n" " --bison-locations include yylloc support.\n" " --stdinit initialize yyin/yyout to stdin/stdout\n" " --noansi-definitions old-style function definitions\n" " --noansi-prototypes empty parameter list in prototypes\n" " --nounistd do not include \n" " --noFUNCTION do not generate a particular FUNCTION\n" "\n" "Miscellaneous:\n" " -c do-nothing POSIX option\n" " -n do-nothing POSIX option\n" " -?\n" " -h, --help produce this help message\n" " -V, --version report %s version\n"), backing_name, program_name, outfile_path, program_name); } freebsd-buildutils-10.0/src/contrib/flex/filter.c0000644000000000000000000002655512146744056016754 0ustar /* filter - postprocessing of flex output through filters */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #include "flexdef.h" static const char * check_4_gnu_m4 = "m4_dnl ifdef(`__gnu__', ," "`errprint(Flex requires GNU M4. Set the PATH or set the M4 environment variable to its path name.)" " m4exit(2)')\n"; /** global chain. */ struct filter *output_chain = NULL; /* Allocate and initialize an external filter. * @param chain the current chain or NULL for new chain * @param cmd the command to execute. * @param ... a NULL terminated list of (const char*) arguments to command, * not including argv[0]. * @return newest filter in chain */ struct filter *filter_create_ext (struct filter *chain, const char *cmd, ...) { struct filter *f; int max_args; const char *s; va_list ap; /* allocate and initialize new filter */ f = (struct filter *) flex_alloc (sizeof (struct filter)); if (!f) flexerror (_("flex_alloc failed (f) in filter_create_ext")); memset (f, 0, sizeof (*f)); f->filter_func = NULL; f->extra = NULL; f->next = NULL; f->argc = 0; if (chain != NULL) { /* append f to end of chain */ while (chain->next) chain = chain->next; chain->next = f; } /* allocate argv, and populate it with the argument list. */ max_args = 8; f->argv = (const char **) flex_alloc (sizeof (char *) * (max_args + 1)); if (!f->argv) flexerror (_("flex_alloc failed (f->argv) in filter_create_ext")); f->argv[f->argc++] = cmd; va_start (ap, cmd); while ((s = va_arg (ap, const char *)) != NULL) { if (f->argc >= max_args) { max_args += 8; f->argv = (const char **) flex_realloc (f->argv, sizeof (char *) * (max_args + 1)); } f->argv[f->argc++] = s; } f->argv[f->argc] = NULL; va_end (ap); return f; } /* Allocate and initialize an internal filter. * @param chain the current chain or NULL for new chain * @param filter_func The function that will perform the filtering. * filter_func should return 0 if successful, and -1 * if an error occurs -- or it can simply exit(). * @param extra optional user-defined data to pass to the filter. * @return newest filter in chain */ struct filter *filter_create_int (struct filter *chain, int (*filter_func) (struct filter *), void *extra) { struct filter *f; /* allocate and initialize new filter */ f = (struct filter *) flex_alloc (sizeof (struct filter)); if (!f) flexerror (_("flex_alloc failed in filter_create_int")); memset (f, 0, sizeof (*f)); f->next = NULL; f->argc = 0; f->argv = NULL; f->filter_func = filter_func; f->extra = extra; if (chain != NULL) { /* append f to end of chain */ while (chain->next) chain = chain->next; chain->next = f; } return f; } /** Fork and exec entire filter chain. * @param chain The head of the chain. * @return true on success. */ bool filter_apply_chain (struct filter * chain) { int pid, pipes[2]; /* Tricky recursion, since we want to begin the chain * at the END. Why? Because we need all the forked processes * to be children of the main flex process. */ if (chain) filter_apply_chain (chain->next); else return true; /* Now we are the right-most unprocessed link in the chain. */ fflush (stdout); fflush (stderr); if (pipe (pipes) == -1) flexerror (_("pipe failed")); if ((pid = fork ()) == -1) flexerror (_("fork failed")); if (pid == 0) { /* child */ /* We need stdin (the FILE* stdin) to connect to this new pipe. * There is no portable way to set stdin to a new file descriptor, * as stdin is not an lvalue on some systems (BSD). * So we dup the new pipe onto the stdin descriptor and use a no-op fseek * to sync the stream. This is a Hail Mary situation. It seems to work. */ close (pipes[1]); clearerr(stdin); if (dup2 (pipes[0], fileno (stdin)) == -1) flexfatal (_("dup2(pipes[0],0)")); close (pipes[0]); fseek (stdin, 0, SEEK_CUR); /* run as a filter, either internally or by exec */ if (chain->filter_func) { int r; if ((r = chain->filter_func (chain)) == -1) flexfatal (_("filter_func failed")); exit (0); } else { execvp (chain->argv[0], (char **const) (chain->argv)); lerrsf_fatal ( _("exec of %s failed"), chain->argv[0]); } exit (1); } /* Parent */ close (pipes[0]); if (dup2 (pipes[1], fileno (stdout)) == -1) flexfatal (_("dup2(pipes[1],1)")); close (pipes[1]); fseek (stdout, 0, SEEK_CUR); return true; } /** Truncate the chain to max_len number of filters. * @param chain the current chain. * @param max_len the maximum length of the chain. * @return the resulting length of the chain. */ int filter_truncate (struct filter *chain, int max_len) { int len = 1; if (!chain) return 0; while (chain->next && len < max_len) { chain = chain->next; ++len; } chain->next = NULL; return len; } /** Splits the chain in order to write to a header file. * Similar in spirit to the 'tee' program. * The header file name is in extra. * @return 0 (zero) on success, and -1 on failure. */ int filter_tee_header (struct filter *chain) { /* This function reads from stdin and writes to both the C file and the * header file at the same time. */ const int readsz = 512; char *buf; int to_cfd = -1; FILE *to_c = NULL, *to_h = NULL; bool write_header; write_header = (chain->extra != NULL); /* Store a copy of the stdout pipe, which is already piped to C file * through the running chain. Then create a new pipe to the H file as * stdout, and fork the rest of the chain again. */ if ((to_cfd = dup (1)) == -1) flexfatal (_("dup(1) failed")); to_c = fdopen (to_cfd, "w"); if (write_header) { if (freopen ((char *) chain->extra, "w", stdout) == NULL) flexfatal (_("freopen(headerfilename) failed")); filter_apply_chain (chain->next); to_h = stdout; } /* Now to_c is a pipe to the C branch, and to_h is a pipe to the H branch. */ if (write_header) { fputs (check_4_gnu_m4, to_h); fputs ("m4_changecom`'m4_dnl\n", to_h); fputs ("m4_changequote`'m4_dnl\n", to_h); fputs ("m4_changequote([[,]])[[]]m4_dnl\n", to_h); fputs ("m4_define([[M4_YY_NOOP]])[[]]m4_dnl\n", to_h); fputs ("m4_define( [[M4_YY_IN_HEADER]],[[]])m4_dnl\n", to_h); fprintf (to_h, "#ifndef %sHEADER_H\n", prefix); fprintf (to_h, "#define %sHEADER_H 1\n", prefix); fprintf (to_h, "#define %sIN_HEADER 1\n\n", prefix); fprintf (to_h, "m4_define( [[M4_YY_OUTFILE_NAME]],[[%s]])m4_dnl\n", headerfilename ? headerfilename : ""); } fputs (check_4_gnu_m4, to_c); fputs ("m4_changecom`'m4_dnl\n", to_c); fputs ("m4_changequote`'m4_dnl\n", to_c); fputs ("m4_changequote([[,]])[[]]m4_dnl\n", to_c); fputs ("m4_define([[M4_YY_NOOP]])[[]]m4_dnl\n", to_c); fprintf (to_c, "m4_define( [[M4_YY_OUTFILE_NAME]],[[%s]])m4_dnl\n", outfilename ? outfilename : ""); buf = (char *) flex_alloc (readsz); if (!buf) flexerror (_("flex_alloc failed in filter_tee_header")); while (fgets (buf, readsz, stdin)) { fputs (buf, to_c); if (write_header) fputs (buf, to_h); } if (write_header) { fprintf (to_h, "\n"); /* write a fake line number. It will get fixed by the linedir filter. */ fprintf (to_h, "#line 4000 \"M4_YY_OUTFILE_NAME\"\n"); fprintf (to_h, "#undef %sIN_HEADER\n", prefix); fprintf (to_h, "#endif /* %sHEADER_H */\n", prefix); fputs ("m4_undefine( [[M4_YY_IN_HEADER]])m4_dnl\n", to_h); fflush (to_h); if (ferror (to_h)) lerrsf (_("error writing output file %s"), (char *) chain->extra); else if (fclose (to_h)) lerrsf (_("error closing output file %s"), (char *) chain->extra); } fflush (to_c); if (ferror (to_c)) lerrsf (_("error writing output file %s"), outfilename ? outfilename : ""); else if (fclose (to_c)) lerrsf (_("error closing output file %s"), outfilename ? outfilename : ""); while (wait (0) > 0) ; exit (0); return 0; } /** Adjust the line numbers in the #line directives of the generated scanner. * After the m4 expansion, the line numbers are incorrect since the m4 macros * can add or remove lines. This only adjusts line numbers for generated code, * not user code. This also happens to be a good place to squeeze multiple * blank lines into a single blank line. */ int filter_fix_linedirs (struct filter *chain) { char *buf; const int readsz = 512; int lineno = 1; bool in_gen = true; /* in generated code */ bool last_was_blank = false; if (!chain) return 0; buf = (char *) flex_alloc (readsz); if (!buf) flexerror (_("flex_alloc failed in filter_fix_linedirs")); while (fgets (buf, readsz, stdin)) { regmatch_t m[10]; /* Check for #line directive. */ if (buf[0] == '#' && regexec (®ex_linedir, buf, 3, m, 0) == 0) { int num; char *fname; /* extract the line number and filename */ num = regmatch_strtol (&m[1], buf, NULL, 0); fname = regmatch_dup (&m[2], buf); if (strcmp (fname, outfilename ? outfilename : "") == 0 || strcmp (fname, headerfilename ? headerfilename : "") == 0) { char *s1, *s2; char filename[MAXLINE]; s1 = fname; s2 = filename; while ((s2 - filename) < (MAXLINE - 1) && *s1) { /* Escape the backslash */ if (*s1 == '\\') *s2++ = '\\'; /* Escape the double quote */ if (*s1 == '\"') *s2++ = '\\'; /* Copy the character as usual */ *s2++ = *s1++; } *s2 = '\0'; /* Adjust the line directives. */ in_gen = true; snprintf (buf, readsz, "#line %d \"%s\"\n", lineno + 1, filename); } else { /* it's a #line directive for code we didn't write */ in_gen = false; } free (fname); last_was_blank = false; } /* squeeze blank lines from generated code */ else if (in_gen && regexec (®ex_blank_line, buf, 0, NULL, 0) == 0) { if (last_was_blank) continue; else last_was_blank = true; } else { /* it's a line of normal, non-empty code. */ last_was_blank = false; } fputs (buf, stdout); lineno++; } fflush (stdout); if (ferror (stdout)) lerrsf (_("error writing output file %s"), outfilename ? outfilename : ""); else if (fclose (stdout)) lerrsf (_("error closing output file %s"), outfilename ? outfilename : ""); return 0; } /* vim:set expandtab cindent tabstop=4 softtabstop=4 shiftwidth=4 textwidth=0: */ freebsd-buildutils-10.0/src/contrib/flex/ccl.c0000644000000000000000000001650012146743317016214 0ustar /* ccl - routines for character classes */ /* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */ /* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */ /* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #include "flexdef.h" /* return true if the chr is in the ccl. Takes negation into account. */ static bool ccl_contains (const int cclp, const int ch) { int ind, len, i; len = ccllen[cclp]; ind = cclmap[cclp]; for (i = 0; i < len; ++i) if (ccltbl[ind + i] == ch) return !cclng[cclp]; return cclng[cclp]; } /* ccladd - add a single character to a ccl */ void ccladd (cclp, ch) int cclp; int ch; { int ind, len, newpos, i; check_char (ch); len = ccllen[cclp]; ind = cclmap[cclp]; /* check to see if the character is already in the ccl */ for (i = 0; i < len; ++i) if (ccltbl[ind + i] == ch) return; /* mark newlines */ if (ch == nlch) ccl_has_nl[cclp] = true; newpos = ind + len; if (newpos >= current_max_ccl_tbl_size) { current_max_ccl_tbl_size += MAX_CCL_TBL_SIZE_INCREMENT; ++num_reallocs; ccltbl = reallocate_Character_array (ccltbl, current_max_ccl_tbl_size); } ccllen[cclp] = len + 1; ccltbl[newpos] = ch; } /* dump_cclp - same thing as list_character_set, but for cclps. */ static void dump_cclp (FILE* file, int cclp) { int i; putc ('[', file); for (i = 0; i < csize; ++i) { if (ccl_contains(cclp, i)){ int start_char = i; putc (' ', file); fputs (readable_form (i), file); while (++i < csize && ccl_contains(cclp,i)) ; if (i - 1 > start_char) /* this was a run */ fprintf (file, "-%s", readable_form (i - 1)); putc (' ', file); } } putc (']', file); } /* ccl_set_diff - create a new ccl as the set difference of the two given ccls. */ int ccl_set_diff (int a, int b) { int d, ch; /* create new class */ d = cclinit(); /* In order to handle negation, we spin through all possible chars, * addding each char in a that is not in b. * (This could be O(n^2), but n is small and bounded.) */ for ( ch = 0; ch < csize; ++ch ) if (ccl_contains (a, ch) && !ccl_contains(b, ch)) ccladd (d, ch); /* debug */ if (0){ fprintf(stderr, "ccl_set_diff ("); fprintf(stderr, "\n "); dump_cclp (stderr, a); fprintf(stderr, "\n "); dump_cclp (stderr, b); fprintf(stderr, "\n "); dump_cclp (stderr, d); fprintf(stderr, "\n)\n"); } return d; } /* ccl_set_union - create a new ccl as the set union of the two given ccls. */ int ccl_set_union (int a, int b) { int d, i; /* create new class */ d = cclinit(); /* Add all of a */ for (i = 0; i < ccllen[a]; ++i) ccladd (d, ccltbl[cclmap[a] + i]); /* Add all of b */ for (i = 0; i < ccllen[b]; ++i) ccladd (d, ccltbl[cclmap[b] + i]); /* debug */ if (0){ fprintf(stderr, "ccl_set_union (%d + %d = %d", a, b, d); fprintf(stderr, "\n "); dump_cclp (stderr, a); fprintf(stderr, "\n "); dump_cclp (stderr, b); fprintf(stderr, "\n "); dump_cclp (stderr, d); fprintf(stderr, "\n)\n"); } return d; } /* cclinit - return an empty ccl */ int cclinit () { if (++lastccl >= current_maxccls) { current_maxccls += MAX_CCLS_INCREMENT; ++num_reallocs; cclmap = reallocate_integer_array (cclmap, current_maxccls); ccllen = reallocate_integer_array (ccllen, current_maxccls); cclng = reallocate_integer_array (cclng, current_maxccls); ccl_has_nl = reallocate_bool_array (ccl_has_nl, current_maxccls); } if (lastccl == 1) /* we're making the first ccl */ cclmap[lastccl] = 0; else /* The new pointer is just past the end of the last ccl. * Since the cclmap points to the \first/ character of a * ccl, adding the length of the ccl to the cclmap pointer * will produce a cursor to the first free space. */ cclmap[lastccl] = cclmap[lastccl - 1] + ccllen[lastccl - 1]; ccllen[lastccl] = 0; cclng[lastccl] = 0; /* ccl's start out life un-negated */ ccl_has_nl[lastccl] = false; return lastccl; } /* cclnegate - negate the given ccl */ void cclnegate (cclp) int cclp; { cclng[cclp] = 1; ccl_has_nl[cclp] = !ccl_has_nl[cclp]; } /* list_character_set - list the members of a set of characters in CCL form * * Writes to the given file a character-class representation of those * characters present in the given CCL. A character is present if it * has a non-zero value in the cset array. */ void list_character_set (file, cset) FILE *file; int cset[]; { int i; putc ('[', file); for (i = 0; i < csize; ++i) { if (cset[i]) { int start_char = i; putc (' ', file); fputs (readable_form (i), file); while (++i < csize && cset[i]) ; if (i - 1 > start_char) /* this was a run */ fprintf (file, "-%s", readable_form (i - 1)); putc (' ', file); } } putc (']', file); } /** Determines if the range [c1-c2] is unambiguous in a case-insensitive * scanner. Specifically, if a lowercase or uppercase character, x, is in the * range [c1-c2], then we require that UPPERCASE(x) and LOWERCASE(x) must also * be in the range. If not, then this range is ambiguous, and the function * returns false. For example, [@-_] spans [a-z] but not [A-Z]. Beware that * [a-z] will be labeled ambiguous because it does not include [A-Z]. * * @param c1 the lower end of the range * @param c2 the upper end of the range * @return true if [c1-c2] is not ambiguous for a caseless scanner. */ bool range_covers_case (int c1, int c2) { int i, o; for (i = c1; i <= c2; i++) { if (has_case (i)) { o = reverse_case (i); if (o < c1 || c2 < o) return false; } } return true; } /** Reverse the case of a character, if possible. * @return c if case-reversal does not apply. */ int reverse_case (int c) { return isupper (c) ? tolower (c) : (islower (c) ? toupper (c) : c); } /** Return true if c is uppercase or lowercase. */ bool has_case (int c) { return (isupper (c) || islower (c)) ? true : false; } freebsd-buildutils-10.0/src/contrib/flex/NEWS0000644000000000000000000003624612146741165016016 0ustar This is the file NEWS for the flex package. It records user -visible changes between releases of flex. See the file COPYING for copying conditions. * version 2.5.37 released 2012-08-03 ** Import flex into git. See git://flex.git.sourceforge.net/gitroot/flex/flex. ** Fix make install target to not fail when the flex++ program is already installed ** New translations from the translation project: de, fi, pl, vi * version 2.5.36 released 2012-07-20 ** various portability fixes that quiet compiler warnings on 64-bit hosts ** various manual fixes, including correcting the name of a %option and updating some simple examples to use ANSI C syntax ** various bug fixes that prevent certain error conditions from persisting when they should not persist ** improvements to the test suite so it behaves better when linking compiled files ** new translations from the translation project: ca, da, es, fi, fr, ga, ko, pt_br, ro, ru, sv, tr, zh_cn ** the flex distribution is now built with automake 1.10.1 and automake 2.61 * version 2.5.35 released 2008-02-26 ** fixed bug that prevented flex from accepting certain comments in the scanner file (resolves bugs #1849809 and #1849805) ** fix bug that prevented headers for all functions from being generated (resolves bug #1628314) ** change yy_size_t to be size_t (resolves bug #1849812) ** new de, nl, pl, pt_br, vi translations from the translation project * version 2.5.34 released 2007-12-12 ** introduce yylex_init_extra; see the manual for details ** introduce %option extra-type="your_type *" (resolves bug #1744505) ** The flex program now parses multiple short concatenated options (resolves bug #1619820). Thanks to Petr Machata of Red Hat on this issue. ** better checking after yyalloc/yyrealloc (resolves bug #1595967) ** flex now provides for a libfl_pic.a compiled with position independent code. Particularly useful when including a flex scanner in a shared library and with more recent versions of gcc. Thanks to the Debian project for the idea. ** SourceForge feature request #1658379: Expose YY_BUF_SIZE in the header file. ** flex better escapes filenames with special characters in them (resolves bug #1623600) ** a memory leak was plugged(resolves bug #1601111) ** pattern language expanded; see the manual for details on the below highlights *** pattern options added to specify patterns as case-insensitive or case-sensitive *** pattern options to specify whether the "." character should match the newline character *** pattern options added to allow ignoring of whitespace in patterns *** POSIX character classes may be negated in patterns *** patterns may now use set difference, union operators ** the manual now contains an appendix listing various common patterns which may be useful when writing scanners ** some memory leaks were removed from the C++ scanner (but the C++ scanner is still experimental and may change radically without notice) ** c++ scanners can now use yywrap ** added new unit test for c++ and yywrap ** portability fixes to some unit tests ** flex man page and flex manual in pdf now distributed in the flex distribution ** new ca, vi, ga, nl translations from the translation project ** flex no longer comes with an rpm spec file ** flex development now happens with automake 1.9.6 * version 2.5.33 released 2006-2-20 ** all flex resources are now to be found from the website at http://flex.sourceforge.net/ ** there was no release 2.5.32 published ** numerous bug and security fixes ** new nl, vi, sv, ro, po, ga, ca, fr, tr translations from the translation project ** upgrade to use gettext 0.12 (this now makes the "pdf" and "ps" targets in the build system able to be run successfully) * version 2.5.31 released 2003-4-1 ** remove --enable-maintainer-mode configure option; none of the Makefiles were using it and it can be unduely confusing * version 2.5.30 released 2003-4-1 ** yylineno is per-buffer in reentrant scanners ** added %top directive for placing code at the top of the generated scanner; see manual for details ** flex now uses m4 to generate scanners; while this means that scanners are more readable, it means that flex requires m4 to be installed; see manual for details * version 2.5.29 released 2003-3-5 ** Automatic stack management for multiple input buffers in C and C++ scanners ** moved the flex documentation to a new doc/ subdirectory ** cleanups to the yy namespace * version 2.5.28 released 2003-2-12 ** flex is now hosted at sourceforge ** Fixed trailing slash bug in YY_INPUT macro def ** Flex now warns if always-interactive is specified with fast or full * version 2.5.27 released 2003-1-21 ** flex now works with recent bison versions ** new pt_br translation from the translation project * version 2.5.26 released 2003-1-14 ** Fixed table deserialization bug on big-endian archs. Patch sent from Bryce Nichols ** yyleng has proper declarations now; this caused flex to generate unusable scanners for some programs ** the flex distribution now includes a spec file suitable for use with rpm ** some more c++ fixes ** new es translation from the translation project ** slight tweeks to the flex_int*_t types ** flex now warns about pattern ranges that might be ambiguous when generating a case-insensitive scanner * version 2.5.25 released 2002-12-2 ** flex now uses flex_int*_t types. For C99 systems, they are just the int*_t types; for non-C99 systems, we just make some typedefs ** new pt_br translation from the translation project * version 2.5.24 released 2002-11-25 * more portability fixes ** the manual continues to be updated and edited, but it's still got a ways to go ** it is possible to have multiple c++ scanners in the same program again ** new turkish translation from the translation project * version 2.5.23 released 2002-10-21 ** more portability fixes ** the manual includes a title page and a table-of-contents when printed ** the test suite can be run with "make check" from the top-level directory ** configure now accepts the --enable-maintainer-mode option ** gettext functionality is now only available externally ** the constant FLEX_BETA is defined if flex is a beta release ** the script create-test was not included in the distribution and it should have been * version 2.5.22 released 2002-10-10 ** more portability fixes around how we get ahold of the integral types; there is a constant FLEX_NEED_INTEGRAL_TYPE_DEFINITIONS which you should define if you don't have the header file (after you complain to your C vendor for not providing a reasonable C environment) ** more test suite cleanups; in particular, the test suite should run correctly when build from a different directory ** upgraded automake to 1.7 and consequently autoconf to 2.54; this means, among other things, that there is some support for formatting the manual in postscript and pdf in the distributed Makefile.in (and therefore in the Makefile built by configure) ** the flex.1 manpage is generated by help2man; (this has been true for quite a while but was not listed here) ** flex now includes three defined constants to indicate which version of flex generated a scanner (YY_FLEX_{MAJOR,MINOR,SUBMINOR}_VERSION) ** flex tries its best to output only the relevant portions of the skeleton when generating a scanner, thus avoiding as much conditional compilation as possible * version 2.5.21 released 2002-9-17 ** one of the tests in the test suite broke the dist target * version 2.5.20 released 2002-9-16 ** A flex scanner has the ability to save the DFA tables to a file, and load them at runtime when needed; see the manual for details ** Added %option bison-bridge (--bison-bridge) ** Removed %option reentrant-bison/--reentrant-bison/-Rb ** yylineno is present in all scanners; Modified nasty performance penalty warning with yylineno in documentation ** test-table-opts is now run last in the test suite because it's so fat ** flex can, to some extent, diagnose where internal problems occur ** new translations from the translation project: fr, ca, de, ru, sv **Flex generates C99 defs now; see YY_TRADITIONAL_FUNC_DEFS in the manual if that's not a good thing for you * version 2.5.19 released 2002-9-5 ** prevent segfault on input lines which are longer than the allocated space (problem report from Manoj Srivastava ) ** Changed option 'header' to 'header-file' * version 2.5.18 released 2002-9-4 ** portability fixes for integer constants and in the way the test suite reports its results ** the test for bison was reporting bison missing when it was, in fact, found ** if we don't find GNU indent, we're more careful when we're not finding it * version 2.5.17 released 2002-8-29 ** more portability fixes ** updated config.sub and config.guess ** flex is indented by GNU indent (this was done earlier but not explicitly documented) * version 2.5.16 released 2002-8-28 ** c++ scanners compile again ** there is now an indent target in the top-level Makefile; configure checks for GNU indent which is required for proper operation of the indent target ** some more portability fixes were made ** %options and invocation sections of manual merged ** a c++ test was added to the test suite ** we're trying to clean up more files in the test suite's make clean targets * version 2.5.15 released 2002-8-21 ** reject-state buffer is now dynamically allocated and REJECT buffer variables are reentrant-safe ** manual now discusses memory usage ** skeleton now processed by m4 before mkskel.sh; (this only matters if you want to change the skeleton or if you're doing flex development) ** zh_cn translation added from translation project ** a bug that caused a segfault has now been fixed ** the test suite now respects the usual CFLAGS, etc. variables ** removed some warnings which some tests trigggered with the -s option ** the flex-generated header file now tries to be smarter about conditionally including start conditions ** tables code omitted from generated scanner when not used * version 2.5.14 released 2002-8-15 ** the tests using the reentrant c scanner as c++ were reworked slightly to be sure that the c++ was enforced ** de translation now included in the distribution ** various portability fixes regarding nls support, c++ include headers, etc. * version 2.5.13 released 2002-8-15 ** the header file output with %option header is now much smaller ** Fixed type mismatch in printf in scanner skeleton ** yylex_init now reports errors * version 2.5.12 released 2002-8-8 ** updated gettext support to 0.11.5 ** new fr translation from the translation project ** bison is no longer needed to build flex; If you are building flex from a release (i.e., not from a cvs snapshot), then you don't need to have a pre-built lex around either (unless you modify scan.l, of course); (This has been true for some time, but was not mentioned here.) * version 2.5.11 released 2002-7-31 ** Fixed bug where yyless did not consider yylineno ** the yylineno performance hit is now gone ** fixed some typos in the manual and we now include texinfo.tex in the distribution ** traditional prototypes output for C scanners, controlled by a preprocessor symbol; see documentation for details * version 2.5.10 released 2002-7-24 ** yy_globals renamed to yyscanner and yy_globals_t renamed to yy_guts_t ** added dist-bzip2 option to Makefile.am so we now produce a bzip2'd archive in addition to the standard gzip archive * version 2.5.9 ** new tests in test suite: test-mem-{nr,r}, test-posix, test-posixly-correct, test-debug-{nr,r} ** made changes to work with gcc-3.2 development code ** ability to choose which memory functions are used in flex ** new yylex_destroy() function for the non-reentrant scanner ** new handling of POSIXLY_CORRECT environment variable ** the test suite now has its copyrights explicitly described ** new ca, de, fr, ru, sv, tr translations * version 2.5.8 ** a new --posix option generates scanners with posix-style abc{1,3} compatible parsing, see manual for the screwy details * version 2.5.7 ** configure.in now includes a call to AC_PREREQ to enforce the requirement for autoconf at least 2.50 (This only effects you if you're doing flex development.) ** configure now uses autoconf's versioning information and configure --help reports the bug-reporting address for flex ** test suite now only reports success versus failure; reporting skipped is problematic under the current setup ** compilation with --disable-nls now works ** flex can now be built in a separate directory * version 2.5.6 ** gettext support added (from gettext 0.11) *** translations for ca, da, de, es, fr, ko, ru, sv, tr included ** distribution now built under automake 1.6 and autoconf 2.53 ** command-line option parsing happens differently now: *** Added long option parsing *** Options -n and -c, previously deprecated, now simply do nothing *** Options are now parsed left to right ** added a number of new options *** All positive %options are now accessible from the command line *** Added option -D, to define a preprocessor symbol *** Added option --header=FILE to specify a C .h file to generate *** added option --yywrap to call yywrap on EOF *** added option --yylineno to track line count in yylineno *** --yyclass=NAME name of C++ class when generating c++ scanners *** for long option names which are associated with existing short options, see accompanying documentation *** new %option nounistd or command-line --nounistd added to prevent flex from generating #include on systems that don't have that include file ** Support for reentrant C scanners has been added *** Updated the manual with the new reentrant API *** Two new options %option reentrant (-R) and %option reentrant-bison (-Rb) *** All globals optionally placed into struct yyglobals_t *** All access to globals replaced by macro invocations *** All functions optionally take one additional argument, yy_globals *** New style for invoking reentrant scanner: yylex_init(void** scanner ); yylex( scanner ); yylex_destroy( scanner ); *** Added get/set functions for members of struct yy_globals_t e.g., yyget_text, yyget_leng, etc *** Prefix substitution added for new functions *** Macro shortcuts to the lengthy get/set functions provided for use in actions, e.g., yytext, yyleng, etc *** Arbitrary, user-defined data, "yyextra", may be added to scanner ** %option nomain no longer implies %option yywrap But the inverse is still true ** Developer test suite added *** TESTS/ directory has been added. Users can 'make test' in the TESTS directory to execute the test suite ** Support for bison variables yylval and yylloc added ** automake support for the build process ** manual is now in texinfo/info format *** flex.1 removed from distribution ** flex no longer generates C-language scanners with C++-style comments ** flex now generates scanners in c++ which are compatible with recent c++ compilers ** flex input scanner now recognizes '\r' as an EOL character See the file ONEWS for changes in earlier releases. Local Variables: mode: text mode: outline-minor end: freebsd-buildutils-10.0/src/contrib/flex/sym.c0000644000000000000000000001501312146743317016261 0ustar /* sym - symbol table routines */ /* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */ /* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */ /* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #include "flexdef.h" /* Variables for symbol tables: * sctbl - start-condition symbol table * ndtbl - name-definition symbol table * ccltab - character class text symbol table */ struct hash_entry { struct hash_entry *prev, *next; char *name; char *str_val; int int_val; }; typedef struct hash_entry **hash_table; #define NAME_TABLE_HASH_SIZE 101 #define START_COND_HASH_SIZE 101 #define CCL_HASH_SIZE 101 static struct hash_entry *ndtbl[NAME_TABLE_HASH_SIZE]; static struct hash_entry *sctbl[START_COND_HASH_SIZE]; static struct hash_entry *ccltab[CCL_HASH_SIZE]; /* declare functions that have forward references */ static int addsym PROTO ((char[], char *, int, hash_table, int)); static struct hash_entry *findsym PROTO ((const char *sym, hash_table table, int table_size)); static int hashfunct PROTO ((const char *, int)); /* addsym - add symbol and definitions to symbol table * * -1 is returned if the symbol already exists, and the change not made. */ static int addsym (sym, str_def, int_def, table, table_size) char sym[]; char *str_def; int int_def; hash_table table; int table_size; { int hash_val = hashfunct (sym, table_size); struct hash_entry *sym_entry = table[hash_val]; struct hash_entry *new_entry; struct hash_entry *successor; while (sym_entry) { if (!strcmp (sym, sym_entry->name)) { /* entry already exists */ return -1; } sym_entry = sym_entry->next; } /* create new entry */ new_entry = (struct hash_entry *) flex_alloc (sizeof (struct hash_entry)); if (new_entry == NULL) flexfatal (_("symbol table memory allocation failed")); if ((successor = table[hash_val]) != 0) { new_entry->next = successor; successor->prev = new_entry; } else new_entry->next = NULL; new_entry->prev = NULL; new_entry->name = sym; new_entry->str_val = str_def; new_entry->int_val = int_def; table[hash_val] = new_entry; return 0; } /* cclinstal - save the text of a character class */ void cclinstal (ccltxt, cclnum) Char ccltxt[]; int cclnum; { /* We don't bother checking the return status because we are not * called unless the symbol is new. */ (void) addsym ((char *) copy_unsigned_string (ccltxt), (char *) 0, cclnum, ccltab, CCL_HASH_SIZE); } /* ccllookup - lookup the number associated with character class text * * Returns 0 if there's no CCL associated with the text. */ int ccllookup (ccltxt) Char ccltxt[]; { return findsym ((char *) ccltxt, ccltab, CCL_HASH_SIZE)->int_val; } /* findsym - find symbol in symbol table */ static struct hash_entry *findsym (sym, table, table_size) const char *sym; hash_table table; int table_size; { static struct hash_entry empty_entry = { (struct hash_entry *) 0, (struct hash_entry *) 0, (char *) 0, (char *) 0, 0, }; struct hash_entry *sym_entry = table[hashfunct (sym, table_size)]; while (sym_entry) { if (!strcmp (sym, sym_entry->name)) return sym_entry; sym_entry = sym_entry->next; } return &empty_entry; } /* hashfunct - compute the hash value for "str" and hash size "hash_size" */ static int hashfunct (str, hash_size) const char *str; int hash_size; { int hashval; int locstr; hashval = 0; locstr = 0; while (str[locstr]) { hashval = (hashval << 1) + (unsigned char) str[locstr++]; hashval %= hash_size; } return hashval; } /* ndinstal - install a name definition */ void ndinstal (name, definition) const char *name; Char definition[]; { if (addsym (copy_string (name), (char *) copy_unsigned_string (definition), 0, ndtbl, NAME_TABLE_HASH_SIZE)) synerr (_("name defined twice")); } /* ndlookup - lookup a name definition * * Returns a nil pointer if the name definition does not exist. */ Char *ndlookup (nd) const char *nd; { return (Char *) findsym (nd, ndtbl, NAME_TABLE_HASH_SIZE)->str_val; } /* scextend - increase the maximum number of start conditions */ void scextend () { current_max_scs += MAX_SCS_INCREMENT; ++num_reallocs; scset = reallocate_integer_array (scset, current_max_scs); scbol = reallocate_integer_array (scbol, current_max_scs); scxclu = reallocate_integer_array (scxclu, current_max_scs); sceof = reallocate_integer_array (sceof, current_max_scs); scname = reallocate_char_ptr_array (scname, current_max_scs); } /* scinstal - make a start condition * * NOTE * The start condition is "exclusive" if xcluflg is true. */ void scinstal (str, xcluflg) const char *str; int xcluflg; { if (++lastsc >= current_max_scs) scextend (); scname[lastsc] = copy_string (str); if (addsym (scname[lastsc], (char *) 0, lastsc, sctbl, START_COND_HASH_SIZE)) format_pinpoint_message (_ ("start condition %s declared twice"), str); scset[lastsc] = mkstate (SYM_EPSILON); scbol[lastsc] = mkstate (SYM_EPSILON); scxclu[lastsc] = xcluflg; sceof[lastsc] = false; } /* sclookup - lookup the number associated with a start condition * * Returns 0 if no such start condition. */ int sclookup (str) const char *str; { return findsym (str, sctbl, START_COND_HASH_SIZE)->int_val; } freebsd-buildutils-10.0/src/contrib/flex/regex.c0000644000000000000000000001145112146741165016564 0ustar /** regex - regular expression functions related to POSIX regex lib. */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #include "flexdef.h" static const char* REGEXP_LINEDIR = "^#line ([[:digit:]]+) \"(.*)\""; static const char* REGEXP_BLANK_LINE = "^[[:space:]]*$"; regex_t regex_linedir; /**< matches line directives */ regex_t regex_blank_line; /**< matches blank lines */ /** Initialize the regular expressions. * @return true upon success. */ bool flex_init_regex(void) { flex_regcomp(®ex_linedir, REGEXP_LINEDIR, REG_EXTENDED); flex_regcomp(®ex_blank_line, REGEXP_BLANK_LINE, REG_EXTENDED); return true; } /** Compiles a regular expression or dies trying. * @param preg Same as for regcomp(). * @param regex Same as for regcomp(). * @param cflags Same as for regcomp(). */ void flex_regcomp(regex_t *preg, const char *regex, int cflags) { int err; memset (preg, 0, sizeof (regex_t)); if ((err = regcomp (preg, regex, cflags)) != 0) { const int errbuf_sz = 200; char *errbuf, *rxerr; errbuf = (char*)flex_alloc(errbuf_sz *sizeof(char)); if (!errbuf) flexfatal(_("Unable to allocate buffer to report regcomp")); rxerr = (char*)flex_alloc(errbuf_sz *sizeof(char)); if (!rxerr) flexfatal(_("Unable to allocate buffer for regerror")); regerror (err, preg, rxerr, errbuf_sz); snprintf (errbuf, errbuf_sz, "regcomp for \"%s\" failed: %s", regex, rxerr); flexfatal (errbuf); free(errbuf); free(rxerr); } } /** Extract a copy of the match, or NULL if no match. * @param m A match as returned by regexec(). * @param src The source string that was passed to regexec(). * @return The allocated string. */ char *regmatch_dup (regmatch_t * m, const char *src) { char *str; int len; if (m == NULL || m->rm_so < 0) return NULL; len = m->rm_eo - m->rm_so; str = (char *) flex_alloc ((len + 1) * sizeof (char)); if (!str) flexfatal(_("Unable to allocate a copy of the match")); strncpy (str, src + m->rm_so, len); str[len] = 0; return str; } /** Copy the match. * @param m A match as returned by regexec(). * @param dest The destination buffer. * @param src The source string that was passed to regexec(). * @return dest */ char *regmatch_cpy (regmatch_t * m, char *dest, const char *src) { if (m == NULL || m->rm_so < 0) { if (dest) dest[0] = '\0'; return dest; } snprintf (dest, regmatch_len(m), "%s", src + m->rm_so); return dest; } /** Get the length in characters of the match. * @param m A match as returned by regexec(). * @param src The source string that was passed to regexec(). * @return The length of the match. */ int regmatch_len (regmatch_t * m) { if (m == NULL || m->rm_so < 0) { return 0; } return m->rm_eo - m->rm_so; } /** Convert a regmatch_t object to an integer using the strtol() function. * @param m A match as returned by regexec(). * @param src The source string that was passed to regexec(). * @param endptr Same as the second argument to strtol(). * @param base Same as the third argument to strtol(). * @return The converted integer or error (Return value is the same as for strtol()). */ int regmatch_strtol (regmatch_t * m, const char *src, char **endptr, int base) { int n = 0; #define bufsz 20 char buf[bufsz]; char *s; if (m == NULL || m->rm_so < 0) return 0; if (regmatch_len (m) < bufsz) s = regmatch_cpy (m, buf, src); else s = regmatch_dup (m, src); n = strtol (s, endptr, base); if (s != buf) free (s); return n; } /** Check for empty or non-existent match. * @param m A match as returned by regexec(). * @return false if match length is non-zero. * Note that reg_empty returns true even if match did not occur at all. */ bool regmatch_empty (regmatch_t * m) { return (m == NULL || m->rm_so < 0 || m->rm_so == m->rm_eo); } /* vim:set expandtab cindent tabstop=4 softtabstop=4 shiftwidth=4 textwidth=0: */ freebsd-buildutils-10.0/src/contrib/flex/flexdef.h0000644000000000000000000012455712146744343017111 0ustar /* flexdef - definitions file for flex */ /* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */ /* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */ /* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #ifndef FLEXDEF_H #define FLEXDEF_H 1 #ifdef HAVE_CONFIG_H #include #endif /* AIX requires this to be the first thing in the file. */ #ifndef __GNUC__ # if HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #endif #ifdef STDC_HEADERS #include #include #include #include #include #include #endif #ifdef HAVE_ASSERT_H #include #else #define assert(Pred) #endif #ifdef HAVE_LIMITS_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_SYS_PARAMS_H #include #endif #ifdef HAVE_SYS_WAIT_H #include #endif #ifdef HAVE_STDBOOL_H #include #else #define bool int #define true 1 #define false 0 #endif #ifdef HAVE_REGEX_H #include #endif #include "flexint.h" /* We use gettext. So, when we write strings which should be translated, we mark them with _() */ #ifdef ENABLE_NLS #ifdef HAVE_LOCALE_H #include #endif /* HAVE_LOCALE_H */ #include "gettext.h" #define _(String) gettext (String) #else #define _(STRING) STRING #endif /* ENABLE_NLS */ /* Always be prepared to generate an 8-bit scanner. */ #define CSIZE 256 #define Char unsigned char /* Size of input alphabet - should be size of ASCII set. */ #ifndef DEFAULT_CSIZE #define DEFAULT_CSIZE 128 #endif #ifndef PROTO #if defined(__STDC__) #define PROTO(proto) proto #else #define PROTO(proto) () #endif #endif #ifdef VMS #ifndef __VMS_POSIX #define unlink remove #define SHORT_FILE_NAMES #endif #endif #ifdef MS_DOS #define SHORT_FILE_NAMES #endif /* Maximum line length we'll have to deal with. */ #define MAXLINE 2048 #ifndef MIN #define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif #ifndef MAX #define MAX(x,y) ((x) > (y) ? (x) : (y)) #endif #ifndef ABS #define ABS(x) ((x) < 0 ? -(x) : (x)) #endif /* ANSI C does not guarantee that isascii() is defined */ #ifndef isascii #define isascii(c) ((c) <= 0177) #endif #define unspecified -1 /* Special chk[] values marking the slots taking by end-of-buffer and action * numbers. */ #define EOB_POSITION -1 #define ACTION_POSITION -2 /* Number of data items per line for -f output. */ #define NUMDATAITEMS 10 /* Number of lines of data in -f output before inserting a blank line for * readability. */ #define NUMDATALINES 10 /* Number of characters to print a line number, i.e., 1 + log10(INT_MAX) */ #define NUMCHARLINES 10 /* transition_struct_out() definitions. */ #define TRANS_STRUCT_PRINT_LENGTH 14 /* Returns true if an nfa state has an epsilon out-transition slot * that can be used. This definition is currently not used. */ #define FREE_EPSILON(state) \ (transchar[state] == SYM_EPSILON && \ trans2[state] == NO_TRANSITION && \ finalst[state] != state) /* Returns true if an nfa state has an epsilon out-transition character * and both slots are free */ #define SUPER_FREE_EPSILON(state) \ (transchar[state] == SYM_EPSILON && \ trans1[state] == NO_TRANSITION) \ /* Maximum number of NFA states that can comprise a DFA state. It's real * big because if there's a lot of rules, the initial state will have a * huge epsilon closure. */ #define INITIAL_MAX_DFA_SIZE 750 #define MAX_DFA_SIZE_INCREMENT 750 /* A note on the following masks. They are used to mark accepting numbers * as being special. As such, they implicitly limit the number of accepting * numbers (i.e., rules) because if there are too many rules the rule numbers * will overload the mask bits. Fortunately, this limit is \large/ (0x2000 == * 8192) so unlikely to actually cause any problems. A check is made in * new_rule() to ensure that this limit is not reached. */ /* Mask to mark a trailing context accepting number. */ #define YY_TRAILING_MASK 0x2000 /* Mask to mark the accepting number of the "head" of a trailing context * rule. */ #define YY_TRAILING_HEAD_MASK 0x4000 /* Maximum number of rules, as outlined in the above note. */ #define MAX_RULE (YY_TRAILING_MASK - 1) /* NIL must be 0. If not, its special meaning when making equivalence classes * (it marks the representative of a given e.c.) will be unidentifiable. */ #define NIL 0 #define JAM -1 /* to mark a missing DFA transition */ #define NO_TRANSITION NIL #define UNIQUE -1 /* marks a symbol as an e.c. representative */ #define INFINITE_REPEAT -1 /* for x{5,} constructions */ #define INITIAL_MAX_CCLS 100 /* max number of unique character classes */ #define MAX_CCLS_INCREMENT 100 /* Size of table holding members of character classes. */ #define INITIAL_MAX_CCL_TBL_SIZE 500 #define MAX_CCL_TBL_SIZE_INCREMENT 250 #define INITIAL_MAX_RULES 100 /* default maximum number of rules */ #define MAX_RULES_INCREMENT 100 #define INITIAL_MNS 2000 /* default maximum number of nfa states */ #define MNS_INCREMENT 1000 /* amount to bump above by if it's not enough */ #define INITIAL_MAX_DFAS 1000 /* default maximum number of dfa states */ #define MAX_DFAS_INCREMENT 1000 #define JAMSTATE -32766 /* marks a reference to the state that always jams */ /* Maximum number of NFA states. */ #define MAXIMUM_MNS 31999 #define MAXIMUM_MNS_LONG 1999999999 /* Enough so that if it's subtracted from an NFA state number, the result * is guaranteed to be negative. */ #define MARKER_DIFFERENCE (maximum_mns+2) /* Maximum number of nxt/chk pairs for non-templates. */ #define INITIAL_MAX_XPAIRS 2000 #define MAX_XPAIRS_INCREMENT 2000 /* Maximum number of nxt/chk pairs needed for templates. */ #define INITIAL_MAX_TEMPLATE_XPAIRS 2500 #define MAX_TEMPLATE_XPAIRS_INCREMENT 2500 #define SYM_EPSILON (CSIZE + 1) /* to mark transitions on the symbol epsilon */ #define INITIAL_MAX_SCS 40 /* maximum number of start conditions */ #define MAX_SCS_INCREMENT 40 /* amount to bump by if it's not enough */ #define ONE_STACK_SIZE 500 /* stack of states with only one out-transition */ #define SAME_TRANS -1 /* transition is the same as "default" entry for state */ /* The following percentages are used to tune table compression: * The percentage the number of out-transitions a state must be of the * number of equivalence classes in order to be considered for table * compaction by using protos. */ #define PROTO_SIZE_PERCENTAGE 15 /* The percentage the number of homogeneous out-transitions of a state * must be of the number of total out-transitions of the state in order * that the state's transition table is first compared with a potential * template of the most common out-transition instead of with the first * proto in the proto queue. */ #define CHECK_COM_PERCENTAGE 50 /* The percentage the number of differences between a state's transition * table and the proto it was first compared with must be of the total * number of out-transitions of the state in order to keep the first * proto as a good match and not search any further. */ #define FIRST_MATCH_DIFF_PERCENTAGE 10 /* The percentage the number of differences between a state's transition * table and the most similar proto must be of the state's total number * of out-transitions to use the proto as an acceptable close match. */ #define ACCEPTABLE_DIFF_PERCENTAGE 50 /* The percentage the number of homogeneous out-transitions of a state * must be of the number of total out-transitions of the state in order * to consider making a template from the state. */ #define TEMPLATE_SAME_PERCENTAGE 60 /* The percentage the number of differences between a state's transition * table and the most similar proto must be of the state's total number * of out-transitions to create a new proto from the state. */ #define NEW_PROTO_DIFF_PERCENTAGE 20 /* The percentage the total number of out-transitions of a state must be * of the number of equivalence classes in order to consider trying to * fit the transition table into "holes" inside the nxt/chk table. */ #define INTERIOR_FIT_PERCENTAGE 15 /* Size of region set aside to cache the complete transition table of * protos on the proto queue to enable quick comparisons. */ #define PROT_SAVE_SIZE 2000 #define MSP 50 /* maximum number of saved protos (protos on the proto queue) */ /* Maximum number of out-transitions a state can have that we'll rummage * around through the interior of the internal fast table looking for a * spot for it. */ #define MAX_XTIONS_FULL_INTERIOR_FIT 4 /* Maximum number of rules which will be reported as being associated * with a DFA state. */ #define MAX_ASSOC_RULES 100 /* Number that, if used to subscript an array, has a good chance of producing * an error; should be small enough to fit into a short. */ #define BAD_SUBSCRIPT -32767 /* Absolute value of largest number that can be stored in a short, with a * bit of slop thrown in for general paranoia. */ #define MAX_SHORT 32700 /* Declarations for global variables. */ /* Variables for flags: * printstats - if true (-v), dump statistics * syntaxerror - true if a syntax error has been found * eofseen - true if we've seen an eof in the input file * ddebug - if true (-d), make a "debug" scanner * trace - if true (-T), trace processing * nowarn - if true (-w), do not generate warnings * spprdflt - if true (-s), suppress the default rule * interactive - if true (-I), generate an interactive scanner * lex_compat - if true (-l), maximize compatibility with AT&T lex * posix_compat - if true (-X), maximize compatibility with POSIX lex * do_yylineno - if true, generate code to maintain yylineno * useecs - if true (-Ce flag), use equivalence classes * fulltbl - if true (-Cf flag), don't compress the DFA state table * usemecs - if true (-Cm flag), use meta-equivalence classes * fullspd - if true (-F flag), use Jacobson method of table representation * gen_line_dirs - if true (i.e., no -L flag), generate #line directives * performance_report - if > 0 (i.e., -p flag), generate a report relating * to scanner performance; if > 1 (-p -p), report on minor performance * problems, too * backing_up_report - if true (i.e., -b flag), generate "lex.backup" file * listing backing-up states * C_plus_plus - if true (i.e., -+ flag), generate a C++ scanner class; * otherwise, a standard C scanner * reentrant - if true (-R), generate a reentrant C scanner. * bison_bridge_lval - if true (--bison-bridge), bison pure calling convention. * bison_bridge_lloc - if true (--bison-locations), bison yylloc. * long_align - if true (-Ca flag), favor long-word alignment. * use_read - if true (-f, -F, or -Cr) then use read() for scanner input; * otherwise, use fread(). * yytext_is_array - if true (i.e., %array directive), then declare * yytext as an array instead of a character pointer. Nice and inefficient. * do_yywrap - do yywrap() processing on EOF. If false, EOF treated as * "no more files". * csize - size of character set for the scanner we're generating; * 128 for 7-bit chars and 256 for 8-bit * yymore_used - if true, yymore() is used in input rules * reject - if true, generate back-up tables for REJECT macro * real_reject - if true, scanner really uses REJECT (as opposed to just * having "reject" set for variable trailing context) * continued_action - true if this rule's action is to "fall through" to * the next rule's action (i.e., the '|' action) * in_rule - true if we're inside an individual rule, false if not. * yymore_really_used - whether to treat yymore() as really used, regardless * of what we think based on references to it in the user's actions. * reject_really_used - same for REJECT */ extern int printstats, syntaxerror, eofseen, ddebug, trace, nowarn, spprdflt; extern int interactive, lex_compat, posix_compat, do_yylineno; extern int useecs, fulltbl, usemecs, fullspd; extern int gen_line_dirs, performance_report, backing_up_report; extern int reentrant, bison_bridge_lval, bison_bridge_lloc; extern bool ansi_func_defs, ansi_func_protos; extern int C_plus_plus, long_align, use_read, yytext_is_array, do_yywrap; extern int csize; extern int yymore_used, reject, real_reject, continued_action, in_rule; extern int yymore_really_used, reject_really_used; /* Variables used in the flex input routines: * datapos - characters on current output line * dataline - number of contiguous lines of data in current data * statement. Used to generate readable -f output * linenum - current input line number * skelfile - the skeleton file * skel - compiled-in skeleton array * skel_ind - index into "skel" array, if skelfile is nil * yyin - input file * backing_up_file - file to summarize backing-up states to * infilename - name of input file * outfilename - name of output file * headerfilename - name of the .h file to generate * did_outfilename - whether outfilename was explicitly set * prefix - the prefix used for externally visible names ("yy" by default) * yyclass - yyFlexLexer subclass to use for YY_DECL * do_stdinit - whether to initialize yyin/yyout to stdin/stdout * use_stdout - the -t flag * input_files - array holding names of input files * num_input_files - size of input_files array * program_name - name with which program was invoked * * action_array - array to hold the rule actions * action_size - size of action_array * defs1_offset - index where the user's section 1 definitions start * in action_array * prolog_offset - index where the prolog starts in action_array * action_offset - index where the non-prolog starts in action_array * action_index - index where the next action should go, with respect * to "action_array" */ extern int datapos, dataline, linenum; extern FILE *skelfile, *yyin, *backing_up_file; extern const char *skel[]; extern int skel_ind; extern char *infilename, *outfilename, *headerfilename; extern int did_outfilename; extern char *prefix, *yyclass, *extra_type; extern int do_stdinit, use_stdout; extern char **input_files; extern int num_input_files; extern char *program_name; extern char *action_array; extern int action_size; extern int defs1_offset, prolog_offset, action_offset, action_index; /* Variables for stack of states having only one out-transition: * onestate - state number * onesym - transition symbol * onenext - target state * onedef - default base entry * onesp - stack pointer */ extern int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE]; extern int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp; /* Variables for nfa machine data: * maximum_mns - maximal number of NFA states supported by tables * current_mns - current maximum on number of NFA states * num_rules - number of the last accepting state; also is number of * rules created so far * num_eof_rules - number of <> rules * default_rule - number of the default rule * current_max_rules - current maximum number of rules * lastnfa - last nfa state number created * firstst - physically the first state of a fragment * lastst - last physical state of fragment * finalst - last logical state of fragment * transchar - transition character * trans1 - transition state * trans2 - 2nd transition state for epsilons * accptnum - accepting number * assoc_rule - rule associated with this NFA state (or 0 if none) * state_type - a STATE_xxx type identifying whether the state is part * of a normal rule, the leading state in a trailing context * rule (i.e., the state which marks the transition from * recognizing the text-to-be-matched to the beginning of * the trailing context), or a subsequent state in a trailing * context rule * rule_type - a RULE_xxx type identifying whether this a ho-hum * normal rule or one which has variable head & trailing * context * rule_linenum - line number associated with rule * rule_useful - true if we've determined that the rule can be matched * rule_has_nl - true if rule could possibly match a newline * ccl_has_nl - true if current ccl could match a newline * nlch - default eol char */ extern int maximum_mns, current_mns, current_max_rules; extern int num_rules, num_eof_rules, default_rule, lastnfa; extern int *firstst, *lastst, *finalst, *transchar, *trans1, *trans2; extern int *accptnum, *assoc_rule, *state_type; extern int *rule_type, *rule_linenum, *rule_useful; extern bool *rule_has_nl, *ccl_has_nl; extern int nlch; /* Different types of states; values are useful as masks, as well, for * routines like check_trailing_context(). */ #define STATE_NORMAL 0x1 #define STATE_TRAILING_CONTEXT 0x2 /* Global holding current type of state we're making. */ extern int current_state_type; /* Different types of rules. */ #define RULE_NORMAL 0 #define RULE_VARIABLE 1 /* True if the input rules include a rule with both variable-length head * and trailing context, false otherwise. */ extern int variable_trailing_context_rules; /* Variables for protos: * numtemps - number of templates created * numprots - number of protos created * protprev - backlink to a more-recently used proto * protnext - forward link to a less-recently used proto * prottbl - base/def table entry for proto * protcomst - common state of proto * firstprot - number of the most recently used proto * lastprot - number of the least recently used proto * protsave contains the entire state array for protos */ extern int numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP]; extern int protcomst[MSP], firstprot, lastprot, protsave[PROT_SAVE_SIZE]; /* Variables for managing equivalence classes: * numecs - number of equivalence classes * nextecm - forward link of Equivalence Class members * ecgroup - class number or backward link of EC members * nummecs - number of meta-equivalence classes (used to compress * templates) * tecfwd - forward link of meta-equivalence classes members * tecbck - backward link of MEC's */ /* Reserve enough room in the equivalence class arrays so that we * can use the CSIZE'th element to hold equivalence class information * for the NUL character. Later we'll move this information into * the 0th element. */ extern int numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs; /* Meta-equivalence classes are indexed starting at 1, so it's possible * that they will require positions from 1 .. CSIZE, i.e., CSIZE + 1 * slots total (since the arrays are 0-based). nextecm[] and ecgroup[] * don't require the extra position since they're indexed from 1 .. CSIZE - 1. */ extern int tecfwd[CSIZE + 1], tecbck[CSIZE + 1]; /* Variables for start conditions: * lastsc - last start condition created * current_max_scs - current limit on number of start conditions * scset - set of rules active in start condition * scbol - set of rules active only at the beginning of line in a s.c. * scxclu - true if start condition is exclusive * sceof - true if start condition has EOF rule * scname - start condition name */ extern int lastsc, *scset, *scbol, *scxclu, *sceof; extern int current_max_scs; extern char **scname; /* Variables for dfa machine data: * current_max_dfa_size - current maximum number of NFA states in DFA * current_max_xpairs - current maximum number of non-template xtion pairs * current_max_template_xpairs - current maximum number of template pairs * current_max_dfas - current maximum number DFA states * lastdfa - last dfa state number created * nxt - state to enter upon reading character * chk - check value to see if "nxt" applies * tnxt - internal nxt table for templates * base - offset into "nxt" for given state * def - where to go if "chk" disallows "nxt" entry * nultrans - NUL transition for each state * NUL_ec - equivalence class of the NUL character * tblend - last "nxt/chk" table entry being used * firstfree - first empty entry in "nxt/chk" table * dss - nfa state set for each dfa * dfasiz - size of nfa state set for each dfa * dfaacc - accepting set for each dfa state (if using REJECT), or accepting * number, if not * accsiz - size of accepting set for each dfa state * dhash - dfa state hash value * numas - number of DFA accepting states created; note that this * is not necessarily the same value as num_rules, which is the analogous * value for the NFA * numsnpairs - number of state/nextstate transition pairs * jambase - position in base/def where the default jam table starts * jamstate - state number corresponding to "jam" state * end_of_buffer_state - end-of-buffer dfa state number */ extern int current_max_dfa_size, current_max_xpairs; extern int current_max_template_xpairs, current_max_dfas; extern int lastdfa, *nxt, *chk, *tnxt; extern int *base, *def, *nultrans, NUL_ec, tblend, firstfree, **dss, *dfasiz; extern union dfaacc_union { int *dfaacc_set; int dfaacc_state; } *dfaacc; extern int *accsiz, *dhash, numas; extern int numsnpairs, jambase, jamstate; extern int end_of_buffer_state; /* Variables for ccl information: * lastccl - ccl index of the last created ccl * current_maxccls - current limit on the maximum number of unique ccl's * cclmap - maps a ccl index to its set pointer * ccllen - gives the length of a ccl * cclng - true for a given ccl if the ccl is negated * cclreuse - counts how many times a ccl is re-used * current_max_ccl_tbl_size - current limit on number of characters needed * to represent the unique ccl's * ccltbl - holds the characters in each ccl - indexed by cclmap */ extern int lastccl, *cclmap, *ccllen, *cclng, cclreuse; extern int current_maxccls, current_max_ccl_tbl_size; extern Char *ccltbl; /* Variables for miscellaneous information: * nmstr - last NAME scanned by the scanner * sectnum - section number currently being parsed * nummt - number of empty nxt/chk table entries * hshcol - number of hash collisions detected by snstods * dfaeql - number of times a newly created dfa was equal to an old one * numeps - number of epsilon NFA states created * eps2 - number of epsilon states which have 2 out-transitions * num_reallocs - number of times it was necessary to realloc() a group * of arrays * tmpuses - number of DFA states that chain to templates * totnst - total number of NFA states used to make DFA states * peakpairs - peak number of transition pairs we had to store internally * numuniq - number of unique transitions * numdup - number of duplicate transitions * hshsave - number of hash collisions saved by checking number of states * num_backing_up - number of DFA states requiring backing up * bol_needed - whether scanner needs beginning-of-line recognition */ extern char nmstr[MAXLINE]; extern int sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs; extern int tmpuses, totnst, peakpairs, numuniq, numdup, hshsave; extern int num_backing_up, bol_needed; void *allocate_array PROTO ((int, size_t)); void *reallocate_array PROTO ((void *, int, size_t)); void *flex_alloc PROTO ((size_t)); void *flex_realloc PROTO ((void *, size_t)); void flex_free PROTO ((void *)); #define allocate_integer_array(size) \ (int *) allocate_array( size, sizeof( int ) ) #define reallocate_integer_array(array,size) \ (int *) reallocate_array( (void *) array, size, sizeof( int ) ) #define allocate_bool_array(size) \ (bool *) allocate_array( size, sizeof( bool ) ) #define reallocate_bool_array(array,size) \ (bool *) reallocate_array( (void *) array, size, sizeof( bool ) ) #define allocate_int_ptr_array(size) \ (int **) allocate_array( size, sizeof( int * ) ) #define allocate_char_ptr_array(size) \ (char **) allocate_array( size, sizeof( char * ) ) #define allocate_dfaacc_union(size) \ (union dfaacc_union *) \ allocate_array( size, sizeof( union dfaacc_union ) ) #define reallocate_int_ptr_array(array,size) \ (int **) reallocate_array( (void *) array, size, sizeof( int * ) ) #define reallocate_char_ptr_array(array,size) \ (char **) reallocate_array( (void *) array, size, sizeof( char * ) ) #define reallocate_dfaacc_union(array, size) \ (union dfaacc_union *) \ reallocate_array( (void *) array, size, sizeof( union dfaacc_union ) ) #define allocate_character_array(size) \ (char *) allocate_array( size, sizeof( char ) ) #define reallocate_character_array(array,size) \ (char *) reallocate_array( (void *) array, size, sizeof( char ) ) #define allocate_Character_array(size) \ (Char *) allocate_array( size, sizeof( Char ) ) #define reallocate_Character_array(array,size) \ (Char *) reallocate_array( (void *) array, size, sizeof( Char ) ) /* Used to communicate between scanner and parser. The type should really * be YYSTYPE, but we can't easily get our hands on it. */ extern int yylval; /* External functions that are cross-referenced among the flex source files. */ /* from file ccl.c */ extern void ccladd PROTO ((int, int)); /* add a single character to a ccl */ extern int cclinit PROTO ((void)); /* make an empty ccl */ extern void cclnegate PROTO ((int)); /* negate a ccl */ extern int ccl_set_diff (int a, int b); /* set difference of two ccls. */ extern int ccl_set_union (int a, int b); /* set union of two ccls. */ /* List the members of a set of characters in CCL form. */ extern void list_character_set PROTO ((FILE *, int[])); /* from file dfa.c */ /* Check a DFA state for backing up. */ extern void check_for_backing_up PROTO ((int, int[])); /* Check to see if NFA state set constitutes "dangerous" trailing context. */ extern void check_trailing_context PROTO ((int *, int, int *, int)); /* Construct the epsilon closure of a set of ndfa states. */ extern int *epsclosure PROTO ((int *, int *, int[], int *, int *)); /* Increase the maximum number of dfas. */ extern void increase_max_dfas PROTO ((void)); extern void ntod PROTO ((void)); /* convert a ndfa to a dfa */ /* Converts a set of ndfa states into a dfa state. */ extern int snstods PROTO ((int[], int, int[], int, int, int *)); /* from file ecs.c */ /* Convert character classes to set of equivalence classes. */ extern void ccl2ecl PROTO ((void)); /* Associate equivalence class numbers with class members. */ extern int cre8ecs PROTO ((int[], int[], int)); /* Update equivalence classes based on character class transitions. */ extern void mkeccl PROTO ((Char[], int, int[], int[], int, int)); /* Create equivalence class for single character. */ extern void mkechar PROTO ((int, int[], int[])); /* from file gen.c */ extern void do_indent PROTO ((void)); /* indent to the current level */ /* Generate the code to keep backing-up information. */ extern void gen_backing_up PROTO ((void)); /* Generate the code to perform the backing up. */ extern void gen_bu_action PROTO ((void)); /* Generate full speed compressed transition table. */ extern void genctbl PROTO ((void)); /* Generate the code to find the action number. */ extern void gen_find_action PROTO ((void)); extern void genftbl PROTO ((void)); /* generate full transition table */ /* Generate the code to find the next compressed-table state. */ extern void gen_next_compressed_state PROTO ((char *)); /* Generate the code to find the next match. */ extern void gen_next_match PROTO ((void)); /* Generate the code to find the next state. */ extern void gen_next_state PROTO ((int)); /* Generate the code to make a NUL transition. */ extern void gen_NUL_trans PROTO ((void)); /* Generate the code to find the start state. */ extern void gen_start_state PROTO ((void)); /* Generate data statements for the transition tables. */ extern void gentabs PROTO ((void)); /* Write out a formatted string at the current indentation level. */ extern void indent_put2s PROTO ((const char *, const char *)); /* Write out a string + newline at the current indentation level. */ extern void indent_puts PROTO ((const char *)); extern void make_tables PROTO ((void)); /* generate transition tables */ /* from file main.c */ extern void check_options PROTO ((void)); extern void flexend PROTO ((int)); extern void usage PROTO ((void)); /* from file misc.c */ /* Add a #define to the action file. */ extern void action_define PROTO ((const char *defname, int value)); /* Add the given text to the stored actions. */ extern void add_action PROTO ((const char *new_text)); /* True if a string is all lower case. */ extern int all_lower PROTO ((char *)); /* True if a string is all upper case. */ extern int all_upper PROTO ((char *)); /* Compare two integers for use by qsort. */ extern int intcmp PROTO ((const void *, const void *)); /* Check a character to make sure it's in the expected range. */ extern void check_char PROTO ((int c)); /* Replace upper-case letter to lower-case. */ extern Char clower PROTO ((int)); /* Returns a dynamically allocated copy of a string. */ extern char *copy_string PROTO ((const char *)); /* Returns a dynamically allocated copy of a (potentially) unsigned string. */ extern Char *copy_unsigned_string PROTO ((Char *)); /* Compare two characters for use by qsort with '\0' sorting last. */ extern int cclcmp PROTO ((const void *, const void *)); /* Finish up a block of data declarations. */ extern void dataend PROTO ((void)); /* Flush generated data statements. */ extern void dataflush PROTO ((void)); /* Report an error message and terminate. */ extern void flexerror PROTO ((const char *)); /* Report a fatal error message and terminate. */ extern void flexfatal PROTO ((const char *)); /* Report a fatal error with a pinpoint, and terminate */ #if HAVE_DECL___FUNC__ #define flex_die(msg) \ do{ \ fprintf (stderr,\ _("%s: fatal internal error at %s:%d (%s): %s\n"),\ program_name, __FILE__, (int)__LINE__,\ __func__,msg);\ FLEX_EXIT(1);\ }while(0) #else /* ! HAVE_DECL___FUNC__ */ #define flex_die(msg) \ do{ \ fprintf (stderr,\ _("%s: fatal internal error at %s:%d %s\n"),\ program_name, __FILE__, (int)__LINE__,\ msg);\ FLEX_EXIT(1);\ }while(0) #endif /* ! HAVE_DECL___func__ */ /* Convert a hexadecimal digit string to an integer value. */ extern int htoi PROTO ((Char[])); /* Report an error message formatted with one integer argument. */ extern void lerrif PROTO ((const char *, int)); /* Report an error message formatted with one string argument. */ extern void lerrsf PROTO ((const char *, const char *)); /* Like lerrsf, but also exit after displaying message. */ extern void lerrsf_fatal PROTO ((const char *, const char *)); /* Spit out a "#line" statement. */ extern void line_directive_out PROTO ((FILE *, int)); /* Mark the current position in the action array as the end of the section 1 * user defs. */ extern void mark_defs1 PROTO ((void)); /* Mark the current position in the action array as the end of the prolog. */ extern void mark_prolog PROTO ((void)); /* Generate a data statement for a two-dimensional array. */ extern void mk2data PROTO ((int)); extern void mkdata PROTO ((int)); /* generate a data statement */ /* Return the integer represented by a string of digits. */ extern int myctoi PROTO ((const char *)); /* Return character corresponding to escape sequence. */ extern Char myesc PROTO ((Char[])); /* Convert an octal digit string to an integer value. */ extern int otoi PROTO ((Char[])); /* Output a (possibly-formatted) string to the generated scanner. */ extern void out PROTO ((const char *)); extern void out_dec PROTO ((const char *, int)); extern void out_dec2 PROTO ((const char *, int, int)); extern void out_hex PROTO ((const char *, unsigned int)); extern void out_str PROTO ((const char *, const char *)); extern void out_str3 PROTO ((const char *, const char *, const char *, const char *)); extern void out_str_dec PROTO ((const char *, const char *, int)); extern void outc PROTO ((int)); extern void outn PROTO ((const char *)); extern void out_m4_define (const char* def, const char* val); /* Return a printable version of the given character, which might be * 8-bit. */ extern char *readable_form PROTO ((int)); /* Write out one section of the skeleton file. */ extern void skelout PROTO ((void)); /* Output a yy_trans_info structure. */ extern void transition_struct_out PROTO ((int, int)); /* Only needed when using certain broken versions of bison to build parse.c. */ extern void *yy_flex_xmalloc PROTO ((int)); /* Set a region of memory to 0. */ extern void zero_out PROTO ((char *, size_t)); /* from file nfa.c */ /* Add an accepting state to a machine. */ extern void add_accept PROTO ((int, int)); /* Make a given number of copies of a singleton machine. */ extern int copysingl PROTO ((int, int)); /* Debugging routine to write out an nfa. */ extern void dumpnfa PROTO ((int)); /* Finish up the processing for a rule. */ extern void finish_rule PROTO ((int, int, int, int, int)); /* Connect two machines together. */ extern int link_machines PROTO ((int, int)); /* Mark each "beginning" state in a machine as being a "normal" (i.e., * not trailing context associated) state. */ extern void mark_beginning_as_normal PROTO ((int)); /* Make a machine that branches to two machines. */ extern int mkbranch PROTO ((int, int)); extern int mkclos PROTO ((int)); /* convert a machine into a closure */ extern int mkopt PROTO ((int)); /* make a machine optional */ /* Make a machine that matches either one of two machines. */ extern int mkor PROTO ((int, int)); /* Convert a machine into a positive closure. */ extern int mkposcl PROTO ((int)); extern int mkrep PROTO ((int, int, int)); /* make a replicated machine */ /* Create a state with a transition on a given symbol. */ extern int mkstate PROTO ((int)); extern void new_rule PROTO ((void)); /* initialize for a new rule */ /* from file parse.y */ /* Build the "<>" action for the active start conditions. */ extern void build_eof_action PROTO ((void)); /* Write out a message formatted with one string, pinpointing its location. */ extern void format_pinpoint_message PROTO ((const char *, const char *)); /* Write out a message, pinpointing its location. */ extern void pinpoint_message PROTO ((const char *)); /* Write out a warning, pinpointing it at the given line. */ extern void line_warning PROTO ((const char *, int)); /* Write out a message, pinpointing it at the given line. */ extern void line_pinpoint PROTO ((const char *, int)); /* Report a formatted syntax error. */ extern void format_synerr PROTO ((const char *, const char *)); extern void synerr PROTO ((const char *)); /* report a syntax error */ extern void format_warn PROTO ((const char *, const char *)); extern void warn PROTO ((const char *)); /* report a warning */ extern void yyerror PROTO ((const char *)); /* report a parse error */ extern int yyparse PROTO ((void)); /* the YACC parser */ /* from file scan.l */ /* The Flex-generated scanner for flex. */ extern int flexscan PROTO ((void)); /* Open the given file (if NULL, stdin) for scanning. */ extern void set_input_file PROTO ((char *)); /* Wrapup a file in the lexical analyzer. */ extern int yywrap PROTO ((void)); /* from file sym.c */ /* Save the text of a character class. */ extern void cclinstal PROTO ((Char[], int)); /* Lookup the number associated with character class. */ extern int ccllookup PROTO ((Char[])); extern void ndinstal PROTO ((const char *, Char[])); /* install a name definition */ extern Char *ndlookup PROTO ((const char *)); /* lookup a name definition */ /* Increase maximum number of SC's. */ extern void scextend PROTO ((void)); extern void scinstal PROTO ((const char *, int)); /* make a start condition */ /* Lookup the number associated with a start condition. */ extern int sclookup PROTO ((const char *)); /* from file tblcmp.c */ /* Build table entries for dfa state. */ extern void bldtbl PROTO ((int[], int, int, int, int)); extern void cmptmps PROTO ((void)); /* compress template table entries */ extern void expand_nxt_chk PROTO ((void)); /* increase nxt/chk arrays */ /* Finds a space in the table for a state to be placed. */ extern int find_table_space PROTO ((int *, int)); extern void inittbl PROTO ((void)); /* initialize transition tables */ /* Make the default, "jam" table entries. */ extern void mkdeftbl PROTO ((void)); /* Create table entries for a state (or state fragment) which has * only one out-transition. */ extern void mk1tbl PROTO ((int, int, int, int)); /* Place a state into full speed transition table. */ extern void place_state PROTO ((int *, int, int)); /* Save states with only one out-transition to be processed later. */ extern void stack1 PROTO ((int, int, int, int)); /* from file yylex.c */ extern int yylex PROTO ((void)); /* A growable array. See buf.c. */ struct Buf { void *elts; /* elements. */ int nelts; /* number of elements. */ size_t elt_size; /* in bytes. */ int nmax; /* max capacity of elements. */ }; extern void buf_init PROTO ((struct Buf * buf, size_t elem_size)); extern void buf_destroy PROTO ((struct Buf * buf)); extern struct Buf *buf_append PROTO ((struct Buf * buf, const void *ptr, int n_elem)); extern struct Buf *buf_concat PROTO((struct Buf* dest, const struct Buf* src)); extern struct Buf *buf_strappend PROTO ((struct Buf *, const char *str)); extern struct Buf *buf_strnappend PROTO ((struct Buf *, const char *str, int nchars)); extern struct Buf *buf_strdefine PROTO ((struct Buf * buf, const char *str, const char *def)); extern struct Buf *buf_prints PROTO((struct Buf *buf, const char *fmt, const char* s)); extern struct Buf *buf_m4_define PROTO((struct Buf *buf, const char* def, const char* val)); extern struct Buf *buf_m4_undefine PROTO((struct Buf *buf, const char* def)); extern struct Buf *buf_print_strings PROTO((struct Buf * buf, FILE* out)); extern struct Buf *buf_linedir PROTO((struct Buf *buf, const char* filename, int lineno)); extern struct Buf userdef_buf; /* a string buffer for #define's generated by user-options on cmd line. */ extern struct Buf defs_buf; /* a char* buffer to save #define'd some symbols generated by flex. */ extern struct Buf yydmap_buf; /* a string buffer to hold yydmap elements */ extern struct Buf m4defs_buf; /* Holds m4 definitions. */ extern struct Buf top_buf; /* contains %top code. String buffer. */ /* For blocking out code from the header file. */ #define OUT_BEGIN_CODE() outn("m4_ifdef( [[M4_YY_IN_HEADER]],,[[") #define OUT_END_CODE() outn("]])") /* For setjmp/longjmp (instead of calling exit(2)). Linkage in main.c */ extern jmp_buf flex_main_jmp_buf; #define FLEX_EXIT(status) longjmp(flex_main_jmp_buf,(status)+1) /* Removes all \n and \r chars from tail of str. returns str. */ extern char *chomp (char *str); /* ctype functions forced to return boolean */ #define b_isalnum(c) (isalnum(c)?true:false) #define b_isalpha(c) (isalpha(c)?true:false) #define b_isascii(c) (isascii(c)?true:false) #define b_isblank(c) (isblank(c)?true:false) #define b_iscntrl(c) (iscntrl(c)?true:false) #define b_isdigit(c) (isdigit(c)?true:false) #define b_isgraph(c) (isgraph(c)?true:false) #define b_islower(c) (islower(c)?true:false) #define b_isprint(c) (isprint(c)?true:false) #define b_ispunct(c) (ispunct(c)?true:false) #define b_isspace(c) (isspace(c)?true:false) #define b_isupper(c) (isupper(c)?true:false) #define b_isxdigit(c) (isxdigit(c)?true:false) /* return true if char is uppercase or lowercase. */ bool has_case(int c); /* Change case of character if possible. */ int reverse_case(int c); /* return false if [c1-c2] is ambiguous for a caseless scanner. */ bool range_covers_case (int c1, int c2); /* * From "filter.c" */ /** A single stdio filter to execute. * The filter may be external, such as "sed", or it * may be internal, as a function call. */ struct filter { int (*filter_func)(struct filter*); /**< internal filter function */ void * extra; /**< extra data passed to filter_func */ int argc; /**< arg count */ const char ** argv; /**< arg vector, \0-terminated */ struct filter * next; /**< next filter or NULL */ }; /* output filter chain */ extern struct filter * output_chain; extern struct filter *filter_create_ext PROTO((struct filter * chain, const char *cmd, ...)); struct filter *filter_create_int PROTO((struct filter *chain, int (*filter_func) (struct filter *), void *extra)); extern bool filter_apply_chain PROTO((struct filter * chain)); extern int filter_truncate (struct filter * chain, int max_len); extern int filter_tee_header PROTO((struct filter *chain)); extern int filter_fix_linedirs PROTO((struct filter *chain)); /* * From "regex.c" */ extern regex_t regex_linedir, regex_blank_line; bool flex_init_regex(void); void flex_regcomp(regex_t *preg, const char *regex, int cflags); char *regmatch_dup (regmatch_t * m, const char *src); char *regmatch_cpy (regmatch_t * m, char *dest, const char *src); int regmatch_len (regmatch_t * m); int regmatch_strtol (regmatch_t * m, const char *src, char **endptr, int base); bool regmatch_empty (regmatch_t * m); /* From "scanflags.h" */ typedef unsigned int scanflags_t; extern scanflags_t* _sf_stk; extern size_t _sf_top_ix, _sf_max; /**< stack of scanner flags. */ #define _SF_CASE_INS 0x0001 #define _SF_DOT_ALL 0x0002 #define _SF_SKIP_WS 0x0004 #define sf_top() (_sf_stk[_sf_top_ix]) #define sf_case_ins() (sf_top() & _SF_CASE_INS) #define sf_dot_all() (sf_top() & _SF_DOT_ALL) #define sf_skip_ws() (sf_top() & _SF_SKIP_WS) #define sf_set_case_ins(X) ((X) ? (sf_top() |= _SF_CASE_INS) : (sf_top() &= ~_SF_CASE_INS)) #define sf_set_dot_all(X) ((X) ? (sf_top() |= _SF_DOT_ALL) : (sf_top() &= ~_SF_DOT_ALL)) #define sf_set_skip_ws(X) ((X) ? (sf_top() |= _SF_SKIP_WS) : (sf_top() &= ~_SF_SKIP_WS)) extern void sf_init(void); extern void sf_push(void); extern void sf_pop(void); #endif /* not defined FLEXDEF_H */ freebsd-buildutils-10.0/src/contrib/flex/yylex.c0000644000000000000000000000775612146741165016641 0ustar /* yylex - scanner front-end for flex */ /* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */ /* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */ /* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #include #include "flexdef.h" #include "parse.h" /* yylex - scan for a regular expression token */ int yylex () { int toktype; static int beglin = false; extern char *yytext; if (eofseen) toktype = EOF; else toktype = flexscan (); if (toktype == EOF || toktype == 0) { eofseen = 1; if (sectnum == 1) { synerr (_("premature EOF")); sectnum = 2; toktype = SECTEND; } else toktype = 0; } if (trace) { if (beglin) { fprintf (stderr, "%d\t", num_rules + 1); beglin = 0; } switch (toktype) { case '<': case '>': case '^': case '$': case '"': case '[': case ']': case '{': case '}': case '|': case '(': case ')': case '-': case '/': case '\\': case '?': case '.': case '*': case '+': case ',': (void) putc (toktype, stderr); break; case '\n': (void) putc ('\n', stderr); if (sectnum == 2) beglin = 1; break; case SCDECL: fputs ("%s", stderr); break; case XSCDECL: fputs ("%x", stderr); break; case SECTEND: fputs ("%%\n", stderr); /* We set beglin to be true so we'll start * writing out numbers as we echo rules. * flexscan() has already assigned sectnum. */ if (sectnum == 2) beglin = 1; break; case NAME: fprintf (stderr, "'%s'", nmstr); break; case CHAR: switch (yylval) { case '<': case '>': case '^': case '$': case '"': case '[': case ']': case '{': case '}': case '|': case '(': case ')': case '-': case '/': case '\\': case '?': case '.': case '*': case '+': case ',': fprintf (stderr, "\\%c", yylval); break; default: if (!isascii (yylval) || !isprint (yylval)) fprintf (stderr, "\\%.3o", (unsigned int) yylval); else (void) putc (yylval, stderr); break; } break; case NUMBER: fprintf (stderr, "%d", yylval); break; case PREVCCL: fprintf (stderr, "[%d]", yylval); break; case EOF_OP: fprintf (stderr, "<>"); break; case OPTION_OP: fprintf (stderr, "%s ", yytext); break; case OPT_OUTFILE: case OPT_PREFIX: case CCE_ALNUM: case CCE_ALPHA: case CCE_BLANK: case CCE_CNTRL: case CCE_DIGIT: case CCE_GRAPH: case CCE_LOWER: case CCE_PRINT: case CCE_PUNCT: case CCE_SPACE: case CCE_UPPER: case CCE_XDIGIT: fprintf (stderr, "%s", yytext); break; case 0: fprintf (stderr, _("End Marker\n")); break; default: fprintf (stderr, _ ("*Something Weird* - tok: %d val: %d\n"), toktype, yylval); break; } } return toktype; } freebsd-buildutils-10.0/src/contrib/flex/tables.c0000644000000000000000000003176712146741165016740 0ustar /* tables.c - tables serialization code * * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Vern Paxson. * * The United States Government has rights in this work pursuant * to contract no. DE-AC03-76SF00098 between the United States * Department of Energy and the University of California. * * This file is part of flex. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. */ #include "flexdef.h" #include "tables.h" /** Convert size_t to t_flag. * @param n in {1,2,4} * @return YYTD_DATA*. */ #define BYTES2TFLAG(n)\ (((n) == sizeof(flex_int8_t))\ ? YYTD_DATA8\ :(((n)== sizeof(flex_int16_t))\ ? YYTD_DATA16\ : YYTD_DATA32)) /** Clear YYTD_DATA* bit flags * @return the flag with the YYTD_DATA* bits cleared */ #define TFLAGS_CLRDATA(flg) ((flg) & ~(YYTD_DATA8 | YYTD_DATA16 | YYTD_DATA32)) int yytbl_write32 (struct yytbl_writer *wr, flex_uint32_t v); int yytbl_write16 (struct yytbl_writer *wr, flex_uint16_t v); int yytbl_write8 (struct yytbl_writer *wr, flex_uint8_t v); int yytbl_writen (struct yytbl_writer *wr, void *v, flex_int32_t len); static flex_int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i); /* XXX Not used static flex_int32_t yytbl_data_getijk (const struct yytbl_data *tbl, int i, int j, int k); */ /** Initialize the table writer. * @param wr an uninitialized writer * @param the output file * @return 0 on success */ int yytbl_writer_init (struct yytbl_writer *wr, FILE * out) { wr->out = out; wr->total_written = 0; return 0; } /** Initialize a table header. * @param th The uninitialized structure * @param version_str the version string * @param name the name of this table set */ int yytbl_hdr_init (struct yytbl_hdr *th, const char *version_str, const char *name) { memset (th, 0, sizeof (struct yytbl_hdr)); th->th_magic = YYTBL_MAGIC; th->th_hsize = 14 + strlen (version_str) + 1 + strlen (name) + 1; th->th_hsize += yypad64 (th->th_hsize); th->th_ssize = 0; // Not known at this point. th->th_flags = 0; th->th_version = copy_string (version_str); th->th_name = copy_string (name); return 0; } /** Allocate and initialize a table data structure. * @param tbl a pointer to an uninitialized table * @param id the table identifier * @return 0 on success */ int yytbl_data_init (struct yytbl_data *td, enum yytbl_id id) { memset (td, 0, sizeof (struct yytbl_data)); td->td_id = id; td->td_flags = YYTD_DATA32; return 0; } /** Clean up table and data array. * @param td will be destroyed * @return 0 on success */ int yytbl_data_destroy (struct yytbl_data *td) { if (td->td_data) free (td->td_data); td->td_data = 0; free (td); return 0; } /** Write enough padding to bring the file pointer to a 64-bit boundary. */ static int yytbl_write_pad64 (struct yytbl_writer *wr) { int pad, bwritten = 0; pad = yypad64 (wr->total_written); while (pad-- > 0) if (yytbl_write8 (wr, 0) < 0) return -1; else bwritten++; return bwritten; } /** write the header. * @param out the output stream * @param th table header to be written * @return -1 on error, or bytes written on success. */ int yytbl_hdr_fwrite (struct yytbl_writer *wr, const struct yytbl_hdr *th) { int sz, rv; int bwritten = 0; if (yytbl_write32 (wr, th->th_magic) < 0 || yytbl_write32 (wr, th->th_hsize) < 0) flex_die (_("th_magic|th_hsize write32 failed")); bwritten += 8; if (fgetpos (wr->out, &(wr->th_ssize_pos)) != 0) flex_die (_("fgetpos failed")); if (yytbl_write32 (wr, th->th_ssize) < 0 || yytbl_write16 (wr, th->th_flags) < 0) flex_die (_("th_ssize|th_flags write failed")); bwritten += 6; sz = strlen (th->th_version) + 1; if ((rv = yytbl_writen (wr, th->th_version, sz)) != sz) flex_die (_("th_version writen failed")); bwritten += rv; sz = strlen (th->th_name) + 1; if ((rv = yytbl_writen (wr, th->th_name, sz)) != sz) flex_die (_("th_name writen failed")); bwritten += rv; /* add padding */ if ((rv = yytbl_write_pad64 (wr)) < 0) flex_die (_("pad64 failed")); bwritten += rv; /* Sanity check */ if (bwritten != (int) th->th_hsize) flex_die (_("pad64 failed")); return bwritten; } /** Write this table. * @param out the file writer * @param td table data to be written * @return -1 on error, or bytes written on success. */ int yytbl_data_fwrite (struct yytbl_writer *wr, struct yytbl_data *td) { int rv; flex_int32_t bwritten = 0; flex_int32_t i, total_len; fpos_t pos; if ((rv = yytbl_write16 (wr, td->td_id)) < 0) return -1; bwritten += rv; if ((rv = yytbl_write16 (wr, td->td_flags)) < 0) return -1; bwritten += rv; if ((rv = yytbl_write32 (wr, td->td_hilen)) < 0) return -1; bwritten += rv; if ((rv = yytbl_write32 (wr, td->td_lolen)) < 0) return -1; bwritten += rv; total_len = yytbl_calc_total_len (td); for (i = 0; i < total_len; i++) { switch (YYTDFLAGS2BYTES (td->td_flags)) { case sizeof (flex_int8_t): rv = yytbl_write8 (wr, yytbl_data_geti (td, i)); break; case sizeof (flex_int16_t): rv = yytbl_write16 (wr, yytbl_data_geti (td, i)); break; case sizeof (flex_int32_t): rv = yytbl_write32 (wr, yytbl_data_geti (td, i)); break; default: flex_die (_("invalid td_flags detected")); } if (rv < 0) { flex_die (_("error while writing tables")); return -1; } bwritten += rv; } /* Sanity check */ if (bwritten != (int) (12 + total_len * YYTDFLAGS2BYTES (td->td_flags))) { flex_die (_("insanity detected")); return -1; } /* add padding */ if ((rv = yytbl_write_pad64 (wr)) < 0) { flex_die (_("pad64 failed")); return -1; } bwritten += rv; /* Now go back and update the th_hsize member */ if (fgetpos (wr->out, &pos) != 0 || fsetpos (wr->out, &(wr->th_ssize_pos)) != 0 || yytbl_write32 (wr, wr->total_written) < 0 || fsetpos (wr->out, &pos)) { flex_die (_("get|set|fwrite32 failed")); return -1; } else /* Don't count the int we just wrote. */ wr->total_written -= sizeof (flex_int32_t); return bwritten; } /** Write n bytes. * @param wr the table writer * @param v data to be written * @param len number of bytes * @return -1 on error. number of bytes written on success. */ int yytbl_writen (struct yytbl_writer *wr, void *v, flex_int32_t len) { int rv; rv = fwrite (v, 1, len, wr->out); if (rv != len) return -1; wr->total_written += len; return len; } /** Write four bytes in network byte order * @param wr the table writer * @param v a dword in host byte order * @return -1 on error. number of bytes written on success. */ int yytbl_write32 (struct yytbl_writer *wr, flex_uint32_t v) { flex_uint32_t vnet; size_t bytes, rv; vnet = htonl (v); bytes = sizeof (flex_uint32_t); rv = fwrite (&vnet, bytes, 1, wr->out); if (rv != 1) return -1; wr->total_written += bytes; return bytes; } /** Write two bytes in network byte order. * @param wr the table writer * @param v a word in host byte order * @return -1 on error. number of bytes written on success. */ int yytbl_write16 (struct yytbl_writer *wr, flex_uint16_t v) { flex_uint16_t vnet; size_t bytes, rv; vnet = htons (v); bytes = sizeof (flex_uint16_t); rv = fwrite (&vnet, bytes, 1, wr->out); if (rv != 1) return -1; wr->total_written += bytes; return bytes; } /** Write a byte. * @param wr the table writer * @param v the value to be written * @return -1 on error. number of bytes written on success. */ int yytbl_write8 (struct yytbl_writer *wr, flex_uint8_t v) { size_t bytes, rv; bytes = sizeof (flex_uint8_t); rv = fwrite (&v, bytes, 1, wr->out); if (rv != 1) return -1; wr->total_written += bytes; return bytes; } /* XXX Not Used */ #if 0 /** Extract data element [i][j] from array data tables. * @param tbl data table * @param i index into higher dimension array. i should be zero for one-dimensional arrays. * @param j index into lower dimension array. * @param k index into struct, must be 0 or 1. Only valid for YYTD_ID_TRANSITION table * @return data[i][j + k] */ static flex_int32_t yytbl_data_getijk (const struct yytbl_data *tbl, int i, int j, int k) { flex_int32_t lo; k %= 2; lo = tbl->td_lolen; switch (YYTDFLAGS2BYTES (tbl->td_flags)) { case sizeof (flex_int8_t): return ((flex_int8_t *) (tbl->td_data))[(i * lo + j) * (k + 1) + k]; case sizeof (flex_int16_t): return ((flex_int16_t *) (tbl->td_data))[(i * lo + j) * (k + 1) + k]; case sizeof (flex_int32_t): return ((flex_int32_t *) (tbl->td_data))[(i * lo + j) * (k + 1) + k]; default: flex_die (_("invalid td_flags detected")); break; } return 0; } #endif /* Not used */ /** Extract data element [i] from array data tables treated as a single flat array of integers. * Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array * of structs. * @param tbl data table * @param i index into array. * @return data[i] */ static flex_int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i) { switch (YYTDFLAGS2BYTES (tbl->td_flags)) { case sizeof (flex_int8_t): return ((flex_int8_t *) (tbl->td_data))[i]; case sizeof (flex_int16_t): return ((flex_int16_t *) (tbl->td_data))[i]; case sizeof (flex_int32_t): return ((flex_int32_t *) (tbl->td_data))[i]; default: flex_die (_("invalid td_flags detected")); break; } return 0; } /** Set data element [i] in array data tables treated as a single flat array of integers. * Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array * of structs. * @param tbl data table * @param i index into array. * @param newval new value for data[i] */ static void yytbl_data_seti (const struct yytbl_data *tbl, int i, flex_int32_t newval) { switch (YYTDFLAGS2BYTES (tbl->td_flags)) { case sizeof (flex_int8_t): ((flex_int8_t *) (tbl->td_data))[i] = (flex_int8_t) newval; break; case sizeof (flex_int16_t): ((flex_int16_t *) (tbl->td_data))[i] = (flex_int16_t) newval; break; case sizeof (flex_int32_t): ((flex_int32_t *) (tbl->td_data))[i] = (flex_int32_t) newval; break; default: flex_die (_("invalid td_flags detected")); break; } } /** Calculate the number of bytes needed to hold the largest * absolute value in this data array. * @param tbl the data table * @return sizeof(n) where n in {flex_int8_t, flex_int16_t, flex_int32_t} */ static size_t min_int_size (struct yytbl_data *tbl) { flex_uint32_t i, total_len; flex_int32_t max = 0; total_len = yytbl_calc_total_len (tbl); for (i = 0; i < total_len; i++) { flex_int32_t n; n = abs (yytbl_data_geti (tbl, i)); if (n > max) max = n; } if (max <= INT8_MAX) return sizeof (flex_int8_t); else if (max <= INT16_MAX) return sizeof (flex_int16_t); else return sizeof (flex_int32_t); } /** Transform data to smallest possible of (int32, int16, int8). * For example, we may have generated an int32 array due to user options * (e.g., %option align), but if the maximum value in that array * is 80 (for example), then we can serialize it with only 1 byte per int. * This is NOT the same as compressed DFA tables. We're just trying * to save storage space here. * * @param tbl the table to be compressed */ void yytbl_data_compress (struct yytbl_data *tbl) { flex_int32_t i, newsz, total_len; struct yytbl_data newtbl; yytbl_data_init (&newtbl, tbl->td_id); newtbl.td_hilen = tbl->td_hilen; newtbl.td_lolen = tbl->td_lolen; newtbl.td_flags = tbl->td_flags; newsz = min_int_size (tbl); if (newsz == (int) YYTDFLAGS2BYTES (tbl->td_flags)) /* No change in this table needed. */ return; if (newsz > (int) YYTDFLAGS2BYTES (tbl->td_flags)) { flex_die (_("detected negative compression")); return; } total_len = yytbl_calc_total_len (tbl); newtbl.td_data = calloc (total_len, newsz); newtbl.td_flags = TFLAGS_CLRDATA (newtbl.td_flags) | BYTES2TFLAG (newsz); for (i = 0; i < total_len; i++) { flex_int32_t g; g = yytbl_data_geti (tbl, i); yytbl_data_seti (&newtbl, i, g); } /* Now copy over the old table */ free (tbl->td_data); *tbl = newtbl; } /* vim:set noexpandtab cindent tabstop=8 softtabstop=0 shiftwidth=8 textwidth=0: */ freebsd-buildutils-10.0/src/contrib/flex/scan.l0000644000000000000000000006327412146743317016422 0ustar /* scan.l - scanner for flex input -*-C-*- */ %{ /* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */ /* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */ /* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */ #include "flexdef.h" #include "parse.h" extern bool tablesverify, tablesext; extern int trlcontxt; /* Set in parse.y for each rule. */ extern const char *escaped_qstart, *escaped_qend; #define ACTION_ECHO add_action( yytext ) #define ACTION_IFDEF(def, should_define) \ { \ if ( should_define ) \ action_define( def, 1 ); \ } #define ACTION_ECHO_QSTART add_action (escaped_qstart) #define ACTION_ECHO_QEND add_action (escaped_qend) #define ACTION_M4_IFDEF(def, should_define) \ do{ \ if ( should_define ) \ buf_m4_define( &m4defs_buf, def, NULL);\ else \ buf_m4_undefine( &m4defs_buf, def);\ } while(0) #define MARK_END_OF_PROLOG mark_prolog(); #define YY_DECL \ int flexscan() #define RETURNCHAR \ yylval = (unsigned char) yytext[0]; \ return CHAR; #define RETURNNAME \ if(yyleng < MAXLINE) \ { \ strcpy( nmstr, yytext ); \ } \ else \ { \ synerr(_("Input line too long\n")); \ FLEX_EXIT(EXIT_FAILURE); \ } \ return NAME; #define PUT_BACK_STRING(str, start) \ for ( i = strlen( str ) - 1; i >= start; --i ) \ unput((str)[i]) #define CHECK_REJECT(str) \ if ( all_upper( str ) ) \ reject = true; #define CHECK_YYMORE(str) \ if ( all_lower( str ) ) \ yymore_used = true; #define YY_USER_INIT \ if ( getenv("POSIXLY_CORRECT") ) \ posix_compat = true; %} %option caseless nodefault stack noyy_top_state %option nostdinit %x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE %x FIRSTCCL CCL ACTION RECOVER COMMENT ACTION_STRING PERCENT_BRACE_ACTION %x OPTION LINEDIR CODEBLOCK_MATCH_BRACE %x GROUP_WITH_PARAMS %x GROUP_MINUS_PARAMS %x EXTENDED_COMMENT %x COMMENT_DISCARD WS [[:blank:]]+ OPTWS [[:blank:]]* NOT_WS [^[:blank:]\r\n] NL \r?\n NAME ([[:alpha:]_][[:alnum:]_-]*) NOT_NAME [^[:alpha:]_*\n]+ SCNAME {NAME} ESCSEQ (\\([^\n]|[0-7]{1,3}|x[[:xdigit:]]{1,2})) FIRST_CCL_CHAR ([^\\\n]|{ESCSEQ}) CCL_CHAR ([^\\\n\]]|{ESCSEQ}) CCL_EXPR ("[:"^?[[:alpha:]]+":]") LEXOPT [aceknopr] M4QSTART "[[" M4QEND "]]" %% static int bracelevel, didadef, indented_code; static int doing_rule_action = false; static int option_sense; int doing_codeblock = false; int i, brace_depth=0, brace_start_line=0; Char nmdef[MAXLINE]; { ^{WS} indented_code = true; BEGIN(CODEBLOCK); ^"/*" ACTION_ECHO; yy_push_state( COMMENT ); ^#{OPTWS}line{WS} yy_push_state( LINEDIR ); ^"%s"{NAME}? return SCDECL; ^"%x"{NAME}? return XSCDECL; ^"%{".*{NL} { ++linenum; line_directive_out( (FILE *) 0, 1 ); indented_code = false; BEGIN(CODEBLOCK); } ^"%top"[[:blank:]]*"{"[[:blank:]]*{NL} { brace_start_line = linenum; ++linenum; buf_linedir( &top_buf, infilename?infilename:"", linenum); brace_depth = 1; yy_push_state(CODEBLOCK_MATCH_BRACE); } ^"%top".* synerr( _("malformed '%top' directive") ); {WS} /* discard */ ^"%%".* { sectnum = 2; bracelevel = 0; mark_defs1(); line_directive_out( (FILE *) 0, 1 ); BEGIN(SECT2PROLOG); return SECTEND; } ^"%pointer".*{NL} yytext_is_array = false; ++linenum; ^"%array".*{NL} yytext_is_array = true; ++linenum; ^"%option" BEGIN(OPTION); return OPTION_OP; ^"%"{LEXOPT}{OPTWS}[[:digit:]]*{OPTWS}{NL} ++linenum; /* ignore */ ^"%"{LEXOPT}{WS}.*{NL} ++linenum; /* ignore */ /* xgettext: no-c-format */ ^"%"[^sxaceknopr{}].* synerr( _( "unrecognized '%' directive" ) ); ^{NAME} { if(yyleng < MAXLINE) { strcpy( nmstr, yytext ); } else { synerr( _("Definition name too long\n")); FLEX_EXIT(EXIT_FAILURE); } didadef = false; BEGIN(PICKUPDEF); } {SCNAME} RETURNNAME; ^{OPTWS}{NL} ++linenum; /* allows blank lines in section 1 */ {OPTWS}{NL} ACTION_ECHO; ++linenum; /* maybe end of comment line */ } { "*/" ACTION_ECHO; yy_pop_state(); "*" ACTION_ECHO; {M4QSTART} ACTION_ECHO_QSTART; {M4QEND} ACTION_ECHO_QEND; [^*\n] ACTION_ECHO; {NL} ++linenum; ACTION_ECHO; } { /* This is the same as COMMENT, but is discarded rather than output. */ "*/" yy_pop_state(); "*" ; [^*\n] ; {NL} ++linenum; } { ")" yy_pop_state(); [^\n\)]+ ; {NL} ++linenum; } { \n yy_pop_state(); [[:digit:]]+ linenum = myctoi( yytext ); \"[^"\n]*\" { flex_free( (void *) infilename ); infilename = copy_string( yytext + 1 ); infilename[strlen( infilename ) - 1] = '\0'; } . /* ignore spurious characters */ } { ^"%}".*{NL} ++linenum; BEGIN(INITIAL); {M4QSTART} ACTION_ECHO_QSTART; {M4QEND} ACTION_ECHO_QEND; . ACTION_ECHO; {NL} { ++linenum; ACTION_ECHO; if ( indented_code ) BEGIN(INITIAL); } } { "}" { if( --brace_depth == 0){ /* TODO: Matched. */ yy_pop_state(); }else buf_strnappend(&top_buf, yytext, yyleng); } "{" { brace_depth++; buf_strnappend(&top_buf, yytext, yyleng); } {NL} { ++linenum; buf_strnappend(&top_buf, yytext, yyleng); } {M4QSTART} buf_strnappend(&top_buf, escaped_qstart, strlen(escaped_qstart)); {M4QEND} buf_strnappend(&top_buf, escaped_qend, strlen(escaped_qend)); [^{}\r\n] { buf_strnappend(&top_buf, yytext, yyleng); } <> { linenum = brace_start_line; synerr(_("Unmatched '{'")); yyterminate(); } } { {WS} /* separates name and definition */ {NOT_WS}[^\r\n]* { if(yyleng < MAXLINE) { strcpy( (char *) nmdef, yytext ); } else { format_synerr( _("Definition value for {%s} too long\n"), nmstr); FLEX_EXIT(EXIT_FAILURE); } /* Skip trailing whitespace. */ for ( i = strlen( (char *) nmdef ) - 1; i >= 0 && (nmdef[i] == ' ' || nmdef[i] == '\t'); --i ) ; nmdef[i + 1] = '\0'; ndinstal( nmstr, nmdef ); didadef = true; } {NL} { if ( ! didadef ) synerr( _( "incomplete name definition" ) ); BEGIN(INITIAL); ++linenum; } }