home *** CD-ROM | disk | FTP | other *** search
- From: zeppelin@login.dknet.dk (Thomas B. Pedersen)
- Newsgroups: comp.sources.misc
- Subject: v44i057: typhoon - Typhoon Relational Database Management System, Part01/09
- Date: 17 Sep 1994 21:44:04 -0500
- Organization: Sterling Software
- Sender: kent@sparky.sterling.com
- Approved: kent@sparky.sterling.com
- Message-ID: <csm-v44i057=typhoon.214347@sparky.sterling.com>
- X-Md4-Signature: 3ed59d07df131f309b0ca3f158f1f885
-
- Submitted-by: zeppelin@login.dknet.dk (Thomas B. Pedersen)
- Posting-number: Volume 44, Issue 57
- Archive-name: typhoon/part01
- Environment: SCO UNIX, Tandem NonStop UNIX, Sun Solaris, AIX, Linux, OS/2
-
- Typhoon is a freely available relational database management system for
- the UNIX and OS/2 environments.
-
- This release has been prepared in a hurry to get it out as quickly as
- possible. This means that the documentation is rather sparse, since I
- haven't had the time to write extensive documentation yet. However, most
- of you out there are pretty clever, so you'll probably do fine with the
- man pages and the examples.
-
- The system works fine and is currently used in a number of professional
- applications in Denmark, some of them mission critical.
-
- The system was originally inspired by Raima's db_VISTA (today Raima Data
- Manager) but is relational rather than network based. Typhoon lacks some of
- db_VISTA's features, but also contains a number of nice features not found in
- db_VISTA.
-
- All relations are defined in a so called Data Definition Language (ddl) file.
- You define the database relations like you would write a C structure with
- chars, ints, strings, multidimensional arrays, nested union and structures,
- etc. Then you define primary, alternate and foreign keys for each relation.
- The Data Definition Language Processor (ddlp) compiles the database defintion
- into a binary file which constitutes the database description. The database
- relations are accessed via C subroutines which manipulate individual records
- within a table.
-
- - Multiple open database
- - Multi-field keys
- - Nested structures in records
- - Controlled unions
- - Referential integrity
- - Variable length fields
- - Null keys (optional keys in db_VISTA, but easier to use)
- - Dynamic opening and closing of database files
-
- At present the database has no locking mechanism, believe it or not! The
- projects I have used it in, simply didn't need it, even though they were
- multi-user environments. But it's in the works!
-
- I am currently working on extending the library to support the following:
-
- - Locking
- - Logging
- - Transactions
- - Paging (to improve performance)
-
- The library functions will remain intact, except for a number of new functions.
- I expect these things to be ready before the end of the year. Beta testers
- are welcome.
-
- The library comes with three additional utilities:
-
- dbdview - Displayes the database definitions.
- tyexport - Exports tables from a database.
- tyimport - Imports tables into a database.
-
- Originally the library also contained online backup, restore and a replication
- server. These tools would need a lot of extra documentation, so I have left
- them out for now (the code still contains support for these utilities).
- However, if enough people show interest I will probably release them also.
-
- Bug reports and mail should be sent to
-
- Thomas B. Pedersen
- zeppelin@login.dkuug.dk
-
- Also, if you have any suggestions as to how I can improve the library,
- documentation or anything else, please don't hesitate to mail me.
-
- Thomas B. Pedersen
- -------------------------------
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: typhoon typhoon/examples typhoon/man typhoon/src
- # typhoon/src/bt_funcs.c typhoon/src/h typhoon/src/util
- # typhoon/src/util/ddl.y typhoon/src/util/ddlp.c
- # typhoon/src/util/lex.c
- # Wrapped by kent@sparky on Sat Sep 17 21:38:15 1994
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 1 (of 9)."'
- if test ! -d 'typhoon' ; then
- echo shar: Creating directory \"'typhoon'\"
- mkdir 'typhoon'
- fi
- if test ! -d 'typhoon/examples' ; then
- echo shar: Creating directory \"'typhoon/examples'\"
- mkdir 'typhoon/examples'
- fi
- if test ! -d 'typhoon/man' ; then
- echo shar: Creating directory \"'typhoon/man'\"
- mkdir 'typhoon/man'
- fi
- if test ! -d 'typhoon/src' ; then
- echo shar: Creating directory \"'typhoon/src'\"
- mkdir 'typhoon/src'
- fi
- if test -f 'typhoon/src/bt_funcs.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/bt_funcs.c'\"
- else
- echo shar: Extracting \"'typhoon/src/bt_funcs.c'\" \(14705 characters\)
- sed "s/^X//" >'typhoon/src/bt_funcs.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : bt_funcs
- X * Library : typhoon
- X * OS : UNIX, OS/2, DOS
- X * Author : Thomas B. Pedersen
- X *
- X * Copyright (c) 1994 Thomas B. Pedersen. All rights reserved.
- X *
- X * Permission is hereby granted, without written agreement and without
- X * license or royalty fees, to use, copy, modify, and distribute this
- X * software and its documentation for any purpose, provided that the above
- X * copyright notice and the following two paragraphs appear (1) in all
- X * source copies of this software and (2) in accompanying documentation
- X * wherever the programatic interface of this software, or any derivative
- X * of it, is described.
- X *
- X * IN NO EVENT SHALL THOMAS B. PEDERSEN BE LIABLE TO ANY PARTY FOR DIRECT,
- X * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
- X * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF HE HAS BEEN
- X * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- X *
- X * THOMAS B. PEDERSEN SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
- X * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- X * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
- X * BASIS, AND THOMAS B. PEDERSEN HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
- X * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- X *
- X * Description:
- X *
- X * Functions:
- X * btree_add - Insert a new key in a B-tree.
- X * btree_find - Find a key in a B-tree.
- X * btree_exist - See if a key exists in a B-tree.
- X * btree_read - Read the last key found.
- X * btree_delall - Delete all keys in a B-tree.
- X * get_rightmostchild - Find the rightmost child in a subtree.
- X * get_leftmostchild - Find the leftmost child in a subtree.
- X * btree_frst - Find the key with the lowest key value in a B-tree.
- X * btree_last - Find the key with the highest key value in a B-tree.
- X * btree_prev - Find the previous key in a B-tree.
- X * btree_next - Find the next key in a B-btree.
- X *
- X * $Log: bt_funcs.c,v $
- X * Revision 1.2 1994/09/17 16:00:11 tbp
- X * typhoon.h and environ.h are now included from <>.
- X *
- X * Revision 1.1 1994/09/13 21:28:28 tbp
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- Xstatic char rcsid[] = "$Id: bt_funcs.c,v 1.2 1994/09/17 16:00:11 tbp Exp $";
- X
- X#include <sys/types.h>
- X#include <string.h>
- X#include <stdio.h>
- X#include <fcntl.h>
- X#ifdef UNIX
- X# include <unistd.h>
- X#else
- X# include <io.h>
- X#endif
- X#include <typhoon.h>
- X#include "ty_dbd.h"
- X#include "ty_type.h"
- X#include "ty_prot.h"
- X#include "ty_glob.h"
- X#include "btree.h"
- X
- X/*--------------------------- Function prototypes --------------------------*/
- Xstatic void get_rightmostchild PRM( (INDEX *, ulong); )
- X void get_leftmostchild PRM( (INDEX *, ulong); )
- Xstatic void synchronize PRM( (INDEX *); )
- X
- X
- X/*------------------------------- btree_add --------------------------------*\
- X *
- X * Purpose : Inserts the key <key> in a B-tree index file.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * key - Key value to insert.
- X * ref - Reference to insert together with key.
- X *
- X * Returns : S_OKAY - Key value successfully inserted in B-tree.
- X * S_DUPLICATE - The key value is already in the B-tree and
- X * duplicates are not allowed.
- X *
- X */
- X
- Xbtree_add(I, key, ref)
- XINDEX *I;
- Xvoid *key;
- Xulong ref;
- X{
- X ulong Ref;
- X ix_addr Addr, moved, p;
- X int i, mid;
- X
- X I->curr = 0;
- X I->hold = 0;
- X
- X if( d_search(I, key, &p, &i) )
- X {
- X if( I->H.dups )
- X {
- X /* When a duplicate key is already in the tree, the current node
- X * at this point may not be a leaf node. However, insertions
- X * must always be performed in leaf nodes, so we must find the
- X * rightmost entry in the left subtree
- X */
- X
- X if( CHILD(I->node, i) )
- X {
- X get_rightmostchild(I, CHILD(I->node, i));
- X i = I->path[I->level].i;
- X p = I->path[I->level].a;
- X }
- X }
- X else
- X RETURN S_DUPLICATE;
- X }
- X
- X I->H.keys++;
- X Addr = 0;
- X Ref = ref;
- X memcpy(I->curkey, key, I->H.keysize);
- X
- X do
- X {
- X tupleins(I->node, i, 1);
- X memcpy(KEY(I->node,i), I->curkey, I->H.keysize);
- X CHILD(I->node,i+1) = Addr;
- X REF(I->node,i) = Ref;
- X
- X if( NSIZE(I->node) < (ulong)I->H.order )
- X {
- X NSIZE(I->node)++;
- X nodewrite(I, I->node, p);
- X btree_putheader(I);
- X RETURN S_OKAY;
- X }
- X
- X /* split node */
- X mid = I->H.order / 2;
- X
- X /* write left part of node at its old position */
- X NSIZE(I->node) = mid;
- X nodewrite(I, I->node, p);
- X
- X /* Save mid K, A and R */
- X memcpy(I->curkey, KEY(I->node,mid), I->H.keysize);
- X Addr = CHILD(I->node, mid);
- X Ref = REF(I->node, mid);
- X
- X /* write right part of node at new position */
- X NSIZE(I->node) = I->H.order - mid;
- X memmove(&CHILD(I->node,0), &CHILD(I->node,mid+1), NSIZE(I->node) * I->tsize + sizeof(A_type));
- X Addr = nodewrite(I, I->node, NEWPOS);
- X
- X if( (p = I->path[--I->level].a) != 0 )
- X {
- X noderead(I, I->node, p); /* p = I->path[p] */
- X/* nodesearch(I,I->curkey,&i);*/
- X i = I->path[I->level].i;
- X }
- X }
- X while( p );
- X
- X /* Create a new root */
- X noderead(I, I->node, 1);
- X moved = nodewrite(I, I->node, NEWPOS);
- X
- X memcpy(KEY(I->node,0), I->curkey, I->H.keysize);
- X CHILD(I->node,0) = moved;
- X CHILD(I->node,1) = Addr;
- X REF(I->node,0) = Ref;
- X NSIZE(I->node) = 1;
- X nodewrite(I, I->node, 1);
- X I->H.timestamp++;
- X btree_putheader(I);
- X
- X RETURN S_OKAY;
- X}
- X
- X
- X/*------------------------------- btree_find -------------------------------*\
- X *
- X * Purpose : Searches for the key value <key> in a B-tree index file.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * key - Key value to find.
- X * ref - Contains reference when function returns.
- X *
- X * Returns : S_OKAY - The key value was found. <ref> contains
- X * reference.
- X * S_NOTFOUND - The key value was not found.
- X *
- X */
- Xbtree_find(I, key, ref)
- XINDEX *I;
- Xvoid *key;
- Xulong *ref;
- X{
- X ix_addr dummy;
- X int i;
- X
- X btree_getheader(I); /* Inserted temporarily */
- X
- X if( !d_search(I, key, &dummy, &i) )
- X {
- X /* Do only set hold if there are actually keys in the index */
- X I->hold = I->H.keys > 0 ? 1 : 0;
- X I->curr = 0;
- X RETURN S_NOTFOUND;
- X }
- X
- X *ref = REF(I->node, i);
- X memcpy(I->curkey, KEY(I->node, I->path[I->level].i), I->H.keysize);
- X I->hold = 0;
- X I->curr = 1;
- X RETURN S_OKAY;
- X}
- X
- X
- X/*------------------------------- btree_keyread -------------------------------*\
- X *
- X * Purpose : Copies the contents of the current key value to <buf>.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * buf - Buffer to copy current key value to.
- X *
- X * Returns : S_NOCR - There is no current key.
- X * S_OKAY - Key value copied to <buf>.
- X *
- X */
- Xbtree_keyread(I, buf)
- XINDEX *I;
- Xvoid *buf;
- X{
- X if( !I->curr )
- X RETURN S_NOCR;
- X
- X memcpy(buf, I->curkey, I->H.keysize);
- X RETURN S_OKAY;
- X}
- X
- X
- X/*------------------------------ btree_delall ------------------------------*\
- X *
- X * Purpose : Deletes all key values in a B-tree index file.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X *
- X * Returns : S_OKAY - All keys deleted.
- X *
- X */
- Xbtree_delall(I)
- XINDEX *I;
- X{
- X btree_getheader(I);
- X I->H.first_deleted = 0;
- X I->H.keys = 0;
- X#ifdef UNIX
- X os_close(open(I->fname, O_TRUNC));
- X#else
- X chsize(I->fh, I->H.nodesize);
- X#endif
- X I->curr = 0;
- X I->hold = 0;
- X btree_putheader(I);
- X
- X RETURN S_OKAY;
- X}
- X
- X
- X/*
- X * The following macros are used to enhance the readability of the rest of the
- X * functions in this file. B-tree traversal can be rather tricky, with lots
- X * of pitfalls in it, but these macros should help a great deal. Here is a
- X * short explanation of the macros.
- X *
- X * Keys The number of keys in the current node.
- X * Child(i) The address of the i'th child in the current node.
- X * Key(i) Pointer to the i'th key in the current node.
- X * Ref(i) The reference of the i'th key in the current node.
- X * Pos The current position within the current node.
- X * Addr The current node address at the current level in the tree.
- X * Level The current level in the tree.
- X *
- X */
- X
- X#define Keys NSIZE(I->node)
- X#define Child(i) CHILD(I->node, i)
- X#define Key(i) KEY(I->node, i)
- X#define Ref(i) REF(I->node, i)
- X#define Pos (I->path[I->level].i)
- X#define Addr (I->path[I->level].a)
- X#define Level (I->level)
- X
- X
- X/*--------------------------- get_rightmostchild ---------------------------*\
- X *
- X * Purpose : Reads the rightmost key in a subtree with root address <addr>.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * addr - The root address of the subtree.
- X *
- X * Returns : Nothing.
- X *
- X */
- X
- Xstatic void get_rightmostchild(I, addr)
- XINDEX *I;
- Xulong addr;
- X{
- X /* No tree has root at address 0 */
- X if( !addr )
- X return;
- X
- X do
- X {
- X noderead(I, I->node, addr);
- X
- X Level++;
- X Addr = addr;
- X Pos = Keys;
- X }
- X while( addr = Child(Keys) );
- X}
- X
- X
- X/*--------------------------- get_leftmostchild ----------------------------*\
- X *
- X * Purpose : Reads the leftmost key in a subtree with root address <addr>.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * addr - The root address of the subtree.
- X *
- X * Returns : Nothing.
- X *
- X */
- X
- Xvoid get_leftmostchild(I, addr)
- XINDEX *I;
- Xulong addr;
- X{
- X /* No tree has root at address 0 */
- X if( !addr )
- X return;
- X
- X do
- X {
- X noderead(I, I->node, addr);
- X
- X Level++;
- X Addr = addr;
- X Pos = 0;
- X }
- X while( addr = Child(0) );
- X}
- X
- X
- X/*------------------------------- btree_frst -------------------------------*\
- X *
- X * Purpose : Read the smallest key value in a B-tree, i.e. the leftmost key.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * ref - Contains reference when function returns.
- X *
- X * Returns : S_OKAY - The key was found. <ref> contains reference.
- X * S_NOTFOUND - The B-tree is empty.
- X *
- X */
- Xbtree_frst(I, ref)
- XINDEX *I;
- Xulong *ref;
- X{
- X I->curr = 0;
- X I->hold = 0;
- X Level = 1;
- X Addr = 1;
- X Pos = 0;
- X
- X /* Get the nost recent sequence number */
- X btree_getheader(I);
- X
- X if( noderead(I, I->node, 1) == (ix_addr)-1 )
- X RETURN S_NOTFOUND;
- X
- X get_leftmostchild(I, Child(0));
- X
- X I->curr = 1;
- X *ref = Ref(Pos);
- X memcpy(I->curkey, Key(Pos), I->H.keysize);
- X
- X RETURN S_OKAY;
- X}
- X
- X
- X/*------------------------------- btree_last -------------------------------*\
- X *
- X * Purpose : Read the greatest key value in a B-tree, i.e. the rightmost key.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * ref - Contains reference when function returns.
- X *
- X * Returns : S_OKAY - The key was found. <ref> contains reference.
- X * S_NOTFOUND - The B-tree is empty.
- X *
- X */
- Xbtree_last(I, ref)
- XINDEX *I;
- Xulong *ref;
- X{
- X I->curr = 0;
- X I->hold = 0;
- X Level = 1;
- X Addr = 1;
- X
- X /* Get the nost recent sequence number */
- X btree_getheader(I);
- X
- X if( noderead(I, I->node, 1) == (ix_addr)-1 )
- X RETURN S_NOTFOUND;
- X
- X Pos = Keys;
- X get_rightmostchild(I, Child(Keys));
- X
- X /* Move pos one step leftwards so that Pos is the current key */
- X Pos--;
- X I->curr = 1;
- X *ref = Ref(Pos);
- X memcpy(I->curkey, Key(Pos), I->H.keysize);
- X
- X RETURN S_OKAY;
- X}
- X
- X
- Xstatic void synchronize(I)
- XINDEX *I;
- X{
- X ulong old_ts = I->H.timestamp;
- X ulong ref;
- X
- X btree_getheader(I);
- X
- X if( old_ts != I->H.timestamp )
- X btree_find(I, I->curkey, &ref);
- X}
- X
- X
- X
- X
- X/*------------------------------- btree_prev -------------------------------*\
- X *
- X * Purpose : Find key value in a B-tree with less or equal (if duplicates)
- X * key value that the current key. If there is no current key,
- X * the function is equivalent to btree_last(). If the current
- X * position before the call is the leftmost position in the tree,
- X * S_NOTFOUND is returned.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * ref - Contains reference if a key is found.
- X *
- X * Returns : S_OKAY - Key value found. <ref> contains reference.
- X * S_NOTFOUND - The key with the smallest value has already
- X * been reached.
- X *
- X */
- X
- Xbtree_prev(I,ref)
- XINDEX *I;
- Xulong *ref;
- X{
- X if( I->shared )
- X synchronize(I);
- X
- X if( I->hold )
- X goto out;
- X
- X if( !I->curr )
- X return btree_last(I, ref);
- X
- X if( Child(Pos) > 0 ) /* Non-leaf node */
- X {
- X /* Get the rightmost child in the left subtree */
- X get_rightmostchild(I, Child(Pos));
- X }
- X else if( Pos == 0 ) /* Leaf node at first pos */
- X {
- X /* Move upwards until a node with Pos > 0 or root is reached */
- X while( Pos == 0 && Addr != 1 )
- X {
- X Level--;
- X noderead(I, I->node, Addr);
- X }
- X
- X if( Pos == 0 && Addr == 1 )
- X {
- X I->curr = 0;
- X RETURN S_NOTFOUND;
- X }
- X }
- X Pos--;
- X
- Xout:
- X I->curr = 1;
- X I->hold = 0;
- X
- X *ref = Ref(Pos);
- X memcpy(I->curkey, Key(Pos), I->H.keysize);
- X
- X RETURN S_OKAY;
- X}
- X
- X
- X/*------------------------------- btree_next -------------------------------*\
- X *
- X * Purpose : Find key value in a B-tree with greater or equal (if duplicates)
- X * key value that the current key. If there is no current key,
- X * the function is equivalent to btree_frst(). If the current
- X * position before the call is the rightmost position in the tree,
- X * S_NOTFOUND is returned.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * ref - Contains reference if a key is found.
- X *
- X * Returns : S_OKAY - Key value found. <ref> contains reference.
- X * S_NOTFOUND - The key with the greatest value has already
- X * been reached.
- X *
- X */
- Xbtree_next(I,ref)
- XINDEX *I;
- Xulong *ref;
- X{
- X if( I->shared )
- X synchronize(I);
- X
- X if( I->hold )
- X {
- X /* An unsuccessful keyfind must be handled as a special case:
- X * If we are at the rightmost position in a node, move upwards until
- X * we reach a node where the position is not the rightmost. This
- X * key should be the proper next key in the B-tree.
- X */
- X
- X while( Pos == Keys && Level > 1 )
- X {
- X Level--;
- X noderead(I, I->node, Addr);
- X }
- X
- X if( Level == 1 && Pos == Keys )
- X RETURN S_NOTFOUND;
- X
- X goto out;
- X }
- X
- X if( !I->curr )
- X return btree_frst(I, ref);
- X
- X if( Child(Pos) > 0 ) /* Non-leaf node */
- X {
- X /* Get the leftmost child in the left subtree */
- X Pos++;
- X get_leftmostchild(I, Child(Pos));
- X }
- X else if( Pos >= Keys-1 ) /* Leaf node at first pos */
- X {
- X#if 0
- X if( Pos == Keys-1 && Addr == 1 ) 94/03/17 TBP
- X#else
- X if( Pos >= Keys-1 && Addr == 1 )
- X#endif
- X {
- X I->curr = 0;
- X RETURN S_NOTFOUND;
- X }
- X
- X /* Move upwards until a node with Pos < Keys-1 or root is reached */
- X do
- X {
- X Level--;
- X noderead(I, I->node, Addr);
- X }
- X while( Pos >= Keys && Addr != 1 );
- X
- X if( Pos == Keys && Addr == 1 )
- X {
- X I->curr = 0;
- X RETURN S_NOTFOUND;
- X }
- X }
- X else /* Leaf node */
- X Pos++;
- X
- Xout:
- X I->curr = 1;
- X I->hold = 0;
- X
- X *ref = Ref(Pos);
- X memcpy(I->curkey, Key(Pos), I->H.keysize);
- X
- X RETURN S_OKAY;
- X}
- X
- X/* end-of-file */
- X
- END_OF_FILE
- if test 14705 -ne `wc -c <'typhoon/src/bt_funcs.c'`; then
- echo shar: \"'typhoon/src/bt_funcs.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/bt_funcs.c'
- fi
- if test ! -d 'typhoon/src/h' ; then
- echo shar: Creating directory \"'typhoon/src/h'\"
- mkdir 'typhoon/src/h'
- fi
- if test ! -d 'typhoon/src/util' ; then
- echo shar: Creating directory \"'typhoon/src/util'\"
- mkdir 'typhoon/src/util'
- fi
- if test -f 'typhoon/src/util/ddl.y' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/util/ddl.y'\"
- else
- echo shar: Extracting \"'typhoon/src/util/ddl.y'\" \(14286 characters\)
- sed "s/^X//" >'typhoon/src/util/ddl.y' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : ddl.y
- X * Program : ddlp
- X * OS : UNIX, OS/2, DOS
- X * Author : Thomas B. Pedersen
- X *
- X * Copyright (c) 1994 Thomas B. Pedersen. All rights reserved.
- X *
- X * Permission is hereby granted, without written agreement and without
- X * license or royalty fees, to use, copy, modify, and distribute this
- X * software and its documentation for any purpose, provided that the above
- X * copyright notice and the following two paragraphs appear (1) in all
- X * source copies of this software and (2) in accompanying documentation
- X * wherever the programatic interface of this software, or any derivative
- X * of it, is described.
- X *
- X * IN NO EVENT SHALL THOMAS B. PEDERSEN BE LIABLE TO ANY PARTY FOR DIRECT,
- X * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
- X * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF HE HAS BEEN
- X * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- X *
- X * THOMAS B. PEDERSEN SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
- X * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- X * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
- X * BASIS, AND THOMAS B. PEDERSEN HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
- X * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- X *
- X * Description:
- X * Grammar for ddl-files.
- X *
- X * $Id: ddl.y,v 1.2 1994/09/17 16:11:13 tbp Exp $
- X *
- X * $Log: ddl.y,v $
- X * Revision 1.2 1994/09/17 16:11:13 tbp
- X * Added include directive.
- X *
- X * Added included directive.
- X *
- X * Added include directive.
- X *
- X * Revision 1.1 1994/09/13 21:28:51 tbp
- X * Added to repository.
- X *
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- X%{
- X
- X#include <string.h>
- X#include <stdarg.h>
- X#include <typhoon.h>
- X#include "../ty_dbd.h"
- X#include "../ty_type.h"
- X#include "ddlp.h"
- X#include "ddlpsym.h"
- X#include "ddlpglob.h"
- X
- X/*--------------------------- Function prototypes --------------------------*/
- Xstatic void add_keymember PRM( (sym_struct *, char *, int); )
- X
- X/*---------------------------- Global variables ----------------------------*/
- Xstatic unsigned type; /* Holds FT_.. flags of current field */
- Xstatic int keytype; /* Holds KT_... constants */
- Xstatic sym_member *control_field; /* Field that controls current union */
- X
- X
- Xstatic fieldid[10];
- X
- X%}
- X
- X%union {
- X int val;
- X char is_union;
- X char s[IDENT_LEN+1];
- X}
- X
- X%start database
- X
- X%token T_DATABASE T_KEY T_DATA T_FILE T_CONTAINS T_RECORD
- X%token T_UNIQUE T_DEFINE T_CONTROLLED T_MAP T_ARROW
- X%token T_PRIMARY T_ALTERNATE T_FOREIGN T_ON T_DELETE T_RESTRICT
- X%token T_REFERENCES T_UPDATE T_CASCADE T_NULL
- X%token T_CHAR T_SHORT T_INT T_LONG T_SIGNED T_UNSIGNED T_FLOAT
- X%token T_DOUBLE T_UCHAR T_USHORT T_ULONG T_STRUCT T_UNION
- X%token T_COMPOUND T_ASC T_DESC T_VARIABLE T_BY
- X%token <s> T_IDENT T_STRING
- X%token <val> T_NUMBER T_CHARCONST
- X%token '[' ']' '{' '}' ';' ',' '.' '>'
- X%token '+' '-' '*' '/' '(' ')'
- X
- X%type <val> expr opt_sortorder opt_unique opt_null pagesize action
- X%type <val> map_id
- X%type <is_union> struct_or_union
- X%type <s> opt_ident key_type
- X
- X%left '+' '-'
- X%left '*' '/'
- X
- X%%
- X
- Xdatabase : T_DATABASE T_IDENT '{' decl_list '}'
- X { strcpy(dbname, $2); }
- X ;
- X
- Xpagesize : /* use default page size */
- X { $$ = 512; }
- X | '[' expr ']'
- X {
- X if( $2 < 512 )
- X {
- X printf("Page size too small\n");
- X $$ = 512;
- X }
- X else
- X $$ = $2;
- X }
- X ;
- X
- Xdecl_list : decl
- X | decl_list decl
- X ;
- X
- Xdecl : T_DATA T_FILE pagesize T_STRING T_CONTAINS T_IDENT ';'
- X {
- X add_contains('d', $6, "");
- X add_file('d', $4, $3);
- X }
- X | T_KEY T_FILE pagesize T_STRING T_CONTAINS T_IDENT '.' key_type ';'
- X {
- X char type = strcmp($8, "<ref>") ? 'k' : 'r';
- X
- X add_contains(type, $6, $8);
- X add_file(type, $4, $3);
- X }
- X | record_head '{' member_list opt_key_list '}'
- X {
- X sym_endstruct();
- X record[records-1].size = structnest[curnest+1]->size;
- X structdef[record[records-1].structid].size = record[records-1].size;
- X }
- X | T_DEFINE T_IDENT expr { add_define($2, $3); }
- X | T_MAP '{' map_list '}'
- X ;
- X
- Xrecord_head : T_RECORD T_IDENT { add_record($2);
- X add_structdef($2, 0, 0);
- X sym_addstruct($2, 0); }
- X ;
- X
- Xkey_type : T_IDENT { strcpy($$, $1); }
- X | T_REFERENCES { strcpy($$, "<ref>"); }
- X ;
- X
- Xmember_list : member
- X | member_list member
- X ;
- X
- Xmember : membertype T_IDENT opt_dimen ';'
- X {
- X sym_addmember($2, type, NULL);
- X cur_str->last_member->id = fields;
- X
- X if( type != FT_STRUCT )
- X add_field($2, type);
- X
- X /* Increase the number of level-0 fields of the record */
- X if( curnest == 0 )
- X structdef[record[records-1].structid].members++;
- X
- X type = 0;
- X }
- X | struct_specifier ';'
- X ;
- X
- Xopt_dimen :
- X | dimension opt_varlen_decl
- X ;
- X
- Xdimension : array
- X | dimension array
- X ;
- X
- Xarray : '[' expr ']' { dim[dims++] = $2; }
- X ;
- X
- X
- Xopt_varlen_decl
- X :
- X | T_VARIABLE T_BY T_IDENT
- X {
- X/* if( curnest != 1 )
- X yyerror("variable size fields cannot be nested");*/
- X
- X if( !(size_field = sym_findmember(structnest[0], $3)) )
- X yyerror("unknown struct member '%s'", $3);
- X }
- X ;
- X
- X
- X/*--------------------------------------------------------------------------*/
- X/* Key declaration part */
- X/*--------------------------------------------------------------------------*/
- X
- Xopt_key_list: opt_primary_key_decl
- X opt_alternate_key_decl_list
- X opt_foreign_key_decl_list
- X ;
- X
- X/*--------------------------------------------------------------------------*/
- X/* Primary key */
- X/*--------------------------------------------------------------------------*/
- X
- Xopt_primary_key_decl
- X : /* No primary key */
- X | T_PRIMARY key_decl ';'
- X {
- X key[keys-1].type = KT_PRIMARY|KT_UNIQUE;
- X }
- X ;
- X
- X
- X/*--------------------------------------------------------------------------*/
- X/* Alternate key */
- X/*--------------------------------------------------------------------------*/
- X
- Xopt_alternate_key_decl_list
- X :
- X | alternate_key_decl_list
- X ;
- X
- Xalternate_key_decl_list
- X : alternate_key_decl
- X | alternate_key_decl_list alternate_key_decl
- X ;
- X
- Xalternate_key_decl
- X : T_ALTERNATE opt_unique key_decl opt_null ';'
- X {
- X key[keys-1].type = KT_ALTERNATE | $2 | $4;
- X }
- X ;
- X
- X
- X/*--------------------------------------------------------------------------*/
- X/* Foreign key */
- X/*--------------------------------------------------------------------------*/
- X
- Xopt_foreign_key_decl_list
- X :
- X | foreign_key_decl_list
- X ;
- X
- Xforeign_key_decl_list
- X : foreign_key_decl
- X | foreign_key_decl_list foreign_key_decl
- X ;
- X
- X
- Xforeign_key_decl
- X : T_FOREIGN key_decl T_REFERENCES T_IDENT
- X T_ON T_UPDATE action
- X T_ON T_DELETE action opt_null ';'
- X {
- X /* Set the record's first_foreign field */
- X if( record[records-1].first_foreign == -1 )
- X record[records-1].first_foreign = keys-1;
- X
- X key[keys-1].type = KT_FOREIGN | $7 | $10 | $11;
- X check_foreign_key($4, &key[keys-1]);
- X }
- X ;
- X
- Xaction : T_RESTRICT { $$ = KT_RESTRICT; }
- X | T_CASCADE { $$ = KT_CASCADE;
- X yyerror("'cascade' not supported");
- X }
- X ;
- X
- X
- X/*--------------------------------------------------------------------------*/
- X/* Key declaration rules used by primary, alternate and foreign keys */
- X/*--------------------------------------------------------------------------*/
- X
- Xopt_null : /* not optional */
- X {
- X $$ = 0;
- X }
- X | T_NULL T_BY T_IDENT
- X {
- X sym_member *mem;
- X int type;
- X
- X if( !(mem = sym_findmember(cur_str, $3)) )
- X yyerror("'%s' is not a member the record", $3);
- X else
- X {
- X key[keys-1].null_indicator = mem->id;
- X type = FT_GETBASIC(field[mem->id].type);
- X
- X if( type != FT_CHAR && type != FT_CHARSTR )
- X yyerror("field determiner must be char or string");
- X }
- X
- X $$ = KT_OPTIONAL;
- X }
- X ;
- X
- X
- Xkey_decl : key_decl_head comkey_member_list '}'
- X {
- X sym_endstruct();
- X
- X /* Set the size of the compound key.
- X * Foreign keys have special size.
- X */
- X if( KT_GETBASIC(key[keys-1].type) == KT_FOREIGN )
- X key[keys-1].size = sizeof(REF_ENTRY);
- X else
- X key[keys-1].size = last_str->size;
- X }
- X | T_KEY T_IDENT
- X {
- X sym_member *mem;
- X
- X if( !(mem = sym_findmember(cur_str, $2)) )
- X yyerror("unknown field '%s'", $2);
- X
- X add_key($2);
- X add_keyfield(mem->id, 1);
- X
- X key[keys-1].size = mem->size;
- X field[mem->id].type |= FT_KEY;
- X field[mem->id].keyid = keys-1;
- X }
- X ;
- X
- Xkey_decl_head
- X : T_KEY T_IDENT '{'
- X {
- X /* Ensure that the key name is not also a field name */
- X if( sym_findmember(cur_str, $2) )
- X yyerror("the key '%s' is already a field name", $2);
- X
- X sym_addstruct($2, 0);
- X add_key($2);
- X }
- X ;
- X
- X
- X/*--------------------------------------------------------------------------*/
- X/* Compound key declaration */
- X/*--------------------------------------------------------------------------*/
- X
- Xcomkey_member_list
- X : comkey_member
- X | comkey_member_list ',' comkey_member
- X ;
- X
- Xcomkey_member
- X : T_IDENT opt_sortorder
- X {
- X add_keymember(structnest[curnest-1], $1, $2);
- X }
- X ;
- X
- Xopt_unique : { $$ = 0; /* Not unique */}
- X | T_UNIQUE { $$ = KT_UNIQUE; /* Unique */ }
- X ;
- X
- Xopt_sortorder
- X : /* default */ { $$ = 1; /* Ascending */ }
- X | T_ASC { $$ = 1; /* Ascending */ }
- X | T_DESC { $$ = 0; /* Descending */ }
- X ;
- X
- X/*--------------------------------------------------------------------------*/
- X/* Structure member definition */
- X/*--------------------------------------------------------------------------*/
- X
- Xmembertype : int_type
- X | int_sign { if( type == FT_UNSIGNED )
- X type |= FT_INT; }
- X | int_sign int_type
- X | float_type
- X | u_type
- X | T_LONG float_type { type |= FT_LONG; }
- X ;
- X
- Xint_type : T_CHAR { type |= FT_CHAR; }
- X | T_SHORT { type |= FT_SHORT; }
- X | T_INT { type |= FT_INT; }
- X | T_LONG { type |= FT_LONG; }
- X ;
- X
- Xint_sign : T_SIGNED
- X | T_UNSIGNED { type |= FT_UNSIGNED; }
- X ;
- X
- Xfloat_type : T_FLOAT { type |= FT_FLOAT; }
- X | T_DOUBLE { type |= FT_DOUBLE; }
- X ;
- X
- Xu_type : T_UCHAR { type |= FT_UNSIGNED|FT_CHAR; }
- X | T_USHORT { type |= FT_UNSIGNED|FT_SHORT; }
- X | T_ULONG { type |= FT_UNSIGNED|FT_LONG; }
- X ;
- X
- Xexpr : expr '+' expr { $$ = $1 + $3; }
- X | expr '-' expr { $$ = $1 - $3; }
- X | expr '*' expr { $$ = $1 * $3; }
- X | expr '/' expr { $$ = $1 / $3; }
- X | '(' expr ')' { $$ = $2; }
- X | T_NUMBER
- X ;
- X
- X/*--------------------------------------------------------------------------*/
- X/* struct or union declaration */
- X/*--------------------------------------------------------------------------*/
- X
- Xstruct_specifier
- X : struct_or_union_opt_ident '{' member_list '}' T_IDENT opt_dimen
- X {
- X sym_struct *str;
- X Field *fld;
- X Structdef *strdef;
- X
- X sym_endstruct();
- X
- X str = structnest[curnest + 1];
- X fld = &field[str->fieldid];
- X strdef = &structdef[ fld->structid ];
- X
- X strcpy(fld->name, $5);
- X strdef->size = str->size;
- X strdef->members = str->members;
- X
- X sym_addmember($5, FT_STRUCT, structnest[curnest+1]);
- X
- X fld->size = cur_str->last_member->size;
- X fld->elemsize = cur_str->last_member->elemsize;
- X fld->offset = cur_str->last_member->offset;
- X
- X if( size_field )
- X {
- X fld->type |= FT_VARIABLE;
- X fld->keyid = size_field->id;
- X size_field = NULL;
- X }
- X }
- X | struct_or_union T_IDENT T_IDENT opt_dimen
- X {
- X sym_struct *str = sym_findstruct($2, $1);
- X
- X if( str )
- X {
- X sym_addmember($3, FT_STRUCT, str);
- X/* add_field($3, FT_STRUCT);*/
- X }
- X /* else error message */
- X }
- X ;
- X
- Xstruct_or_union_opt_ident
- X : struct_or_union opt_ident
- X {
- X add_field("<struct>", FT_STRUCT);
- X sym_addstruct($2, $1);
- X cur_str->fieldid = fields-1;
- X field[fields-1].structid = structdefs;
- X
- X add_structdef($2, $1, $1 ? control_field->id : 0);
- X
- X /* Increase the number of level-0 field of the record.
- X * Actually, at this point the grammar we have moved to
- X * level 1.
- X */
- X if( curnest == 1 )
- X structdef[record[records-1].structid].members++;
- X }
- X ;
- X
- Xstruct_or_union
- X : T_STRUCT
- X {
- X $$ = 0;
- X }
- X | T_UNION T_CONTROLLED T_BY T_IDENT
- X {
- X $$ = 1;
- X if( !(control_field = sym_findmember(cur_str, $4)) )
- X yyerror("'%s' is not a member of the union/struct '%s'",
- X $4, cur_str->name);
- X }
- X ;
- X
- Xopt_ident : { *$$ = 0; }
- X | T_IDENT { strcpy($$, $1); }
- X ;
- X
- X
- X
- X/*--------------------------------------------------------------------------*/
- X/* map_list */
- X/*--------------------------------------------------------------------------*/
- X
- Xmap_list : map
- X | map_list map
- X ;
- X
- Xmap : map_id T_ARROW map_id ';' { header.sorttable[$1] = $3; }
- X ;
- X
- Xmap_id : T_CHARCONST { $$ = $1; }
- X | T_NUMBER { $$ = $1; }
- X ;
- X
- X
- X%%
- X
- X#include <stdio.h>
- X
- X
- X
- Xstatic void add_keymember(str, name, sortorder)
- Xsym_struct *str;
- Xchar *name;
- Xint sortorder;
- X{
- X sym_member *mem;
- X
- X if( mem = sym_findmember(str, name) )
- X {
- X dims = mem->dims;
- X memcpy(dim, mem->dim, sizeof(*dim) * dims);
- X sym_addmember(name, mem->type, mem->struc);
- X add_keyfield(mem->id, sortorder);
- X }
- X else
- X yyerror("unknown struct member '%s'", name);
- X}
- X
- X
- X
- X
- Xextern errors;
- X
- Xyyerror(char *fmt ELLIPSIS)
- X{
- X va_list ap;
- X
- X printf("%s %d: ", ddlname, lex_lineno);
- X va_start(ap, fmt);
- X vprintf(fmt, ap);
- X puts("");
- X va_end(ap);
- X errors++;
- X return 0;
- X}
- X
- X/* end-of-file */
- END_OF_FILE
- if test 14286 -ne `wc -c <'typhoon/src/util/ddl.y'`; then
- echo shar: \"'typhoon/src/util/ddl.y'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/util/ddl.y'
- fi
- if test -f 'typhoon/src/util/ddlp.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/util/ddlp.c'\"
- else
- echo shar: Extracting \"'typhoon/src/util/ddlp.c'\" \(21611 characters\)
- sed "s/^X//" >'typhoon/src/util/ddlp.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : ddlp.c
- X * Program : ddlp
- X * OS : UNIX, OS/2, DOS
- X * Author : Thomas B. Pedersen
- X *
- X * Copyright (c) 1994 Thomas B. Pedersen. All rights reserved.
- X *
- X * Permission is hereby granted, without written agreement and without
- X * license or royalty fees, to use, copy, modify, and distribute this
- X * software and its documentation for any purpose, provided that the above
- X * copyright notice and the following two paragraphs appear (1) in all
- X * source copies of this software and (2) in accompanying documentation
- X * wherever the programatic interface of this software, or any derivative
- X * of it, is described.
- X *
- X * IN NO EVENT SHALL THOMAS B. PEDERSEN BE LIABLE TO ANY PARTY FOR DIRECT,
- X * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
- X * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF HE HAS BEEN
- X * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- X *
- X * THOMAS B. PEDERSEN SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
- X * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- X * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
- X * BASIS, AND THOMAS B. PEDERSEN HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
- X * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- X *
- X * Description:
- X * Grammar for ddl-files.
- X *
- X * $Log: ddlp.c,v $
- X * Revision 1.2 1994/09/17 16:00:51 tbp
- X * typhoon.h and environ.h are now included from <>.
- X *
- X * Revision 1.1 1994/09/13 21:28:52 tbp
- X * Added to repository.
- X *
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- Xstatic char rcsid[] = "$Id: ddlp.c,v 1.2 1994/09/17 16:00:51 tbp Exp $";
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <ctype.h>
- X#include <fcntl.h>
- X#include <stdarg.h>
- X#ifndef UNIX
- X# include <sys\types.h>
- X# include <sys\stat.h>
- X# include <stdlib.h>
- X# include <io.h>
- X#endif
- X#define DEFINE_GLOBALS
- X#include <typhoon.h>
- X#include "../ty_dbd.h"
- X#include "../ty_type.h"
- X#include "ddlp.h"
- X#include "ddlpsym.h"
- X#include "ddlpglob.h"
- X#include "ddl_y.h"
- X
- X/*-------------------------- Function prototypes ---------------------------*/
- Xint yyparse PRM( (void); )
- Xvoid align_offset PRM( (unsigned *, int); )
- Xvoid check_consistency PRM( (void); )
- Xvoid print_fieldname PRM( (FILE *, int, Id); )
- Xvoid fix_file PRM( (void); )
- Xvoid fix_fields PRM( (void); )
- X
- X/*---------------------------- Global variables ----------------------------*/
- XFILE *lex_file, *hfile;
- Xint dbdfile;
- X
- Xstatic char paramhelp[] = "\
- XSyntax: ddlp [option]... file[.ddl]\n\
- XOptions:\n\
- X -a[1|2|4] Set structure alignment (default is %d)\n\
- X -f Only generate field constants for keys\n\
- X -h<file> Use <file> as header file\n";
- X
- X
- X
- Xchar *strupr(s)
- Xchar *s;
- X{
- X char *olds = s;
- X
- X while( *s )
- X {
- X *s = toupper(*s);
- X s++;
- X }
- X
- X return olds;
- X}
- X
- X
- X#ifdef UNIX
- X#ifndef __STDC__
- Xchar *strstr(s1, s2)
- Xchar *s1, *s2;
- X{
- X int len = strlen(s2);
- X
- X while( *s1 )
- X {
- X if( *s2 == *s1 )
- X if( !memcmp(*s1,s2,len) )
- X return s1;
- X s1++;
- X }
- X return NULL;
- X}
- X#endif
- X#endif
- X
- X
- Xistrcmp(s1, s2)
- Xchar *s1, *s2;
- X{
- X while( tolower(*s1) == tolower(*s2) && *s1 && *s2 )
- X s1++, s2++;
- X
- X return tolower(*s1) - tolower(*s2);
- X}
- X
- X
- X/*------------------------------ align_offset ------------------------------*\
- X *
- X * Purpose : Align an address to fit the next field type.
- X *
- X * Parameters: offset - Offset to align.
- X * type - Field type (FT_...).
- X *
- X * Returns : offset - The aligned offset.
- X *
- X */
- Xvoid align_offset(offset, type)
- Xunsigned *offset;
- Xint type;
- X{
- X int rem = *offset % align;
- X int size;
- X
- X/* if( type == FT_STRUCT )
- X return;*/
- X
- X if( !rem || FT_GETBASIC(type) == FT_CHAR || !*offset )
- X return;
- X
- X if( type == FT_STRUCT )
- X size = sizeof(long);
- X else
- X size = typeinfo[FT_GETBASIC(type) - 1].size;
- X
- X if( rem == size )
- X return;
- X
- X if( size < align - rem )
- X *offset += rem;
- X else
- X *offset += align - rem;
- X}
- X
- X
- X/*--------------------------------- add_key --------------------------------*\
- X *
- X * Purpose : Adds a key definition to the record currently being defined.
- X *
- X * Parameters: name - Key name
- X *
- X * Returns : Nothing.
- X *
- X */
- Xvoid add_key(name)
- Xchar *name;
- X{
- X Key *k = key + keys++;
- X
- X /* Add an entry to the key table */
- X k->first_keyfield = keyfields;
- X k->fields = 0;
- X k->size = 0;
- X strcpy(k->name, name);
- X
- X /* Increase the number of keys in the record */
- X record[records-1].keys++;
- X}
- X
- X
- X/*------------------------------- add_keyfield -----------------------------*\
- X *
- X * Purpose : Adds a field to the key currently being defined.
- X *
- X * Parameters: id - Field id.
- X * ascending - Is key sorted in ascending order?
- X *
- X * Returns : Nothing.
- X *
- X */
- X
- Xvoid add_keyfield(id, ascending)
- XId id;
- Xint ascending;
- X{
- X KeyField *keyfld = keyfield + keyfields++;
- X
- X keyfld->field = id;
- X keyfld->asc = ascending;
- X
- X /* The offset is only used in compound keys */
- X if( key[keys-1].fields )
- X keyfld->offset = cur_str->last_member->offset;
- X else
- X keyfld->offset = 0;
- X
- X /* Increase the number of fields of the key currently being defined */
- X key[keys-1].fields++;
- X}
- X
- X
- Xvoid add_define(name, value)
- Xchar *name;
- Xint value;
- X{
- X strcpy(define[defines].name, name);
- X define[defines++].value = value;
- X}
- X
- X
- Xvoid add_file(type, name, pagesize)
- Xint type;
- Xchar *name;
- Xunsigned pagesize;
- X{
- X file[files].id = -1; /* Unresolved */
- X file[files].type = type;
- X file[files].pagesize= pagesize;
- X strcpy(file[files++].name, name);
- X}
- X
- X
- X/*------------------------------ add_contains ------------------------------*\
- X *
- X * Purpose : Add a new entry to the contains table. This table is used to
- X * determine which records and keys references and are referenced
- X * by the file table entries.
- X *
- X * Parameters: type - 'k' = key, 'r' = record.
- X * record - Record name.
- X * key - Key name ("" if type is 'r').
- X *
- X * Returns : Nothing.
- X *
- X */
- Xvoid add_contains(type, record, key)
- Xint type;
- Xchar *record, *key;
- X{
- X Contains *con = contains + conts++;
- X
- X strcpy(con->record, record);
- X strcpy(con->key, key);
- X con->fileid = files;
- X con->type = type;
- X con->line = lex_lineno;
- X}
- X
- X
- X/*------------------------------- add_record -------------------------------*\
- X *
- X * Purpose : This function adds a new entry to the record table. The fileid
- X * is set to -1 to indicate that the index into file[] is
- X * unresolved. This file be fixed by fix_file().
- X *
- X * Parameters: name - Record name.
- X *
- X * Returns : Nothing.
- X *
- X */
- Xvoid add_record(name)
- Xchar *name;
- X{
- X Record *rec = record + records++;
- X int i;
- X
- X /* Add an entry to the record table */
- X rec->first_field = fields;
- X rec->first_key = keys;
- X rec->first_foreign = -1;
- X rec->size = 0;
- X rec->is_vlr = 0;
- X rec->fileid = -1;
- X rec->structid = structdefs;
- X strcpy(rec->name, name);
- X
- X /* If this record has a reference file, <ref_file> must be set */
- X for( i=0; i<conts; i++ )
- X if( !strcmp(contains[i].record, name) && !strcmp(contains[i].key, "<ref>") )
- X break;
- X
- X if( i < conts )
- X rec->ref_file = contains[i].fileid;
- X else
- X rec->ref_file = -1;
- X
- X /* No variable length fields have occurred in this record so far */
- X varlen_field_occurred = 0;
- X}
- X
- X
- X/*------------------------------- add_field --------------------------------*\
- X *
- X * Purpose : Adds a new entry to the field table.
- X *
- X * If the <size_field> variable is not empty it contains the
- X * name of the field that determines the size of the field being
- X * added. Thus, if <size_field> is non-empty, the field being
- X * added is of variable length.
- X *
- X * Parameters: name - Field name.
- X * type - Field type. Contains FT_... flags.
- X *
- X * Returns : Nothing.
- X *
- X */
- Xvoid add_field(name, type)
- Xchar *name;
- Xint type;
- X{
- X sym_member *mem = cur_str->last_member;
- X Field *fld = field + fields;
- X int i;
- X
- X /* If the field is a char string the FT_CHARSTR flag must be set */
- X if( FT_GETBASIC(type) == FT_CHAR && mem->size > 1 )
- X {
- X type &= ~FT_BASIC; /* Clear the basic flags and set */
- X type |= FT_CHARSTR; /* the FT_CHARSTR flag instead */
- X }
- X
- X fld->recid = records-1; /* Link field to current record */
- X fld->type = type;
- X fld->nesting = curnest;
- X strcpy(fld->name, name);
- X
- X if( type != FT_STRUCT )
- X {
- X fld->size = mem->size;
- X fld->offset = mem->offset;
- X fld->elemsize = mem->elemsize;
- X }
- X
- X record[records-1].fields++;
- X
- X /* Check if the current field is of variable length */
- X if( size_field )
- X {
- X if( mem->dims != 1 )
- X yyerror("variable size fields must be one-dimension arrays");
- X
- X if( (size_field->type & (FT_SHORT|FT_UNSIGNED)) != (FT_SHORT|FT_UNSIGNED) )
- X yyerror("size field '%s' must be 'unsigned short'", size_field->name);
- X
- X /* Store id of size field in keyid (dirty, but saves space) */
- X fld->keyid = size_field->id;
- X fld->type |= FT_VARIABLE;
- X record[records-1].is_vlr = 1;
- X
- X size_field = NULL;
- X
- X /* Ensure that no fixed length fields follow */
- X varlen_field_occurred = 1;
- X }
- X else if( varlen_field_occurred && curnest == 0 )
- X yyerror("fixed length field '%s' follows variable length field", name);
- X
- X fields++;
- X}
- X
- X
- X
- X/*------------------------------ add_structdef -----------------------------*\
- X *
- X * Purpose : Add a structure definition.
- X *
- X * Parameters: name - Structure name.
- X * is_union - Is the structure a union.
- X * control_field- If <is_union> is true this is the id of the
- X * control field.
- X *
- X * Returns : Nothing.
- X *
- X */
- Xvoid add_structdef(name, is_union, control_field)
- Xchar *name;
- Xint is_union, control_field;
- X{
- X Structdef *str = structdef + structdefs++;
- X
- X strcpy(str->name, name);
- X str->first_member = fields;
- X str->is_union = is_union;
- X
- X if( is_union )
- X str->control_field = control_field;
- X}
- X
- X
- X
- X
- X/*---------------------------- check_foreign_key ---------------------------*\
- X *
- X * Purpose : Check that a foreign key matches its target (primary key).
- X *
- X * Parameters: name - Target record name.
- X * foreign_key - Pointer to foreign key.
- X *
- X * Returns : Nothing.
- X *
- X */
- Xvoid check_foreign_key(name, foreign_key)
- Xchar *name;
- XKey *foreign_key;
- X{
- X Record *rec; /* Ptr to parent record */
- X Key *primary_key; /* Ptr to parent's primary key */
- X KeyField *primary_fld; /* Ptr to first field of primary_key */
- X KeyField *foreign_fld; /* Ptr to first field of foreign_key */
- X int i;
- X
- X /* Check if the record has a primary key */
- X for( rec=record, i=0; i<records; rec++, i++ )
- X if( !strcmp(rec->name, name) )
- X break;
- X
- X if( i == records )
- X {
- X yyerror("unknown target record '%s'", name);
- X return;
- X }
- X
- X if( !rec->keys )
- X {
- X yyerror("The target '%s' has no primary key", name);
- X return;
- X }
- X
- X primary_key = &key[ rec->first_key ];
- X
- X if( KT_GETBASIC(primary_key->type) != KT_PRIMARY )
- X {
- X yyerror("The target '%s' has no primary key", name);
- X return;
- X }
- X
- X if( primary_key->fields != foreign_key->fields )
- X {
- X yyerror("The foreign key '%s' does not match its target", name);
- X return;
- X }
- X
- X primary_fld = &keyfield[ primary_key->first_keyfield ];
- X foreign_fld = &keyfield[ foreign_key->first_keyfield ];
- X
- X /* Find the reference file of the parent */
- X foreign_key->parent = rec - record;
- X rec->dependents++;
- X
- X
- X if( rec->ref_file == -1 )
- X {
- X yyerror("The parent table '%s' has no reference file", name);
- X return;
- X }
- X
- X foreign_key->fileid = rec->ref_file;
- X
- X /* Compare the format of the primary key with that of the foreign key */
- X for( i=0; i<primary_key->fields; i++, foreign_fld++, primary_fld++ )
- X {
- X if( FT_GETSIGNEDBASIC(field[primary_fld->field].type) !=
- X FT_GETSIGNEDBASIC(field[foreign_fld->field].type) )
- X break;
- X
- X /* Set sort order */
- X foreign_fld->asc = primary_fld->asc;
- X }
- X
- X if( i < primary_key->fields )
- X {
- X yyerror("The foreign key '%s' does not match its target", name);
- X return;
- X }
- X}
- X
- X
- X/*-------------------------------- fix_file --------------------------------*\
- X *
- X * Purpose : This function sets the fileid of all the records and the keys.
- X *
- X * Parameters: None.
- X *
- X * Returns : Nothing.
- X *
- X */
- Xvoid fix_file()
- X{
- X Contains *con;
- X Record *rec;
- X int i, j, n;
- X
- X for( i=0, con=contains; i<conts; i++, con++ )
- X {
- X /* First find the record entry of this contains */
- X for( j=0, rec=record; j<records; j++, rec++ )
- X if( !strcmp(rec->name, con->record) )
- X break;
- X
- X if( j == records )
- X {
- X printf("unknown record '%s' in contains statement\n", con->record);
- X continue;
- X }
- X
- X /* Link the record or the key to a file and vice versa */
- X switch( con->type )
- X {
- X case 'r':
- X break;
- X
- X case 'd':
- X rec->fileid = con->fileid;
- X
- X if( rec->is_vlr )
- X file[i].type = 'v';
- X break;
- X
- X case 'k':
- X for( n=rec->keys, j=rec->first_key; n--; j++ )
- X if( !strcmp( key[j].name, con->key) )
- X break;
- X
- X if( KT_GETBASIC(key[j].type) == KT_FOREIGN )
- X {
- X int tmp = lex_lineno;
- X
- X lex_lineno = con->line;
- X yyerror("a foreign key cannot be contained in a file");
- X lex_lineno = tmp;
- X break;
- X }
- X
- X if( n < 0 && strcmp(con->key, "<ref>") )
- X {
- X printf("unknown key '%s' contained in file '%s'\n",
- X con->key, file[con->fileid].name);
- X continue;
- X }
- X
- X key[j].fileid = con->fileid;
- X break;
- X }
- X
- X con->entry = j;
- X file[i].id = j;
- X }
- X
- X /* Check that each record is contained is contained in a data file and
- X * each key is contained in a key file
- X */
- X for( i=0, rec=record; i<records; i++, rec++ )
- X {
- X Key *keyptr;
- X
- X /* Calculate the size of the preamble */
- X if( rec->first_foreign != -1 )
- X rec->preamble = (rec->keys - (rec->first_foreign - rec->first_key))
- X * sizeof(ulong);
- X
- X if( rec->fileid == -1 )
- X printf("record '%s' is not contained in a file\n", rec->name);
- X
- X /* If the key is not a foreign key, it must be contained in a file */
- X for( keyptr=&key[rec->first_key], j=0; j<rec->keys; j++, keyptr++ )
- X {
- X if( keyptr->fileid == -1 && KT_GETBASIC(keyptr->type) != KT_FOREIGN )
- X {
- X printf("key '%s.%s' is not contained in a file\n",
- X rec->name, keyptr->name);
- X }
- X }
- X }
- X}
- X
- X
- X
- X/*------------------------------- fix_fields -------------------------------*\
- X *
- X * Purpose : The parser sets the FT_KEY flags on all fields that is a key
- X * or part of a key. This flag should be removed for foreign keys.
- X *
- X * Parameters: None.
- X *
- X * Returns : Nothing.
- X *
- X */
- Xvoid fix_fields()
- X{
- X Field *fld = field;
- X int n = fields;
- X
- X while( n-- )
- X {
- X if( fld->type & FT_KEY )
- X {
- X if( KT_GETBASIC(key[fld->keyid].type) == KT_FOREIGN )
- X fld->type &= ~FT_KEY;
- X }
- X fld++;
- X }
- X}
- X
- X
- X/*---------------------------- print_fieldname -----------------------------*\
- X *
- X * Purpose : Print a field name and its field id in the header file. If the
- X * field name is defined in more than one record it is prefixed
- X * with "<record name>_" to prevent name clashes.
- X *
- X * Parameters: file - File descriptor.
- X * fieldno - Field number.
- X * fieldid - Field id.
- X *
- X * Returns : Nothing.
- X *
- X */
- Xvoid print_fieldname(file, fieldno, fieldid)
- XFILE *file;
- Xint fieldno;
- XId fieldid;
- X{
- X int i;
- X Field *fld = field + fieldno;
- X char *name = fld->name;
- X
- X if( only_keys && !(field[fieldno].type & FT_KEY) )
- X return;
- X
- X fprintf(file, "#define ");
- X
- X for( i=0; i<fields; i++ )
- X {
- X if( field[i].nesting == 0 )
- X {
- X if( !strcmp(field[i].name, name) && i != fieldno )
- X {
- X /* Found a duplicate field name */
- X fprintf(file, "%s_", record[field[fieldno].recid].name);
- X break;
- X }
- X }
- X }
- X
- X fprintf(file, "%s %ldL\n", name, fieldid);
- X
- X if( !strcmp(name, "USERCLASS") )
- X {
- X puts("AAAAAAARRRRRRRRRGGGGGGGG!!!!!!");
- X printf("%d, %d\n", only_keys, field[fieldno].type & FT_KEY);
- X }
- X}
- X
- X
- X
- X#ifdef PROTOTYPES
- Xvoid err_quit(char *s, ...)
- X#else
- Xvoid err_quit(s)
- Xchar *s;
- X#endif
- X{
- X va_list ap;
- X
- X va_start(ap, s);
- X vfprintf(stderr, s, ap);
- X puts("");
- X va_end(ap);
- X exit(1);
- X}
- X
- X
- Xstatic void init_vars()
- X{
- X int i;
- X
- X memset(&header,0,sizeof header);
- X strcpy(header.version, DBD_VERSION);
- X
- X /* Initialize the sorttable */
- X for( i=0; i<256; i++ )
- X header.sorttable[i] = i;
- X
- X for( i=0; i<'z'-'a'+1; i++ )
- X header.sorttable['A' + i] = 'a' + i;
- X}
- X
- X
- Xmain(argc, argv)
- Xchar *argv[];
- X{
- X char *realname;
- X char *p;
- X int i;
- X long n=0, prev;
- X
- X puts("Typhoon Data Definition Language Processsor version 2.24");
- X
- X if( argc == 1 )
- X {
- X printf(paramhelp, align);
- X exit(1);
- X }
- X
- X /* Allocate tables */
- X record = (Record *)calloc(RECORDS_MAX , sizeof(Record));
- X field = (Field *)calloc(FIELDS_MAX , sizeof(Field));
- X file = (File *)calloc(FILES_MAX , sizeof(File));
- X key = (Key *)calloc(KEYS_MAX , sizeof(Key));
- X keyfield = (KeyField *)calloc(KEYFIELDS_MAX , sizeof(KeyField));
- X structdef = (Structdef*)calloc(STRUCTDEFS_MAX, sizeof(Structdef));
- X
- X if( !(record && field && file && key && keyfield && structdef) )
- X {
- X puts("Not enough memory for tables");
- X exit(1);
- X }
- X
- X /* Initialize tables */
- X for( i=0; i<KEYS_MAX; i++ )
- X key[i].fileid = -1;
- X
- X /* Extract the real name of the file */
- X if( (realname = strrchr(argv[argc-1], DIR_SWITCH)) != NULL )
- X realname++;
- X else
- X realname = argv[argc-1];
- X
- X /* remove .ddl extension if present */
- X if( p = strstr(realname, ".ddl") )
- X *p = 0;
- X
- X /* generate file names for .ddl-file, .dbd-file and header file */
- X sprintf(ddlname, "%s.ddl", argv[argc-1]);
- X sprintf(dbdname, "%s.dbd", realname);
- X sprintf(hname, "%s.h", realname);
- X
- X /* process command line options */
- X for( i=1; i<argc-1; i++ )
- X {
- X if( argv[i][0] == '-' || argv[i][0] == '/' )
- X {
- X switch( argv[i][1] )
- X {
- X case 'h':
- X strcpy(hname, argv[i]+2);
- X break;
- X case 'a':
- X align = argv[i][2] - '0';
- X if( align != 1 && align != 2 && align != 4 )
- X err_quit("alignment must be 1, 2 or 4");
- X break;
- X case 'f':
- X only_keys = 1;
- X break;
- X default:
- X err_quit("unknown command line option");
- X }
- X }
- X else
- X err_quit("unknown command line option");
- X }
- X
- X init_vars();
- X
- X /* open files */
- X if( (lex_file=fopen(ddlname, "r")) == NULL )
- X err_quit("cannot open file '%s'", ddlname);
- X
- X if( !(dbdfile=open(dbdname, O_RDWR|O_BINARY|O_TRUNC|O_CREAT, CREATMASK)) )
- X err_quit("cannot create .dbd file '%s'", dbdname);
- X
- X if( (hfile=fopen(hname, "w")) == NULL )
- X err_quit("cannot create header file '%s'", hname);
- X
- X /*---------- initialize h-file ----------*/
- X fprintf(hfile, "/*---------- headerfile for %s ----------*/\n", ddlname);
- X fprintf(hfile, "/* alignment is %d */\n\n", align);
- X
- X /*---------- Initialize tables and parse input ----------*/
- X record[0].first_field = 0;
- X
- X if( !yyparse() )
- X {
- X fix_file();
- X fix_fields();
- X
- X header.files = files;
- X header.keys = keys;
- X header.keyfields = keyfields;
- X header.records = records;
- X header.fields = fields;
- X header.structdefs = structdefs;
- X header.alignment = align;
- X
- X /*---------- write dbd-file ----------*/
- X write(dbdfile, &header, sizeof header);
- X write(dbdfile, file, sizeof(file[0]) * files);
- X write(dbdfile, key, sizeof(key[0]) * keys);
- X write(dbdfile, keyfield, sizeof(keyfield[0]) * keyfields);
- X write(dbdfile, record, sizeof(record[0]) * records);
- X write(dbdfile, field, sizeof(field[0]) * fields);
- X write(dbdfile, structdef, sizeof(structdef[0])* structdefs);
- X
- X /*---------- write h-file ----------*/
- X fprintf(hfile, "/*---------- structures ----------*/\n");
- X print_structures();
- X
- X fprintf(hfile, "/*---------- record names ----------*/\n");
- X for( i=0; i<records; i++ )
- X fprintf(hfile, "#define %s %ldL\n", strupr(record[i].name), (i+1) * REC_FACTOR);
- X
- X for( i=0; i<fields; i++ )
- X strupr(field[i].name);
- X
- X fprintf(hfile, "\n/*---------- field names ----------*/\n");
- X for( i=0, prev=-2; i<fields; i++, n++ )
- X {
- X if( field[i].nesting == 0 )
- X {
- X if( field[i].recid != prev )
- X n = (field[i].recid+1) * REC_FACTOR + 1;
- X
- X print_fieldname(hfile, i, n);
- X prev = field[i].recid;
- X }
- X }
- X
- X /* Print all keys that are either a multi-field key or foreign key */
- X fprintf(hfile, "\n/*---------- key constants ----------*/\n");
- X for( i=0; i<keys; i++ )
- X {
- X /* If the key only has one field, and the name of the key is
- X * the same as the name of the field, then don't print the key name.
- X */
- X if( key[i].fields == 1 &&
- X !istrcmp(key[i].name, field[ keyfield[key[i].first_keyfield].field].name) )
- X continue;
- X
- X if( KT_GETBASIC(key[i].type) != KT_FOREIGN )
- X fprintf(hfile, "#define %s %d\n", strupr(key[i].name), i);
- X }
- X
- X fprintf(hfile, "\n/*---------- integer constants ----------*/\n");
- X for( i=0; i<defines; i++ )
- X fprintf(hfile, "#define %s %d\n", define[i].name, define[i].value);
- X }
- X
- X fclose(hfile);
- X fclose(lex_file);
- X close(dbdfile);
- X
- X if( !errors )
- X printf("%d records, %d fields\n", records, fields);
- X else
- X {
- X unlink(dbdname);
- X unlink(hname);
- X }
- X
- X free(record);
- X free(field);
- X free(file);
- X free(key);
- X free(keyfield);
- X free(structdef);
- X
- X printf("%d lines, %d errors\n", lex_lineno, errors);
- X
- X return errors != 0;
- X}
- X
- X/* end-of-file */
- END_OF_FILE
- if test 21611 -ne `wc -c <'typhoon/src/util/ddlp.c'`; then
- echo shar: \"'typhoon/src/util/ddlp.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/util/ddlp.c'
- fi
- if test -f 'typhoon/src/util/lex.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/util/lex.c'\"
- else
- echo shar: Extracting \"'typhoon/src/util/lex.c'\" \(2849 characters\)
- sed "s/^X//" >'typhoon/src/util/lex.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : @(#)lex.c 93/11/08 Copyright (c) 1993-94 CT Danmark
- X * Compiler: UNIX C, Turbo C, Microsoft C
- X * OS : UNIX, OS/2, DOS
- X * Author : Thomas B. Pedersen
- X *
- X * Description:
- X * General functions for lexical analysers.
- X *
- X * Revision History
- X * ----------------------------------------
- X * 11-Nov-1993 tbp Initial version.
- X *
- X *--------------------------------------------------------------------------*/
- X
- X/*-------------------------- Function prototypes ---------------------------*/
- Xstatic int keywordcmp PRM( (char *, char *); )
- X
- X
- X
- Xvoid lex_skip_comment()
- X{
- X int c, start;
- X
- X start = lex_lineno;
- X for( ;; )
- X {
- X switch( getc(lex_file) )
- X {
- X case '*':
- X if( (c=getc(lex_file)) == '/' )
- X return;
- X else
- X ungetc(c, lex_file);
- X break;
- X case '\n':
- X lex_lineno++;
- X break;
- X case '/':
- X if( (c=getc(lex_file)) == '*' ) /* nested comment */
- X lex_skip_comment();
- X else
- X ungetc(c, lex_file);
- X break;
- X case EOF:
- X fprintf(stderr, "unterminated comment starting in line %d\n", start);
- X exit(1);
- X }
- X }
- X}
- X
- X
- Xstatic keywordcmp(ck,ce)
- Xchar *ck;
- Xchar *ce;
- X{
- X return strcmp(ck, ((LEX_KEYWORD *)ce)->s);
- X}
- X
- X
- X
- Xlex_parse_keyword(char c)
- X{
- X char *p = yylval.s;
- X int i;
- X LEX_KEYWORD *kword;
- X
- X *p = c;
- X
- X do
- X *++p = getc(lex_file);
- X while( isalnum(*p) || *p=='_' );
- X
- X ungetc(*p, lex_file);
- X *p = '\0';
- X
- X if( p - yylval.s > sizeof(yylval.s)-1 )
- X {
- X fprintf(stderr, "line %d: identifier too long, truncated\n", lex_lineno);
- X yylval.s[sizeof(yylval.s)-1] = '\0';
- X }
- X
- X kword = (LEX_KEYWORD *)bsearch(yylval.s,
- X lex_keywordtab,
- X lex_keywords,
- X sizeof(LEX_KEYWORD),
- X (LEX_CMPFUNC)keywordcmp);
- X if( kword == NULL )
- X {
- X#ifdef T_NUMBER
- X /* See if identifier is in define table */
- X for( i=0; i<defines; i++ )
- X if( !strcmp(yylval.s, define[i].name) )
- X {
- X yylval.val = define[i].value;
- X return T_NUMBER;
- X }
- X#endif
- X return T_IDENT;
- X }
- X
- X return kword->token;
- X}
- X
- X#ifdef T_NUMBER
- Xlex_parse_number(char c)
- X{
- X yylval.val = 0;
- X do
- X {
- X yylval.val = yylval.val * 10 + c - '0';
- X c = getc(lex_file);
- X }
- X while( isdigit(c) );
- X ungetc(c, lex_file);
- X
- X return T_NUMBER;
- X}
- X#endif
- X
- X
- X#ifdef T_STRING
- Xlex_parse_string()
- X{
- X char *p = yylval.s;
- X
- X while( (*p = getc(lex_file)) != '"' )
- X {
- X if( *p == '\n' )
- X yyerror("newline in string");
- X else
- X p++;
- X }
- X
- X *p = '\0';
- X
- X return T_STRING;
- X}
- X#endif
- X
- X#ifdef T_CHARCONST
- Xlex_parse_charconst()
- X{
- X /* ' has already been read */
- X yylval.val = getc(lex_file);
- X
- X if( getc(lex_file) != '\'' )
- X yyerror("unterminated character constant");
- X
- X return T_CHARCONST;
- X}
- X#endif
- X
- Xvoid lex_skip_line(void)
- X{
- X int c;
- X
- X while( (c = getc(lex_file)) != '\n' && c != EOF )
- X ;
- X if( c == EOF )
- X ungetc(EOF, lex_file);
- X
- X lex_lineno++;
- X}
- X
- X/* end-of-file */
- X
- END_OF_FILE
- if test 2849 -ne `wc -c <'typhoon/src/util/lex.c'`; then
- echo shar: \"'typhoon/src/util/lex.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/util/lex.c'
- fi
- echo shar: End of archive 1 \(of 9\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 9 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-