File Annotation
Not logged in
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: }