Jump to content

Hamilton C shell: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
Undid revision 392794197 by Janemillert (talk) Vandalism
Undid revision 392795281 by Msnicki User Msnicki is removing spam, advert, coi tags to conceal {{afd}} is vandalism
Line 1: Line 1:
{{db-spam}}
{{advert|date=October 2010}}
{{coi|date=October 2010}}

{{Infobox software
{{Infobox software
| name = Hamilton C shell
| name = Hamilton C shell

Revision as of 14:53, 25 October 2010

Hamilton C shell
Original author(s)Nicole Hamilton
Initial release1988 (1988)
Stable release
4.0 / June 5, 2009; 15 years ago (2009-06-05)
Written inC
Operating systemWindows
TypeUnix Shell on Windows
LicenseHamilton Laboratories EULA
Websitewww.hamiltonlabs.com/Cshell.htm Edit this on Wikidata

Hamilton C shell is a clone[1] of the Unix C shell and utilities for Microsoft Windows created by Nicole Hamilton at Hamilton Laboratories. It was first released on OS/2 in December 1988[2][3] and on Windows NT in July 1992[4][5]. The OS/2 version was discontinued in 2003 but the Windows version continues to be actively supported.[6]

Design

The most notable design features of Hamilton C shell are its compiler architecture, the use of threads, and the decision to follow Windows rather than Unix conventions.

Compiler

Hamilton C shell and Cygwin bash on Windows 7, showing the use of recursion for factoring.

Hamilton used a compiler architecture with a recursive parser to avoid the problems in the Unix C shell.

The original C shell used an ad hoc parser and that led to complaints about its limitations. It worked well enough for the kinds of things users typed interactively but not very well on the more complex commands a user might take time to write in a script.[7] Attempting to pipe the output of a foreach into grep simply didn't work. There was a limit to how complex a command it could handle.

To avoid those problems, Hamilton used a compiler architecture with a top-down recursive descent parser, allowing statements and control structures to be piped or nested arbitrarily in a fully recursive fashion. Statements and whole control structures are compiled on-the-fly to an internal form and optimized with constant propagation before running them. Execution is achieved using a separate, similarly recursive evaluation unit. The result was a more robust language implementation with better performance. It also made for a better platform for extending the language.

Threads

Hamilton C shell and Cygwin bash date loops.

Hamilton used threads because Windows doesn't support fork.

Two important features of the Unix C shell language are subshells and support for concurrency. A subshell is a separate child copy of the shell that inherits the current state but can then make changes, e.g., to the current directory, without affecting the parent. When the Unix C shell runs a script, it runs it in a subshell. A subshell can also be specified by putting parentheses around a group of statements. Concurrency occurs in pipelines, where all the stages are intended to run concurrently, or when a command is run in the background.

The Unix C shell's implementation of both these features depends on being able to make copies of its entire process state very inexpensively, which in turn depends on the Unix fork() system call, which has access to the hardware. The semantics of fork are that it creates a child process which is a duplicate of the caller, differing only in the return value from fork. The parent and child are otherwise identical with duplicate sets of open file descriptors, duplicate current directories and duplicate memory images. The memory image, which can be quite large, is duplicated using the hardware page table and a technique called "copy-on-write": Initially, parent and child share the same physical pages in memory but all the pages are marked read-only. When one or the other tries to write to a page, a hardware exception is raised and the Unix kernel makes a copy of the page, gives the original to one process and the copy to the other and marks them both writable.

Windows doesn't support a fork primitive under its native Win32 API, in part because Windows was conceived as graphical OS and it was unclear what it would mean to fork a graphical application with message queues.[8] It's possible to simulate the functionality of fork on Windows at the application layer, but without access to the hardware page tables, it's awkward and not nearly as performant.[9][10][11][12]

Instead, Windows supports threads, but the semantics are quite different. When a new thread is created, it runs within the same process space and it shares all of the process state. If one thread changes the current directory or the contents of memory, it's changed for all the threads. It's much cheaper to create a thread than a process but there's no isolation between them.

Hamilton chose to use threads, dynamically spawned anytime a subshell or concurrency is needed. To recreate the missing isolation of separate processes, the threads cooperate to share resources using locks.[13] For example, when a thread is about to call an API that depends on the settings for the current directories, it locks the current directory resource, ensures it's set properly, calls the API and then releases the resource when done. A handle mechanism is used to allow current directory settings to be checked by comparing integers rather than strings. The result is a small loss due to the overhead of the locking mechanism but an overall performance gain.

Conventions

Hamilton followed Windows conventions.

Most Unix shells ported to Windows expect the user to follow Unix conventions for slashes in filenames and escape characters and so on. This is usually advantageous because it reduces the porting effort and because it offers better compatibility with the Unix version and a better chance of running existing Unix scripts on Windows. Porting, whether done with a porting library or by hand, rewriting code that uses Unix system calls to use the Windows API instead, is done at fairly low layer in the code. Changing the language definition the user sees takes more work and risks compatibility problems. The downside is the need for workarounds to express Windows constructs that violate Unix syntax. For example, Unix has a single-rooted filename space and has no concept of drive letters, each with its own current directory. Cygwin's solution was a special notation, "/cygdrive/c" to mean to the Windows C: drive, that could pass through the application layer to the Cywin DLL, where it could be intercepted.[14][15]

But Hamilton was starting from scratch and had more design freedom. Part of that came from the Unix C shell's own lack of popularity for scripting. Though popular for interactive use and because it looked more like C, the Unix C shell was less popular for scripting in the 1980s than sh because it couldn't be guaranteed to be present on all Unix machines; sh could be, which made it a better choice for scripts that needed to be portable. As a result, there weren't a lot of Unix C shell scripts anyone might want to run on other Unix machines, never mind a Windows machine. This allowed Hamilton to build a C shell specifically for Windows that follows Windows conventions. That theme is carried out throughout, including the utilities, as can be seen, e.g., in Hamilton's ls utility, which reports the Windows "DHSARC" (directory, hidden, system, archive, read-only, compressed) bits, not Unix "rwx" (read, write, execute) bits. Similarly, the key bindings for Hamilton's command line editing match the labels on a PC keyboard, not vi or emacs.

Language

The most notable features of Hamilton C shell's language implementation are the fully recursive grammar, improved syntax and additional control structures.

Grammar

The grammar in Hamilton C shell is fully recursive, meaning it's possible to nest or pipe control structures arbitrarily, use them in command substitution and to run them in the background. Hamilton C shell's language implementation avoids the limits the Unix C shell's ad hoc parser imposed on the complexity of a statement.

Syntax

Hamilton C shell's syntax is a little easier than the Unix C shell's. All control blocks end with the same "end" keyword (but aliases allow the old keywords.) When the context is an expression, white space around operators and dollar signs in front of variable names are optional. The set, setenv and alias statements all accept the same syntax.

Hamilton also introduced two new notational conveniences:

... is the the indefinite directory construct. Used in a wildcard, it means zero or more directory levels as required to make the rest of the pattern match. For example, "c:\...\*.c" matches all of the ".c" files anywhere on the C: drive. The effect is similar to having find built into the command line.
`` ... `` is line-at-a-time command substitution. On Windows, filenames often have embedded spaces, which causes them to be broken into meaningless separate words by ordinary command substitution. If the filenames appear one-per-line, line-at-a-time command substitution allows each one to be parsed as a whole word.

Control structures

In addition to control structures provided by the Unix C shell, Hamilton added procedures, a numeric for loop and a conditional repeat.

See also

References

  1. ^ Described as "full compliance with the entire C shell language (except job control) as defined in the Berkeley 4.3 Unix Programmer's Manual and by Anderson & Anderson in The UNIX C Shell Field Guide" in Hamilton C shell Quick Reference. Hamilton Laboratories, Wayland, MA. 1988 - 1990 (Revised July 10, 1990). {{cite book}}: Check date values in: |date= (help)
  2. ^ Hamilton, Douglas. "Hamilton C shell Announcement". IBM Personal Systems Developer (Summer 1989): 119–121.
  3. ^ Richman, Scott (Jan 1 1991). "Examining the Hamilton C Shell". Dr. Dobb's. Retrieved Oct 4 2010. {{cite journal}}: Check date values in: |accessdate= and |date= (help)
  4. ^ Hamilton C shell for Windows Release Notes 4.0, retrieved June 19, 2010.
  5. ^ Hamilton, Doug (Jul 27 1995). "Looking for C-Shell on NT". Newsgroupcomp.os.ms-windows.nt.misc. hamilton.806823765@BIX.com. Retrieved Oct 8 2010. {{cite newsgroup}}: Check date values in: |accessdate= and |date= (help)
  6. ^ Oliver, Robert (Sep 29 2009). "Hamilton C Shell 2009 – The Missing Shell for Windows". Retrieved Oct 10 2010. {{cite web}}: Check date values in: |accessdate= and |date= (help)
  7. ^ Csh Programming Considered Harmful by Tom Christiansen
  8. ^ Hamilton, Douglas A. (Jan 9 1997, 1:00 am). "Why doesn't OS/2 have fork()?". Newsgroupcomp.os.os2.programmer.misc. 01bbfe48$929ec640$0f02000a@hamilton. Retrieved Oct 8 2010. {{cite newsgroup}}: Check date values in: |accessdate= and |date= (help)
  9. ^ Hamilton, Doug (Feb 6 1994 18:17:22 GMT). "fork() on NT! or info on porting Unix apps to NT". Newsgroupcomp.os.ms-windows.nt.misc. hamilton.760558642@BIX.com. Retrieved Oct 8 2010. {{cite newsgroup}}: Check date values in: |accessdate= and |date= (help)
  10. ^ "Cygwin FAQ: How is fork() implemented?". Retrieved Oct 10 2010. {{cite web}}: Check date values in: |accessdate= (help)
  11. ^ "Highlights of Cygwin Functionality: Process Creation". Retrieved Oct 10 2010. {{cite web}}: Check date values in: |accessdate= (help)
  12. ^ Blake, Eric (Jan 15 2009). "Bash doesn't launch the applications directly". Cygwin project (Mailing list). Retrieved Oct 10 2010. {{cite mailing list}}: Check date values in: |accessdate= and |date= (help); Unknown parameter |mailinglist= ignored (|mailing-list= suggested) (help)
  13. ^ Hamilton, Doug (Apr 21 1995). "Suggestions for multiple-reader/single-writer lock?". Newsgroupcomp.os.ms-windows.nt.misc. hamilton.798430053@BIX.com. Retrieved Oct 8 2010. {{cite newsgroup}}: Check date values in: |accessdate= and |date= (help)
  14. ^ "Highlights of Cygwin Functionality: File Access". Retrieved Oct 10 2010. {{cite web}}: Check date values in: |accessdate= (help)
  15. ^ "Cygwin FAQ: How can I access other drives?". Retrieved Oct 10 2010. {{cite web}}: Check date values in: |accessdate= (help)