home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / less3292.zip / main.c < prev    next >
C/C++ Source or Header  |  1996-10-19  |  8KB  |  370 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 *    tagoption;
  61. extern int    jump_sline;
  62. #endif
  63.  
  64. extern int    missing_cap;
  65. extern int    know_dumb;
  66.  
  67.  
  68. /*
  69.  * Entry point.
  70.  */
  71. int
  72. main(argc, argv)
  73.     int argc;
  74.     char *argv[];
  75. {
  76.     IFILE ifile;
  77.     char *s;
  78.  
  79. #if OS2
  80. #ifdef __EMX__
  81.     _response(&argc, &argv);
  82.     _wildcard(&argc, &argv);
  83. #endif
  84.     if (isatty(0) && argc == 1)
  85.     {
  86.       extern char version[];
  87.       printf("\nless  version %s.\n", version);
  88.       printf("\nUsage: less [-[+]aABcCdeEfgimMnNqQruUsw] [-bN] [-hN] [-xN] [-[z]N]"
  89.              "\n            [-P[mM=]string] [-[lL]logfile] [-kkeyfile]"
  90.              "\n            [+cmd] [-ttag] [filename]...\n"
  91.              "\n   or: less -?\n", progname);
  92.       exit(1);
  93.     }
  94. #endif
  95.  
  96.     progname = *argv++;
  97.     argc--;
  98.  
  99.     secure = 0;
  100.     s = lgetenv("LESSSECURE");
  101.     if (s != NULL && *s != '\0')
  102.         secure = 1;
  103.  
  104.     /*
  105.      * Process command line arguments and LESS environment arguments.
  106.      * Command line arguments override environment arguments.
  107.      */
  108.     is_tty = isatty(1);
  109.     get_term();
  110.     init_cmds();
  111.     init_prompt();
  112.     init_charset();
  113.     init_option();
  114.     scan_option(lgetenv("LESS"));
  115.  
  116. #if GNU_OPTIONS
  117.     /*
  118.      * Special case for "less --help" and "less --version".
  119.      */
  120.     if (argc == 1)
  121.     {
  122.         if (strcmp(argv[0], "--help") == 0)
  123.         {
  124.             scan_option("-?");
  125.             argc = 0;
  126.         }
  127.         if (strcmp(argv[0], "--version") == 0)
  128.         {
  129.             scan_option("-V");
  130.             argc = 0;
  131.         }
  132.     }
  133. #endif
  134. #define    isoptstring(s)    (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
  135.     while (argc > 0 && (isoptstring(*argv) || isoptpending()))
  136.     {
  137.         s = *argv++;
  138.         argc--;
  139.         if (strcmp(s, "--") == 0)
  140.             break;
  141.         scan_option(s);
  142.     }
  143. #undef isoptstring
  144.  
  145.     if (isoptpending())
  146.     {
  147.         /*
  148.          * Last command line option was a flag requiring a
  149.          * following string, but there was no following string.
  150.          */
  151.         nopendopt();
  152.         quit(QUIT_OK);
  153.     }
  154.  
  155. #if EDITOR
  156.     editor = lgetenv("VISUAL");
  157.     if (editor == NULL || *editor == '\0')
  158.     {
  159.         editor = lgetenv("EDITOR");
  160.         if (editor == NULL || *editor == '\0')
  161.             editor = EDIT_PGM;
  162.     }
  163.     editproto = lgetenv("LESSEDIT");
  164.     if (editproto == NULL || *editproto == '\0')
  165.         editproto = "%E ?lm+%lm. %f";
  166. #endif
  167.  
  168.     /*
  169.      * Call get_ifile with all the command line filenames
  170.      * to "register" them with the ifile system.
  171.      */
  172.     ifile = NULL_IFILE;
  173.     if (dohelp)
  174.         ifile = get_ifile(FAKE_HELPFILE, ifile);
  175.     while (argc-- > 0)
  176.     {
  177. #if (MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC) || OS2
  178.         /*
  179.          * Because the "shell" doesn't expand filename patterns,
  180.          * treat each argument as a filename pattern rather than
  181.          * a single filename.  
  182.          * Expand the pattern and iterate over the expanded list.
  183.          */
  184.         struct textlist tlist;
  185.         char *gfilename;
  186.         char *filename;
  187.         
  188.         gfilename = lglob(*argv++);
  189.         init_textlist(&tlist, gfilename);
  190.         filename = NULL;
  191.         while ((filename = forw_textlist(&tlist, filename)) != NULL)
  192.             ifile = get_ifile(filename, ifile);
  193.         free(gfilename);
  194. #else
  195.         ifile = get_ifile(*argv++, ifile);
  196. #endif
  197.     }
  198.     /*
  199.      * Set up terminal, etc.
  200.      */
  201.     if (!is_tty)
  202.     {
  203.         /*
  204.          * Output is not a tty.
  205.          * Just copy the input file(s) to output.
  206.          */
  207.         SET_BINARY(1);
  208.         if (nifile() == 0)
  209.         {
  210.             if (edit_stdin() == 0)
  211.                 cat_file();
  212.         } else if (edit_first() == 0)
  213.         {
  214.             do {
  215.                 cat_file();
  216.             } while (edit_next(1) == 0);
  217.         }
  218.         quit(QUIT_OK);
  219.     }
  220.  
  221.     if (missing_cap && !know_dumb)
  222.         error("WARNING: terminal is not fully functional", NULL_PARG);
  223.     init_mark();
  224.     raw_mode(1);
  225.     open_getchr();
  226.     init_signals(1);
  227.  
  228.     /*
  229.      * Select the first file to examine.
  230.      */
  231. #if TAGS
  232.     if (tagoption != NULL)
  233.     {
  234.         /*
  235.          * A -t option was given.
  236.          * Verify that no filenames were also given.
  237.          * Edit the file selected by the "tags" search,
  238.          * and search for the proper line in the file.
  239.          */
  240.         if (nifile() > 0)
  241.         {
  242.             error("No filenames allowed with -t option", NULL_PARG);
  243.             quit(QUIT_ERROR);
  244.         }
  245.         findtag(tagoption);
  246.         if (edit_tagfile())  /* Edit file which contains the tag */
  247.             quit(QUIT_ERROR);
  248.         /*
  249.          * Search for the line which contains the tag.
  250.          * Set up initial_scrpos so we display that line.
  251.          */
  252.         initial_scrpos.pos = tagsearch();
  253.         if (initial_scrpos.pos == NULL_POSITION)
  254.             quit(QUIT_ERROR);
  255.         initial_scrpos.ln = jump_sline;
  256.     } else
  257. #endif
  258.     if (nifile() == 0)
  259.     {
  260.         if (edit_stdin())  /* Edit standard input */
  261.             quit(QUIT_ERROR);
  262.     } else 
  263.     {
  264.         if (edit_first())  /* Edit first valid file in cmd line */
  265.             quit(QUIT_ERROR);
  266.     }
  267.  
  268.     init();
  269.     commands();
  270.     quit(QUIT_OK);
  271.     /*NOTREACHED*/
  272. }
  273.  
  274. /*
  275.  * Copy a string, truncating to the specified length if necessary.
  276.  * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
  277.  */
  278.     public void
  279. strtcpy(to, from, len)
  280.     char *to;
  281.     char *from;
  282.     unsigned int len;
  283. {
  284.     strncpy(to, from, len);
  285.     to[len-1] = '\0';
  286. }
  287.  
  288. /*
  289.  * Copy a string to a "safe" place
  290.  * (that is, to a buffer allocated by calloc).
  291.  */
  292.     public char *
  293. save(s)
  294.     char *s;
  295. {
  296.     register char *p;
  297.  
  298.     p = (char *) ecalloc(strlen(s)+1, sizeof(char));
  299.     strcpy(p, s);
  300.     return (p);
  301. }
  302.  
  303. /*
  304.  * Allocate memory.
  305.  * Like calloc(), but never returns an error (NULL).
  306.  */
  307.     public VOID_POINTER
  308. ecalloc(count, size)
  309.     int count;
  310.     unsigned int size;
  311. {
  312.     register VOID_POINTER p;
  313.  
  314.     p = (VOID_POINTER) calloc(count, size);
  315.     if (p != NULL)
  316.         return (p);
  317.     error("Cannot allocate memory", NULL_PARG);
  318.     quit(QUIT_ERROR);
  319.     /*NOTREACHED*/
  320. }
  321.  
  322. /*
  323.  * Skip leading spaces in a string.
  324.  */
  325.     public char *
  326. skipsp(s)
  327.     register char *s;
  328. {
  329.     while (*s == ' ' || *s == '\t')    
  330.         s++;
  331.     return (s);
  332. }
  333.  
  334. /*
  335.  * Exit the program.
  336.  */
  337.     public void
  338. quit(status)
  339.     int status;
  340. {
  341.     static int save_status;
  342.  
  343.     /*
  344.      * Put cursor at bottom left corner, clear the line,
  345.      * reset the terminal modes, and exit.
  346.      */
  347.     if (status < 0)
  348.         status = save_status;
  349.     else
  350.         save_status = status;
  351.     quitting = 1;
  352.     edit((char*)NULL);
  353.     if (any_display && is_tty)
  354.         clear_bot();
  355.     deinit();
  356.     flush();
  357.     raw_mode(0);
  358. #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
  359.     /* 
  360.      * If we don't close 2, we get some garbage from
  361.      * 2's buffer when it flushes automatically.
  362.      * I cannot track this one down  RB
  363.      * The same bug shows up if we use ^C^C to abort.
  364.      */
  365.     close(2);
  366. #endif
  367.     close_getchr();
  368.     exit(status);
  369. }
  370.