dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Copyright (c) 2002 D. Richard Hipp dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is free software; you can redistribute it and/or dbda8d6ce9 2007-07-21 drh: ** modify it under the terms of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License as published by the Free Software Foundation; either dbda8d6ce9 2007-07-21 drh: ** version 2 of the License, or (at your option) any later version. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is distributed in the hope that it will be useful, dbda8d6ce9 2007-07-21 drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of dbda8d6ce9 2007-07-21 drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dbda8d6ce9 2007-07-21 drh: ** General Public License for more details. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** You should have received a copy of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License along with this library; if not, write to the dbda8d6ce9 2007-07-21 drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, dbda8d6ce9 2007-07-21 drh: ** Boston, MA 02111-1307, USA. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Author contact information: dbda8d6ce9 2007-07-21 drh: ** drh@hwaci.com dbda8d6ce9 2007-07-21 drh: ** http://www.hwaci.com/drh/ dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ******************************************************************************* dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Build a static hash table that maps URLs into functions to generate dbda8d6ce9 2007-07-21 drh: ** web pages. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** The source code is scanned for comment lines of the form: dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** WEBPAGE: /abc/xyz dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This comment should be followed by a function definition of the dbda8d6ce9 2007-07-21 drh: ** form: dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** void function_name(void){ dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This routine creates C source code for a constant table that maps dbda8d6ce9 2007-07-21 drh: ** webpage name into pointers to the function. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** We also scan for comments lines of this form: dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** COMMAND: cmdname dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** These entries build a constant table used to map command names into dbda8d6ce9 2007-07-21 drh: ** functions. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #include <stdio.h> dbda8d6ce9 2007-07-21 drh: #include <stdlib.h> dbda8d6ce9 2007-07-21 drh: #include <ctype.h> dbda8d6ce9 2007-07-21 drh: #include <assert.h> dbda8d6ce9 2007-07-21 drh: #include <string.h> dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Each entry looks like this: dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: typedef struct Entry { dbda8d6ce9 2007-07-21 drh: int eType; dbda8d6ce9 2007-07-21 drh: char *zFunc; dbda8d6ce9 2007-07-21 drh: char *zPath; c9fdb846fb 2007-08-18 drh: char *zHelp; dbda8d6ce9 2007-07-21 drh: } Entry; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Maximum number of entries dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #define N_ENTRY 500 dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* c9fdb846fb 2007-08-18 drh: ** Maximum size of a help message c9fdb846fb 2007-08-18 drh: */ c9fdb846fb 2007-08-18 drh: #define MX_HELP 10000 c9fdb846fb 2007-08-18 drh: c9fdb846fb 2007-08-18 drh: /* dbda8d6ce9 2007-07-21 drh: ** Table of entries dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: Entry aEntry[N_ENTRY]; c9fdb846fb 2007-08-18 drh: c9fdb846fb 2007-08-18 drh: /* c9fdb846fb 2007-08-18 drh: ** Current help message accumulator c9fdb846fb 2007-08-18 drh: */ c9fdb846fb 2007-08-18 drh: char zHelp[MX_HELP]; c9fdb846fb 2007-08-18 drh: int nHelp; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** How many entries are used dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: int nUsed; dbda8d6ce9 2007-07-21 drh: int nFixed; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Current filename and line number dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: char *zFile; dbda8d6ce9 2007-07-21 drh: int nLine; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Duplicate N characters of a string. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: char *string_dup(const char *zSrc, int n){ dbda8d6ce9 2007-07-21 drh: char *z; dbda8d6ce9 2007-07-21 drh: if( n<0 ) n = strlen(zSrc); dbda8d6ce9 2007-07-21 drh: z = malloc( n+1 ); dbda8d6ce9 2007-07-21 drh: if( z==0 ){ fprintf(stderr,"Out of memory!\n"); exit(1); } dbda8d6ce9 2007-07-21 drh: strncpy(z, zSrc, n); dbda8d6ce9 2007-07-21 drh: z[n] = 0; dbda8d6ce9 2007-07-21 drh: return z; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Scan a line looking for comments containing zLabel. Make dbda8d6ce9 2007-07-21 drh: ** new entries if found. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void scan_for_label(const char *zLabel, char *zLine, int eType){ dbda8d6ce9 2007-07-21 drh: int i, j; dbda8d6ce9 2007-07-21 drh: int len = strlen(zLabel); dbda8d6ce9 2007-07-21 drh: if( nUsed>=N_ENTRY ) return; dbda8d6ce9 2007-07-21 drh: for(i=0; isspace(zLine[i]) || zLine[i]=='*'; i++){} dbda8d6ce9 2007-07-21 drh: if( zLine[i]!=zLabel[0] ) return; dbda8d6ce9 2007-07-21 drh: if( strncmp(&zLine[i],zLabel, len)==0 ){ dbda8d6ce9 2007-07-21 drh: i += len; dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: return; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: while( isspace(zLine[i]) ){ i++; } dbda8d6ce9 2007-07-21 drh: if( zLine[i]=='/' ) i++; dbda8d6ce9 2007-07-21 drh: for(j=0; zLine[i+j] && !isspace(zLine[i+j]); j++){} dbda8d6ce9 2007-07-21 drh: aEntry[nUsed].eType = eType; dbda8d6ce9 2007-07-21 drh: aEntry[nUsed].zPath = string_dup(&zLine[i], j); dbda8d6ce9 2007-07-21 drh: aEntry[nUsed].zFunc = 0; dbda8d6ce9 2007-07-21 drh: nUsed++; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Scan a line for a function that implements a web page or command. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void scan_for_func(char *zLine){ dbda8d6ce9 2007-07-21 drh: int i,j,k; c9fdb846fb 2007-08-18 drh: char *z; dbda8d6ce9 2007-07-21 drh: if( nUsed<=nFixed ) return; c9fdb846fb 2007-08-18 drh: if( strncmp(zLine, "**", 2)==0 && isspace(zLine[2]) c9fdb846fb 2007-08-18 drh: && strlen(zLine)<sizeof(zHelp)-nHelp-1 && nUsed>nFixed ){ c9fdb846fb 2007-08-18 drh: if( zLine[2]=='\n' ){ c9fdb846fb 2007-08-18 drh: zHelp[nHelp++] = '\n'; c9fdb846fb 2007-08-18 drh: }else{ c9fdb846fb 2007-08-18 drh: if( strncmp(&zLine[3], "Usage: ", 6)==0 ) nHelp = 0; c9fdb846fb 2007-08-18 drh: strcpy(&zHelp[nHelp], &zLine[3]); c9fdb846fb 2007-08-18 drh: nHelp += strlen(&zHelp[nHelp]); c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: return; c9fdb846fb 2007-08-18 drh: } dbda8d6ce9 2007-07-21 drh: for(i=0; isspace(zLine[i]); i++){} dbda8d6ce9 2007-07-21 drh: if( zLine[i]==0 ) return; dbda8d6ce9 2007-07-21 drh: if( strncmp(&zLine[i],"void",4)!=0 ){ dbda8d6ce9 2007-07-21 drh: if( zLine[i]!='*' ) goto page_skip; dbda8d6ce9 2007-07-21 drh: return; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: i += 4; dbda8d6ce9 2007-07-21 drh: if( !isspace(zLine[i]) ) goto page_skip; dbda8d6ce9 2007-07-21 drh: while( isspace(zLine[i]) ){ i++; } dbda8d6ce9 2007-07-21 drh: for(j=0; isalnum(zLine[i+j]) || zLine[i+j]=='_'; j++){} dbda8d6ce9 2007-07-21 drh: if( j==0 ) goto page_skip; c9fdb846fb 2007-08-18 drh: for(k=nHelp-1; k>=0 && isspace(zHelp[k]); k--){} c9fdb846fb 2007-08-18 drh: nHelp = k+1; c9fdb846fb 2007-08-18 drh: zHelp[nHelp] = 0; c9fdb846fb 2007-08-18 drh: for(k=0; k<nHelp && isspace(zHelp[k]); k++){} c9fdb846fb 2007-08-18 drh: if( k<nHelp ){ c9fdb846fb 2007-08-18 drh: z = string_dup(&zHelp[k], nHelp-k); c9fdb846fb 2007-08-18 drh: }else{ c9fdb846fb 2007-08-18 drh: z = 0; c9fdb846fb 2007-08-18 drh: } dbda8d6ce9 2007-07-21 drh: for(k=nFixed; k<nUsed; k++){ dbda8d6ce9 2007-07-21 drh: aEntry[k].zFunc = string_dup(&zLine[i], j); c9fdb846fb 2007-08-18 drh: aEntry[k].zHelp = z; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: i+=j; dbda8d6ce9 2007-07-21 drh: while( isspace(zLine[i]) ){ i++; } dbda8d6ce9 2007-07-21 drh: if( zLine[i]!='(' ) goto page_skip; dbda8d6ce9 2007-07-21 drh: nFixed = nUsed; c9fdb846fb 2007-08-18 drh: nHelp = 0; dbda8d6ce9 2007-07-21 drh: return; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: page_skip: dbda8d6ce9 2007-07-21 drh: for(i=nFixed; i<nUsed; i++){ dbda8d6ce9 2007-07-21 drh: fprintf(stderr,"%s:%d: skipping page \"%s\"\n", dbda8d6ce9 2007-07-21 drh: zFile, nLine, aEntry[i].zPath); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: nUsed = nFixed; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Compare two entries dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: int e_compare(const void *a, const void *b){ dbda8d6ce9 2007-07-21 drh: const Entry *pA = (const Entry*)a; dbda8d6ce9 2007-07-21 drh: const Entry *pB = (const Entry*)b; dbda8d6ce9 2007-07-21 drh: int x = pA->eType - pB->eType; dbda8d6ce9 2007-07-21 drh: if( x==0 ){ dbda8d6ce9 2007-07-21 drh: x = strcmp(pA->zPath, pB->zPath); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: return x; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Build the binary search table. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void build_table(void){ dbda8d6ce9 2007-07-21 drh: int i; c9fdb846fb 2007-08-18 drh: int nType0; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: qsort(aEntry, nFixed, sizeof(aEntry[0]), e_compare); dbda8d6ce9 2007-07-21 drh: for(i=0; i<nFixed; i++){ dbda8d6ce9 2007-07-21 drh: printf("extern void %s(void);\n", aEntry[i].zFunc); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: printf( dbda8d6ce9 2007-07-21 drh: "typedef struct NameMap NameMap;\n" dbda8d6ce9 2007-07-21 drh: "struct NameMap {\n" dbda8d6ce9 2007-07-21 drh: " const char *zName;\n" dbda8d6ce9 2007-07-21 drh: " void (*xFunc)(void);\n" dbda8d6ce9 2007-07-21 drh: "};\n" dbda8d6ce9 2007-07-21 drh: "static const NameMap aWebpage[] = {\n" dbda8d6ce9 2007-07-21 drh: ); dbda8d6ce9 2007-07-21 drh: for(i=0; i<nFixed && aEntry[i].eType==0; i++){ dbda8d6ce9 2007-07-21 drh: printf(" { \"%s\",%*s %s },\n", dbda8d6ce9 2007-07-21 drh: aEntry[i].zPath, (int)(25-strlen(aEntry[i].zPath)), "", dbda8d6ce9 2007-07-21 drh: aEntry[i].zFunc dbda8d6ce9 2007-07-21 drh: ); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: printf("};\n"); c9fdb846fb 2007-08-18 drh: nType0 = i; dbda8d6ce9 2007-07-21 drh: printf( dbda8d6ce9 2007-07-21 drh: "static const NameMap aCommand[] = {\n" dbda8d6ce9 2007-07-21 drh: ); c9fdb846fb 2007-08-18 drh: for(i=nType0; i<nFixed && aEntry[i].eType==1; i++){ dbda8d6ce9 2007-07-21 drh: printf(" { \"%s\",%*s %s },\n", dbda8d6ce9 2007-07-21 drh: aEntry[i].zPath, (int)(25-strlen(aEntry[i].zPath)), "", dbda8d6ce9 2007-07-21 drh: aEntry[i].zFunc dbda8d6ce9 2007-07-21 drh: ); c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: printf("};\n"); c9fdb846fb 2007-08-18 drh: for(i=nType0; i<nFixed; i++){ c9fdb846fb 2007-08-18 drh: char *z = aEntry[i].zHelp; c9fdb846fb 2007-08-18 drh: if( z && z[0] ){ c9fdb846fb 2007-08-18 drh: printf("static const char zHelp_%s[] = \n", aEntry[i].zFunc); c9fdb846fb 2007-08-18 drh: printf(" \""); c9fdb846fb 2007-08-18 drh: while( *z ){ c9fdb846fb 2007-08-18 drh: if( *z=='\n' ){ c9fdb846fb 2007-08-18 drh: printf("\\n\"\n \""); c9fdb846fb 2007-08-18 drh: }else if( *z=='"' ){ c9fdb846fb 2007-08-18 drh: printf("\\\""); c9fdb846fb 2007-08-18 drh: }else{ c9fdb846fb 2007-08-18 drh: putchar(*z); c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: z++; c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: printf("\";\n"); c9fdb846fb 2007-08-18 drh: aEntry[i].zHelp[0] = 0; c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: printf( c9fdb846fb 2007-08-18 drh: "static const char * const aCmdHelp[] = {\n" c9fdb846fb 2007-08-18 drh: ); c9fdb846fb 2007-08-18 drh: for(i=nType0; i<nFixed; i++){ c9fdb846fb 2007-08-18 drh: if( aEntry[i].zHelp==0 ){ c9fdb846fb 2007-08-18 drh: printf(" 0,\n"); c9fdb846fb 2007-08-18 drh: }else{ c9fdb846fb 2007-08-18 drh: printf(" zHelp_%s,\n", aEntry[i].zFunc); c9fdb846fb 2007-08-18 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: printf("};\n"); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Process a single file of input dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void process_file(void){ dbda8d6ce9 2007-07-21 drh: FILE *in = fopen(zFile, "r"); dbda8d6ce9 2007-07-21 drh: char zLine[2000]; dbda8d6ce9 2007-07-21 drh: if( in==0 ){ dbda8d6ce9 2007-07-21 drh: fprintf(stderr,"%s: cannot open\n", zFile); dbda8d6ce9 2007-07-21 drh: return; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: nLine = 0; dbda8d6ce9 2007-07-21 drh: while( fgets(zLine, sizeof(zLine), in) ){ dbda8d6ce9 2007-07-21 drh: nLine++; dbda8d6ce9 2007-07-21 drh: scan_for_label("WEBPAGE:",zLine,0); dbda8d6ce9 2007-07-21 drh: scan_for_label("COMMAND:",zLine,1); dbda8d6ce9 2007-07-21 drh: scan_for_func(zLine); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: fclose(in); dbda8d6ce9 2007-07-21 drh: nUsed = nFixed; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: int main(int argc, char **argv){ dbda8d6ce9 2007-07-21 drh: int i; dbda8d6ce9 2007-07-21 drh: for(i=1; i<argc; i++){ dbda8d6ce9 2007-07-21 drh: zFile = argv[i]; dbda8d6ce9 2007-07-21 drh: process_file(); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: build_table(); dbda8d6ce9 2007-07-21 drh: return 0; dbda8d6ce9 2007-07-21 drh: }