summaryrefslogtreecommitdiffstats
path: root/tkhtml1/tools
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2019-01-07 19:34:50 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2019-01-07 19:34:50 (GMT)
commit488dcf87e8e9f24a6d0e7955b7be56d972480ca4 (patch)
treefb96917e1f49ca7bcef7efc1107c1306f604a471 /tkhtml1/tools
parent0dd09186b4455ddd6c9dc09a2e27ea961a185784 (diff)
downloadblt-488dcf87e8e9f24a6d0e7955b7be56d972480ca4.zip
blt-488dcf87e8e9f24a6d0e7955b7be56d972480ca4.tar.gz
blt-488dcf87e8e9f24a6d0e7955b7be56d972480ca4.tar.bz2
update TEA 3.13
Diffstat (limited to 'tkhtml1/tools')
-rw-r--r--tkhtml1/tools/getpage.c171
-rw-r--r--tkhtml1/tools/httpget.c188
-rw-r--r--tkhtml1/tools/makeheaders.c3129
-rw-r--r--tkhtml1/tools/maketokens.tcl94
-rw-r--r--tkhtml1/tools/sgmlparse.c207
-rw-r--r--tkhtml1/tools/url.c268
6 files changed, 0 insertions, 4057 deletions
diff --git a/tkhtml1/tools/getpage.c b/tkhtml1/tools/getpage.c
deleted file mode 100644
index 2b2bc56..0000000
--- a/tkhtml1/tools/getpage.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
-** This is a simple program used to retrieve an HTML document using
-** HTTP. The program also fetches all images that the document
-** references.
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include "getpage.h"
-
-#define stricmp strcasecmp
-
-
-/*
-** Each image to be loaded is an instance of the following structure.
-*/
-typedef struct Image Image;
-struct Image {
- char *zUrl; /* The URL for this image */
- char *zLocal; /* The local filename */
- Image *pNext; /* Next in a list of them all */
-};
-
-static FILE *html; /* Html output to this file. */
-static int nImage = 0; /* Number of images loaded so far */
-static Image *pImage; /* List of all images */
-static global_nErr = 0; /* System wide errors */
-static char baseUrl[1000];/* The base URL */
-static int quiet = 0; /* The quiet flag */
-
-/*
-** Make sure the given URL is loaded as a local file. Return the
-** name of the local file.
-*/
-static char *GetImage(char *zUrl){
- Image *p;
- for(p=pImage; p; p=p->pNext){
- if( strcmp(p->zUrl,zUrl)==0 ){
- return p->zLocal;
- }
- }
- p = malloc( sizeof(*p) + strlen(zUrl) + 100 );
- p->zUrl = (char*)&p[1];
- strcpy(p->zUrl, zUrl);
- p->zLocal = &p->zUrl[strlen(zUrl)+1];
- sprintf(p->zLocal,"image%d", ++nImage);
- p->pNext = pImage;
- pImage = p;
- HttpFetch(zUrl, p->zLocal, quiet, 0, 0);
- return p->zLocal;
-}
-
-/*
-** Print a usage comment and exit
-*/
-void usage(char *argv0){
- fprintf(stderr,"Usage: %s URL\n",argv0);
- exit(1);
-}
-
-/*
-** Handle anything that isn't markup
-*/
-static void WordHandler(const char *zText, void *notUsed){
- fprintf(html, zText);
-}
-
-/*
-** Handle all markup that we don't care about.
-*/
-static void DefaultMarkup(int argc, const char **argv, void *notUsed){
- int i;
- fprintf(html,"<%s",argv[0]);
- for(i=1; i<argc-1; i+=2){
- fprintf(html," %s=\"%s\"", argv[i], argv[i+1]);
- }
- fprintf(html,">");
-}
-
-/*
-** Handler for <IMG> markup
-*/
-static void ImageMarkup(int argc, const char **argv, void *notUsed){
- int i;
- for(i=1; i<argc-1; i+=2){
- if( stricmp(argv[i],"src")==0 ){
- const char *azUrl[2];
- char *zResolved;
- azUrl[0] = argv[i+1];
- azUrl[1] = 0;
- zResolved = ResolveUrl(baseUrl, azUrl);
- if( !quiet ){
- printf("Resolved: (%s) (%s) -> (%s)\n",baseUrl, azUrl[0], zResolved);
- }
- argv[i+1] = GetImage(zResolved);
- /* printf("%s -> %s -> argv[i+1]\n",argv[i+1], zResolved); */
- free(zResolved);
- }
- }
- DefaultMarkup(argc, argv, 0);
-}
-
-/*
-** Handler for <BASE> markup
-*/
-static void BaseMarkup(int argc, const char **argv, void *notUsed){
- int i;
- for(i=1; i<argc-1; i+=2){
- if( stricmp(argv[i],"href")==0 ){
- if( !quiet ){
- printf("Base Href=%s\n",argv[i+1]);
- }
- sprintf(baseUrl,"%.*s", sizeof(baseUrl), argv[i+1]);
- }
- }
-}
-
-/*
-** Name of a temporary file
-*/
-static char zTemp[] = "index.html.orig";
-
-/*
-** The main routine
-*/
-int main(int argc, char **argv){
- int i; /* Loop counter */
- int nErr; /* Number of errors */
- int rc; /* Result code */
- char *zUrl = 0; /* The URL */
- FILE *in; /* For reading the raw html */
-
- if( argc<2 ) usage(argv[0]);
- zUrl = 0;
- for(i=1; i<argc; i++){
- if( strcmp(argv[i],"-quiet")==0 ){
- quiet = 1;
- }else if( argv[i][0]=='-' ){
- usage(argv[0]);
- }else{
- zUrl = argv[i];
- }
- }
- if( zUrl==0 ) usage(argv[0]);
- rc = HttpFetch(zUrl, zTemp, quiet, sizeof(baseUrl), baseUrl);
- if( rc!=200 ){
- unlink(zTemp);
- fprintf(stderr,"Unable to fetch base page %s\n", zUrl);
- exit(1);
- }
- in = fopen(zTemp,"r");
- /* unlink(zTemp); */
- if( in==0 ){
- perror("can't reopen temporary file!");
- exit(1);
- }
- html = fopen("index.html","w");
- if( html==0 ){
- perror("can't open output file \"index.html\"");
- exit(1);
- }
- SgmlWordHandler(WordHandler);
- SgmlSpaceHandler(WordHandler);
- SgmlCommentHandler(WordHandler);
- SgmlDefaultMarkupHandler(DefaultMarkup);
- SgmlHandler("img", ImageMarkup);
- SgmlHandler("base", BaseMarkup);
- SgmlParse(in, 0);
- fclose(in);
- fclose(html);
- return global_nErr;
-}
diff --git a/tkhtml1/tools/httpget.c b/tkhtml1/tools/httpget.c
deleted file mode 100644
index 3532147..0000000
--- a/tkhtml1/tools/httpget.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
-** This file contains code to fetch a single URL into a local file.
-*/
-#include <stdio.h>
-#include <netdb.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <linux/in.h>
-#include "httpget.h"
-
-#define strnicmp strncasecmp
-
-/*
-** Get a URL using HTTP. Return the result code. If a Location: field
-** appears in the header, write it into zLocation[]. Location[] should
-** be at least 200 characters in size.
-*/
-static int
-HttpTryOnce(char *zUrl, char *zLocalFile, int quiet, char *zLocation){
- int i, j;
- int nErr = 0; /* Number of errors */
- char *zPath; /* Pathname to send as second argument to GET */
- int iPort; /* TCP port for the server */
- struct hostent *pHost; /* Name information */
- int s; /* The main communications socket */
- int c; /* A character read from the remote side */
- int n; /* Number of characters in header */
- int rc = 200; /* The result code */
- FILE *sock; /* FILE corresponding to file descriptor s */
- FILE *out; /* Write output here */
- int last_was_nl; /* TRUE if last character received was '\n' */
- struct sockaddr_in addr; /* The address structure */
- int nByte = 0;
- char zIpAddr[400]; /* The IP address of the server to print */
- char zMsg[1000]; /* Space to hold error messages */
- char zLine[1000]; /* A single line of the header */
-
- out = fopen(zLocalFile, "w");
- if( out==0 ){
- sprintf(zMsg, "can't open output fule \"%.100s\"", zLocalFile);
- perror(zMsg);
- return 1;
- }
-
- i = 0;
- if( strnicmp(zUrl,"http:",5)==0 ){ i = 5; }
- while( zUrl[i]=='/' ){ i++; }
- j = 0;
- while( zUrl[i] && zUrl[i]!=':' && zUrl[i]!='/' ){
- if( j<sizeof(zIpAddr)-1 ){ zIpAddr[j++] = zUrl[i]; }
- i++;
- }
- zIpAddr[j] = 0;
- if( zUrl[i]==':' ){
- iPort = 0;
- i++;
- while( isdigit(zUrl[i]) ){
- iPort = iPort*10 + zUrl[i] - '0';
- i++;
- }
- }else{
- iPort = 80;
- }
- zPath = &zUrl[i];
-
- addr.sin_family = AF_INET;
- addr.sin_port = htons(iPort);
- *(int*)&addr.sin_addr = inet_addr(zIpAddr);
- if( -1 == *(int*)&addr.sin_addr ){
- pHost = gethostbyname(zIpAddr);
- if( pHost==0 ){
- fprintf(stderr,"can't resolve host name: %s\n",zIpAddr);
- return 1;
- }
- memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
- if( !quiet ){
- fprintf(stderr,"Address resolution: %s -> %d.%d.%d.%d\n",zIpAddr,
- pHost->h_addr_list[0][0]&0xff,
- pHost->h_addr_list[0][1]&0xff,
- pHost->h_addr_list[0][2]&0xff,
- pHost->h_addr_list[0][3]&0xff);
- }
- }
- s = socket(AF_INET,SOCK_STREAM,0);
- if( s<0 ){
- sprintf(zMsg,"can't open socket to %.100s", zIpAddr);
- perror(zMsg);
- fclose(out);
- return 1;
- }
- if( connect(s,(struct sockaddr*)&addr,sizeof(addr))<0 ){
- sprintf(zMsg,"can't connect to host %.100s", zIpAddr);
- perror(zMsg);
- fclose(out);
- return 1;
- }
- sock = fdopen(s,"r+");
- if( *zPath==0 ) zPath = "/";
- fprintf(sock,"GET %s HTTP/1.0\r\n",zPath);
- fprintf(sock,"User-Agent: Mozilla/2.0 (X11; U; Linux 0.99p17 i486)\r\n");
- if( iPort!=80 ){
- fprintf(sock,"Host: %s:%d\r\n", zIpAddr, iPort);
- }else{
- fprintf(sock,"Host: %s\r\n", zIpAddr);
- }
- fprintf(sock,"Accept: image/gif, image/x-xbitmap, image/jpeg, */*\r\n");
- fprintf(sock,"\r\n");
- fflush(sock);
- n = 0;
- rc = 0;
- while( (c=getc(sock))!=EOF && (c!='\n' || !last_was_nl) ){
- if( c=='\r' ) continue;
- last_was_nl = (c=='\n');
- if( last_was_nl ){
- zLine[n] = 0;
- if( strncmp(zLine,"Location:",9)==0 && zLocation ){
- int j, k;
- for(j=9; isspace(zLine[j]); j++){}
- k = 0;
- while( zLine[j] && !isspace(zLine[j]) && k<199 ){
- zLocation[k++] = zLine[j++];
- }
- zLocation[k] = 0;
- if( !quiet ) fprintf(stderr,"Location: %s\n", zLocation);
- }else if( rc==0 ){
- sscanf(zLine,"HTTP/%*d.%*d %d ",&rc);
- if( !quiet ) fprintf(stderr,"Status: %d\n", rc);
- }
- }
- if( n<sizeof(zLine)-1 ){ zLine[n++] = c; }
- if( last_was_nl ){ n = 0; }
- }
- if( rc==0 ) rc = 200;
- if( !quiet ){
- fprintf(stderr, "Reading %s...", zUrl);
- }
- while( (c=getc(sock))!=EOF ){
- nByte++;
- putc(c,out);
- }
- if( !quiet ){
- fprintf(stderr, " %d bytes\n", nByte);
- }
- fclose(sock);
- fclose(out);
- return rc;
-}
-
-/*
-** Get the file. Take up to 7 redirects.
-*/
-int HttpFetch(
- char *zUrl, /* Fetch this URL */
- char *zLocalFile, /* Write to this file */
- int quiet, /* Be quiet if true */
- int nActual, /* Size of zActual[] */
- char *zActual /* Write actual URL retrieved here */
-){
- int i;
- int rc;
- char *zOriginalUrl = zUrl;
- char zLocation[300];
-
- for(i=0; i<7; i++){
- if( !quiet ) fprintf(stderr,"HTTP: %s -> %s\n", zUrl, zLocalFile);
- rc = HttpTryOnce(zUrl, zLocalFile, quiet, zLocation);
- if( rc==301 || rc==302 ){
- char *z;
- const char *az[2];
- az[0] = zLocation;
- az[1] = 0;
- z = ResolveUrl(zUrl, az);
- if( zUrl!=zOriginalUrl ){
- free(zUrl);
- }
- zUrl = z;
- }else{
- break;
- }
- }
- if( nActual>0 && zActual!=0 ){
- sprintf(zActual, "%.*s", nActual, zUrl);
- }
- if( zUrl!=zOriginalUrl ){
- free(zUrl);
- }
- return rc;
-}
diff --git a/tkhtml1/tools/makeheaders.c b/tkhtml1/tools/makeheaders.c
deleted file mode 100644
index 6d05935..0000000
--- a/tkhtml1/tools/makeheaders.c
+++ /dev/null
@@ -1,3129 +0,0 @@
-/*
-** This program scans C and C++ source files and automatically generates
-** appropriate header files.
-** %Z% %P% %I% %G% %Z%
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <memory.h>
-#include <sys/stat.h>
-#include <assert.h>
-#ifndef WIN32
-# include <unistd.h>
-#else
-# include <string.h>
-#endif
-
-/*
-** Macros for debugging.
-*/
-#ifdef DEBUG
-static int debugMask = 0;
-# define debug0(F,M) if( (F)&debugMask ){ fprintf(stderr,M); }
-# define debug1(F,M,A) if( (F)&debugMask ){ fprintf(stderr,M,A); }
-# define debug2(F,M,A,B) if( (F)&debugMask ){ fprintf(stderr,M,A,B); }
-# define debug3(F,M,A,B,C) if( (F)&debugMask ){ fprintf(stderr,M,A,B,C); }
-# define PARSER 0x00000001
-# define DECL_DUMP 0x00000002
-# define TOKENIZER 0x00000004
-#else
-# define debug0(Flags, Format)
-# define debug1(Flags, Format, A)
-# define debug2(Flags, Format, A, B)
-# define debug3(Flags, Format, A, B, C)
-#endif
-
-/*
-** The following macros are purely for the purpose of testing this
-** program on itself. They don't really contribute to the code.
-*/
-#define INTERFACE 1
-#define EXPORT_INTERFACE 1
-#define EXPORT
-
-/*
-** Each token in a source file is represented by an instance of
-** the following structure. Tokens are collected onto a list.
-*/
-typedef struct Token Token;
-struct Token {
- const char *zText; /* The text of the token */
- int nText; /* Number of characters in the token's text */
- int eType; /* The type of this token */
- int nLine; /* The line number on which the token starts */
- Token *pComment; /* Most recent block comment before this token */
- Token *pNext; /* Next token on the list */
- Token *pPrev; /* Previous token on the list */
-};
-
-/*
-** During tokenization, information about the state of the input
-** stream is held in an instance of the following structure
-*/
-typedef struct InStream InStream;
-struct InStream {
- const char *z; /* Complete text of the input */
- int i; /* Next character to read from the input */
- int nLine; /* The line number for character z[i] */
-};
-
-/*
-** Each declaration in the C or C++ source files is parsed out and stored as
-** an instance of the following structure.
-**
-** A "forward declaration" is a declaration that an object exists that
-** doesn't tell about the objects structure. A typical forward declaration
-** is:
-**
-** struct Xyzzy;
-**
-** Not every object has a forward declaration. If it does, thought, the
-** forward declaration will be contained in the zFwd field for C and
-** the zFwdCpp for C++. The zDecl field contains the complete
-** declaration text.
-*/
-typedef struct Decl Decl;
-struct Decl {
- char *zName; /* Name of the object being declared. The appearance
- ** of this name is a source file triggers the declaration
- ** to be added to the header for that file. */
- char *zFile; /* File from which extracted. */
- char *zIf; /* Surround the declaration with this #if */
- char *zFwd; /* A forward declaration. NULL if there is none. */
- char *zFwdCpp; /* Use this forward declaration for C++. */
- char *zDecl; /* A full declaration of this object */
- struct Include *pInclude; /* #includes that come before this declaration */
- int flags; /* See the "Properties" below */
- Token *pComment; /* A block comment associated with this declaration */
- Token tokenCode; /* Implementation of functions and procedures */
- Decl *pSameName; /* Next declaration with the same "zName" */
- Decl *pSameHash; /* Next declaration with same hash but different zName */
- Decl *pNext; /* Next declaration with a different name */
-};
-
-/*
-** Properties associated with declarations.
-**
-** DP_Forward and DP_Declared are used during the generation of a single
-** header file in order to prevent duplicate declarations and definitions.
-** DP_Forward is set after the object has been given a forward declaration
-** and DP_Declared is set after the object gets a full declarations.
-** (Example: A forward declaration is "typedef struct Abc Abc;" and the
-** full declaration is "struct Abc { int a; float b; };".)
-**
-** The DP_Export and DP_Local flags are more permanent. They mark objects
-** that have EXPORT scope and LOCAL scope respectively. If both of these
-** marks are missing, then the object has library scope. The meanings of
-** the scopes are as follows:
-**
-** LOCAL scope The object is only usable within the file in
-** which it is declared.
-**
-** library scope The object is visible and usable within other
-** files in the same project. By if the project is
-** a library, then the object is not visible to users
-** of the library. (i.e. the object does not appear
-** in the output when using the -H option.)
-**
-** EXPORT scope The object is visible and usable everywhere.
-**
-** The DP_Flag is a temporary use flag that is used during processing to
-** prevent an infinite loop. It's use is localized.
-**
-** The DP_Cplusplus, DP_ExternCReqd and DP_ExternReqd flags are permanent
-** and are used to specify what type of declaration the object requires.
-*/
-#define DP_Forward 0x001 /* Has a forward declaration in this file */
-#define DP_Declared 0x002 /* Has a full declaration in this file */
-#define DP_Export 0x004 /* Export this declaration */
-#define DP_Local 0x008 /* Declare in its home file only */
-#define DP_Flag 0x010 /* Use to mark a subset of a Decl list
- ** for special processing */
-#define DP_Cplusplus 0x020 /* Has C++ linkage and cannot appear in a
- ** C header file */
-#define DP_ExternCReqd 0x040 /* Prepend 'extern "C"' in a C++ header.
- ** Prepend nothing in a C header */
-#define DP_ExternReqd 0x080 /* Prepend 'extern "C"' in a C++ header if
- ** DP_Cplusplus is not also set. If DP_Cplusplus
- ** is set or this is a C header then
- ** prepend 'extern' */
-
-/*
-** Convenience macros for dealing with declaration properties
-*/
-#define DeclHasProperty(D,P) (((D)->flags&(P))==(P))
-#define DeclHasAnyProperty(D,P) (((D)->flags&(P))!=0)
-#define DeclSetProperty(D,P) (D)->flags |= (P)
-#define DeclClearProperty(D,P) (D)->flags &= ~(P)
-
-/*
-** These are state properties of the parser. Each of the values is
-** distinct from the DP_ values above so that both can be used in
-** the same "flags" field.
-**
-** Be careful not to confuse PS_Export with DP_Export or
-** PS_Local with DP_Local. Their names are similar, but the meanings
-** of these flags are very different.
-*/
-#define PS_Extern 0x000800 /* "extern" has been seen */
-#define PS_Export 0x001000 /* If between "#if EXPORT_INTERFACE"
- ** and "#endif" */
-#define PS_Export2 0x002000 /* If "EXPORT" seen */
-#define PS_Typedef 0x004000 /* If "typedef" has been seen */
-#define PS_Static 0x008000 /* If "static" has been seen */
-#define PS_Interface 0x010000 /* If within #if INTERFACE..#endif */
-#define PS_Method 0x020000 /* If "::" token has been seen */
-#define PS_Local 0x040000 /* If within #if LOCAL_INTERFACE..#endif */
-#define PS_Local2 0x080000 /* If "LOCAL" seen. */
-
-/*
-** The following set of flags are ORed into the "flags" field of
-** a Decl in order to identify what type of object is being
-** declared.
-*/
-#define TY_Class 0x00100000
-#define TY_Subroutine 0x00200000
-#define TY_Macro 0x00400000
-#define TY_Typedef 0x00800000
-#define TY_Variable 0x01000000
-#define TY_Structure 0x02000000
-#define TY_Union 0x04000000
-#define TY_Enumeration 0x08000000
-#define TY_Defunct 0x10000000 /* Used to erase a declaration */
-
-/*
-** Each nested #if (or #ifdef or #ifndef) is stored in a stack of
-** instances of the following structure.
-*/
-typedef struct Ifmacro Ifmacro;
-struct Ifmacro {
- int nLine; /* Line number where this macro occurs */
- char *zCondition; /* Text of the condition for this macro */
- Ifmacro *pNext; /* Next down in the stack */
- int flags; /* Can hold PS_Export, PS_Interface or PS_Local flags */
-};
-
-/*
-** When parsing a file, we need to keep track of what other files have
-** be #include-ed. For each #include found, we create an instance of
-** the following structure.
-*/
-typedef struct Include Include;
-struct Include {
- char *zFile; /* The name of file include. Includes "" or <> */
- char *zIf; /* If not NULL, #include should be enclosed in #if */
- char *zLabel; /* A unique label used to test if this #include has
- * appeared already in a file or not */
- Include *pNext; /* Previous include file, or NULL if this is the first */
-};
-
-/*
-** Identifiers found in a source file that might be used later to provoke
-** the copying of a declaration into the corresponding header file are
-** stored in a hash table as instances of the following structure.
-*/
-typedef struct Ident Ident;
-struct Ident {
- char *zName; /* The text of this identifier */
- Ident *pCollide; /* Next identifier with the same hash */
- Ident *pNext; /* Next identifier in a list of them all */
-};
-
-/*
-** A complete table of identifiers is stored in an instance of
-** the next structure.
-*/
-#define IDENT_HASH_SIZE 2237
-typedef struct IdentTable IdentTable;
-struct IdentTable {
- Ident *pList; /* List of all identifiers in this table */
- Ident *apTable[IDENT_HASH_SIZE]; /* The hash table */
-};
-
-/*
-** The following structure holds all information for a single
-** source file named on the command line of this program.
-*/
-typedef struct InFile InFile;
-struct InFile {
- char *zSrc; /* Name of input file */
- char *zHdr; /* Name of the generated .h file for this input.
- ** Will be NULL if input is to be scanned only */
- int flags; /* One or more DP_, PS_ and/or TY_ flags */
- InFile *pNext; /* Next input file in the list of them all */
- IdentTable idTable; /* All identifiers in this input file */
-};
-
-/*
-** An unbounded string is able to grow without limit. We use these
-** to construct large in-memory strings from lots of smaller components.
-*/
-typedef struct String String;
-struct String {
- int nAlloc; /* Number of bytes allocated */
- int nUsed; /* Number of bytes used (not counting null terminator) */
- char *zText; /* Text of the string */
-};
-
-/*
-** The following structure contains a lot of state information used
-** while generating a .h file. We put the information in this structure
-** and pass around a pointer to this structure, rather than pass around
-** all of the information separately. This helps reduce the number of
-** arguments to generator functions.
-*/
-typedef struct GenState GenState;
-struct GenState {
- String *pStr; /* Write output to this string */
- IdentTable *pTable; /* A table holding the zLabel of every #include that
- * has already been generated. Used to avoid
- * generating duplicate #includes. */
- const char *zIf; /* If not NULL, then we are within a #if with
- * this argument. */
- int nErr; /* Number of errors */
- const char *zFilename; /* Name of the source file being scanned */
- int flags; /* Various flags (DP_ and PS_ flags above) */
-};
-
-/*
-** The following text line appears at the top of every file generated
-** by this program. By recognizing this line, the program can be sure
-** never to read a file that it generated itself.
-*/
-const char zTopLine[] =
- "/* \aThis file was automatically generated. Do not edit! */\n";
-#define nTopLine (sizeof(zTopLine)-1)
-
-/*
-** The name of the file currently being parsed.
-*/
-static char *zFilename;
-
-/*
-** The stack of #if macros for the file currently being parsed.
-*/
-static Ifmacro *ifStack = 0;
-
-/*
-** A list of all files that have been #included so far in a file being
-** parsed.
-*/
-static Include *includeList = 0;
-
-/*
-** The last block comment seen.
-*/
-static Token *blockComment = 0;
-
-/*
-** The following flag is set if the -doc flag appears on the
-** command line.
-*/
-static int doc_flag = 0;
-
-/*
-** If the following flag is set, then makeheaders will attempt to
-** generate prototypes for static functions and procedures.
-*/
-static int proto_static = 0;
-
-/*
-** A list of all declarations. The list is held together using the
-** pNext field of the Decl structure.
-*/
-static Decl *pDeclFirst; /* First on the list */
-static Decl *pDeclLast; /* Last on the list */
-
-/*
-** A hash table of all declarations
-*/
-#define DECL_HASH_SIZE 3371
-static Decl *apTable[DECL_HASH_SIZE];
-
-/*
-** The TEST macro must be defined to something. Make sure this is the
-** case.
-*/
-#ifndef TEST
-# define TEST 0
-#endif
-
-#ifdef NOT_USED
-/*
-** We do our own assertion macro so that we can have more control
-** over debugging.
-*/
-#define Assert(X) if(!(X)){ CantHappen(__LINE__); }
-#define CANT_HAPPEN CantHappen(__LINE__)
-static void CantHappen(int iLine){
- fprintf(stderr,"Assertion failed on line %d\n",iLine);
- *(char*)1 = 0; /* Force a core-dump */
-}
-#endif
-
-/*
-** Memory allocation functions that are guaranteed never to return NULL.
-*/
-static void *SafeMalloc(int nByte){
- void *p = malloc( nByte );
- if( p==0 ){
- fprintf(stderr,"Out of memory. Can't allocate %d bytes.\n",nByte);
- exit(1);
- }
- return p;
-}
-static void SafeFree(void *pOld){
- if( pOld ){
- free(pOld);
- }
-}
-static void *SafeRealloc(void *pOld, int nByte){
- void *p;
- if( pOld==0 ){
- p = SafeMalloc(nByte);
- }else{
- p = realloc(pOld, nByte);
- if( p==0 ){
- fprintf(stderr,
- "Out of memory. Can't enlarge an allocation to %d bytes\n",nByte);
- exit(1);
- }
- }
- return p;
-}
-static char *StrDup(const char *zSrc, int nByte){
- char *zDest;
- if( nByte<=0 ){
- nByte = strlen(zSrc);
- }
- zDest = SafeMalloc( nByte + 1 );
- strncpy(zDest,zSrc,nByte);
- zDest[nByte] = 0;
- return zDest;
-}
-
-/*
-** Return TRUE if the character X can be part of an identifier
-*/
-#define ISALNUM(X) ((X)=='_' || isalnum(X))
-
-/*
-** Routines for dealing with unbounded strings.
-*/
-static void StringInit(String *pStr){
- pStr->nAlloc = 0;
- pStr->nUsed = 0;
- pStr->zText = 0;
-}
-static void StringReset(String *pStr){
- SafeFree(pStr->zText);
- StringInit(pStr);
-}
-static void StringAppend(String *pStr, const char *zText, int nByte){
- if( nByte<=0 ){
- nByte = strlen(zText);
- }
- if( pStr->nUsed + nByte >= pStr->nAlloc ){
- if( pStr->nAlloc==0 ){
- pStr->nAlloc = nByte + 100;
- pStr->zText = SafeMalloc( pStr->nAlloc );
- }else{
- pStr->nAlloc = pStr->nAlloc*2 + nByte;
- pStr->zText = SafeRealloc(pStr->zText, pStr->nAlloc);
- }
- }
- strncpy(&pStr->zText[pStr->nUsed],zText,nByte);
- pStr->nUsed += nByte;
- pStr->zText[pStr->nUsed] = 0;
-}
-#define StringGet(S) ((S)->zText?(S)->zText:"")
-
-/*
-** Compute a hash on a string. The number returned is a non-negative
-** value between 0 and 2**31 - 1
-*/
-static int Hash(const char *z, int n){
- int h = 0;
- if( n<=0 ){
- n = strlen(z);
- }
- while( n-- ){
- h = h ^ (h<<5) ^ *z++;
- }
- if( h<0 ) h = -h;
- return h;
-}
-
-/*
-** Given an identifier name, try to find a declaration for that
-** identifier in the hash table. If found, return a pointer to
-** the Decl structure. If not found, return 0.
-*/
-static Decl *FindDecl(const char *zName, int len){
- int h;
- Decl *p;
-
- if( len<=0 ){
- len = strlen(zName);
- }
- h = Hash(zName,len) % DECL_HASH_SIZE;
- p = apTable[h];
- while( p && (strncmp(p->zName,zName,len)!=0 || p->zName[len]!=0) ){
- p = p->pSameHash;
- }
- return p;
-}
-
-/*
-** Install the given declaration both in the hash table and on
-** the list of all declarations.
-*/
-static void InstallDecl(Decl *pDecl){
- int h;
- Decl *pOther;
-
- h = Hash(pDecl->zName,0) % DECL_HASH_SIZE;
- pOther = apTable[h];
- while( pOther && strcmp(pDecl->zName,pOther->zName)!=0 ){
- pOther = pOther->pSameHash;
- }
- if( pOther ){
- pDecl->pSameName = pOther->pSameName;
- pOther->pSameName = pDecl;
- }else{
- pDecl->pSameName = 0;
- pDecl->pSameHash = apTable[h];
- apTable[h] = pDecl;
- }
- pDecl->pNext = 0;
- if( pDeclFirst==0 ){
- pDeclFirst = pDeclLast = pDecl;
- }else{
- pDeclLast->pNext = pDecl;
- pDeclLast = pDecl;
- }
-}
-
-/*
-** Look at the current ifStack. If anything declared at the current
-** position must be surrounded with
-**
-** #if STUFF
-** #endif
-**
-** Then this routine computes STUFF and returns a pointer to it. Memory
-** to hold the value returned is obtained from malloc().
-*/
-static char *GetIfString(void){
- Ifmacro *pIf;
- char *zResult = 0;
- int hasIf = 0;
- String str;
-
- for(pIf = ifStack; pIf; pIf=pIf->pNext){
- if( pIf->zCondition==0 || *pIf->zCondition==0 ) continue;
- if( !hasIf ){
- hasIf = 1;
- StringInit(&str);
- }else{
- StringAppend(&str," && ",4);
- }
- StringAppend(&str,pIf->zCondition,0);
- }
- if( hasIf ){
- zResult = StrDup(StringGet(&str),0);
- StringReset(&str);
- }else{
- zResult = 0;
- }
- return zResult;
-}
-
-/*
-** Create a new declaration and put it in the hash table. Also
-** return a pointer to it so that we can fill in the zFwd and zDecl
-** fields, and so forth.
-*/
-static Decl *CreateDecl(
- const char *zName, /* Name of the object being declared. */
- int nName /* Length of the name */
-){
- Decl *pDecl;
-
- pDecl = SafeMalloc( sizeof(Decl) + nName + 1);
- memset(pDecl,0,sizeof(Decl));
- pDecl->zName = (char*)&pDecl[1];
- sprintf(pDecl->zName,"%.*s",nName,zName);
- pDecl->zFile = zFilename;
- pDecl->pInclude = includeList;
- pDecl->zIf = GetIfString();
- InstallDecl(pDecl);
- return pDecl;
-}
-
-/*
-** Insert a new identifier into an table of identifiers. Return TRUE if
-** a new identifier was inserted and return FALSE if the identifier was
-** already in the table.
-*/
-static int IdentTableInsert(
- IdentTable *pTable, /* The table into which we will insert */
- const char *zId, /* Name of the identifiers */
- int nId /* Length of the identifier name */
-){
- int h;
- Ident *pId;
-
- if( nId<=0 ){
- nId = strlen(zId);
- }
- h = Hash(zId,nId) % IDENT_HASH_SIZE;
- for(pId = pTable->apTable[h]; pId; pId=pId->pCollide){
- if( strncmp(zId,pId->zName,nId)==0 && pId->zName[nId]==0 ){
- /* printf("Already in table: %.*s\n",nId,zId); */
- return 0;
- }
- }
- pId = SafeMalloc( sizeof(Ident) + nId + 1 );
- pId->zName = (char*)&pId[1];
- sprintf(pId->zName,"%.*s",nId,zId);
- pId->pNext = pTable->pList;
- pTable->pList = pId;
- pId->pCollide = pTable->apTable[h];
- pTable->apTable[h] = pId;
- /* printf("Add to table: %.*s\n",nId,zId); */
- return 1;
-}
-
-/*
-** Check to see if the given value is in the given IdentTable. Return
-** true if it is and false if it is not.
-*/
-static int IdentTableTest(
- IdentTable *pTable, /* The table in which to search */
- const char *zId, /* Name of the identifiers */
- int nId /* Length of the identifier name */
-){
- int h;
- Ident *pId;
-
- if( nId<=0 ){
- nId = strlen(zId);
- }
- h = Hash(zId,nId) % IDENT_HASH_SIZE;
- for(pId = pTable->apTable[h]; pId; pId=pId->pCollide){
- if( strncmp(zId,pId->zName,nId)==0 && pId->zName[nId]==0 ){
- return 1;
- }
- }
- return 0;
-}
-
-/*
-** Remove every identifier from the given table. Reset the table to
-** its initial state.
-*/
-static void IdentTableReset(IdentTable *pTable){
- Ident *pId, *pNext;
-
- for(pId = pTable->pList; pId; pId = pNext){
- pNext = pId->pNext;
- SafeFree(pId);
- }
- memset(pTable,0,sizeof(IdentTable));
-}
-
-#ifdef DEBUG
-/*
-** Print the name of every identifier in the given table, one per line
-*/
-static void IdentTablePrint(IdentTable *pTable, FILE *pOut){
- Ident *pId;
-
- for(pId = pTable->pList; pId; pId = pId->pNext){
- fprintf(pOut,"%s\n",pId->zName);
- }
-}
-#endif
-
-/*
-** Read an entire file into memory. Return a pointer to the memory.
-**
-** The memory is obtained from SafeMalloc and must be freed by the
-** calling function.
-**
-** If the read fails for any reason, 0 is returned.
-*/
-static char *ReadFile(const char *zFilename){
- struct stat sStat;
- FILE *pIn;
- char *zBuf;
- int n;
-
- if( stat(zFilename,&sStat)!=0
-#ifndef WIN32
- || !S_ISREG(sStat.st_mode)
-#endif
- ){
- return 0;
- }
- pIn = fopen(zFilename,"r");
- if( pIn==0 ){
- return 0;
- }
- zBuf = SafeMalloc( sStat.st_size + 1 );
- n = fread(zBuf,1,sStat.st_size,pIn);
- zBuf[n] = 0;
- fclose(pIn);
- return zBuf;
-}
-
-/*
-** Write the contents of a string into a file. Return the number of
-** errors
-*/
-static int WriteFile(const char *zFilename, const char *zOutput){
- FILE *pOut;
- pOut = fopen(zFilename,"w");
- if( pOut==0 ){
- return 1;
- }
- fwrite(zOutput,1,strlen(zOutput),pOut);
- fclose(pOut);
- return 0;
-}
-
-/*
-** Major token types
-*/
-#define TT_Space 1 /* Contiguous white space */
-#define TT_Id 2 /* An identifier */
-#define TT_Preprocessor 3 /* Any C preprocessor directive */
-#define TT_Comment 4 /* Either C or C++ style comment */
-#define TT_Number 5 /* Any numeric constant */
-#define TT_String 6 /* String or character constants. ".." or '.' */
-#define TT_Braces 7 /* All text between { and a matching } */
-#define TT_EOF 8 /* End of file */
-#define TT_Error 9 /* An error condition */
-#define TT_BlockComment 10 /* A C-Style comment at the left margin that
- * spans multple lines */
-#define TT_Other 0 /* None of the above */
-
-/*
-** Get a single low-level token from the input file. Update the
-** file pointer so that it points to the first character beyond the
-** token.
-**
-** A "low-level token" is any token except TT_Braces. A TT_Braces token
-** consists of many smaller tokens and is assembled by a routine that
-** calls this one.
-**
-** The function returns the number of errors. An error is an
-** unterminated string or character literal or an unterminated
-** comment.
-**
-** Profiling shows that this routine consumes about half the
-** CPU time on a typical run of makeheaders.
-*/
-static int GetToken(InStream *pIn, Token *pToken){
- int i;
- const char *z;
- int cStart;
- int c;
- int startLine; /* Line on which a structure begins */
- int nlisc = 0; /* True if there is a new-line in a ".." or '..' */
- int nErr = 0; /* Number of errors seen */
-
- z = pIn->z;
- i = pIn->i;
- pToken->nLine = pIn->nLine;
- pToken->zText = &z[i];
- switch( z[i] ){
- case 0:
- pToken->eType = TT_EOF;
- pToken->nText = 0;
- break;
-
- case '#':
- if( i==0 || z[i-1]=='\n' || (i>1 && z[i-1]=='\r' && z[i-2]=='\n')){
- /* We found a preprocessor statement */
- pToken->eType = TT_Preprocessor;
- i++;
- while( z[i]!=0 && z[i]!='\n' ){
- if( z[i]=='\\' ){
- i++;
- if( z[i]=='\n' ) pIn->nLine++;
- }
- i++;
- }
- pToken->nText = i - pIn->i;
- }else{
- /* Just an operator */
- pToken->eType = TT_Other;
- pToken->nText = 1;
- }
- break;
-
- case ' ':
- case '\t':
- case '\r':
- case '\f':
- case '\n':
- while( isspace(z[i]) ){
- if( z[i]=='\n' ) pIn->nLine++;
- i++;
- }
- pToken->eType = TT_Space;
- pToken->nText = i - pIn->i;
- break;
-
- case '\\':
- pToken->nText = 2;
- pToken->eType = TT_Other;
- if( z[i+1]=='\n' ){
- pIn->nLine++;
- pToken->eType = TT_Space;
- }else if( z[i+1]==0 ){
- pToken->nText = 1;
- }
- break;
-
- case '\'':
- case '\"':
- cStart = z[i];
- startLine = pIn->nLine;
- do{
- i++;
- c = z[i];
- if( c=='\n' ){
- if( !nlisc ){
- fprintf(stderr,
- "%s:%d: (warning) Newline in string or character literal.\n",
- zFilename, pIn->nLine);
- nlisc = 1;
- }
- pIn->nLine++;
- }
- if( c=='\\' ){
- i++;
- c = z[i];
- if( c=='\n' ){
- pIn->nLine++;
- }
- }else if( c==cStart ){
- i++;
- c = 0;
- }else if( c==0 ){
- fprintf(stderr, "%s:%d: Unterminated string or character literal.\n",
- zFilename, startLine);
- nErr++;
- }
- }while( c );
- pToken->eType = TT_String;
- pToken->nText = i - pIn->i;
- break;
-
- case '/':
- if( z[i+1]=='/' ){
- /* C++ style comment */
- while( z[i] && z[i]!='\n' ){ i++; }
- pToken->eType = TT_Comment;
- pToken->nText = i - pIn->i;
- }else if( z[i+1]=='*' ){
- /* C style comment */
- int isBlockComment = i==0 || z[i-1]=='\n';
- i += 2;
- startLine = pIn->nLine;
- while( z[i] && (z[i]!='*' || z[i+1]!='/') ){
- if( z[i]=='\n' ){
- pIn->nLine++;
- if( isBlockComment ){
- if( z[i+1]=='*' || z[i+2]=='*' ){
- isBlockComment = 2;
- }else{
- isBlockComment = 0;
- }
- }
- }
- i++;
- }
- if( z[i] ){
- i += 2;
- }else{
- isBlockComment = 0;
- fprintf(stderr,"%s:%d: Unterminated comment\n",
- zFilename, startLine);
- nErr++;
- }
- pToken->eType = isBlockComment==2 ? TT_BlockComment : TT_Comment;
- pToken->nText = i - pIn->i;
- }else{
- /* A divide operator */
- pToken->eType = TT_Other;
- pToken->nText = 1;
- }
- break;
-
- case '0':
- if( z[i+1]=='x' || z[i+1]=='X' ){
- /* A hex constant */
- i += 2;
- while( isxdigit(z[i]) ){ i++; }
- }else{
- /* An octal constant */
- while( isdigit(z[i]) ){ i++; }
- }
- pToken->eType = TT_Number;
- pToken->nText = i - pIn->i;
- break;
-
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- while( isdigit(z[i]) ){ i++; }
- if( (c=z[i])=='.' ){
- i++;
- while( isdigit(z[i]) ){ i++; }
- c = z[i];
- if( c=='e' || c=='E' ){
- i++;
- if( ((c=z[i])=='+' || c=='-') && isdigit(z[i+1]) ){ i++; }
- while( isdigit(z[i]) ){ i++; }
- c = z[i];
- }
- if( c=='f' || c=='F' || c=='l' || c=='L' ){ i++; }
- }else if( c=='e' || c=='E' ){
- i++;
- if( ((c=z[i])=='+' || c=='-') && isdigit(z[i+1]) ){ i++; }
- while( isdigit(z[i]) ){ i++; }
- }else if( c=='L' || c=='l' ){
- i++;
- c = z[i];
- if( c=='u' || c=='U' ){ i++; }
- }else if( c=='u' || c=='U' ){
- i++;
- c = z[i];
- if( c=='l' || c=='L' ){ i++; }
- }
- pToken->eType = TT_Number;
- pToken->nText = i - pIn->i;
- break;
-
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
- case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
- case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
- case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B':
- case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I':
- case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
- case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W':
- case 'X': case 'Y': case 'Z': case '_':
- while( isalnum(z[i]) || z[i]=='_' ){ i++; };
- pToken->eType = TT_Id;
- pToken->nText = i - pIn->i;
- break;
-
- default:
- pToken->eType = TT_Other;
- pToken->nText = 1;
- break;
- }
- pIn->i += pToken->nText;
- return nErr;
-}
-
-/*
-** This routine recovers the next token from the input file which is
-** not a space or a comment or any text between an "#if 0" and "#endif".
-**
-** This routine returns the number of errors encountered. An error
-** is an unterminated token or unmatched "#if 0".
-**
-** Profiling shows that this routine uses about a quarter of the
-** CPU time in a typical run.
-*/
-static int GetNonspaceToken(InStream *pIn, Token *pToken){
- int nIf = 0;
- int inZero = 0;
- const char *z;
- int value;
- int startLine;
- int nErr = 0;
-
- startLine = pIn->nLine;
- while( 1 ){
- nErr += GetToken(pIn,pToken);
- /* printf("%04d: Type=%d nIf=%d [%.*s]\n",
- pToken->nLine,pToken->eType,nIf,pToken->nText,
- pToken->eType!=TT_Space ? pToken->zText : "<space>"); */
- pToken->pComment = blockComment;
- switch( pToken->eType ){
- case TT_Comment:
- case TT_Space:
- break;
-
- case TT_BlockComment:
- if( doc_flag ){
- blockComment = SafeMalloc( sizeof(Token) );
- *blockComment = *pToken;
- }
- break;
-
- case TT_EOF:
- if( nIf ){
- fprintf(stderr,"%s:%d: Unterminated \"#if\"\n",
- zFilename, startLine);
- nErr++;
- }
- return nErr;
-
- case TT_Preprocessor:
- z = &pToken->zText[1];
- while( *z==' ' || *z=='\t' ) z++;
- if( sscanf(z,"if %d",&value)==1 && value==0 ){
- nIf++;
- inZero = 1;
- }else if( inZero ){
- if( strncmp(z,"if",2)==0 ){
- nIf++;
- }else if( strncmp(z,"endif",5)==0 ){
- nIf--;
- if( nIf==0 ) inZero = 0;
- }
- }else{
- return nErr;
- }
- break;
-
- default:
- if( !inZero ){
- return nErr;
- }
- break;
- }
- }
- /* NOT REACHED */
-}
-
-/*
-** This routine looks for identifiers (strings of contiguous alphanumeric
-** characters) within a preprocessor directive and adds every such string
-** found to the given identifier table
-*/
-static void FindIdentifiersInMacro(Token *pToken, IdentTable *pTable){
- Token sToken;
- InStream sIn;
- int go = 1;
-
- sIn.z = pToken->zText;
- sIn.i = 1;
- sIn.nLine = 1;
- while( go && sIn.i < pToken->nText ){
- GetToken(&sIn,&sToken);
- switch( sToken.eType ){
- case TT_Id:
- IdentTableInsert(pTable,sToken.zText,sToken.nText);
- break;
-
- case TT_EOF:
- go = 0;
- break;
-
- default:
- break;
- }
- }
-}
-
-/*
-** This routine gets the next token. Everything contained within
-** {...} is collapsed into a single TT_Braces token. Whitespace is
-** omitted.
-**
-** If pTable is not NULL, then insert every identifier seen into the
-** IdentTable. This includes any identifiers seen inside of {...}.
-**
-** The number of errors encountered is returned. An error is an
-** unterminated token.
-*/
-static int GetBigToken(InStream *pIn, Token *pToken, IdentTable *pTable){
- const char *z, *zStart;
- int iStart;
- int nBrace;
- int c;
- int nLine;
- int nErr;
-
- nErr = GetNonspaceToken(pIn,pToken);
- switch( pToken->eType ){
- case TT_Id:
- if( pTable!=0 ){
- IdentTableInsert(pTable,pToken->zText,pToken->nText);
- }
- return nErr;
-
- case TT_Preprocessor:
- if( pTable!=0 ){
- FindIdentifiersInMacro(pToken,pTable);
- }
- return nErr;
-
- case TT_Other:
- if( pToken->zText[0]=='{' ) break;
- return nErr;
-
- default:
- return nErr;
- }
-
- z = pIn->z;
- iStart = pIn->i;
- zStart = pToken->zText;
- nLine = pToken->nLine;
- nBrace = 1;
- while( nBrace ){
- nErr += GetNonspaceToken(pIn,pToken);
- /* printf("%04d: nBrace=%d [%.*s]\n",pToken->nLine,nBrace,
- pToken->nText,pToken->zText); */
- switch( pToken->eType ){
- case TT_EOF:
- fprintf(stderr,"%s:%d: Unterminated \"{\"\n",
- zFilename, nLine);
- nErr++;
- pToken->eType = TT_Error;
- return nErr;
-
- case TT_Id:
- if( pTable ){
- IdentTableInsert(pTable,pToken->zText,pToken->nText);
- }
- break;
-
- case TT_Preprocessor:
- if( pTable!=0 ){
- FindIdentifiersInMacro(pToken,pTable);
- }
- break;
-
- case TT_Other:
- if( (c = pToken->zText[0])=='{' ){
- nBrace++;
- }else if( c=='}' ){
- nBrace--;
- }
- break;
-
- default:
- break;
- }
- }
- pToken->eType = TT_Braces;
- pToken->nText = 1 + pIn->i - iStart;
- pToken->zText = zStart;
- pToken->nLine = nLine;
- return nErr;
-}
-
-/*
-** This routine frees up a list of Tokens. The pComment tokens are
-** not cleared by this. So we leak a little memory when using the -doc
-** option. So what.
-*/
-static void FreeTokenList(Token *pList){
- Token *pNext;
- while( pList ){
- pNext = pList->pNext;
- SafeFree(pList);
- pList = pNext;
- }
-}
-
-/*
-** Tokenize an entire file. Return a pointer to the list of tokens.
-**
-** Space for each token is obtained from a separate malloc() call. The
-** calling function is responsible for freeing this space.
-**
-** If pTable is not NULL, then fill the table with all identifiers seen in
-** the input file.
-*/
-static Token *TokenizeFile(const char *zFile, IdentTable *pTable){
- InStream sIn;
- Token *pFirst = 0, *pLast = 0, *pNew;
- int nErr = 0;
-
- sIn.z = zFile;
- sIn.i = 0;
- sIn.nLine = 1;
- blockComment = 0;
-
- while( sIn.z[sIn.i]!=0 ){
- pNew = SafeMalloc( sizeof(Token) );
- nErr += GetBigToken(&sIn,pNew,pTable);
- debug3(TOKENIZER, "Token on line %d: [%.*s]\n",
- pNew->nLine, pNew->nText<50 ? pNew->nText : 50, pNew->zText);
- if( pFirst==0 ){
- pFirst = pLast = pNew;
- pNew->pPrev = 0;
- }else{
- pLast->pNext = pNew;
- pNew->pPrev = pLast;
- pLast = pNew;
- }
- if( pNew->eType==TT_EOF ) break;
- }
- if( pLast ) pLast->pNext = 0;
- blockComment = 0;
- if( nErr ){
- FreeTokenList(pFirst);
- pFirst = 0;
- }
-
- return pFirst;
-}
-
-#if TEST==1
-/*
-** Use the following routine to test or debug the tokenizer.
-*/
-void main(int argc, char **argv){
- char *zFile;
- Token *pList, *p;
- IdentTable sTable;
-
- if( argc!=2 ){
- fprintf(stderr,"Usage: %s filename\n",*argv);
- exit(1);
- }
- memset(&sTable,0,sizeof(sTable));
- zFile = ReadFile(argv[1]);
- if( zFile==0 ){
- fprintf(stderr,"Can't read file \"%s\"\n",argv[1]);
- exit(1);
- }
- pList = TokenizeFile(zFile,&sTable);
- for(p=pList; p; p=p->pNext){
- int j;
- switch( p->eType ){
- case TT_Space:
- printf("%4d: Space\n",p->nLine);
- break;
- case TT_Id:
- printf("%4d: Id %.*s\n",p->nLine,p->nText,p->zText);
- break;
- case TT_Preprocessor:
- printf("%4d: Preprocessor %.*s\n",p->nLine,p->nText,p->zText);
- break;
- case TT_Comment:
- printf("%4d: Comment\n",p->nLine);
- break;
- case TT_BlockComment:
- printf("%4d: Block Comment\n",p->nLine);
- break;
- case TT_Number:
- printf("%4d: Number %.*s\n",p->nLine,p->nText,p->zText);
- break;
- case TT_String:
- printf("%4d: String %.*s\n",p->nLine,p->nText,p->zText);
- break;
- case TT_Other:
- printf("%4d: Other %.*s\n",p->nLine,p->nText,p->zText);
- break;
- case TT_Braces:
- for(j=0; j<p->nText && j<30 && p->zText[j]!='\n'; j++){}
- printf("%4d: Braces %.*s...}\n",p->nLine,j,p->zText);
- break;
- case TT_EOF:
- printf("%4d: End of file\n",p->nLine);
- break;
- default:
- printf("%4d: type %d\n",p->nLine,p->eType);
- break;
- }
- }
- FreeTokenList(pList);
- SafeFree(zFile);
- IdentTablePrint(&sTable,stdout);
-}
-#endif
-
-#ifdef DEBUG
-/*
-** For debugging purposes, write out a list of tokens.
-*/
-static void PrintTokens(Token *pFirst, Token *pLast){
- int needSpace = 0;
- int c;
-
- pLast = pLast->pNext;
- while( pFirst!=pLast ){
- switch( pFirst->eType ){
- case TT_Preprocessor:
- printf("\n%.*s\n",pFirst->nText,pFirst->zText);
- needSpace = 0;
- break;
-
- case TT_Id:
- case TT_Number:
- printf("%s%.*s", needSpace ? " " : "", pFirst->nText, pFirst->zText);
- needSpace = 1;
- break;
-
- default:
- c = pFirst->zText[0];
- printf("%s%.*s",
- (needSpace && (c=='*' || c=='{')) ? " " : "",
- pFirst->nText, pFirst->zText);
- needSpace = pFirst->zText[0]==',';
- break;
- }
- pFirst = pFirst->pNext;
- }
-}
-#endif
-
-/*
-** Convert a sequence of tokens into a string and return a pointer
-** to that string. Space to hold the string is obtained from malloc()
-** and must be freed by the calling function.
-**
-** The characters ";\n" are always appended.
-*/
-static char *TokensToString(Token *pFirst, Token *pLast){
- char *zReturn;
- String str;
- int needSpace = 0;
- int c;
-
- StringInit(&str);
- pLast = pLast->pNext;
- while( pFirst!=pLast ){
- switch( pFirst->eType ){
- case TT_Preprocessor:
- StringAppend(&str,"\n",1);
- StringAppend(&str,pFirst->zText,pFirst->nText);
- StringAppend(&str,"\n",1);
- needSpace = 0;
- break;
-
- case TT_Id:
- if( pFirst->nText==6 && pFirst->zText[0]=='E'
- && strncmp(pFirst->zText,"EXPORT",6)==0 ){
- break;
- }
- /* Fall thru to the next case */
- case TT_Number:
- if( needSpace ){
- StringAppend(&str," ",1);
- }
- StringAppend(&str,pFirst->zText,pFirst->nText);
- needSpace = 1;
- break;
-
- default:
- c = pFirst->zText[0];
- if( needSpace && (c=='*' || c=='{') ){
- StringAppend(&str," ",1);
- }
- StringAppend(&str,pFirst->zText,pFirst->nText);
- /* needSpace = pFirst->zText[0]==','; */
- needSpace = 0;
- break;
- }
- pFirst = pFirst->pNext;
- }
- StringAppend(&str,";\n",2);
- zReturn = StrDup(StringGet(&str),0);
- StringReset(&str);
- return zReturn;
-}
-
-/*
-** This routine is called when we see one of the keywords "struct",
-** "enum", "union" or "class". This might be the beginning of a
-** type declaration. This routine will process the declaration and
-** remove the declaration tokens from the input stream.
-**
-** If this is a type declaration that is immediately followed by a
-** semicolon (in other words it isn't also a variable definition)
-** then set *pReset to ';'. Otherwise leave *pReset at 0. The
-** *pReset flag causes the parser to skip ahead to the next token
-** that begins with the value placed in the *pReset flag, if that
-** value is different from 0.
-*/
-static int ProcessTypeDecl(Token *pList, int flags, int *pReset){
- Token *pName, *pEnd;
- Decl *pDecl;
- String str;
- int need_to_collapse = 1;
-
- *pReset = 0;
- if( pList==0 || pList->pNext==0 || pList->pNext->eType!=TT_Id ){
- return 0;
- }
- pName = pList->pNext;
-
- /* Catch the case of "struct Foo;" and skip it. */
- if( pName->pNext && pName->pNext->zText[0]==';' ){
- *pReset = ';';
- return 0;
- }
-
- for(pEnd=pName->pNext; pEnd && pEnd->eType!=TT_Braces; pEnd=pEnd->pNext){
- switch( pEnd->zText[0] ){
- case '(':
- case '*':
- case '[':
- case '=':
- case ';':
- return 0;
- }
- }
- if( pEnd==0 ){
- return 0;
- }
-
- /*
- ** At this point, we know we have a type declaration that is bounded
- ** by pList and pEnd and has the name pName.
- */
-
- /*
- ** If the braces are followed immedately by a semicolon, then we are
- ** dealing a type declaration only. There is not variable definition
- ** following the type declaration. So reset...
- */
- if( pEnd->pNext==0 || pEnd->pNext->zText[0]==';' ){
- *pReset = ';';
- need_to_collapse = 0;
- }else{
- need_to_collapse = 1;
- }
-
- if( proto_static==0 && (flags & (PS_Local|PS_Export|PS_Interface))==0 ){
- /* Ignore these objects unless they are explicitly declared as interface,
- ** or unless the "-local" command line option was specified. */
- *pReset = ';';
- return 0;
- }
-
-#ifdef DEBUG
- if( debugMask & PARSER ){
- printf("**** Found type: %.*s %.*s...\n",
- pList->nText, pList->zText, pName->nText, pName->zText);
- PrintTokens(pList,pEnd);
- printf(";\n");
- }
-#endif
- pDecl = CreateDecl(pName->zText,pName->nText);
- if( (flags & PS_Static) || !(flags & (PS_Interface|PS_Export)) ){
- DeclSetProperty(pDecl,DP_Local);
- }
- switch( *pList->zText ){
- case 'c': DeclSetProperty(pDecl,TY_Class); break;
- case 's': DeclSetProperty(pDecl,TY_Structure); break;
- case 'e': DeclSetProperty(pDecl,TY_Enumeration); break;
- case 'u': DeclSetProperty(pDecl,TY_Union); break;
- default: /* Can't Happen */ break;
- }
-
- /* The object has a full declaration only if it is contained within
- ** "#if INTERFACE...#endif" or "#if EXPORT_INTERFACE...#endif" or
- ** "#if LOCAL_INTERFACE...#endif". Otherwise, we only give it a
- ** forward declaration.
- */
- if( flags & (PS_Local | PS_Export | PS_Interface) ){
- pDecl->zDecl = TokensToString(pList,pEnd);
- }else{
- pDecl->zDecl = 0;
- }
- pDecl->pComment = pList->pComment;
- StringInit(&str);
- StringAppend(&str,"typedef ",0);
- StringAppend(&str,pList->zText,pList->nText);
- StringAppend(&str," ",0);
- StringAppend(&str,pName->zText,pName->nText);
- StringAppend(&str," ",0);
- StringAppend(&str,pName->zText,pName->nText);
- StringAppend(&str,";\n",2);
- pDecl->zFwd = StrDup(StringGet(&str),0);
- StringReset(&str);
- StringInit(&str);
- StringAppend(&str,pList->zText,pList->nText);
- StringAppend(&str," ",0);
- StringAppend(&str,pName->zText,pName->nText);
- StringAppend(&str,";\n",2);
- pDecl->zFwdCpp = StrDup(StringGet(&str),0);
- StringReset(&str);
- if( flags & PS_Export ){
- DeclSetProperty(pDecl,DP_Export);
- }else if( flags & PS_Local ){
- DeclSetProperty(pDecl,DP_Local);
- }
-
- /* Here's something weird. ANSI-C doesn't allow a forward declaration
- ** of an enumeration. So we have to build the typedef into the
- ** definition.
- */
- if( pDecl->zDecl && DeclHasProperty(pDecl, TY_Enumeration) ){
- StringInit(&str);
- StringAppend(&str,pDecl->zDecl,0);
- StringAppend(&str,pDecl->zFwd,0);
- SafeFree(pDecl->zDecl);
- SafeFree(pDecl->zFwd);
- pDecl->zFwd = 0;
- pDecl->zDecl = StrDup(StringGet(&str),0);
- StringReset(&str);
- }
-
- if( pName->pNext->zText[0]==':' ){
- DeclSetProperty(pDecl,DP_Cplusplus);
- }
- if( pName->nText==5 && strncmp(pName->zText,"class",5)==0 ){
- DeclSetProperty(pDecl,DP_Cplusplus);
- }
-
- /*
- ** Remove all but pList and pName from the input stream.
- */
- if( need_to_collapse ){
- while( pEnd!=pName ){
- Token *pPrev = pEnd->pPrev;
- pPrev->pNext = pEnd->pNext;
- pEnd->pNext->pPrev = pPrev;
- SafeFree(pEnd);
- pEnd = pPrev;
- }
- }
- return 0;
-}
-
-/*
-** Given a list of tokens that declare something (a function, procedure,
-** variable or typedef) find the token which contains the name of the
-** thing being declared.
-**
-** Algorithm:
-**
-** The name is:
-**
-** 1. The first identifier that is followed by a "[", or
-**
-** 2. The first identifier that is followed by a "(" where the
-** "(" is followed by another identifier, or
-**
-** 3. The first identifier followed by "::", or
-**
-** 4. If none of the above, then the last identifier.
-**
-** In all of the above, certain reserved words (like "char") are
-** not considered identifiers.
-*/
-static Token *FindDeclName(Token *pFirst, Token *pLast){
- Token *pName = 0;
- Token *p;
- int c;
-
- if( pFirst==0 || pLast==0 ){
- return 0;
- }
- pLast = pLast->pNext;
- for(p=pFirst; p && p!=pLast; p=p->pNext){
- if( p->eType==TT_Id ){
- static IdentTable sReserved;
- static int isInit = 0;
- static char *aWords[] = { "char", "class",
- "const", "double", "enum", "extern", "EXPORT", "ET_PROC",
- "float", "int", "long",
- "register", "static", "struct", "sizeof", "signed", "typedef",
- "union", "volatile", "virtual", "void", };
-
- if( !isInit ){
- int i;
- for(i=0; i<sizeof(aWords)/sizeof(aWords[0]); i++){
- IdentTableInsert(&sReserved,aWords[i],0);
- }
- isInit = 1;
- }
- if( !IdentTableTest(&sReserved,p->zText,p->nText) ){
- pName = p;
- }
- }else if( p==pFirst ){
- continue;
- }else if( (c=p->zText[0])=='[' && pName ){
- break;
- }else if( c=='(' && p->pNext && p->pNext->eType==TT_Id && pName ){
- break;
- }else if( c==':' && p->zText[1]==':' && pName ){
- break;
- }
- }
- return pName;
-}
-
-/*
-** This routine is called when we see a function or procedure definition.
-** We make an entry in the declaration table that is a prototype for this
-** function or procedure.
-*/
-static int ProcessProcedureDef(Token *pFirst, Token *pLast, int flags){
- Token *pName;
- Decl *pDecl;
- Token *pCode;
-
- if( pFirst==0 || pLast==0 ){
- return 0;
- }
- if( flags & PS_Method ){
- return 0;
- }
- if( (flags & PS_Static)!=0 && !proto_static ){
- return 0;
- }
- pCode = pLast;
- while( pLast && pLast!=pFirst && pLast->zText[0]!=')' ){
- pLast = pLast->pPrev;
- }
- if( pLast==0 || pLast==pFirst || pFirst->pNext==pLast ){
- fprintf(stderr,"%s:%d: Unrecognized syntax.\n",
- zFilename, pFirst->nLine);
- return 1;
- }
- if( flags & (PS_Interface|PS_Export|PS_Local) ){
- fprintf(stderr,"%s:%d: Missing \"inline\" on function or procedure.\n",
- zFilename, pFirst->nLine);
- return 1;
- }
- pName = FindDeclName(pFirst,pLast);
- if( pName==0 ){
- fprintf(stderr,"%s:%d: Malformed function or procedure definition.\n",
- zFilename, pFirst->nLine);
- return 1;
- }
-
- /*
- ** At this point we've isolated a procedure declaration between pFirst
- ** and pLast with the name pName.
- */
-#ifdef DEBUG
- if( debugMask & PARSER ){
- printf("**** Found routine: %.*s on line %d...\n", pName->nText,
- pName->zText, pFirst->nLine);
- PrintTokens(pFirst,pLast);
- printf(";\n");
- }
-#endif
- pDecl = CreateDecl(pName->zText,pName->nText);
- pDecl->pComment = pFirst->pComment;
- if( pCode && pCode->eType==TT_Braces ){
- pDecl->tokenCode = *pCode;
- }
- DeclSetProperty(pDecl,TY_Subroutine);
- pDecl->zDecl = TokensToString(pFirst,pLast);
- if( (flags & (PS_Static|PS_Local2))!=0 ){
- DeclSetProperty(pDecl,DP_Local);
- }else if( (flags & (PS_Export2))!=0 ){
- DeclSetProperty(pDecl,DP_Export);
- }
-
- if( flags & DP_Cplusplus ){
- DeclSetProperty(pDecl,DP_Cplusplus);
- }else{
- DeclSetProperty(pDecl,DP_ExternCReqd);
- }
-
- return 0;
-}
-
-/*
-** This routine is called whenever we see the "inline" keyword. We
-** need to seek-out the inline function or procedure and make a
-** declaration out of the entire definition.
-*/
-static int ProcessInlineProc(Token *pFirst, int flags, int *pReset){
- Token *pName;
- Token *pEnd;
- Decl *pDecl;
-
- for(pEnd=pFirst; pEnd; pEnd = pEnd->pNext){
- if( pEnd->zText[0]=='{' || pEnd->zText[0]==';' ){
- *pReset = pEnd->zText[0];
- break;
- }
- }
- if( pEnd==0 ){
- *pReset = ';';
- fprintf(stderr,"%s:%d: incomplete inline procedure definition\n",
- zFilename, pFirst->nLine);
- return 1;
- }
- pName = FindDeclName(pFirst,pEnd);
- if( pName==0 ){
- fprintf(stderr,"%s:%d: malformed inline procedure definition\n",
- zFilename, pFirst->nLine);
- return 1;
- }
-
-#ifdef DEBUG
- if( debugMask & PARSER ){
- printf("**** Found inline routine: %.*s on line %d...\n",
- pName->nText, pName->zText, pFirst->nLine);
- PrintTokens(pFirst,pEnd);
- printf("\n");
- }
-#endif
- pDecl = CreateDecl(pName->zText,pName->nText);
- pDecl->pComment = pFirst->pComment;
- DeclSetProperty(pDecl,TY_Subroutine);
- pDecl->zDecl = TokensToString(pFirst,pEnd);
- if( (flags & (PS_Static|PS_Local|PS_Local2)) ){
- DeclSetProperty(pDecl,DP_Local);
- }else if( flags & (PS_Export|PS_Export2) ){
- DeclSetProperty(pDecl,DP_Export);
- }
-
- if( flags & DP_Cplusplus ){
- DeclSetProperty(pDecl,DP_Cplusplus);
- }else{
- DeclSetProperty(pDecl,DP_ExternCReqd);
- }
-
- return 0;
-}
-
-/*
-** Determine if the tokens between pFirst and pEnd form a variable
-** definition or a function prototype. Return TRUE if we are dealing
-** with a variable defintion and FALSE for a prototype.
-**
-** pEnd is the token that ends the object. It can be either a ';' or
-** a '='. If it is '=', then assume we have a variable definition.
-**
-** If pEnd is ';', then the determination is more difficult. We have
-** to search for an occurance of an ID followed immediately by '('.
-** If found, we have a prototype. Otherwise we are dealing with a
-** variable definition.
-*/
-static int isVariableDef(Token *pFirst, Token *pEnd){
- if( pEnd && pEnd->zText[0]=='=' ){
- return 1;
- }
- while( pFirst && pFirst!=pEnd && pFirst->pNext && pFirst->pNext!=pEnd ){
- if( pFirst->eType==TT_Id && pFirst->pNext->zText[0]=='(' ){
- return 0;
- }
- pFirst = pFirst->pNext;
- }
- return 1;
-}
-
-
-/*
-** This routine is called whenever we encounter a ";" or "=". The stuff
-** between pFirst and pLast constitutes either a typedef or a global
-** variable definition. Do the right thing.
-*/
-static int ProcessDecl(Token *pFirst, Token *pEnd, int flags){
- Token *pName;
- Decl *pDecl;
- int isLocal = 0;
- int isVar;
- int nErr = 0;
-
- if( pFirst==0 || pEnd==0 ){
- return 0;
- }
- if( flags & PS_Typedef ){
- if( (flags & (PS_Export2|PS_Local2))!=0 ){
- fprintf(stderr,"%s:%d: \"EXPORT\" or \"LOCAL\" ignored before typedef.\n",
- zFilename, pFirst->nLine);
- nErr++;
- }
- if( (flags & (PS_Interface|PS_Export|PS_Local|DP_Cplusplus))==0 ){
- /* It is illegal to duplicate a typedef in C (but OK in C++).
- ** So don't record typedefs that aren't within a C++ file or
- ** within #if INTERFACE..#endif */
- return nErr;
- }
- if( (flags & (PS_Interface|PS_Export|PS_Local))==0 && proto_static==0 ){
- /* Ignore typedefs that are not with "#if INTERFACE..#endif" unless
- ** the "-local" command line option is used. */
- return nErr;
- }
- if( (flags & (PS_Interface|PS_Export))==0 ){
- /* typedefs are always local, unless within #if INTERFACE..#endif */
- isLocal = 1;
- }
- }else if( flags & (PS_Static|PS_Local2) ){
- if( proto_static==0 && (flags & PS_Local2)==0 ){
- /* Don't record static variables unless the "-local" command line
- ** option was specified or the "LOCAL" keyword is used. */
- return nErr;
- }
- while( pFirst!=0 && pFirst->pNext!=pEnd &&
- ((pFirst->nText==6 && strncmp(pFirst->zText,"static",6)==0)
- || (pFirst->nText==5 && strncmp(pFirst->zText,"LOCAL",6)==0))
- ){
- /* Lose the initial "static" or local from local variables.
- ** We'll prepend "extern" later. */
- pFirst = pFirst->pNext;
- isLocal = 1;
- }
- if( pFirst==0 || !isLocal ){
- return nErr;
- }
- }else if( flags & PS_Method ){
- /* Methods are declared by their class. Don't declare separately. */
- return nErr;
- }
- isVar = (flags & (PS_Typedef|PS_Method))==0 && isVariableDef(pFirst,pEnd);
- if( isVar && (flags & (PS_Interface|PS_Export|PS_Local))!=0
- && (flags & PS_Extern)==0 ){
- fprintf(stderr,"%s:%d: Can't define a variable in this context\n",
- zFilename, pFirst->nLine);
- nErr++;
- }
- pName = FindDeclName(pFirst,pEnd->pPrev);
- if( pName==0 ){
- fprintf(stderr,"%s:%d: Can't find a name for the object declared here.\n",
- zFilename, pFirst->nLine);
- return nErr+1;
- }
-
-#ifdef DEBUG
- if( debugMask & PARSER ){
- if( flags & PS_Typedef ){
- printf("**** Found typedef %.*s at line %d...\n",
- pName->nText, pName->zText, pName->nLine);
- }else if( isVar ){
- printf("**** Found variable %.*s at line %d...\n",
- pName->nText, pName->zText, pName->nLine);
- }else{
- printf("**** Found prototype %.*s at line %d...\n",
- pName->nText, pName->zText, pName->nLine);
- }
- PrintTokens(pFirst,pEnd->pPrev);
- printf(";\n");
- }
-#endif
-
- pDecl = CreateDecl(pName->zText,pName->nText);
- if( (flags & PS_Typedef) ){
- DeclSetProperty(pDecl, TY_Typedef);
- }else if( isVar ){
- DeclSetProperty(pDecl,DP_ExternReqd | TY_Variable);
- if( !(flags & DP_Cplusplus) ){
- DeclSetProperty(pDecl,DP_ExternCReqd);
- }
- }else{
- DeclSetProperty(pDecl, TY_Subroutine);
- if( !(flags & DP_Cplusplus) ){
- DeclSetProperty(pDecl,DP_ExternCReqd);
- }
- }
- pDecl->pComment = pFirst->pComment;
- pDecl->zDecl = TokensToString(pFirst,pEnd->pPrev);
- if( isLocal || (flags & (PS_Local|PS_Local2))!=0 ){
- DeclSetProperty(pDecl,DP_Local);
- }else if( flags & (PS_Export|PS_Export2) ){
- DeclSetProperty(pDecl,DP_Export);
- }
- if( flags & DP_Cplusplus ){
- DeclSetProperty(pDecl,DP_Cplusplus);
- }
- return nErr;
-}
-
-/*
-** Push an if condition onto the if stack
-*/
-static void PushIfMacro(
- const char *zPrefix, /* A prefix, like "define" or "!" */
- const char *zText, /* The condition */
- int nText, /* Number of characters in zText */
- int nLine, /* Line number where this macro occurs */
- int flags /* Either 0, PS_Interface, PS_Export or PS_Local */
-){
- Ifmacro *pIf;
- int nByte;
-
- nByte = sizeof(Ifmacro);
- if( zText ){
- if( zPrefix ){
- nByte += strlen(zPrefix) + 2;
- }
- nByte += nText + 1;
- }
- pIf = SafeMalloc( nByte );
- if( zText ){
- pIf->zCondition = (char*)&pIf[1];
- if( zPrefix ){
- sprintf(pIf->zCondition,"%s(%.*s)",zPrefix,nText,zText);
- }else{
- sprintf(pIf->zCondition,"%.*s",nText,zText);
- }
- }else{
- pIf->zCondition = 0;
- }
- pIf->nLine = nLine;
- pIf->flags = flags;
- pIf->pNext = ifStack;
- ifStack = pIf;
-}
-
-/*
-** This routine is called to handle all preprocessor directives.
-**
-** This routine will recompute the value of *pPresetFlags to be the
-** logical or of all flags on all nested #ifs. The #ifs that set flags
-** are as follows:
-**
-** conditional flag set
-** ------------------------ --------------------
-** #if INTERFACE PS_Interface
-** #if EXPORT_INTERFACE PS_Export
-** #if LOCAL_INTERFACE PS_Local
-**
-** For example, if after processing the preprocessor token given
-** by pToken there is an "#if INTERFACE" on the preprocessor
-** stack, then *pPresetFlags will be set to PS_Interface.
-*/
-static int ParsePreprocessor(Token *pToken, int flags, int *pPresetFlags){
- const char *zCmd;
- int nCmd;
- const char *zArg;
- int nArg;
- int nErr = 0;
- Ifmacro *pIf;
-
- zCmd = &pToken->zText[1];
- while( isspace(*zCmd) && *zCmd!='\n' ){
- zCmd++;
- }
- if( !isalpha(*zCmd) ){
- return 0;
- }
- nCmd = 1;
- while( isalpha(zCmd[nCmd]) ){
- nCmd++;
- }
-
- if( nCmd==5 && strncmp(zCmd,"endif",5)==0 ){
- /*
- ** Pop the if stack
- */
- pIf = ifStack;
- if( pIf==0 ){
- fprintf(stderr,"%s:%d: extra '#endif'.\n",zFilename,pToken->nLine);
- return 1;
- }
- ifStack = pIf->pNext;
- SafeFree(pIf);
- }else if( nCmd==6 && strncmp(zCmd,"define",6)==0 ){
- /*
- ** Record a #define if we are in PS_Interface or PS_Export
- */
- Decl *pDecl;
- if( !(flags & (PS_Local|PS_Interface|PS_Export)) ){ return 0; }
- zArg = &zCmd[6];
- while( *zArg && isspace(*zArg) && *zArg!='\n' ){
- zArg++;
- }
- if( *zArg==0 || *zArg=='\n' ){ return 0; }
- for(nArg=0; ISALNUM(zArg[nArg]); nArg++){}
- if( nArg==0 ){ return 0; }
- pDecl = CreateDecl(zArg,nArg);
- pDecl->pComment = pToken->pComment;
- DeclSetProperty(pDecl,TY_Macro);
- pDecl->zDecl = SafeMalloc( pToken->nText + 2 );
- sprintf(pDecl->zDecl,"%.*s\n",pToken->nText,pToken->zText);
- if( flags & PS_Export ){
- DeclSetProperty(pDecl,DP_Export);
- }else if( flags & PS_Local ){
- DeclSetProperty(pDecl,DP_Local);
- }
- }else if( nCmd==7 && strncmp(zCmd,"include",7)==0 ){
- /*
- ** Record an #include if we are in PS_Interface or PS_Export
- */
- Include *pInclude;
- char *zIf;
-
- if( !(flags & (PS_Interface|PS_Export)) ){ return 0; }
- zArg = &zCmd[7];
- while( *zArg && isspace(*zArg) ){ zArg++; }
- for(nArg=0; !isspace(zArg[nArg]); nArg++){}
- if( (zArg[0]=='"' && zArg[nArg-1]!='"')
- ||(zArg[0]=='<' && zArg[nArg-1]!='>')
- ){
- fprintf(stderr,"%s:%d: malformed #include statement.\n",
- zFilename,pToken->nLine);
- return 1;
- }
- zIf = GetIfString();
- if( zIf ){
- pInclude = SafeMalloc( sizeof(Include) + nArg*2 + strlen(zIf) + 10 );
- pInclude->zFile = (char*)&pInclude[1];
- pInclude->zLabel = &pInclude->zFile[nArg+1];
- sprintf(pInclude->zFile,"%.*s",nArg,zArg);
- sprintf(pInclude->zLabel,"%.*s:%s",nArg,zArg,zIf);
- pInclude->zIf = &pInclude->zLabel[nArg+1];
- SafeFree(zIf);
- }else{
- pInclude = SafeMalloc( sizeof(Include) + nArg + 1 );
- pInclude->zFile = (char*)&pInclude[1];
- sprintf(pInclude->zFile,"%.*s",nArg,zArg);
- pInclude->zIf = 0;
- pInclude->zLabel = pInclude->zFile;
- }
- pInclude->pNext = includeList;
- includeList = pInclude;
- }else if( nCmd==2 && strncmp(zCmd,"if",2)==0 ){
- /*
- ** Push an #if. Watch for the special cases of INTERFACE
- ** and EXPORT_INTERFACE and LOCAL_INTERFACE
- */
- zArg = &zCmd[2];
- while( *zArg && isspace(*zArg) && *zArg!='\n' ){
- zArg++;
- }
- if( *zArg==0 || *zArg=='\n' ){ return 0; }
- nArg = pToken->nText + (int)pToken->zText - (int)zArg;
- if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){
- PushIfMacro(0,0,0,pToken->nLine,PS_Interface);
- }else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){
- PushIfMacro(0,0,0,pToken->nLine,PS_Export);
- }else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){
- PushIfMacro(0,0,0,pToken->nLine,PS_Local);
- }else{
- PushIfMacro(0,zArg,nArg,pToken->nLine,0);
- }
- }else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){
- /*
- ** Push an #ifdef.
- */
- zArg = &zCmd[5];
- while( *zArg && isspace(*zArg) && *zArg!='\n' ){
- zArg++;
- }
- if( *zArg==0 || *zArg=='\n' ){ return 0; }
- nArg = pToken->nText + (int)pToken->zText - (int)zArg;
- PushIfMacro("defined",zArg,nArg,pToken->nLine,0);
- }else if( nCmd==6 && strncmp(zCmd,"ifndef",6)==0 ){
- /*
- ** Push an #ifndef.
- */
- zArg = &zCmd[6];
- while( *zArg && isspace(*zArg) && *zArg!='\n' ){
- zArg++;
- }
- if( *zArg==0 || *zArg=='\n' ){ return 0; }
- nArg = pToken->nText + (int)pToken->zText - (int)zArg;
- PushIfMacro("!defined",zArg,nArg,pToken->nLine,0);
- }else if( nCmd==4 && strncmp(zCmd,"else",4)==0 ){
- /*
- ** Invert the #if on the top of the stack
- */
- if( ifStack==0 ){
- fprintf(stderr,"%s:%d: '#else' without an '#if'\n",zFilename,
- pToken->nLine);
- return 1;
- }
- pIf = ifStack;
- if( pIf->zCondition ){
- ifStack = ifStack->pNext;
- PushIfMacro("!",pIf->zCondition,strlen(pIf->zCondition),pIf->nLine,0);
- SafeFree(pIf);
- }else{
- pIf->flags = 0;
- }
- }else{
- /*
- ** This directive can be safely ignored
- */
- return 0;
- }
-
- /*
- ** Recompute the preset flags
- */
- *pPresetFlags = 0;
- for(pIf = ifStack; pIf; pIf=pIf->pNext){
- *pPresetFlags |= pIf->flags;
- }
-
- return nErr;
-}
-
-/*
-** Parse an entire file. Return the number of errors.
-**
-** pList is a list of tokens in the file. Whitespace tokens have been
-** eliminated, and text with {...} has been collapsed into a
-** single TT_Brace token.
-**
-** initFlags are a set of parse flags that should always be set for this
-** file. For .c files this is normally 0. For .h files it is PS_Interface.
-*/
-static int ParseFile(Token *pList, int initFlags){
- int nErr = 0;
- Token *pStart = 0;
- int flags = initFlags;
- int presetFlags = initFlags;
- int resetFlag = 0;
-
- includeList = 0;
- while( pList ){
- switch( pList->eType ){
- case TT_EOF:
- goto end_of_loop;
-
- case TT_Preprocessor:
- nErr += ParsePreprocessor(pList,flags,&presetFlags);
- pStart = 0;
- presetFlags |= initFlags;
- flags = presetFlags;
- break;
-
- case TT_Other:
- switch( pList->zText[0] ){
- case ';':
- nErr += ProcessDecl(pStart,pList,flags);
- pStart = 0;
- flags = presetFlags;
- break;
-
- case '=':
- nErr += ProcessDecl(pStart,pList,flags);
- pStart = 0;
- while( pList && pList->zText[0]!=';' ){
- pList = pList->pNext;
- }
- if( pList==0 ) goto end_of_loop;
- flags = presetFlags;
- break;
-
- case ':':
- if( pList->zText[1]==':' ){
- flags |= PS_Method;
- }
- break;
-
- default:
- break;
- }
- break;
-
- case TT_Braces:
- nErr += ProcessProcedureDef(pStart,pList,flags);
- pStart = 0;
- flags = presetFlags;
- break;
-
- case TT_Id:
- if( pStart==0 ){
- pStart = pList;
- flags = presetFlags;
- }
- resetFlag = 0;
- switch( pList->zText[0] ){
- case 'c':
- if( pList->nText==5 && strncmp(pList->zText,"class",5)==0 ){
- nErr += ProcessTypeDecl(pList,flags,&resetFlag);
- }
- break;
-
- case 'E':
- if( pList->nText==6 && strncmp(pList->zText,"EXPORT",6)==0 ){
- flags |= PS_Export2;
- /* pStart = 0; */
- }
- break;
-
- case 'e':
- if( pList->nText==4 && strncmp(pList->zText,"enum",4)==0 ){
- if( pList->pNext && pList->pNext->eType==TT_Braces ){
- pList = pList->pNext;
- }else{
- nErr += ProcessTypeDecl(pList,flags,&resetFlag);
- }
- }else if( pList->nText==6 && strncmp(pList->zText,"extern",6)==0 ){
- pList = pList->pNext;
- if( pList && pList->nText==3 && strncmp(pList->zText,"\"C\"",3)==0 ){
- pList = pList->pNext;
- flags &= ~DP_Cplusplus;
- }else{
- flags |= PS_Extern;
- }
- pStart = pList;
- }
- break;
-
- case 'i':
- if( pList->nText==6 && strncmp(pList->zText,"inline",6)==0 ){
- nErr += ProcessInlineProc(pList,flags,&resetFlag);
- }
- break;
-
- case 'L':
- if( pList->nText==5 && strncmp(pList->zText,"LOCAL",5)==0 ){
- flags |= PS_Local2;
- pStart = pList;
- }
- break;
-
- case 's':
- if( pList->nText==6 && strncmp(pList->zText,"struct",6)==0 ){
- if( pList->pNext && pList->pNext->eType==TT_Braces ){
- pList = pList->pNext;
- }else{
- nErr += ProcessTypeDecl(pList,flags,&resetFlag);
- }
- }else if( pList->nText==6 && strncmp(pList->zText,"static",6)==0 ){
- flags |= PS_Static;
- }
- break;
-
- case 't':
- if( pList->nText==7 && strncmp(pList->zText,"typedef",7)==0 ){
- flags |= PS_Typedef;
- }
- break;
-
- case 'u':
- if( pList->nText==5 && strncmp(pList->zText,"union",5)==0 ){
- if( pList->pNext && pList->pNext->eType==TT_Braces ){
- pList = pList->pNext;
- }else{
- nErr += ProcessTypeDecl(pList,flags,&resetFlag);
- }
- }
- break;
-
- default:
- break;
- }
- if( resetFlag!=0 ){
- while( pList && pList->zText[0]!=resetFlag ){
- pList = pList->pNext;
- }
- if( pList==0 ) goto end_of_loop;
- pStart = 0;
- flags = presetFlags;
- }
- break;
-
- case TT_Number:
- break;
-
- default:
- pStart = pList;
- flags = presetFlags;
- break;
- }
- pList = pList->pNext;
- }
- end_of_loop:
-
- /* Verify that all #ifs have a matching "#endif" */
- while( ifStack ){
- Ifmacro *pIf = ifStack;
- ifStack = pIf->pNext;
- fprintf(stderr,"%s:%d: This '#if' has no '#endif'\n",zFilename,
- pIf->nLine);
- SafeFree(pIf);
- }
-
- return nErr;
-}
-
-/*
-** Reset the DP_Forward and DP_Declared flags on all Decl structures.
-** Set both flags for anything that is tagged as local and isn't
-** in the file zFilename so that it won't be printing in other files.
-*/
-static void ResetDeclFlags(char *zFilename){
- Decl *pDecl;
-
- for(pDecl = pDeclFirst; pDecl; pDecl = pDecl->pNext){
- DeclClearProperty(pDecl,DP_Forward|DP_Declared);
- if( DeclHasProperty(pDecl,DP_Local) && pDecl->zFile!=zFilename ){
- DeclSetProperty(pDecl,DP_Forward|DP_Declared);
- }
- }
-}
-
-/*
-** Forward declaration of the ScanText() function.
-*/
-static void ScanText(const char*, GenState *pState);
-
-/*
-** The output in pStr is currently within an #if CONTEXT where context
-** is equal to *pzIf. (*pzIf might be NULL to indicate that we are
-** not within any #if at the moment.) We are getting ready to output
-** some text that needs to be within the context of "#if NEW" where
-** NEW is zIf. Make an appropriate change to the context.
-*/
-static void ChangeIfContext(
- const char *zIf, /* The desired #if context */
- GenState *pState /* Current state of the code generator */
-){
- if( zIf==0 ){
- if( pState->zIf==0 ) return;
- StringAppend(pState->pStr,"#endif\n",0);
- pState->zIf = 0;
- }else{
- if( pState->zIf ){
- if( strcmp(zIf,pState->zIf)==0 ) return;
- StringAppend(pState->pStr,"#endif\n",0);
- pState->zIf = 0;
- }
- ScanText(zIf, pState);
- if( pState->zIf!=0 ){
- StringAppend(pState->pStr,"#endif\n",0);
- }
- StringAppend(pState->pStr,"#if ",0);
- StringAppend(pState->pStr,zIf,0);
- StringAppend(pState->pStr,"\n",0);
- pState->zIf = zIf;
- }
-}
-
-/*
-** Add to the string pStr a #include of every file on the list of
-** include files pInclude. The table pTable contains all files that
-** have already been #included at least once. Don't add any
-** duplicates. Update pTable with every new #include that is added.
-*/
-static void AddIncludes(
- Include *pInclude, /* Write every #include on this list */
- GenState *pState /* Current state of the code generator */
-){
- if( pInclude ){
- if( pInclude->pNext ){
- AddIncludes(pInclude->pNext,pState);
- }
- if( IdentTableInsert(pState->pTable,pInclude->zLabel,0) ){
- ChangeIfContext(pInclude->zIf,pState);
- StringAppend(pState->pStr,"#include ",0);
- StringAppend(pState->pStr,pInclude->zFile,0);
- StringAppend(pState->pStr,"\n",1);
- }
- }
-}
-
-/*
-** Add to the string pStr a declaration for the object described
-** in pDecl.
-**
-** If pDecl has already been declared in this file, detect that
-** fact and abort early. Do not duplicate a declaration.
-**
-** If the needFullDecl flag is false and this object has a forward
-** declaration, then supply the forward declaration only. A later
-** call to CompleteForwardDeclarations() will finish the declaration
-** for us. But if needFullDecl is true, we must supply the full
-** declaration now. Some objects do not have a forward declaration.
-** For those objects, we must print the full declaration now.
-**
-** Because it is illegal to duplicate a typedef in C, care is taken
-** to insure that typedefs for the same identifier are only issued once.
-*/
-static void DeclareObject(
- Decl *pDecl, /* The thing to be declared */
- GenState *pState, /* Current state of the code generator */
- int needFullDecl /* Must have the full declaration. A forward
- * declaration isn't enough */
-){
- Decl *p; /* The object to be declared */
- int flag;
- int isCpp; /* True if generating C++ */
- int doneTypedef = 0; /* True if a typedef has been done for this object */
-
- /*
- ** For any object that has a forward declaration, go ahead and do the
- ** forward declaration first.
- */
- isCpp = (pState->flags & DP_Cplusplus) != 0;
- for(p=pDecl; p; p=p->pSameName){
- if( p->zFwd ){
- if( !DeclHasProperty(p,DP_Forward) ){
- DeclSetProperty(p,DP_Forward);
- if( strncmp(p->zFwd,"typedef",7)==0 ){
- if( doneTypedef ) continue;
- doneTypedef = 1;
- }
- ChangeIfContext(p->zIf,pState);
- StringAppend(pState->pStr,isCpp ? p->zFwdCpp : p->zFwd,0);
- }
- }
- }
-
- /*
- ** Early out if everything is already suitably declared.
- **
- ** This is a very important step because it prevents us from
- ** executing the code the follows in a recursive call to this
- ** function with the same value for pDecl.
- */
- flag = needFullDecl ? DP_Declared|DP_Forward : DP_Forward;
- for(p=pDecl; p; p=p->pSameName){
- if( !DeclHasProperty(p,flag) ) break;
- }
- if( p==0 ){
- return;
- }
-
- /*
- ** Make sure we have all necessary #includes
- */
- for(p=pDecl; p; p=p->pSameName){
- AddIncludes(p->pInclude,pState);
- }
-
- /*
- ** Go ahead an mark everything as being declared, to prevent an
- ** infinite loop thru the ScanText() function. At the same time,
- ** we decide which objects need a full declaration and mark them
- ** with the DP_Flag bit. We are only able to use DP_Flag in this
- ** way because we know we'll never execute this far into this
- ** function on a recursive call with the same pDecl. Hence, recursive
- ** calls to this function (through ScanText()) can never change the
- ** value of DP_Flag out from under us.
- */
- for(p=pDecl; p; p=p->pSameName){
- if( !DeclHasProperty(p,DP_Declared)
- && (p->zFwd==0 || needFullDecl)
- && p->zDecl!=0
- ){
- DeclSetProperty(p,DP_Forward|DP_Declared|DP_Flag);
- }else{
- DeclClearProperty(p,DP_Flag);
- }
- }
-
- /*
- ** Call ScanText() recusively (this routine is called from ScanText())
- ** to include declarations required to come before these declarations.
- */
- for(p=pDecl; p; p=p->pSameName){
- if( DeclHasProperty(p,DP_Flag) ){
- if( p->zDecl[0]=='#' ){
- ScanText(&p->zDecl[1],pState);
- }else{
- ScanText(p->zDecl,pState);
- }
- }
- }
-
- /*
- ** Output the declarations. Do this in two passes. First
- ** output everything that isn't a typedef. Then go back and
- ** get the typedefs by the same name.
- */
- for(p=pDecl; p; p=p->pSameName){
- if( DeclHasProperty(p,DP_Flag) && !DeclHasProperty(p,TY_Typedef) ){
- if( DeclHasAnyProperty(p,TY_Enumeration) ){
- if( doneTypedef ) continue;
- doneTypedef = 1;
- }
- ChangeIfContext(p->zIf,pState);
- if( !isCpp && DeclHasAnyProperty(p,DP_ExternReqd) ){
- StringAppend(pState->pStr,"extern ",0);
- }else if( isCpp && DeclHasProperty(p,DP_Cplusplus|DP_ExternReqd) ){
- StringAppend(pState->pStr,"extern ",0);
- }else if( isCpp && DeclHasAnyProperty(p,DP_ExternCReqd|DP_ExternReqd) ){
- StringAppend(pState->pStr,"extern \"C\" ",0);
- }
- StringAppend(pState->pStr,p->zDecl,0);
- if( !isCpp && DeclHasProperty(p,DP_Cplusplus) ){
- fprintf(stderr,
- "%s: C code ought not reference the C++ object \"%s\"\n",
- pState->zFilename, p->zName);
- pState->nErr++;
- }
- DeclClearProperty(p,DP_Flag);
- }
- }
- for(p=pDecl; p && !doneTypedef; p=p->pSameName){
- if( DeclHasProperty(p,DP_Flag) ){
- /* This has to be a typedef */
- doneTypedef = 1;
- ChangeIfContext(p->zIf,pState);
- StringAppend(pState->pStr,p->zDecl,0);
- }
- }
-}
-
-/*
-** This routine scans the input text given, and appends to the
-** string in pState->pStr the text of any declarations that must
-** occur before the text in zText.
-**
-** If an identifier in zText is immediately followed by '*', then
-** only forward declarations are needed for that identifier. If the
-** identifier name is not followed immediately by '*', we must supply
-** a full declaration.
-*/
-static void ScanText(
- const char *zText, /* The input text to be scanned */
- GenState *pState /* Current state of the code generator */
-){
- int nextValid = 0; /* True is sNext contains valid data */
- InStream sIn; /* The input text */
- Token sToken; /* The current token being examined */
- Token sNext; /* The next non-space token */
-
- sIn.z = zText;
- sIn.i = 0;
- sIn.nLine = 1;
- while( sIn.z[sIn.i]!=0 ){
- if( nextValid ){
- sToken = sNext;
- nextValid = 0;
- }else{
- GetNonspaceToken(&sIn,&sToken);
- }
- if( sToken.eType==TT_Id ){
- int needFullDecl; /* True if we need to provide the full declaration,
- ** not just the forward declaration */
- Decl *pDecl; /* The declaration having the name in sToken */
-
- /*
- ** See if there is a declaration in the database with the name given
- ** by sToken.
- */
- pDecl = FindDecl(sToken.zText,sToken.nText);
- if( pDecl==0 ) continue;
-
- /*
- ** If we get this far, we've found an identifier that has a
- ** declaration in the database. Now see if we the full declaration
- ** or just a forward declaration.
- */
- GetNonspaceToken(&sIn,&sNext);
- if( sNext.zText[0]=='*' ){
- needFullDecl = 0;
- }else{
- needFullDecl = 1;
- nextValid = sNext.eType==TT_Id;
- }
-
- /*
- ** Generate the needed declaration.
- */
- DeclareObject(pDecl,pState,needFullDecl);
- }else if( sToken.eType==TT_Preprocessor ){
- sIn.i -= sToken.nText - 1;
- }
- }
-}
-
-/*
-** Provide a full declaration to any object which so far has had only
-** a foward declaration.
-*/
-static void CompleteForwardDeclarations(GenState *pState){
- Decl *pDecl;
- int progress;
-
- do{
- progress = 0;
- for(pDecl=pDeclFirst; pDecl; pDecl=pDecl->pNext){
- if( DeclHasProperty(pDecl,DP_Forward)
- && !DeclHasProperty(pDecl,DP_Declared)
- ){
- DeclareObject(pDecl,pState,1);
- progress = 1;
- assert( DeclHasProperty(pDecl,DP_Declared) );
- }
- }
- }while( progress );
-}
-
-/*
-** Generate an include file for the given source file. Return the number
-** of errors encountered.
-**
-** if nolocal_flag is true, then we do not generate declarations for
-** objected marked DP_Local.
-*/
-static int MakeHeader(InFile *pFile, FILE *report, int nolocal_flag){
- int nErr = 0;
- GenState sState;
- String outStr;
- IdentTable includeTable;
- Ident *pId;
- char *zNewVersion;
- char *zOldVersion;
-
- if( pFile->zHdr==0 || *pFile->zHdr==0 ) return 0;
- sState.pStr = &outStr;
- StringInit(&outStr);
- StringAppend(&outStr,zTopLine,nTopLine);
- sState.pTable = &includeTable;
- memset(&includeTable,0,sizeof(includeTable));
- sState.zIf = 0;
- sState.nErr = 0;
- sState.zFilename = pFile->zSrc;
- sState.flags = pFile->flags & DP_Cplusplus;
- ResetDeclFlags(nolocal_flag ? "no" : pFile->zSrc);
- for(pId = pFile->idTable.pList; pId; pId=pId->pNext){
- Decl *pDecl = FindDecl(pId->zName,0);
- if( pDecl ){
- DeclareObject(pDecl,&sState,1);
- }
- }
- CompleteForwardDeclarations(&sState);
- ChangeIfContext(0,&sState);
- nErr += sState.nErr;
- zOldVersion = ReadFile(pFile->zHdr);
- zNewVersion = StringGet(&outStr);
- if( report ) fprintf(report,"%s: ",pFile->zHdr);
- if( zOldVersion==0 ){
- if( report ) fprintf(report,"updated\n");
- if( WriteFile(pFile->zHdr,zNewVersion) ){
- fprintf(stderr,"%s: Can't write to file\n",pFile->zHdr);
- nErr++;
- }
- }else if( strncmp(zOldVersion,zTopLine,nTopLine)!=0 ){
- if( report ) fprintf(report,"error!\n");
- fprintf(stderr,
- "%s: Can't overwrite this file because it wasn't previously\n"
- "generated by 'makeheaders'.\n", pFile->zHdr);
- nErr++;
- }else if( strcmp(zOldVersion,zNewVersion)!=0 ){
- if( report ) fprintf(report,"updated\n");
- if( WriteFile(pFile->zHdr,zNewVersion) ){
- fprintf(stderr,"%s: Can't write to file\n",pFile->zHdr);
- nErr++;
- }
- }else if( report ){
- fprintf(report,"unchanged\n");
- }
- SafeFree(zOldVersion);
- IdentTableReset(&includeTable);
- StringReset(&outStr);
- return nErr;
-}
-
-/*
-** Generate a global header file -- a header file that contains all
-** declarations. If the forExport flag is true, then only those
-** objects that are exported are included in the header file.
-*/
-static int MakeGlobalHeader(int forExport){
- GenState sState;
- String outStr;
- IdentTable includeTable;
- Decl *pDecl;
-
- sState.pStr = &outStr;
- StringInit(&outStr);
- /* StringAppend(&outStr,zTopLine,nTopLine); */
- sState.pTable = &includeTable;
- memset(&includeTable,0,sizeof(includeTable));
- sState.zIf = 0;
- sState.nErr = 0;
- sState.zFilename = "(all)";
- sState.flags = 0;
- ResetDeclFlags(0);
- for(pDecl=pDeclFirst; pDecl; pDecl=pDecl->pNext){
- if( forExport==0 || DeclHasProperty(pDecl,DP_Export) ){
- DeclareObject(pDecl,&sState,1);
- }
- }
- ChangeIfContext(0,&sState);
- printf("%s",StringGet(&outStr));
- IdentTableReset(&includeTable);
- StringReset(&outStr);
- return 0;
-}
-
-#ifdef DEBUG
-/*
-** Return the number of characters in the given string prior to the
-** first newline.
-*/
-static int ClipTrailingNewline(char *z){
- int n = strlen(z);
- while( n>0 && (z[n-1]=='\n' || z[n-1]=='\r') ){ n--; }
- return n;
-}
-
-/*
-** Dump the entire declaration list for debugging purposes
-*/
-static void DumpDeclList(void){
- Decl *pDecl;
-
- for(pDecl = pDeclFirst; pDecl; pDecl=pDecl->pNext){
- printf("**** %s from file %s ****\n",pDecl->zName,pDecl->zFile);
- if( pDecl->zIf ){
- printf("If: [%.*s]\n",ClipTrailingNewline(pDecl->zIf),pDecl->zIf);
- }
- if( pDecl->zFwd ){
- printf("Decl: [%.*s]\n",ClipTrailingNewline(pDecl->zFwd),pDecl->zFwd);
- }
- if( pDecl->zDecl ){
- printf("Def: [%.*s]\n",ClipTrailingNewline(pDecl->zDecl),pDecl->zDecl);
- }
- if( pDecl->flags ){
- static struct {
- int mask;
- char *desc;
- } flagSet[] = {
- { TY_Class, "class" },
- { TY_Enumeration, "enum" },
- { TY_Structure, "struct" },
- { TY_Union, "union" },
- { TY_Variable, "variable" },
- { TY_Subroutine, "function" },
- { TY_Typedef, "typedef" },
- { TY_Macro, "macro" },
- { DP_Export, "export" },
- { DP_Local, "local" },
- { DP_Cplusplus, "C++" },
- };
- int i;
- printf("flags:");
- for(i=0; i<sizeof(flagSet)/sizeof(flagSet[0]); i++){
- if( flagSet[i].mask & pDecl->flags ){
- printf(" %s", flagSet[i].desc);
- }
- }
- printf("\n");
- }
- if( pDecl->pInclude ){
- Include *p;
- printf("includes:");
- for(p=pDecl->pInclude; p; p=p->pNext){
- printf(" %s",p->zFile);
- }
- printf("\n");
- }
- }
-}
-#endif
-
-/*
-** When the "-doc" command-line option is used, this routine is called
-** to print all of the database information to standard output.
-*/
-static void DocumentationDump(void){
- Decl *pDecl;
- static struct {
- int mask;
- char flag;
- } flagSet[] = {
- { TY_Class, 'c' },
- { TY_Enumeration, 'e' },
- { TY_Structure, 's' },
- { TY_Union, 'u' },
- { TY_Variable, 'v' },
- { TY_Subroutine, 'f' },
- { TY_Typedef, 't' },
- { TY_Macro, 'm' },
- { DP_Export, 'x' },
- { DP_Local, 'l' },
- { DP_Cplusplus, '+' },
- };
-
- for(pDecl = pDeclFirst; pDecl; pDecl=pDecl->pNext){
- int i;
- int nLabel = 0;
- char *zDecl;
- char zLabel[50];
- for(i=0; i<sizeof(flagSet)/sizeof(flagSet[0]); i++){
- if( DeclHasProperty(pDecl,flagSet[i].mask) ){
- zLabel[nLabel++] = flagSet[i].flag;
- }
- }
- if( nLabel==0 ) continue;
- zLabel[nLabel] = 0;
- zDecl = pDecl->zDecl;
- if( zDecl==0 ) zDecl = pDecl->zFwd;
- printf("%s %s %s %d %d %d %d %d %d\n",
- pDecl->zName,
- zLabel,
- pDecl->zFile,
- (int)(pDecl->pComment ? (int)pDecl->pComment/sizeof(Token) : 0),
- (int)(pDecl->pComment ? pDecl->pComment->nText+1 : 0),
- (int)(pDecl->zIf ? strlen(pDecl->zIf)+1 : 0),
- (int)(zDecl ? strlen(zDecl) : 0),
- (int)(pDecl->pComment ? pDecl->pComment->nLine : 0),
- pDecl->tokenCode.nText ? pDecl->tokenCode.nText+1 : 0
- );
- if( pDecl->pComment ){
- printf("%.*s\n",pDecl->pComment->nText, pDecl->pComment->zText);
- }
- if( pDecl->zIf ){
- printf("%s\n",pDecl->zIf);
- }
- if( zDecl ){
- printf("%s",zDecl);
- }
- if( pDecl->tokenCode.nText ){
- printf("%.*s\n",pDecl->tokenCode.nText, pDecl->tokenCode.zText);
- }
- }
-}
-
-/*
-** Given the complete text of an input file, this routine prints a
-** documentation record for the header comment at the beginning of the
-** file (if the file has a header comment.)
-*/
-void PrintModuleRecord(const char *zFile, const char *zFilename){
- int i;
- static int addr = 5;
- while( isspace(*zFile) ){ zFile++; }
- if( *zFile!='/' || zFile[1]!='*' ) return;
- for(i=2; zFile[i] && (zFile[i-1]!='/' || zFile[i-2]!='*'); i++){}
- if( zFile[i]==0 ) return;
- printf("%s M %s %d %d 0 0 0\n%.*s\n",
- zFilename, zFilename, addr, i+1, i, zFile);
- addr += 4;
-}
-
-
-/*
-** Given an input argument to the program, construct a new InFile
-** object.
-*/
-static InFile *CreateInFile(char *zArg, int *pnErr){
- int nSrc;
- char *zSrc;
- InFile *pFile;
- int i;
-
- /*
- ** Get the name of the input file to be scanned
- */
- zSrc = zArg;
- for(nSrc=0; zSrc[nSrc] && zArg[nSrc]!=':'; nSrc++){}
- pFile = SafeMalloc( sizeof(InFile) );
- memset(pFile,0,sizeof(InFile));
- pFile->zSrc = StrDup(zSrc,nSrc);
-
- /* Figure out if we are dealing with C or C++ code. Assume any
- ** file with ".c" or ".h" is C code and all else is C++.
- */
- if( nSrc>2 && zSrc[nSrc-2]=='.' && (zSrc[nSrc-1]=='c' || zSrc[nSrc-1]=='h')){
- pFile->flags &= ~DP_Cplusplus;
- }else{
- pFile->flags |= DP_Cplusplus;
- }
-
- /*
- ** If a separate header file is specified, use it
- */
- if( zSrc[nSrc]==':' ){
- int nHdr;
- char *zHdr;
- zHdr = &zSrc[nSrc+1];
- for(nHdr=0; zHdr[nHdr] && zHdr[nHdr]!=':'; nHdr++){}
- pFile->zHdr = StrDup(zHdr,nHdr);
- }
-
- /* Look for any 'c' or 'C' in the suffix of the file name and change
- ** that character to 'h' or 'H' respectively. If no 'c' or 'C' is found,
- ** then assume we are dealing with a header.
- */
- else{
- int foundC = 0;
- pFile->zHdr = StrDup(zSrc,nSrc);
- for(i = nSrc-1; i>0 && pFile->zHdr[i]!='.'; i--){
- if( pFile->zHdr[i]=='c' ){
- foundC = 1;
- pFile->zHdr[i] = 'h';
- }else if( pFile->zHdr[i]=='C' ){
- foundC = 1;
- pFile->zHdr[i] = 'H';
- }
- }
- if( !foundC ){
- SafeFree(pFile->zHdr);
- pFile->zHdr = 0;
- }
- }
-
- /*
- ** If pFile->zSrc contains no 'c' or 'C' in its extension, it
- ** must be a header file. In that case, we need to set the
- ** PS_Interface flag.
- */
- pFile->flags |= PS_Interface;
- for(i=nSrc-1; i>0 && zSrc[i]!='.'; i--){
- if( zSrc[i]=='c' || zSrc[i]=='C' ){
- pFile->flags &= ~PS_Interface;
- break;
- }
- }
-
- /* Done!
- */
- return pFile;
-}
-
-/* MS-Windows and MS-DOS both have the following serious OS bug: the
-** length of a command line is severely restricted. But this program
-** occasionally requires long command lines. Hence the following
-** work around.
-**
-** If the parameters "-f FILENAME" appear anywhere on the command line,
-** then the named file is scanned for additional command line arguments.
-** These arguments are substituted in place of the "FILENAME" argument
-** in the original argument list.
-**
-** This first parameter to this routine is the index of the "-f"
-** parameter in the argv[] array. The argc and argv are passed by
-** pointer so that they can be changed.
-**
-** Parsing of the parameters in the file is very simple. Parameters
-** can be separated by any amount of white-space (including newlines
-** and carriage returns.) There are now quoting characters of any
-** kind. The length of a token is limited to about 1000 characters.
-*/
-static void AddParameters(int index, int *pArgc, char ***pArgv){
- int argc = *pArgc; /* The original argc value */
- char **argv = *pArgv; /* The original argv value */
- int newArgc; /* Value for argc after inserting new arguments */
- char **zNew; /* The new argv after this routine is done */
- char *zFile; /* Name of the input file */
- int nNew = 0; /* Number of new entries in the argv[] file */
- int nAlloc = 0; /* Space allocated for zNew[] */
- int i; /* Loop counter */
- int n; /* Number of characters in a new argument */
- int c; /* Next character of input */
- int startOfLine = 1; /* True if we are where '#' can start a comment */
- FILE *in; /* The input file */
- char zBuf[1000]; /* A single argument is accumulated here */
-
- if( index+1==argc ) return;
- zFile = argv[index+1];
- in = fopen(zFile,"r");
- if( in==0 ){
- fprintf(stderr,"Can't open input file \"%s\"\n",zFile);
- exit(1);
- }
- c = ' ';
- while( c!=EOF ){
- while( c!=EOF && isspace(c) ){
- if( c=='\n' ){
- startOfLine = 1;
- }
- c = getc(in);
- if( startOfLine && c=='#' ){
- while( c!=EOF && c!='\n' ){
- c = getc(in);
- }
- }
- }
- n = 0;
- while( c!=EOF && !isspace(c) ){
- if( n<sizeof(zBuf)-1 ){ zBuf[n++] = c; }
- startOfLine = 0;
- c = getc(in);
- }
- zBuf[n] = 0;
- if( n>0 ){
- nNew++;
- if( nNew + argc > nAlloc ){
- if( nAlloc==0 ){
- nAlloc = 100 + argc;
- zNew = malloc( sizeof(char*) * nAlloc );
- }else{
- nAlloc *= 2;
- zNew = realloc( zNew, sizeof(char*) * nAlloc );
- }
- }
- if( zNew ){
- int j = nNew + index;
- zNew[j] = malloc( n + 1 );
- if( zNew[j] ){
- strcpy( zNew[j], zBuf );
- }
- }
- }
- }
- newArgc = argc + nNew - 1;
- for(i=0; i<=index; i++){
- zNew[i] = argv[i];
- }
- for(i=nNew + index + 1; i<newArgc; i++){
- zNew[i] = argv[i + 1 - nNew];
- }
- zNew[newArgc] = 0;
- *pArgc = newArgc;
- *pArgv = zNew;
-}
-
-#ifdef NOT_USED
-/*
-** Return the time that the given file was last modified. If we can't
-** locate the file (because, for example, it doesn't exist), then
-** return 0.
-*/
-static unsigned int ModTime(const char *zFilename){
- unsigned int mTime = 0;
- struct stat sStat;
- if( stat(zFilename,&sStat)==0 ){
- mTime = sStat.st_mtime;
- }
- return mTime;
-}
-#endif
-
-/*
-** Print a usage comment for this program.
-*/
-static void Usage(const char *argv0, const char *argvN){
- fprintf(stderr,"%s: Illegal argument \"%s\"\n",argv0,argvN);
- fprintf(stderr,"Usage: %s [options] filename...\n"
- "Options:\n"
- " -h Generate a single .h to standard output.\n"
- " -H Like -h, but only output EXPORT declarations.\n"
- " -v (verbose) Write status information to the screen.\n"
- " -doc Generate no header files. Instead, output information\n"
- " that can be used by an automatic program documentation\n"
- " and cross-reference generator.\n"
- " -local Generate prototypes for \"static\" functions and\n"
- " procedures.\n"
- " -f FILE Read additional command-line arguments from the file named\n"
- " \"FILE\".\n"
-#ifdef DEBUG
- " -! MASK Set the debugging mask to the number \"MASK\".\n"
-#endif
- " -- Treat all subsequent comment-line parameters as filenames,\n"
- " even if they begin with \"-\".\n",
- argv0
- );
-}
-
-/*
-** The following text contains a few simple #defines that we want
-** to be available to every file.
-*/
-static char zInit[] =
- "#define INTERFACE 0\n"
- "#define EXPORT_INTERFACE 0\n"
- "#define LOCAL_INTERFACE 0\n"
- "#define EXPORT\n"
- "#define LOCAL static\n"
-;
-
-#if TEST==0
-int main(int argc, char **argv){
- int i; /* Loop counter */
- int nErr = 0; /* Number of errors encountered */
- Token *pList; /* List of input tokens for one file */
- InFile *pFileList = 0;/* List of all input files */
- InFile *pTail; /* Last file on the list */
- InFile *pFile; /* for looping over the file list */
- int h_flag = 0; /* True if -h is present. Output unified header */
- int H_flag = 0; /* True if -H is present. Output EXPORT header */
- int v_flag = 0; /* Verbose */
- int noMoreFlags; /* True if -- has been seen. */
- FILE *report; /* Send progress reports to this, if not NULL */
-
- noMoreFlags = 0;
- for(i=1; i<argc; i++){
- if( argv[i][0]=='-' && !noMoreFlags ){
- switch( argv[i][1] ){
- case 'h': h_flag = 1; break;
- case 'H': H_flag = 1; break;
- case 'v': v_flag = 1; break;
- case 'd': doc_flag = 1; proto_static = 1; break;
- case 'l': proto_static = 1; break;
- case 'f': AddParameters(i, &argc, &argv); break;
- case '-': noMoreFlags = 1; break;
-#ifdef DEBUG
- case '!': i++; debugMask = strtol(argv[i],0,0); break;
-#endif
- default: Usage(argv[0],argv[i]); return 1;
- }
- }else{
- pFile = CreateInFile(argv[i],&nErr);
- if( pFile ){
- if( pFileList ){
- pTail->pNext = pFile;
- pTail = pFile;
- }else{
- pFileList = pTail = pFile;
- }
- }
- }
- }
- if( h_flag && H_flag ){
- h_flag = 0;
- }
- if( v_flag ){
- report = (h_flag || H_flag) ? stderr : stdout;
- }else{
- report = 0;
- }
- if( nErr>0 ){
- return nErr;
- }
- for(pFile=pFileList; pFile; pFile=pFile->pNext){
- char *zFile;
-
- zFilename = pFile->zSrc;
- if( zFilename==0 ) continue;
- zFile = ReadFile(zFilename);
- if( zFile==0 ){
- fprintf(stderr,"Can't read input file \"%s\"\n",zFilename);
- nErr++;
- continue;
- }
- if( strncmp(zFile,zTopLine,nTopLine)==0 ){
- pFile->zSrc = 0;
- }else{
- if( report ) fprintf(report,"Reading %s...\n",zFilename);
- pList = TokenizeFile(zFile,&pFile->idTable);
- if( pList ){
- nErr += ParseFile(pList,pFile->flags);
- FreeTokenList(pList);
- }else if( zFile[0]==0 ){
- fprintf(stderr,"Input file \"%s\" is empty.\n", zFilename);
- nErr++;
- }else{
- fprintf(stderr,"Errors while processing \"%s\"\n", zFilename);
- nErr++;
- }
- }
- if( !doc_flag ) SafeFree(zFile);
- if( doc_flag ) PrintModuleRecord(zFile,zFilename);
- }
- if( nErr>0 ){
- return nErr;
- }
-#ifdef DEBUG
- if( debugMask & DECL_DUMP ){
- DumpDeclList();
- return nErr;
- }
-#endif
- if( doc_flag ){
- DocumentationDump();
- return nErr;
- }
- zFilename = "--internal--";
- pList = TokenizeFile(zInit,0);
- if( pList==0 ){
- return nErr+1;
- }
- ParseFile(pList,PS_Interface);
- FreeTokenList(pList);
- if( h_flag || H_flag ){
- nErr += MakeGlobalHeader(H_flag);
- }else{
- for(pFile=pFileList; pFile; pFile=pFile->pNext){
- if( pFile->zSrc==0 ) continue;
- nErr += MakeHeader(pFile,report,0);
- }
- }
- return nErr;
-}
-#endif
diff --git a/tkhtml1/tools/maketokens.tcl b/tkhtml1/tools/maketokens.tcl
deleted file mode 100644
index 95cd34e..0000000
--- a/tkhtml1/tools/maketokens.tcl
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/sh
-# This script is a replacement for the maketokens.sh shell script.
-# The shell script required GNU awk. This script should work with
-# any old version of tclsh.
-# \
-exec tclsh "$0" ${1+"$@"}
-
-if {$argc!=1} {
- puts stderr "Usage: $argv0 tokenlist.txt >htmltokens.c"
- exit 1
-}
-if {[catch {open [lindex $argv 0] r} f]} {
- puts stderr "$argv0: can not open \"[lindex $argv 0]\": $f"
- exit 1
-}
-set tokenlist {}
-while {![eof $f]} {
- set line [string trim [gets $f]]
- if {$line==""} continue
- if {[string index $line 0]=="#"} continue
- if {[llength $line]!=2 && [llength $line]!=3} continue
- lappend tokenlist [lindex $line 0]
- lappend tokenlist [lindex $line 1]
- lappend tokenlist [lindex $line 2]
-}
-close $f
-
-global tcl_platform
-if {$tcl_platform(platform) == "windows"} {
- fconfigure stdout -translation lf
-}
-
-puts {/* DO NOT EDIT
-** The code in this file was automatically generated.
-*/
-#include <tk.h>
-#include "htmltokens.h"
-#if INTERFACE
-struct HtmlTokenMap {
- char *zName; /* Name of a markup */
- Html_16 type; /* Markup type code */
- Html_16 extra; /* Extra space needed above HtmlBaseElement */
- HtmlTokenMap *pCollide; /* Hash table collision chain */
-};
-#define Html_Text 1
-#define Html_Space 2
-#define Html_Unknown 3
-#define Html_Block 4
-#define HtmlIsMarkup(X) ((X)->base.type>Html_Block)
-}
-
-set count 5
-set fmt {#define %-20s %d}
-
-foreach {name start end} $tokenlist {
- set upr [string toupper $name]
- puts [format $fmt Html_$upr $count]
- incr count
- if {$end!=""} {
- puts [format $fmt Html_End$upr $count]
- incr count
- }
-}
-
-puts [format $fmt Html_TypeCount [expr $count-1]]
-puts "#define HTML_MARKUP_HASH_SIZE [expr $count+11]"
-puts "#define HTML_MARKUP_COUNT [expr $count-5]"
-puts "#endif /* INTERFACE */"
-puts "HtmlTokenMap HtmlMarkupMap\[\] = {"
-
-set fmt " { %-15s %-25s %-30s },"
-
-foreach {name start end} $tokenlist {
- set upr [string toupper $name]
- set nm "\"$name\","
- set val Html_$upr,
- if {$start=="0"} {
- set size "0,"
- } else {
- set size "sizeof($start),"
- }
- puts [format $fmt $nm $val $size]
- if {$end==""} continue
- set nm "\"/$name\","
- set val Html_End$upr,
- if {$end=="0"} {
- set size "0,"
- } else {
- set size "sizeof($end),"
- }
- puts [format $fmt $nm $val $size]
-}
-
-puts "};"
diff --git a/tkhtml1/tools/sgmlparse.c b/tkhtml1/tools/sgmlparse.c
deleted file mode 100644
index d85806e..0000000
--- a/tkhtml1/tools/sgmlparse.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
-** This file contains code used to tokenize SGML.
-*/
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include "sgmlparse.h"
-
-#define stricmp strcasecmp
-
-/* These three pointers define certain special handlers. All whitespace
-** is sent to xSpaceHandler. Non-whitespace is given to xWordHandler.
-** Any markup that isn't specifically directed elsewhere is given
-** to xDefaultMarkupHandlers.
-*/
-static void (*xSpaceHandler)(const char*,void*);
-static void (*xWordHandler)(const char*,void*);
-static void (*xCommentHandler)(const char*,void*);
-static void (*xDefaultMarkupHandler)(int, const char**, void*);
-
-/* Each handler is stored in a hash table as an instance of the
-** following structure.
-*/
-typedef struct sgHandler Handler;
-struct sgHandler {
- char *zName; /* Name of markup to handle */
- void (*xHandler)(int, const char**, void*); /* Routine to do the work */
- Handler *pCollide; /* Next handler with same hash */
-};
-
-/* The size of the handler hash table.
-** For best results, this should be a prime number which is larger than
-** the number of markups in the hash table.
-*/
-#define SGML_HASH_SIZE 203
-
-/* The handler hash table */
-static Handler *apHandler[SGML_HASH_SIZE];
-
-/* Hash a handler name */
-static int SgmlHash(const char *zName){
- int h = 0;
- char c;
- while( (c=*zName)!=0 ){
- if( isupper(c) ) c = tolower(c);
- h = h<<5 ^ h ^ c;
- zName++;
- }
- if( h<0 ) h = -h;
- return h % SGML_HASH_SIZE;
-}
-
-/* Given a pointer to an input file, read and parse that file
-** as if it were SGML.
-**
-** This is not a true SGML parser because it handles some unusual
-** cases differently, and ignores the & operator completely.
-*/
-void SgmlParse(FILE *in, void *pArg){
- int c;
- int i, j;
- int argc;
- Handler *pHandler;
- char *argv[100];
- char zBuf[10000];
-
- c = getc(in);
- while( c!=EOF ){
- if( isspace(c) ){
- /* Case 1: spaces */
- zBuf[0] = c;
- i = 1;
- while( i<sizeof(zBuf)-2 && (c=getc(in))!=EOF && isspace(c) ){
- zBuf[i++] = c;
- }
- zBuf[i] = 0;
- /* Dispose of space */
- if( xSpaceHandler ){
- (*xSpaceHandler)(zBuf,pArg);
- }
- }else if( c=='<' ){
- int cQuote = 0;
- i = 0;
- zBuf[i++] = c;
- while( (c=getc(in))!=EOF && (cQuote || c!='>') ){
- if( i<sizeof(zBuf)-3 ) zBuf[i++] = c;
- if( cQuote ){
- if( cQuote==c ) cQuote = 0;
- }else if( c=='"' || c=='\'' ){
- cQuote = c;
- }
- }
- if( c=='>' ) c = getc(in);
- zBuf[i] = 0;
- if( strncmp(zBuf,"<!--",4)==0 ){
- zBuf[i++] = '>';
- zBuf[i] = 0;
- if( xCommentHandler ){
- (*xCommentHandler)(zBuf,pArg);
- }
- continue;
- }
- argc = 0;
- argv[0] = &zBuf[1];
- for(j=1; zBuf[j] && !isspace(zBuf[j]); j++){}
- if( zBuf[j] ){
- zBuf[j++] = 0;
- while( argc<(sizeof(argv)/sizeof(argv[0])) - 4 && zBuf[j] ){
- while( isspace(zBuf[j]) ) j++;
- argv[++argc] = &zBuf[j];
- while( zBuf[j] && !isspace(zBuf[j]) && zBuf[j]!='=' ) j++;
- if( zBuf[j]!='=' ){
- argv[argc+1] = argv[argc];
- argc++;
- if( zBuf[j] ) zBuf[j++] = 0;
- continue;
- }
- zBuf[j++] = 0;
- if( zBuf[j]=='"' || zBuf[j]=='\'' ){
- cQuote = zBuf[j++];
- }else{
- cQuote = 0;
- }
- argv[++argc] = &zBuf[j];
- if( cQuote ){
- while( zBuf[j] && zBuf[j]!=cQuote ) j++;
- }else{
- while( zBuf[j] && !isspace(zBuf[j]) ) j++;
- }
- if( zBuf[j] ) zBuf[j++] = 0;
- }
- }
- argv[++argc] = 0;
- /* Despose of a markup */
- pHandler = apHandler[SgmlHash(argv[0])];
- while( pHandler && stricmp(pHandler->zName,argv[0])!=0 ){
- pHandler = pHandler->pCollide;
- }
- if( pHandler ){
- if( pHandler->xHandler ){
- (*pHandler->xHandler)(argc,(const char**)argv,pArg);
- }
- }else if( xDefaultMarkupHandler ){
- (*xDefaultMarkupHandler)(argc,(const char**)argv,pArg);
- }
- }else{
- zBuf[0] = c;
- i = 1;
- while( i<sizeof(zBuf)-2 && (c=getc(in))!=EOF && c!='<' && !isspace(c) ){
- zBuf[i++] = c;
- }
- zBuf[i] = 0;
- /* Dispose of a word */
- if( xWordHandler ){
- (*xWordHandler)(zBuf,pArg);
- }
- }
- }
-}
-
-/*
-** Clear out the handler hash table
-*/
-void SgmlHandlerReset(void){
- Handler *pHandler;
- int i;
-
- for(i=0; i<SGML_HASH_SIZE; i++){
- Handler *pNext;
- for(pHandler=apHandler[i]; pHandler; pHandler=pNext){
- pNext = pHandler->pCollide;
- free(pHandler);
- }
- apHandler[i] = 0;
- }
-}
-
-/* Install a new handler
-*/
-void SgmlHandler(const char *zName, void (*xFunc)(int,const char**,void*)){
- int h = SgmlHash(zName);
- extern void *malloc();
- Handler *pNew = malloc( sizeof(Handler) + strlen(zName) + 1 );
- if( pNew==0 ) return;
- pNew->zName = (char*)&pNew[1];
- strcpy(pNew->zName,zName);
- pNew->pCollide = apHandler[h];
- pNew->xHandler = xFunc;
- apHandler[h] = pNew;
-}
-
-/* Install the default handlers
-*/
-void SgmlWordHandler(void (*xWord)(const char*,void*)){
- xWordHandler = xWord;
-}
-void SgmlSpaceHandler(void (*xSpace)(const char*,void*)){
- xSpaceHandler = xSpace;
-}
-void SgmlCommentHandler(void (*xComment)(const char*,void*)){
- xCommentHandler = xComment;
-}
-void SgmlDefaultMarkupHandler(void (*xMarkup)(int,const char**,void*)){
- xDefaultMarkupHandler = xMarkup;
-}
diff --git a/tkhtml1/tools/url.c b/tkhtml1/tools/url.c
deleted file mode 100644
index 677cbba..0000000
--- a/tkhtml1/tools/url.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
-** This file contains code use for resolving relative URLs
-*/
-#include <stdlib.h>
-#include "url.h"
-
-#if INTERFACE
-/*
-** A parsed URI is held in an instance of the following structure.
-** Each component is recorded in memory obtained from malloc().
-**
-** The examples are from the URI
-**
-** http://192.168.1.1:8080/cgi-bin/printenv?name=xyzzy&addr=none#frag
-*/
-typedef struct Url Url;
-struct Url {
- char *zScheme; /* Ex: "http" */
- char *zAuthority; /* Ex: "192.168.1.1:8080" */
- char *zPath; /* Ex: "cgi-bin/printenv" */
- char *zQuery; /* Ex: "name=xyzzy&addr=none" */
- char *zFragment; /* Ex: "frag" */
-};
-#endif
-
-/*
-** Return the length of the next component of the URL in z[] given
-** that the component starts at z[0]. The initial sequence of the
-** component must be zInit[]. The component is terminated by any
-** character in zTerm[]. The length returned is 0 if the component
-** doesn't exist. The length includes the zInit[] string, but not
-** the termination character.
-**
-** Component zInit zTerm
-** ---------- ------- -------
-** scheme "" ":/?#"
-** authority "//" "/?#"
-** path "/" "?#"
-** query "?" "#"
-** fragment "#" ""
-*/
-static int ComponentLength(const char *z, const char *zInit, const char *zTerm){
- int i, n;
- for(n=0; zInit[n]; n++){
- if( zInit[n]!=z[n] ) return 0;
- }
- while( z[n] ){
- for(i=0; zTerm[i]; i++){
- if( z[n]==zTerm[i] ) return n;
- }
- n++;
- }
- return n;
-}
-
-/*
-** Duplicate a string of length n.
-*/
-static char *StrNDup(const char *z, int n){
- char *zResult;
- if( n<=0 ){
- n = strlen(z);
- }
- zResult = malloc( n + 1 );
- if( zResult ){
- memcpy(zResult, z, n);
- zResult[n] = 0;
- }
- return zResult;
-}
-
-/*
-** Parse a text URI into an Url structure.
-*/
-Url *ParseUrl(const char *zUri){
- Url *p;
- int n;
-
- p = malloc( sizeof(*p) );
- if( p==0 ) return 0;
- memset(p, 0, sizeof(*p));
- if( zUri==0 || zUri[0]==0 ) return p;
- while( isspace(zUri[0]) ){ zUri++; }
- n = ComponentLength(zUri, "", ":/?# ");
- if( n>0 && zUri[n]==':' ){
- p->zScheme = StrNDup(zUri, n);
- zUri += n+1;
- }
- n = ComponentLength(zUri, "//", "/?# ");
- if( n>0 ){
- p->zAuthority = StrNDup(&zUri[2], n-2);
- zUri += n;
- }
- n = ComponentLength(zUri, "", "?# ");
- if( n>0 ){
- p->zPath = StrNDup(zUri, n);
- zUri += n;
- }
- n = ComponentLength(zUri, "?", "# ");
- if( n>0 ){
- p->zQuery = StrNDup(&zUri[1], n-1);
- zUri += n;
- }
- n = ComponentLength(zUri, "#", " ");
- if( n>0 ){
- p->zFragment = StrNDup(&zUri[1], n-1);
- }
- return p;
-}
-
-/*
-** Delete an Url structure.
-*/
-void FreeUrl(Url *p){
- if( p==0 ) return;
- if( p->zScheme ) free(p->zScheme);
- if( p->zAuthority ) free(p->zAuthority);
- if( p->zPath ) free(p->zPath);
- if( p->zQuery ) free(p->zQuery);
- if( p->zFragment ) free(p->zFragment);
- free(p);
-}
-
-/*
-** Create a string to hold the given URI. Memory to hold the string
-** is obtained from malloc() and must be freed by the calling
-** function.
-*/
-char *BuildUrl(Url *p){
- int n = 1;
- char *z;
- if( p->zScheme ) n += strlen(p->zScheme)+1;
- if( p->zAuthority ) n += strlen(p->zAuthority)+2;
- if( p->zPath ) n += strlen(p->zPath)+1;
- if( p->zQuery ) n += strlen(p->zQuery)+1;
- if( p->zFragment ) n += strlen(p->zFragment)+1;
- z = malloc( n );
- if( z==0 ) return 0;
- n = 0;
- if( p->zScheme ){
- sprintf(z, "%s:", p->zScheme);
- n = strlen(z);
- }
- if( p->zAuthority ){
- sprintf(&z[n], "//%s", p->zAuthority);
- n += strlen(&z[n]);
- }
- if( p->zPath ){
- sprintf(&z[n], "%s", p->zPath);
- n += strlen(&z[n]);
- }
- if( p->zQuery ){
- sprintf(&z[n], "?%s", p->zQuery);
- n += strlen(&z[n]);
- }
- if( p->zFragment ){
- sprintf(&z[n], "#%s", p->zFragment);
- }
- return z;
-}
-
-/*
-** Replace the string in *pzDest with the string in zSrc
-*/
-static void ReplaceStr(char **pzDest, const char *zSrc){
- if( *pzDest!=0 ) free(*pzDest);
- if( zSrc==0 ){
- *pzDest = 0;
- }else{
- *pzDest = StrNDup(zSrc, -1);
- }
-}
-
-/*
-** Remove leading and trailing spaces from the given string. Return
-** a new string obtained from malloc().
-*/
-static char *Trim(char *z){
- int i;
- char *zNew;
- while( isspace(*z) ) z++;
- i = strlen(z);
- zNew = malloc( i+1 );
- if( zNew==0 ) return 0;
- strcpy(zNew, z);
- if( i>0 && isspace(zNew[i-1]) ){
- i--;
- zNew[i] = 0;
- }
- return zNew;
-}
-
-/*
-** Resolve a sequence of URLs. Return the result in space obtained
-** from malloc().
-*/
-char *ResolveUrl(
- char *zBase, /* The base URL */
- const char **azSeries /* A list of relatives. NULL terminated */
-){
- Url *base;
- Url *term;
- char *z;
-
- base = ParseUrl(zBase);
- while( azSeries[0] ){
- term = ParseUrl(azSeries[0]);
- azSeries++;
- if( term->zScheme==0 && term->zAuthority==0 && term->zPath==0
- && term->zQuery==0 && term->zFragment ){
- ReplaceStr(&base->zFragment, term->zFragment);
- }else if( term->zScheme ){
- Url temp;
- temp = *term;
- *term = *base;
- *base = temp;
- }else if( term->zAuthority ){
- ReplaceStr(&base->zAuthority, term->zAuthority);
- ReplaceStr(&base->zPath, term->zPath);
- ReplaceStr(&base->zQuery, term->zQuery);
- ReplaceStr(&base->zFragment, term->zFragment);
- }else if( term->zPath && term->zPath[0]=='/' ){
- ReplaceStr(&base->zPath, term->zPath);
- ReplaceStr(&base->zQuery, term->zQuery);
- ReplaceStr(&base->zFragment, term->zFragment);
- }else if( term->zPath && base->zPath ){
- char *zBuf;
- int i, j;
- zBuf = malloc( strlen(base->zPath) + strlen(term->zPath) + 2 );
- if( zBuf ){
- sprintf(zBuf,"%s", base->zPath);
- for(i=strlen(zBuf)-1; i>=0 && zBuf[i]!='/'; i--){ zBuf[i] = 0; }
- strcat(zBuf, term->zPath);
- for(i=0; zBuf[i]; i++){
- if( zBuf[i]=='/' && zBuf[i+1]=='.' && zBuf[i+2]=='/' ){
- strcpy(&zBuf[i+1], &zBuf[i+3]);
- i--;
- continue;
- }
- if( zBuf[i]=='/' && zBuf[i+1]=='.' && zBuf[i+2]==0 ){
- zBuf[i+1] = 0;
- continue;
- }
- if( i>0 && zBuf[i]=='/' && zBuf[i+1]=='.' && zBuf[i+2]=='.'
- && (zBuf[i+3]=='/' || zBuf[i+3]==0) ){
- for(j=i-1; j>=0 && zBuf[j]!='/'; j--){}
- if( zBuf[i+3] ){
- strcpy(&zBuf[j+1], &zBuf[i+4]);
- }else{
- zBuf[j+1] = 0;
- }
- i = j-1;
- if( i<-1 ) i = -1;
- continue;
- }
- }
- free(base->zPath);
- base->zPath = zBuf;
- }
- ReplaceStr(&base->zQuery, term->zQuery);
- ReplaceStr(&base->zFragment, term->zFragment);
- }
- FreeUrl(term);
- }
- z = BuildUrl(base);
- FreeUrl(base);
- return z;
-}