Fossil

Check-in [eb8d989dae]
Login

Check-in [eb8d989dae]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Simplify the implementation of the --args FILENAME patch, as requested by the FIXME comment.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | stephan-hack
Files: files | file ages | folders
SHA1: eb8d989daebfce1fd22513bb3718b25bd572e86a
User & Date: drh 2011-10-04 23:03:17.321
Original Comment: Simplify the implementation of the --args FILENAME patch, as requested by the FIXME comment.
Context
2011-10-20
14:39
pulled in trunk for clean slate on subsequent changes. ... (check-in: a37d80e8af user: stephan tags: stephan-hack)
2011-10-04
23:07
Merge the --args FILENAME patch into trunk. ... (check-in: c0274f9962 user: drh tags: trunk)
23:03
Simplify the implementation of the --args FILENAME patch, as requested by the FIXME comment. ... (check-in: eb8d989dae user: drh tags: stephan-hack)
21:41
Initial --args FILENAME patch. Impl seems over-complex to me, but works as described in the list thread. ... (check-in: 8a6568c3a3 user: stephan tags: stephan-hack)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/main.c.
230
231
232
233
234
235
236
237
238
239
240

241
242


243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269



270
271
272
273
274

275
276
277
278
279
280
281
282
283
284
285
286

287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321
322
323
324
325



326
327
328
329
330

331
332
333

334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
    *pIndex = m;
    return 0;
  }
  return 1+(cnt>1);
}

/*
** Reads all non-empty lines of the given file and replaces g.argv
** with their contents. argsPos is the position of the --args
** parameter, and zFile is assumed to be the argument immediately
** following g.argv[argsPos].

**
** FIXME: this impl is certainly way too complicated.


*/
static void read_args_lines(unsigned int argsPos, char const * zFile){
  Blob buffer = empty_blob;
  Blob line = empty_blob;
  typedef struct StringList {
    char * str;
    struct StringList * next;
  } StringList;
  StringList * head = NULL;
  StringList * current = NULL;
  FILE * infile;
  int blobSize = 0;
  unsigned int lineCount = 0;
  unsigned int i = 0;
  assert(argsPos>=1);
  assert(g.argc>=(argsPos+1));
  assert(0==strcmp(zFile,g.argv[argsPos+1]));
  infile = fopen(zFile,"rb");
  if(!infile){
    fossil_panic("Could not open file [%s].",zFile);
  }
  blob_read_from_channel(&buffer,infile,-1);
  fclose(infile);
  blobSize = blob_size(&buffer);
  if(blobSize<=0){
    /* FIXME? error here? */
    blob_reset(&buffer);



    return;
  }
  blob_rewind(&buffer);
  while(1){
    int lineLen = blob_line(&buffer,&line);

    StringList * next = NULL;
    if(0==lineLen){
      break;
    }
    else if(lineLen<2){
      continue; /* ignore empty lines */
    }
    next = (StringList*)calloc(1,sizeof(StringList));
    ++lineCount;
    if( !head ) {
      head = next;
    }

    if( current ){
      current->next = next;
      current = next;
    }else{
      assert(head==next);
      current = head;
    }
    current->str = strdup(blob_buffer(&line));
    current->str[lineLen-1] = 0/*replace \n with NULL. FIXME: strip \r as well.*/;
    blob_reset(&line);
  }
  blob_reset(&buffer);
  if(lineCount){
    int const newArgc = g.argc + lineCount - 2;
    unsigned int i;
    unsigned int argOffset = 0;
    char ** newArgv = calloc(newArgc,sizeof(char*));
    assert(NULL != newArgv);
    for(i = 0; i < argsPos; ++i){
      newArgv[i] = g.argv[i];
    }
    argOffset = i;
    current = head;
    for( i = 0; i < lineCount; ++i, ++argOffset ){
      StringList * toFree = current;
      assert(NULL != current);
      assert(NULL != current->str);

      newArgv[argOffset] = current->str;
      current = current->next;
      free(toFree);
    }
    /* FIXME: to simplify the code we move the --args args AFTER all
       others. This is, however, arguablly very wrong. We should
       instead insert them in place of --args XYZ.
    */
    for(i = argsPos+2; i < g.argc; ++i, ++argOffset){
      newArgv[argOffset] = g.argv[i];
    }
    assert(NULL==current);



    g.argc = newArgc;
    g.argv = newArgv;
  }
#if 0
  {

    int i;
    printf("g.argc=%d\n",g.argc);
    for( i = 0; i < g.argc; ++i ){

      printf("g.argv[%d] = %s\n",i, g.argv[i]);
    }
  }
#endif
}


/*
** Reads the --args FILENAME CLI option and massages g.argc/g.argv
*/
static void expand_args_arg(){
  assert((g.argc>0) && g.argv[g.argc-1]);
  if(g.argc<3){
    return;
  }else{
    unsigned int i = 1;
    char got = 0;
    for( ; i < (unsigned int)g.argc; ++i ){
      if(0==strcmp("--args",g.argv[i])){
        got = 1;
        break;
      }
    }
    if(!got){
      return;
    }else{
      char const * zFile;
      if(i==(g.argc-1)){
        /* FIXME: error out/exit here. Missing filename. */
        return;
      }
      zFile = g.argv[i+1];
      read_args_lines(i,zFile);
    }
  }
}

/*
** This procedure runs first.
*/
int main(int argc, char **argv){
  const char *zCmdName = "unknown";
  int idx;
  int rc;
  int i;

  sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
  g.now = time(0);
  g.argc = argc;
  g.argv = argv;
  expand_args_arg();
  argc = g.argc;
  argv = g.argv;
  for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]);
  if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
    zCmdName = "cgi";
  }else if( argc<2 ){
    fossil_fatal("Usage: %s COMMAND ...\n"







<
|
|
|
>
|
|
>
>

|
|
|
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
>
>
>
<
|
<
<
<
>
|
<
<
<
<
|
<
<
|
|
<
<
>
|
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
|
|
|
<
<
<
<
>
|
<
<
<
<
<
<
<
<
|
|
|
>
>
>
|
|
<
|
<
>
|
<
|
>
|
<
|
<
|
|
|
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<















|







230
231
232
233
234
235
236

237
238
239
240
241
242
243
244
245
246
247
248








249
250













251
252
253

254



255
256




257


258
259


260
261





262






263






264
265
266




267
268








269
270
271
272
273
274
275
276

277

278
279

280
281
282

283

284
285
286





287



288










289



290



291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
    *pIndex = m;
    return 0;
  }
  return 1+(cnt>1);
}

/*

** Search g.argv for arguments "--args FILENAME".  If found, then
** (1) remove the two arguments from g.argv
** (2) Read the file FILENAME
** (3) Use the contents of FILE to replace the two removed arguments:
**     (a) Ignore blank lines in the file
**     (b) Each non-empty line of the file is an argument, except
**     (c) If the line begins with "-" and contains a space, it is broken
**         into two arguments at the space.
*/
static void expand_args_option(void){
  Blob file = empty_blob;   /* Content of the file */
  Blob line = empty_blob;   /* One line of the file */








  unsigned int nLine;       /* Number of lines in the file*/
  unsigned int i, j, k;     /* Loop counters */













  int n;                    /* Number of bytes in one line */
  char *z;            /* General use string pointer */
  char **newArgv;     /* New expanded g.argv under construction */





  for(i=1; i<g.argc-1; i++){
    z = g.argv[i];




    if( z[0]!='-' ) continue;


    z++;
    if( z[0]=='-' ) z++;


    if( z[0]==0 ) return;   /* Stop searching at "--" */
    if( fossil_strcmp(z, "args")==0 ) break;





  }






  if( i>=g.argc-1 ) return;







  blob_read_from_file(&file, g.argv[i+1]);
  z = blob_str(&file);




  for(k=0, nLine=1; z[k]; k++) if( z[k]=='\n' ) nLine++;
  newArgv = fossil_malloc( sizeof(char*)*(g.argc + nLine*2) );








  for(j=0; j<i; j++) newArgv[j] = g.argv[j];
  
  blob_rewind(&file);
  while( (n = blob_line(&file, &line))>0 ){
    if( n<=1 ) continue;
    z = blob_buffer(&line);
    z[n-1] = 0;
    newArgv[j++] = z;

    if( z[0]=='-' ){

      for(k=1; z[k] && !fossil_isspace(z[k]); k++){}
      if( z[k] ){

        z[k] = 0;
        k++;
        if( z[k] ) newArgv[j++] = &z[k];

      }

    }
  }
  i += 2;





  while( i<g.argc ) newArgv[j++] = g.argv[i++];



  newArgv[j] = 0;










  g.argc = j;



  g.argv = newArgv;



}

/*
** This procedure runs first.
*/
int main(int argc, char **argv){
  const char *zCmdName = "unknown";
  int idx;
  int rc;
  int i;

  sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
  g.now = time(0);
  g.argc = argc;
  g.argv = argv;
  expand_args_option();
  argc = g.argc;
  argv = g.argv;
  for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]);
  if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
    zCmdName = "cgi";
  }else if( argc<2 ){
    fossil_fatal("Usage: %s COMMAND ...\n"