home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / less-321-src.tgz / tar.out / fsf / less / main.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  8KB  |  360 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994,1995,1996  Mark Nudelman
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice in the documentation and/or other materials provided with 
  12.  *    the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  17.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
  18.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
  20.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
  21.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  22.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
  23.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
  24.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * Entry point, initialization, miscellaneous routines.
  30.  */
  31.  
  32. #include "less.h"
  33. #include "position.h"
  34.  
  35. public char *    every_first_cmd = NULL;
  36. public int    new_file;
  37. public int    is_tty;
  38. public IFILE    curr_ifile = NULL_IFILE;
  39. public IFILE    old_ifile = NULL_IFILE;
  40. public struct scrpos initial_scrpos;
  41. public int    any_display = FALSE;
  42. public int    wscroll;
  43. public char *    progname;
  44. public int    quitting;
  45. public int    secure;
  46. public int    dohelp;
  47.  
  48. #if LOGFILE
  49. public int    logfile = -1;
  50. public int    force_logfile = FALSE;
  51. public char *    namelogfile = NULL;
  52. #endif
  53.  
  54. #if EDITOR
  55. public char *    editor;
  56. public char *    editproto;
  57. #endif
  58.  
  59. #if TAGS
  60. extern char *    tagfile;
  61. extern char *    tagoption;
  62. extern int    jump_sline;
  63. #endif
  64.  
  65. extern int    missing_cap;
  66. extern int    know_dumb;
  67.  
  68.  
  69. /*
  70.  * Entry point.
  71.  */
  72. int
  73. main(argc, argv)
  74.     int argc;
  75.     char *argv[];
  76. {
  77.     IFILE ifile;
  78.     char *s;
  79.  
  80. #ifdef __EMX__
  81.     _response(&argc, &argv);
  82.     _wildcard(&argc, &argv);
  83. #endif
  84.  
  85.     progname = *argv++;
  86.     argc--;
  87.  
  88.     secure = 0;
  89.     s = lgetenv("LESSSECURE");
  90.     if (s != NULL && *s != '\0')
  91.         secure = 1;
  92.  
  93.     /*
  94.      * Process command line arguments and LESS environment arguments.
  95.      * Command line arguments override environment arguments.
  96.      */
  97.     is_tty = isatty(1);
  98.     get_term();
  99.     init_cmds();
  100.     init_prompt();
  101.     init_charset();
  102.     init_option();
  103.     scan_option(lgetenv("LESS"));
  104.  
  105. #if GNU_OPTIONS
  106.     /*
  107.      * Special case for "less --help" and "less --version".
  108.      */
  109.     if (argc == 1)
  110.     {
  111.         if (strcmp(argv[0], "--help") == 0)
  112.         {
  113.             scan_option("-?");
  114.             argc = 0;
  115.         }
  116.         if (strcmp(argv[0], "--version") == 0)
  117.         {
  118.             scan_option("-V");
  119.             argc = 0;
  120.         }
  121.     }
  122. #endif
  123. #define    isoptstring(s)    (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
  124.     while (argc > 0 && (isoptstring(*argv) || isoptpending()))
  125.     {
  126.         s = *argv++;
  127.         argc--;
  128.         if (strcmp(s, "--") == 0)
  129.             break;
  130.         scan_option(s);
  131.     }
  132. #undef isoptstring
  133.  
  134.     if (isoptpending())
  135.     {
  136.         /*
  137.          * Last command line option was a flag requiring a
  138.          * following string, but there was no following string.
  139.          */
  140.         nopendopt();
  141.         quit(QUIT_OK);
  142.     }
  143.  
  144. #if EDITOR
  145.     editor = lgetenv("VISUAL");
  146.     if (editor == NULL || *editor == '\0')
  147.     {
  148.         editor = lgetenv("EDITOR");
  149.         if (editor == NULL || *editor == '\0')
  150.             editor = EDIT_PGM;
  151.     }
  152.     editproto = lgetenv("LESSEDIT");
  153.     if (editproto == NULL || *editproto == '\0')
  154.         editproto = "%E ?lm+%lm. %f";
  155. #endif
  156.  
  157.     /*
  158.      * Call get_ifile with all the command line filenames
  159.      * to "register" them with the ifile system.
  160.      */
  161.     ifile = NULL_IFILE;
  162.     if (dohelp)
  163.         ifile = get_ifile(FAKE_HELPFILE, ifile);
  164.     while (argc-- > 0)
  165.     {
  166. #if MSDOS_COMPILER || OS2
  167.         /*
  168.          * Because the "shell" doesn't expand filename patterns,
  169.          * treat each argument as a filename pattern rather than
  170.          * a single filename.  
  171.          * Expand the pattern and iterate over the expanded list.
  172.          */
  173.         struct textlist tlist;
  174.         char *gfilename;
  175.         char *filename;
  176.         
  177.         gfilename = lglob(*argv++);
  178.         init_textlist(&tlist, gfilename);
  179.         filename = NULL;
  180.         while ((filename = forw_textlist(&tlist, filename)) != NULL)
  181.             ifile = get_ifile(filename, ifile);
  182.         free(gfilename);
  183. #else
  184.         ifile = get_ifile(*argv++, ifile);
  185. #endif
  186.     }
  187.     /*
  188.      * Set up terminal, etc.
  189.      */
  190.     if (!is_tty)
  191.     {
  192.         /*
  193.          * Output is not a tty.
  194.          * Just copy the input file(s) to output.
  195.          */
  196.         if (nifile() == 0)
  197.         {
  198.             if (edit_stdin() == 0)
  199.                 cat_file();
  200.         } else if (edit_first() == 0)
  201.         {
  202.             do {
  203.                 cat_file();
  204.             } while (edit_next(1) == 0);
  205.         }
  206.         quit(QUIT_OK);
  207.     }
  208.  
  209.     if (missing_cap && !know_dumb)
  210.         error("WARNING: terminal is not fully functional", NULL_PARG);
  211.     init_mark();
  212.     raw_mode(1);
  213.     open_getchr();
  214.     init_signals(1);
  215.  
  216.     /*
  217.      * Select the first file to examine.
  218.      */
  219. #if TAGS
  220.     if (tagoption != NULL)
  221.     {
  222.         /*
  223.          * A -t option was given.
  224.          * Verify that no filenames were also given.
  225.          * Edit the file selected by the "tags" search,
  226.          * and search for the proper line in the file.
  227.          */
  228.         if (nifile() > 0)
  229.         {
  230.             error("No filenames allowed with -t option", NULL_PARG);
  231.             quit(QUIT_ERROR);
  232.         }
  233.         findtag(tagoption);
  234.         if (tagfile == NULL)
  235.             quit(QUIT_ERROR);
  236.         if (edit(tagfile))  /* Edit file which contains the tag */
  237.             quit(QUIT_ERROR);
  238.         /*
  239.          * Search for the line which contains the tag.
  240.          * Set up initial_scrpos so we display that line.
  241.          */
  242.         initial_scrpos.pos = tagsearch();
  243.         if (initial_scrpos.pos == NULL_POSITION)
  244.             quit(QUIT_ERROR);
  245.         initial_scrpos.ln = jump_sline;
  246.     } else
  247. #endif
  248.     if (nifile() == 0)
  249.     {
  250.         if (edit_stdin())  /* Edit standard input */
  251.             quit(QUIT_ERROR);
  252.     } else 
  253.     {
  254.         if (edit_first())  /* Edit first valid file in cmd line */
  255.             quit(QUIT_ERROR);
  256.     }
  257.  
  258.     init();
  259.     commands();
  260.     quit(QUIT_OK);
  261.     /*NOTREACHED*/
  262. }
  263.  
  264. /*
  265.  * Copy a string, truncating to the specified length if necessary.
  266.  * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
  267.  */
  268.     public void
  269. strtcpy(to, from, len)
  270.     char *to;
  271.     char *from;
  272.     unsigned int len;
  273. {
  274.     strncpy(to, from, len);
  275.     to[len-1] = '\0';
  276. }
  277.  
  278. /*
  279.  * Copy a string to a "safe" place
  280.  * (that is, to a buffer allocated by calloc).
  281.  */
  282.     public char *
  283. save(s)
  284.     char *s;
  285. {
  286.     register char *p;
  287.  
  288.     p = (char *) ecalloc(strlen(s)+1, sizeof(char));
  289.     strcpy(p, s);
  290.     return (p);
  291. }
  292.  
  293. /*
  294.  * Allocate memory.
  295.  * Like calloc(), but never returns an error (NULL).
  296.  */
  297.     public VOID_POINTER
  298. ecalloc(count, size)
  299.     int count;
  300.     unsigned int size;
  301. {
  302.     register VOID_POINTER p;
  303.  
  304.     p = (VOID_POINTER) calloc(count, size);
  305.     if (p != NULL)
  306.         return (p);
  307.     error("Cannot allocate memory", NULL_PARG);
  308.     quit(QUIT_ERROR);
  309.     /*NOTREACHED*/
  310. }
  311.  
  312. /*
  313.  * Skip leading spaces in a string.
  314.  */
  315.     public char *
  316. skipsp(s)
  317.     register char *s;
  318. {
  319.     while (*s == ' ' || *s == '\t')    
  320.         s++;
  321.     return (s);
  322. }
  323.  
  324. /*
  325.  * Exit the program.
  326.  */
  327.     public void
  328. quit(status)
  329.     int status;
  330. {
  331.     static int save_status;
  332.  
  333.     /*
  334.      * Put cursor at bottom left corner, clear the line,
  335.      * reset the terminal modes, and exit.
  336.      */
  337.     if (status < 0)
  338.         status = save_status;
  339.     else
  340.         save_status = status;
  341.     quitting = 1;
  342.     edit((char*)NULL);
  343.     if (any_display && is_tty)
  344.         clear_bot();
  345.     deinit();
  346.     flush();
  347.     raw_mode(0);
  348. #if MSDOS_COMPILER
  349.     /* 
  350.      * If we don't close 2, we get some garbage from
  351.      * 2's buffer when it flushes automatically.
  352.      * I cannot track this one down  RB
  353.      * The same bug shows up if we use ^C^C to abort.
  354.      */
  355.     close(2);
  356. #endif
  357.     close_getchr();
  358.     exit(status);
  359. }
  360.